diff --git a/.checkpatch.conf b/.checkpatch.conf
index 8d1e1d9d0df2918c80d7d8977e8bf17106bb0f15..5eafeeba0a8cc5aa4ddabd1560977425fce29d4a 100644
--- a/.checkpatch.conf
+++ b/.checkpatch.conf
@@ -8,6 +8,7 @@
 --ignore=FILE_PATH_CHANGES
 --ignore=GERRIT_CHANGE_ID
 --ignore=NOT_UNIFIED_DIFF
+--ignore=STRLCPY
 --ignore=PREFER_KERNEL_TYPES
 --ignore=USLEEP_RANGE
 --kconfig-prefix=CFG_
diff --git a/.devcontainer/Dockerfile.vscode b/.devcontainer/Dockerfile.vscode
new file mode 100644
index 0000000000000000000000000000000000000000..cdc36067446e7a5cac84c463108776b91f95742f
--- /dev/null
+++ b/.devcontainer/Dockerfile.vscode
@@ -0,0 +1,48 @@
+FROM ubuntu:22.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+RUN apt update && apt upgrade -y && apt-get install -y \
+    build-essential \
+    autoconf \
+    bc \
+    bison \
+    ccache \
+    clang \
+    lld \
+    cmake \
+    codespell \
+    device-tree-compiler \
+    expect \
+    flex \
+    gcc-aarch64-linux-gnu \
+    gcc-arm-linux-gnueabihf \
+    gcc-riscv64-linux-gnu \
+    gdb-multiarch \
+    gdisk \
+    gettext \
+    libncurses5 \
+    libssl-dev \
+    lsb-release \
+    python3 \
+    python3-pip \
+    python3-cryptography \
+    python3-pycodestyle \
+    python3-pycryptodome \
+    python3-pyelftools \
+    sudo \
+    uuid-dev \
+    wget \
+    curl \
+    git-core \
+    git-man \
+    git-email \
+    sudo \
+    nano \
+    vim \
+    openssh-client \
+    bash-completion
+
+# Add non root user
+RUN useradd -ms /bin/bash optee
+RUN echo "optee ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers
+USER optee
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000000000000000000000000000000000..384f9e980bfbd0ef8bb487d56e44266e0f5169cc
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,29 @@
+{
+	"name": "optee-os-docker",
+	"build": {
+		"dockerfile": "Dockerfile.vscode"
+	},
+
+	"customizations": {
+		"vscode": {
+			"settings": {
+				"terminal.integrated.profiles.linux": {
+					"bash": {
+					  "path": "/bin/bash",
+					  "args": ["-l"]
+					}
+				},
+				"terminal.integrated.defaultProfile.linux": "bash"
+			},
+			"extensions": [
+				"ms-vscode.cpptools",
+				"eamodio.gitlens"
+			]
+		}
+	},
+
+	// Map the host .ssh folder into the container for a seamless ssh experience
+	"mounts": [
+		"source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/optee/.ssh,type=bind,consistency=cached"
+	]
+}
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000000000000000000000000000000000..4bdb6854e32416574e1bb6a6184ab94605649982
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,10 @@
+{
+	"recommendations": [
+                "ms-vscode-remote.remote-containers",
+                "ms-vscode-remote.remote-wsl",
+                "ms-vscode-remote.vscode-remote-extensionpack",
+                "ms-vscode.cpptools-extension-pack",
+                "ms-vscode.cpptools",
+                "eamodio.gitlens",
+	]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0b42b334fab680edb83c9bb400d51b9ad902578e..923dbd8a69ca6979d96e66ba83c2b2b4a64f7205 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,123 @@
+# OP-TEE - version 4.5.0 (2025-01-17)
+
+- Links to the release pages, commits and pull requests merged into this release for:
+  - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_5_0], [commits][OP_TEE_optee_os_commits_4_5_0] and [pull requests][OP_TEE_optee_os_pr_4_5_0]
+  - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_5_0], [commits][OP_TEE_optee_client_commits_4_5_0] and [pull requests][OP_TEE_optee_client_pr_4_5_0]
+  - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_5_0], [commits][OP_TEE_optee_test_commits_4_5_0] and [pull requests][OP_TEE_optee_test_pr_4_5_0]
+  - OP-TEE/build: [release page][OP_TEE_build_release_4_5_0], [commits][OP_TEE_build_commits_4_5_0] and [pull requests][OP_TEE_build_pr_4_5_0]
+  - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_5_0], [commits][linaro_swg_optee_examples_commits_4_5_0] and [pull requests][linaro_swg_optee_examples_pr_4_5_0]
+
+
+[OP_TEE_optee_os_release_4_5_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.5.0
+[OP_TEE_optee_os_commits_4_5_0]: https://github.com/OP-TEE/optee_os/compare/4.4.0...4.5.0
+[OP_TEE_optee_os_pr_4_5_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-10-18..2025-01-17
+
+[OP_TEE_optee_client_release_4_5_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.5.0
+[OP_TEE_optee_client_commits_4_5_0]: https://github.com/OP-TEE/optee_client/compare/4.4.0...4.5.0
+[OP_TEE_optee_client_pr_4_5_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-10-18..2025-01-17
+
+[OP_TEE_optee_test_release_4_5_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.5.0
+[OP_TEE_optee_test_commits_4_5_0]: https://github.com/OP-TEE/optee_test/compare/4.4.0...4.5.0
+[OP_TEE_optee_test_pr_4_5_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-10-18..2025-01-17
+
+[OP_TEE_build_release_4_5_0]: https://github.com/OP-TEE/build/releases/tag/4.5.0
+[OP_TEE_build_commits_4_5_0]: https://github.com/OP-TEE/build/compare/4.4.0...4.5.0
+[OP_TEE_build_pr_4_5_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-10-18..2025-01-17
+
+[linaro_swg_optee_examples_release_4_5_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.5.0
+[linaro_swg_optee_examples_commits_4_5_0]: https://github.com/linaro-swg/optee_examples/compare/4.4.0...4.5.0
+[linaro_swg_optee_examples_pr_4_5_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-10-18..2025-01-17
+
+# OP-TEE - version 4.4.0 (2024-10-18)
+
+- Links to the release pages, commits and pull requests merged into this release for:
+  - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_4_0], [commits][OP_TEE_optee_os_commits_4_4_0] and [pull requests][OP_TEE_optee_os_pr_4_4_0]
+  - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_4_0], [commits][OP_TEE_optee_client_commits_4_4_0] and [pull requests][OP_TEE_optee_client_pr_4_4_0]
+  - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_4_0], [commits][OP_TEE_optee_test_commits_4_4_0] and [pull requests][OP_TEE_optee_test_pr_4_4_0]
+  - OP-TEE/build: [release page][OP_TEE_build_release_4_4_0], [commits][OP_TEE_build_commits_4_4_0] and [pull requests][OP_TEE_build_pr_4_4_0]
+  - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_4_0], [commits][linaro_swg_optee_examples_commits_4_4_0] and [pull requests][linaro_swg_optee_examples_pr_4_4_0]
+
+
+[OP_TEE_optee_os_release_4_4_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.4.0
+[OP_TEE_optee_os_commits_4_4_0]: https://github.com/OP-TEE/optee_os/compare/4.3.0...4.4.0
+[OP_TEE_optee_os_pr_4_4_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-07-12..2024-10-18
+
+[OP_TEE_optee_client_release_4_4_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.4.0
+[OP_TEE_optee_client_commits_4_4_0]: https://github.com/OP-TEE/optee_client/compare/4.3.0...4.4.0
+[OP_TEE_optee_client_pr_4_4_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-07-12..2024-10-18
+
+[OP_TEE_optee_test_release_4_4_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.4.0
+[OP_TEE_optee_test_commits_4_4_0]: https://github.com/OP-TEE/optee_test/compare/4.3.0...4.4.0
+[OP_TEE_optee_test_pr_4_4_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-07-12..2024-10-18
+
+[OP_TEE_build_release_4_4_0]: https://github.com/OP-TEE/build/releases/tag/4.4.0
+[OP_TEE_build_commits_4_4_0]: https://github.com/OP-TEE/build/compare/4.3.0...4.4.0
+[OP_TEE_build_pr_4_4_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-07-12..2024-10-18
+
+[linaro_swg_optee_examples_release_4_4_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.4.0
+[linaro_swg_optee_examples_commits_4_4_0]: https://github.com/linaro-swg/optee_examples/compare/4.3.0...4.4.0
+[linaro_swg_optee_examples_pr_4_4_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-07-12..2024-10-18
+
+# OP-TEE - version 4.3.0 (2024-07-12)
+
+- Links to the release pages, commits and pull requests merged into this release for:
+  - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_3_0], [commits][OP_TEE_optee_os_commits_4_3_0] and [pull requests][OP_TEE_optee_os_pr_4_3_0]
+  - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_3_0], [commits][OP_TEE_optee_client_commits_4_3_0] and [pull requests][OP_TEE_optee_client_pr_4_3_0]
+  - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_3_0], [commits][OP_TEE_optee_test_commits_4_3_0] and [pull requests][OP_TEE_optee_test_pr_4_3_0]
+  - OP-TEE/build: [release page][OP_TEE_build_release_4_3_0], [commits][OP_TEE_build_commits_4_3_0] and [pull requests][OP_TEE_build_pr_4_3_0]
+  - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_3_0], [commits][linaro_swg_optee_examples_commits_4_3_0] and [pull requests][linaro_swg_optee_examples_pr_4_3_0]
+
+
+[OP_TEE_optee_os_release_4_3_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.3.0
+[OP_TEE_optee_os_commits_4_3_0]: https://github.com/OP-TEE/optee_os/compare/4.2.0...4.3.0
+[OP_TEE_optee_os_pr_4_3_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12
+
+[OP_TEE_optee_client_release_4_3_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.3.0
+[OP_TEE_optee_client_commits_4_3_0]: https://github.com/OP-TEE/optee_client/compare/4.2.0...4.3.0
+[OP_TEE_optee_client_pr_4_3_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12
+
+[OP_TEE_optee_test_release_4_3_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.3.0
+[OP_TEE_optee_test_commits_4_3_0]: https://github.com/OP-TEE/optee_test/compare/4.2.0...4.3.0
+[OP_TEE_optee_test_pr_4_3_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12
+
+[OP_TEE_build_release_4_3_0]: https://github.com/OP-TEE/build/releases/tag/4.3.0
+[OP_TEE_build_commits_4_3_0]: https://github.com/OP-TEE/build/compare/4.2.0...4.3.0
+[OP_TEE_build_pr_4_3_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12
+
+[linaro_swg_optee_examples_release_4_3_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.3.0
+[linaro_swg_optee_examples_commits_4_3_0]: https://github.com/linaro-swg/optee_examples/compare/4.2.0...4.3.0
+[linaro_swg_optee_examples_pr_4_3_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-04-12..2024-07-12
+
+# OP-TEE - version 4.2.0 (2024-04-12)
+
+- Links to the release pages, commits and pull requests merged into this release for:
+  - OP-TEE/optee_os: [release page][OP_TEE_optee_os_release_4_2_0], [commits][OP_TEE_optee_os_commits_4_2_0] and [pull requests][OP_TEE_optee_os_pr_4_2_0]
+  - OP-TEE/optee_client: [release page][OP_TEE_optee_client_release_4_2_0], [commits][OP_TEE_optee_client_commits_4_2_0] and [pull requests][OP_TEE_optee_client_pr_4_2_0]
+  - OP-TEE/optee_test: [release page][OP_TEE_optee_test_release_4_2_0], [commits][OP_TEE_optee_test_commits_4_2_0] and [pull requests][OP_TEE_optee_test_pr_4_2_0]
+  - OP-TEE/build: [release page][OP_TEE_build_release_4_2_0], [commits][OP_TEE_build_commits_4_2_0] and [pull requests][OP_TEE_build_pr_4_2_0]
+  - linaro-swg/optee_examples: [release page][linaro_swg_optee_examples_release_4_2_0], [commits][linaro_swg_optee_examples_commits_4_2_0] and [pull requests][linaro_swg_optee_examples_pr_4_2_0]
+
+
+[OP_TEE_optee_os_release_4_2_0]: https://github.com/OP-TEE/optee_os/releases/tag/4.2.0
+[OP_TEE_optee_os_commits_4_2_0]: https://github.com/OP-TEE/optee_os/compare/4.1.0...4.2.0
+[OP_TEE_optee_os_pr_4_2_0]: https://github.com/OP-TEE/optee_os/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12
+
+[OP_TEE_optee_client_release_4_2_0]: https://github.com/OP-TEE/optee_client/releases/tag/4.2.0
+[OP_TEE_optee_client_commits_4_2_0]: https://github.com/OP-TEE/optee_client/compare/4.1.0...4.2.0
+[OP_TEE_optee_client_pr_4_2_0]: https://github.com/OP-TEE/optee_client/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12
+
+[OP_TEE_optee_test_release_4_2_0]: https://github.com/OP-TEE/optee_test/releases/tag/4.2.0
+[OP_TEE_optee_test_commits_4_2_0]: https://github.com/OP-TEE/optee_test/compare/4.1.0...4.2.0
+[OP_TEE_optee_test_pr_4_2_0]: https://github.com/OP-TEE/optee_test/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12
+
+[OP_TEE_build_release_4_2_0]: https://github.com/OP-TEE/build/releases/tag/4.2.0
+[OP_TEE_build_commits_4_2_0]: https://github.com/OP-TEE/build/compare/4.1.0...4.2.0
+[OP_TEE_build_pr_4_2_0]: https://github.com/OP-TEE/build/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12
+
+[linaro_swg_optee_examples_release_4_2_0]: https://github.com/linaro-swg/optee_examples/releases/tag/4.2.0
+[linaro_swg_optee_examples_commits_4_2_0]: https://github.com/linaro-swg/optee_examples/compare/4.1.0...4.2.0
+[linaro_swg_optee_examples_pr_4_2_0]: https://github.com/linaro-swg/optee_examples/pulls?q=is%3Apr+is%3Amerged+base%3Amaster+merged%3A2024-01-19..2024-04-12
+
 # OP-TEE - version 4.1.0 (2024-01-19)
 
 - Links to the release pages, commits and pull requests merged into this release for:
diff --git a/MAINTAINERS b/MAINTAINERS
index 095165b2f032fc625d9cfaa1493a939ce48811fd..1a71d42098e18d47a6b93824162000b680845786 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -62,6 +62,12 @@ R:	Amit Singh Tomar <amittomer25@gmail.com> [@Amit-Radur]
 S:	Maintained
 F:	core/arch/arm/plat-sunxi/
 
+AMD Versal Gen 2
+R:	Michal Simek <michal.simek@amd.com> [@michalsimek]
+R:	Akshay Belsare <akshay.belsare@amd.com> [@Akshay-Belsare]
+S:	Maintained
+F:	core/arch/arm/plat-versal2/
+
 AmLogic AXG (A113D)
 R:	Carlo Caione <ccaione@baylibre.com> [@carlocaione]
 S:	Maintained
@@ -180,7 +186,7 @@ F:	core/drivers/ls_dspi.c
 NXP (Freescale) i.MX family
 R:	Peng Fan <peng.fan@nxp.com> [@MrVan]
 R:	Silvano Di Ninno <silvano.dininno@nxp.com> [@sdininno]
-R:	Clement Faure <clement.faure@nxp.com> [@clementfaure]
+R:	Sahil Malhotra <sahil.malhotra@nxp.com> [@sahilnxp]
 S:	Maintained
 F:	core/arch/arm/plat-imx/
 F:	core/arch/arm/plat-imx/registers
@@ -204,7 +210,7 @@ F:	core/drivers/clk/
 Crypto driver interface
 R:	Cedric Neveux <cedric.neveux@nxp.com> [@cneveux]
 R:	Silvano Di Ninno <silvano.dininno@nxp.com> [@sdininno]
-R:	Clement Faure <clement.faure@nxp.com> [@clementfaure]
+R:	Sahil Malhotra <sahil.malhotra@nxp.com> [@sahilnxp]
 S:	Maintained
 F:	core/drivers/crypto/
 
@@ -324,6 +330,13 @@ R:	Neal Liu <neal_liu@aspeedtech.com> [@Neal-liu]
 S:	Maintained
 F:	core/arch/arm/plat-aspeed/
 
+Telechips TCC805x
+R:	Sungmin Han <sungminhan@telechips.com> [@meeneemaru]
+R:	GY Hwang <gy.hwang@telechips.com> [@hwang-telechips]
+S:	Maintained
+F:	core/arch/arm/plat-telechips/
+F:	core/drivers/openedges_omc.c
+
 RISC-V
 R:	Marouene Boubakri <marouene.boubakri@nxp.com> [@maroueneboubakri]
 S:	Maintained
diff --git a/core/arch/arm/arm.mk b/core/arch/arm/arm.mk
index 34f5a633b3026cb16337558085663c9d116c938c..2da4f97ffd48f7ccaaa079095f65766f9eab8163 100644
--- a/core/arch/arm/arm.mk
+++ b/core/arch/arm/arm.mk
@@ -21,6 +21,9 @@ $(error Error: Please use CFG_LPAE_ADDR_SPACE_BITS instead)
 endif
 
 CFG_LPAE_ADDR_SPACE_BITS ?= 32
+ifeq ($(CFG_ARM32_core),y)
+$(call force,CFG_LPAE_ADDR_SPACE_BITS,32)
+endif
 
 CFG_MMAP_REGIONS ?= 13
 CFG_RESERVED_VASPACE_SIZE ?= (1024 * 1024 * 10)
diff --git a/core/arch/arm/cpu/cortex-armv9.mk b/core/arch/arm/cpu/cortex-armv9.mk
new file mode 100644
index 0000000000000000000000000000000000000000..5981f3e30a23b48d68b172d3e7be83860464ec52
--- /dev/null
+++ b/core/arch/arm/cpu/cortex-armv9.mk
@@ -0,0 +1,14 @@
+$(call force,CFG_HWSUPP_MEM_PERM_WXN,y)
+$(call force,CFG_HWSUPP_MEM_PERM_PXN,y)
+$(call force,CFG_ENABLE_SCTLR_RR,n)
+$(call force,CFG_ENABLE_SCTLR_Z,n)
+
+arm32-platform-cflags 	+= -mcpu=$(arm32-platform-cpuarch)
+arm32-platform-aflags 	+= -mcpu=$(arm32-platform-cpuarch)
+arm32-platform-cxxflags	+= -mcpu=$(arm32-platform-cpuarch)
+
+arm64-platform-cflags 	+= -mcpu=$(arm64-platform-cpuarch)
+arm64-platform-aflags 	+= -mcpu=$(arm64-platform-cpuarch)
+arm64-platform-cxxflags	+= -mcpu=$(arm64-platform-cpuarch)
+
+platform-flavor-armv9 	:= 1
diff --git a/core/arch/arm/cpu/neoverse-v2.mk b/core/arch/arm/cpu/neoverse-v2.mk
new file mode 100644
index 0000000000000000000000000000000000000000..fd4c6c4fc0594f3e2c7f932c2a8667faecbf12d4
--- /dev/null
+++ b/core/arch/arm/cpu/neoverse-v2.mk
@@ -0,0 +1,4 @@
+arm32-platform-cpuarch 	:= neoverse-v2
+arm64-platform-cpuarch 	:= neoverse-v2
+
+include core/arch/arm/cpu/cortex-armv9.mk
diff --git a/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S b/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S
index 72dfea71a7558456baee0ea1b44a146f869c6bc0..4714a1f36f07ff3a9bfdeb88dbb76dbc3649de1b 100644
--- a/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S
+++ b/core/arch/arm/crypto/aes_modes_armv8a_ce_a64.S
@@ -507,7 +507,6 @@ FUNC ce_aes_xts_encrypt , :
 	b		.LxtsencNx
 
 .LxtsencloopNx:
-	ldr		q7, .Lxts_mul_x
 	next_tweak	v4, v4, v7, v8
 .LxtsencNx:
 #if INTERLEAVE >= 2
@@ -544,6 +543,7 @@ FUNC ce_aes_xts_encrypt , :
 	eor		v2.16b, v2.16b, v6.16b
 	st1		{v0.16b-v3.16b}, [x0], #64
 	mov		v4.16b, v7.16b
+	ldr		q7, .Lxts_mul_x
 	cbz		w4, .Lxtsencout
 	b		.LxtsencloopNx
 #endif
@@ -588,7 +588,6 @@ FUNC ce_aes_xts_decrypt , :
 	b		.LxtsdecNx
 
 .LxtsdecloopNx:
-	ldr		q7, .Lxts_mul_x
 	next_tweak	v4, v4, v7, v8
 .LxtsdecNx:
 #if INTERLEAVE >= 2
@@ -625,6 +624,7 @@ FUNC ce_aes_xts_decrypt , :
 	eor		v2.16b, v2.16b, v6.16b
 	st1		{v0.16b-v3.16b}, [x0], #64
 	mov		v4.16b, v7.16b
+	ldr		q7, .Lxts_mul_x
 	cbz		w4, .Lxtsdecout
 	b		.LxtsdecloopNx
 #endif
diff --git a/core/arch/arm/crypto/ghash-ce-core_a64.S b/core/arch/arm/crypto/ghash-ce-core_a64.S
index dc86132e9e04919f52db0032f7411bd3eb47df28..0abf91cec937bb7453ea3a6c3759e322757a3939 100644
--- a/core/arch/arm/crypto/ghash-ce-core_a64.S
+++ b/core/arch/arm/crypto/ghash-ce-core_a64.S
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (c) 2020 Linaro Limited
+ * Copyright (c) 2020, 2024 Linaro Limited
  * Copyright (C) 2014 - 2017 Linaro Ltd. <ard.biesheuvel@linaro.org>
  *
  * Accelerated GHASH implementation with ARMv8 PMULL instructions.
@@ -11,11 +11,10 @@
 #define CPU_LE(x...)	x
 
 /*
- * If the lower half of CTR is initialized with zeroes or a low value we
- * can expect that the upper half will remain unchanged. As an optimization
- * make the code to increase the upper half optional.
+ * Only increase the lowest quarter, that is, 32-bits of the counter. If
+ * it wraps it must not propagate into the upper bits.
  */
-#define INC_HALF_CTR	0
+#define INC_QUART_CTR	1
 
 	SHASH		.req	v0
 	SHASH2		.req	v1
@@ -412,7 +411,7 @@ END_FUNC pmull_ghash_update_p8
 	ld1		{SHASH.2d}, [x4], #16
 	ld1		{HH.2d}, [x4]
 	ld1		{XL.2d}, [x1]
-#if INC_HALF_CTR
+#if INC_QUART_CTR
 	ldr		x8, [x5, #8]			// load lower counter
 #else
 	ldp		x9, x8, [x5]			// load counter
@@ -422,7 +421,7 @@ END_FUNC pmull_ghash_update_p8
 	trn1		SHASH2.2d, SHASH.2d, HH.2d
 	trn2		T1.2d, SHASH.2d, HH.2d
 CPU_LE(	rev		x8, x8		)
-#if !INC_HALF_CTR
+#if !INC_QUART_CTR
 CPU_LE(	rev		x9, x9		)
 #endif
 	shl		MASK.2d, MASK.2d, #57
@@ -437,10 +436,13 @@ CPU_LE(	rev		x9, x9		)
 
 0:	ld1		{INP0.16b-INP1.16b}, [x3], #32
 
-#if INC_HALF_CTR
+#if INC_QUART_CTR
+	lsr		x12, x8, #32		// Save the upper 32 bits
 	rev		x9, x8
-	add		x11, x8, #1
-	add		x8, x8, #2
+	add		w11, w8, #1
+	add		w8, w8, #2
+	add		x11, x11, x12, lsl #32	// Restore the upper 32 bits
+	add		x8, x8, x12, lsl #32
 #endif
 
 	.if		\enc == 1
@@ -450,7 +452,7 @@ CPU_LE(	rev		x9, x9		)
 
 	sub		w0, w0, #2
 
-#if INC_HALF_CTR
+#if INC_QUART_CTR
 	ld1		{KS0.8b}, [x5]			// load upper counter
 	rev		x11, x11
 	mov		KS1.8b, KS0.8b
@@ -563,11 +565,11 @@ CPU_LE(	rev		x9, x9		)
 	cbnz		w0, 0b
 
 CPU_LE(	rev		x8, x8		)
-#if !INC_HALF_CTR
+#if !INC_QUART_CTR
 CPU_LE(	rev		x9, x9		)
 #endif
 	st1		{XL.2d}, [x1]
-#if INC_HALF_CTR
+#if INC_QUART_CTR
 	str		x8, [x5, #8]			// store lower counter
 #else
 	stp		x9, x8, [x5]			// store counter
diff --git a/core/arch/arm/crypto/sha3_armv8a_ce_a64.S b/core/arch/arm/crypto/sha3_armv8a_ce_a64.S
index a468998d0646c1e0ff746c404f36f721499b0ea7..5276d823a78a4ed4eca3999dfc577d01884d5993 100644
--- a/core/arch/arm/crypto/sha3_armv8a_ce_a64.S
+++ b/core/arch/arm/crypto/sha3_armv8a_ce_a64.S
@@ -114,9 +114,8 @@ FUNC sha3_ce_transform , :
 	b	4f
 
 	/* SHA3-224: digest size 28 bytes, block size 144 bytes */
-2:	ld1	{v25.8b-v26.8b}, [x1], #16
-	eor	v17.8b, v17.8b, v25.8b
-	eor	v18.8b, v18.8b, v26.8b
+2:	ld1	{v29.8b}, [x1], #8
+	eor	v17.8b, v17.8b, v29.8b
 	b	4f
 
 	/* SHA3-512: digest size 64 bytes , block size 72 bytes */
diff --git a/core/arch/arm/crypto/sm4_armv8a_ce_a64.S b/core/arch/arm/crypto/sm4_armv8a_ce_a64.S
index 1f96bbf84b36a2fc4a312baef1fd6a919a5dffa0..11619172abe63089114016d8c33b9843e27aa912 100644
--- a/core/arch/arm/crypto/sm4_armv8a_ce_a64.S
+++ b/core/arch/arm/crypto/sm4_armv8a_ce_a64.S
@@ -1028,3 +1028,5 @@ FUNC ce_sm4_xts_decrypt , :
 	frame_pop
 	ret
 END_FUNC ce_sm4_xts_decrypt
+
+BTI(emit_aarch64_feature_1_and     GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
diff --git a/core/arch/arm/dts/at91-sama7g54_ek.dts b/core/arch/arm/dts/at91-sama7g54_ek.dts
new file mode 100644
index 0000000000000000000000000000000000000000..de9a8b46c3c4eee2de7fcf0b4dd49c4d782663e7
--- /dev/null
+++ b/core/arch/arm/dts/at91-sama7g54_ek.dts
@@ -0,0 +1,958 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ *  at91-sama7g54_ek.dts - Device Tree file for SAMA7G54-EK board
+ *
+ *  Copyright (c) 2017, Microchip Technology Inc.
+ *                2016 Nicolas Ferre <nicolas.ferre@atmel.com>
+ *                2017 Cristian Birsan <cristian.birsan@microchip.com>
+ *                2017 Claudiu Beznea <claudiu.beznea@microchip.com>
+ */
+/dts-v1/;
+#include "sama7g5-pinfunc.h"
+#include "sama7g5.dtsi"
+#include <dt-bindings/mfd/atmel-flexcom.h>
+
+/ {
+	model = "Microchip SAMA7G5-EK";
+	compatible = "microchip,sama7g5ek", "microchip,sama7g5", "microchip,sama7";
+
+	aliases {
+		serial0 = &uart3;
+		serial1 = &uart4;
+		serial2 = &uart7;
+		serial3 = &uart0;
+		i2c0 = &i2c1;
+		i2c1 = &i2c8;
+		i2c2 = &i2c9;
+	};
+
+	clocks {
+		slow_xtal {
+			clock-frequency = <32768>;
+		};
+
+		main_xtal {
+			clock-frequency = <24000000>;
+		};
+	};
+
+	leds {
+		compatible = "gpio-leds";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_led_gpio_default>;
+		status = "okay"; /* Conflict with pwm. */
+
+		red_led {
+			label = "red";
+			gpios = <&pioA PIN_PB8 GPIO_ACTIVE_HIGH>;
+		};
+
+		green_led {
+			label = "green";
+			gpios = <&pioA PIN_PA13 GPIO_ACTIVE_HIGH>;
+		};
+
+		blue_led {
+			label = "blue";
+			gpios = <&pioA PIN_PD20 GPIO_ACTIVE_HIGH>;
+			linux,default-trigger = "heartbeat";
+		};
+	};
+
+	/* 512 M */
+	memory@60000000 {
+		device_type = "memory";
+		reg = <0x60000000 0x20000000>;
+	};
+
+	sound: sound {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		assigned-clocks = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>;
+		assigned-clock-rates = <196608000>;
+		compatible = "microchip,asrc-card";
+		microchip,model = "mchp-asrc-card @ sama7g5 EK";
+		status = "disabled";
+
+		microchip,audio-asrc = <&asrc 0>, <&asrc 1>, <&asrc 2>, <&asrc 3>;
+
+		microchip,dai-link@0 {
+			reg = <0>;
+			microchip,convert-channels = <2>;
+			microchip,convert-rate = <48000>;
+			cpu {
+				sound-dai = <&spdiftx>;
+			};
+			codec {
+				sound-dai = <&spdif_out>;
+			};
+		};
+
+		microchip,dai-link@1 {
+			reg = <1>;
+			microchip,convert-channels = <2>;
+			microchip,convert-rate = <48000>;
+			cpu {
+				sound-dai = <&spdifrx>;
+			};
+			codec {
+				sound-dai = <&spdif_in>;
+			};
+		};
+	};
+
+	spdif_in: spdif-in {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dir";
+	};
+
+	spdif_out: spdif-out {
+		#sound-dai-cells = <0>;
+		compatible = "linux,spdif-dit";
+	};
+};
+
+&asrc {
+	status = "okay";
+};
+
+&adc {
+	vddana-supply = <&vddout25>;
+	vref-supply = <&vddout25>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_mikrobus1_an_default &pinctrl_mikrobus2_an_default>;
+	status = "disabled";
+};
+
+&can0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can0_default>;
+	status = "okay";
+};
+
+&can1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_can1_default>;
+	status = "okay";
+};
+
+&cpu0 {
+	cpu-supply = <&vddcpu>;
+};
+
+&qspi0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_qspi>;
+	status = "okay";
+
+	flash@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <133000000>;
+		spi-tx-bus-width = <8>;
+		spi-rx-bus-width = <8>;
+		m25p,fast-read;
+
+		at91bootstrap@0 {
+			label = "ospi: at91bootstrap";
+			reg = <0x0 0x40000>;
+		};
+
+		bootloader@40000 {
+			label = "ospi: bootloader";
+			reg = <0x40000 0xc0000>;
+		};
+
+		bootloaderenvred@100000 {
+			label = "ospi: bootloader env redundant";
+			reg = <0x100000 0x40000>;
+		};
+
+		bootloaderenv@140000 {
+			label = "ospi: bootloader env";
+			reg = <0x140000 0x40000>;
+		};
+
+		dtb@180000 {
+			label = "ospi: device tree";
+			reg = <0x180000 0x80000>;
+		};
+
+		kernel@200000 {
+			label = "ospi: kernel";
+			reg = <0x200000 0x600000>;
+		};
+
+		rootfs@800000 {
+			label = "ospi: rootfs";
+			reg = <0x800000 0x7800000>;
+		};
+
+	};
+};
+
+&dma0 {
+	status = "okay";
+};
+
+&dma1 {
+	status = "okay";
+};
+
+&dma2 {
+	status = "okay";
+};
+
+&flx0 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+	status = "disabled";
+
+	uart0: serial@200 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flx0_default>;
+		status = "disabled";
+	};
+};
+
+&flx1 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+	status = "okay";
+
+	i2c1: i2c@600 {
+		dmas = <0>, <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c1_default>;
+		i2c-analog-filter;
+		i2c-digital-filter;
+		i2c-digital-filter-width-ns = <35>;
+		status = "disable";
+		secure-status = "okay";
+
+		pac1934@10 {
+			compatible = "microchip,pac1934";
+			reg = <0x10>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "okay";
+
+			channel@1 {
+				reg = <0x1>;
+				shunt-resistor-micro-ohms = <10000>;
+				label = "VDD3V3";
+			};
+
+			channel@2 {
+				reg = <0x2>;
+				shunt-resistor-micro-ohms = <10000>;
+				label = "VDDIODDR";
+			};
+
+			channel@3 {
+				reg = <0x3>;
+				shunt-resistor-micro-ohms = <10000>;
+				label = "VDDCORE";
+			};
+
+			channel@4 {
+				reg = <0x4>;
+				shunt-resistor-micro-ohms = <10000>;
+				label = "VDDCPU";
+			};
+		};
+
+		mcp16502@5b {
+			compatible = "microchip,mcp16502";
+			reg = <0x5b>;
+			status = "okay";
+
+			regulators {
+				vdd_3v3: VDD_IO {
+					regulator-name = "VDD_IO";
+					regulator-min-microvolt = <3300000>;
+					regulator-max-microvolt = <3300000>;
+					regulator-initial-mode = <2>;
+					regulator-allowed-modes = <2>, <4>;
+					regulator-always-on;
+
+					regulator-state-standby {
+						regulator-on-in-suspend;
+						regulator-suspend-microvolt = <3300000>;
+						regulator-mode = <4>;
+					};
+
+					regulator-state-mem {
+						regulator-off-in-suspend;
+						regulator-mode = <4>;
+					};
+				};
+
+				vddioddr: VDD_DDR {
+					regulator-name = "VDD_DDR";
+					regulator-min-microvolt = <1350000>;
+					regulator-max-microvolt = <1350000>;
+					regulator-initial-mode = <2>;
+					regulator-allowed-modes = <2>, <4>;
+					regulator-always-on;
+
+					regulator-state-standby {
+						regulator-on-in-suspend;
+						regulator-suspend-microvolt = <1350000>;
+						regulator-mode = <4>;
+					};
+
+					regulator-state-mem {
+						regulator-on-in-suspend;
+						regulator-suspend-microvolt = <1350000>;
+						regulator-mode = <4>;
+					};
+				};
+
+				vddcore: VDD_CORE {
+					regulator-name = "VDD_CORE";
+					regulator-min-microvolt = <1150000>;
+					regulator-max-microvolt = <1150000>;
+					regulator-initial-mode = <2>;
+					regulator-allowed-modes = <2>, <4>;
+					regulator-always-on;
+
+					regulator-state-standby {
+						regulator-on-in-suspend;
+						regulator-suspend-voltage = <1150000>;
+						regulator-mode = <4>;
+					};
+
+					regulator-state-mem {
+						regulator-off-in-suspend;
+						regulator-mode = <4>;
+					};
+				};
+
+				vddcpu: VDD_OTHER {
+					regulator-name = "VDD_OTHER";
+					regulator-min-microvolt = <1050000>;
+					regulator-max-microvolt = <1250000>;
+					regulator-initial-mode = <2>;
+					regulator-allowed-modes = <2>, <4>;
+					regulator-ramp-delay = <3125>;
+					regulator-always-on;
+
+					regulator-state-standby {
+						regulator-on-in-suspend;
+						regulator-suspend-voltage = <1050000>;
+						regulator-mode = <4>;
+					};
+
+					regulator-state-mem {
+						regulator-off-in-suspend;
+						regulator-mode = <4>;
+					};
+				};
+
+				vldo1: LDO1 {
+					regulator-name = "LDO1";
+					regulator-min-microvolt = <1800000>;
+					regulator-max-microvolt = <1800000>;
+					regulator-always-on;
+
+					regulator-state-standby {
+						regulator-suspend-voltage = <1800000>;
+						regulator-on-in-suspend;
+					};
+
+					regulator-state-mem {
+						regulator-off-in-suspend;
+					};
+				};
+
+				vldo2: LDO2 {
+					regulator-name = "LDO2";
+					regulator-min-microvolt = <1200000>;
+					regulator-max-microvolt = <3700000>;
+
+					regulator-state-standby {
+						regulator-suspend-voltage = <1800000>;
+						regulator-on-in-suspend;
+					};
+
+					regulator-state-mem {
+						regulator-off-in-suspend;
+					};
+				};
+			};
+		};
+	};
+};
+
+&flx3 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+	status = "okay";
+
+	uart3: serial@200 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flx3_default>;
+		status = "okay";
+	};
+};
+
+&flx4 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+	status = "okay";
+
+	uart4: serial@200 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flx4_default>;
+		status = "okay";
+	};
+};
+
+&flx7 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_USART>;
+	status = "okay";
+
+	uart7: serial@200 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_flx7_default>;
+		status = "okay";
+	};
+};
+
+&flx8 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+	status = "okay";
+
+	i2c8: i2c@600 {
+		dmas = <0>, <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c8_default>;
+		i2c-analog-filter;
+		i2c-digital-filter;
+		i2c-digital-filter-width-ns = <35>;
+		status = "okay";
+
+		eeprom0: eeprom0@52 {
+			compatible = "atmel,24mac02e4";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x52>;
+			pagesize = <16>;
+			size = <256>;
+			status = "okay";
+
+			eeprom0_eui48: eui48@fa {
+				reg = <0xfa 0x6>;
+			};
+		};
+
+		eeprom1: eeprom1@53 {
+			compatible = "atmel,24mac02e4";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0x53>;
+			pagesize = <16>;
+			size = <256>;
+			status = "okay";
+
+			eeprom1_eui48: eui48@fa {
+				reg = <0xfa 0x6>;
+			};
+		};
+	};
+};
+
+&flx9 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_TWI>;
+	status = "okay";
+
+	i2c9: i2c@600 {
+		dmas = <0>, <0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_i2c9_default>;
+		i2c-analog-filter;
+		i2c-digital-filter;
+		i2c-digital-filter-width-ns = <35>;
+		status = "okay";
+	};
+};
+
+&flx11 {
+	atmel,flexcom-mode = <ATMEL_FLEXCOM_MODE_SPI>;
+	status = "okay";
+
+	spi11: spi@400 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_mikrobus1_spi &pinctrl_mikrobus1_spi_cs>;
+		status = "okay";
+	};
+};
+
+&gmac0 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gmac0_default
+		     &pinctrl_gmac0_mdio_default
+		     &pinctrl_gmac0_txck_default
+		     &pinctrl_gmac0_phy_irq>;
+	phy-mode = "rgmii-id";
+	status = "okay";
+
+	nvmem-cells = <&eeprom0_eui48>;
+	nvmem-cell-names = "mac-address";
+
+	ethernet-phy@7 {
+		reg = <0x7>;
+		interrupt-parent = <&pioA>;
+		interrupts = <PIN_PA31 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&gmac1 {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_gmac1_default
+		     &pinctrl_gmac1_mdio_default
+		     &pinctrl_gmac1_phy_irq>;
+	phy-mode = "rmii";
+	status = "disabled"; /* Conflict with pdmc0. */
+
+	nvmem-cells = <&eeprom1_eui48>;
+	nvmem-cell-names = "mac-address";
+
+	ethernet-phy@0 {
+		reg = <0x0>;
+		interrupt-parent = <&pioA>;
+		interrupts = <PIN_PA21 IRQ_TYPE_LEVEL_LOW>;
+	};
+};
+
+&i2s0 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2s0_default>;
+};
+
+&pdmc0 {
+	#sound-dai-cells = <0>;
+	status = "disabled"; /* Conflict with gmac1. */
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_pdmc0_default>;
+};
+
+&pioA {
+
+	pinctrl_can0_default: can0_default {
+		pinmux = <PIN_PD12__CANTX0>,
+			 <PIN_PD13__CANRX0 >;
+		bias-disable;
+	};
+
+	pinctrl_can1_default: can1_default {
+		pinmux = <PIN_PD14__CANTX1>,
+			 <PIN_PD15__CANRX1 >;
+		bias-disable;
+	};
+
+	pinctrl_flx0_default: flx0_default {
+		pinmux = <PIN_PE3__FLEXCOM0_IO0>,
+			 <PIN_PE4__FLEXCOM0_IO1>,
+			 <PIN_PE6__FLEXCOM0_IO3>,
+			 <PIN_PE7__FLEXCOM0_IO4>;
+		bias-disable;
+	};
+
+	pinctrl_flx3_default: flx3_default {
+		pinmux = <PIN_PD16__FLEXCOM3_IO0>,
+			 <PIN_PD17__FLEXCOM3_IO1>;
+		bias-pull-up;
+	};
+
+	pinctrl_flx4_default: flx4_default {
+		pinmux = <PIN_PD18__FLEXCOM4_IO0>,
+			 <PIN_PD19__FLEXCOM4_IO1>;
+		bias-disable;
+	};
+
+	pinctrl_flx7_default: flx7_default {
+		pinmux = <PIN_PC23__FLEXCOM7_IO0>,
+			 <PIN_PC24__FLEXCOM7_IO1>;
+		bias-disable;
+	};
+
+	pinctrl_gmac0_default: gmac0_default {
+		pinmux = <PIN_PA16__G0_TX0>,
+			 <PIN_PA17__G0_TX1>,
+			 <PIN_PA26__G0_TX2>,
+			 <PIN_PA27__G0_TX3>,
+			 <PIN_PA19__G0_RX0>,
+			 <PIN_PA20__G0_RX1>,
+			 <PIN_PA28__G0_RX2>,
+			 <PIN_PA29__G0_RX3>,
+			 <PIN_PA15__G0_TXEN>,
+			 <PIN_PA30__G0_RXCK>,
+			 <PIN_PA18__G0_RXDV>,
+			 <PIN_PA25__G0_125CK>;
+		slew-rate = <0>;
+		bias-disable;
+	};
+
+	pinctrl_gmac0_mdio_default: gmac0_mdio_default {
+		pinmux = <PIN_PA22__G0_MDC>,
+			 <PIN_PA23__G0_MDIO>;
+		bias-disable;
+	};
+
+	pinctrl_gmac0_txck_default: gmac0_txck_default {
+		pinmux = <PIN_PA24__G0_TXCK>;
+		slew-rate = <0>;
+		bias-pull-up;
+	};
+
+	pinctrl_gmac0_phy_irq: gmac0_phy_irq {
+		pinmux = <PIN_PA31__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_gmac1_default: gmac1_default {
+		pinmux = <PIN_PD30__G1_TXCK>,
+			 <PIN_PD22__G1_TX0>,
+			 <PIN_PD23__G1_TX1>,
+			 <PIN_PD21__G1_TXEN>,
+			 <PIN_PD25__G1_RX0>,
+			 <PIN_PD26__G1_RX1>,
+			 <PIN_PD27__G1_RXER>,
+			 <PIN_PD24__G1_RXDV>;
+		slew-rate = <0>;
+		bias-disable;
+	};
+
+	pinctrl_gmac1_mdio_default: gmac1_mdio_default {
+		pinmux = <PIN_PD28__G1_MDC>,
+			 <PIN_PD29__G1_MDIO>;
+		bias-disable;
+	};
+
+	pinctrl_gmac1_phy_irq: gmac1_phy_irq {
+		pinmux = <PIN_PA21__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_i2c1_default: i2c1_default {
+		pinmux = <PIN_PC9__FLEXCOM1_IO0>,
+			 <PIN_PC10__FLEXCOM1_IO1>;
+		bias-disable;
+	};
+
+	pinctrl_i2c8_default: i2c8_default {
+		pinmux = <PIN_PC14__FLEXCOM8_IO0>,
+			 <PIN_PC13__FLEXCOM8_IO1>;
+		bias-disable;
+	};
+
+	pinctrl_i2c9_default: i2c9_default {
+		pinmux = <PIN_PC18__FLEXCOM9_IO0>,
+			 <PIN_PC19__FLEXCOM9_IO1>;
+		bias-disable;
+	};
+
+	pinctrl_i2s0_default: i2s0_default {
+		pinmux = <PIN_PB23__I2SMCC0_CK>,
+			 <PIN_PB24__I2SMCC0_WS>,
+			 <PIN_PB25__I2SMCC0_DOUT1>,
+			 <PIN_PB26__I2SMCC0_DOUT0>,
+			 <PIN_PB27__I2SMCC0_MCK>;
+		bias-disable;
+	};
+
+	pinctrl_key_gpio_default: key_gpio_default {
+		pinmux = <PIN_PA12__GPIO>;
+		bias-pull-up;
+	};
+
+	pinctrl_led_gpio_default: led_gpio_default {
+		pinmux = <PIN_PA13__GPIO>,
+			 <PIN_PB8__GPIO>,
+			 <PIN_PD20__GPIO>;
+		bias-pull-up;
+	};
+
+	pinctrl_mikrobus1_an_default: mikrobus1_an_default {
+		pinmux = <PIN_PD0__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_mikrobus2_an_default: mikrobus2_an_default {
+		pinmux = <PIN_PD1__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_mikrobus1_pwm2_default: mikrobus1_pwm2_default {
+		pinmux = <PIN_PA13__PWMH2>;
+		bias-disable;
+	};
+
+	pinctrl_mikrobus2_pwm3_default: mikrobus2_pwm3_default {
+		pinmux = <PIN_PD20__PWMH3>;
+		bias-disable;
+	};
+
+	pinctrl_mikrobus1_spi_cs: mikrobus1_spi_cs {
+		pinmux = <PIN_PB6__FLEXCOM11_IO3>;
+		bias-disable;
+	};
+
+	pinctrl_mikrobus1_spi: mikrobus1_spi {
+		pinmux = <PIN_PB3__FLEXCOM11_IO0>,
+			 <PIN_PB4__FLEXCOM11_IO1>,
+			 <PIN_PB5__FLEXCOM11_IO2>;
+		bias-disable;
+	};
+
+	pinctrl_pdmc0_default: pdmc0_default {
+		pinmux = <PIN_PD23__PDMC0_DS0>,
+			 <PIN_PD24__PDMC0_DS1>,
+			 <PIN_PD22__PDMC0_CLK>;
+		bias_disable;
+	};
+
+	pinctrl_qspi: qspi {
+		pinmux = <PIN_PB12__QSPI0_IO0>,
+			 <PIN_PB11__QSPI0_IO1>,
+			 <PIN_PB10__QSPI0_IO2>,
+			 <PIN_PB9__QSPI0_IO3>,
+			 <PIN_PB16__QSPI0_IO4>,
+			 <PIN_PB17__QSPI0_IO5>,
+			 <PIN_PB18__QSPI0_IO6>,
+			 <PIN_PB19__QSPI0_IO7>,
+			 <PIN_PB13__QSPI0_CS>,
+			 <PIN_PB14__QSPI0_SCK>,
+			 <PIN_PB15__QSPI0_SCKN>,
+			 <PIN_PB20__QSPI0_DQS>,
+			 <PIN_PB21__QSPI0_INT>;
+		bias-disable;
+		slew-rate = <0>;
+	};
+
+	pinctrl_sdmmc0_default: sdmmc0_default {
+		cmd_data {
+			pinmux = <PIN_PA1__SDMMC0_CMD>,
+				 <PIN_PA3__SDMMC0_DAT0>,
+				 <PIN_PA4__SDMMC0_DAT1>,
+				 <PIN_PA5__SDMMC0_DAT2>,
+				 <PIN_PA6__SDMMC0_DAT3>,
+				 <PIN_PA7__SDMMC0_DAT4>,
+				 <PIN_PA8__SDMMC0_DAT5>,
+				 <PIN_PA9__SDMMC0_DAT6>,
+				 <PIN_PA10__SDMMC0_DAT7>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+
+		ck_cd_rstn_vddsel {
+			pinmux = <PIN_PA0__SDMMC0_CK>,
+				 <PIN_PA2__SDMMC0_RSTN>,
+				 <PIN_PA11__SDMMC0_DS>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+	};
+
+	pinctrl_sdmmc1_default: sdmmc1_default {
+		cmd_data {
+			pinmux = <PIN_PB29__SDMMC1_CMD>,
+				 <PIN_PB31__SDMMC1_DAT0>,
+				 <PIN_PC0__SDMMC1_DAT1>,
+				 <PIN_PC1__SDMMC1_DAT2>,
+				 <PIN_PC2__SDMMC1_DAT3>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+
+		ck_cd_rstn_vddsel {
+			pinmux = <PIN_PB30__SDMMC1_CK>,
+				 <PIN_PB28__SDMMC1_RSTN>,
+				 <PIN_PC5__SDMMC1_1V8SEL>,
+				 <PIN_PC4__SDMMC1_CD>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+	};
+
+	pinctrl_sdmmc2_default: sdmmc2_default {
+		cmd_data {
+			pinmux = <PIN_PD3__SDMMC2_CMD>,
+				 <PIN_PD5__SDMMC2_DAT0>,
+				 <PIN_PD6__SDMMC2_DAT1>,
+				 <PIN_PD7__SDMMC2_DAT2>,
+				 <PIN_PD8__SDMMC2_DAT3>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+
+		ck {
+			pinmux = <PIN_PD4__SDMMC2_CK>;
+			slew-rate = <0>;
+			bias-pull-up;
+		};
+	};
+
+	pinctrl_spdifrx_default: spdifrx_default {
+		pinmux = <PIN_PB0__SPDIF_RX>;
+		bias-disable;
+	};
+
+	pinctrl_spdiftx_default: spdiftx_default {
+		pinmux = <PIN_PB1__SPDIF_TX>;
+		bias-disable;
+	};
+
+	pinctrl_usba_vbus_det: usba_vbus_det {
+		pinmux = <PIN_PD11__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_usbb_vbus_det: usbb_vbus_det {
+		pinmux = <PIN_PC12__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_usba_vbus_en: usba_vbus_en {
+		pinmux = <PIN_PB2__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_usbb_vbus_en: usbb_vbus_en {
+		pinmux = <PIN_PC11__GPIO>;
+		bias-disable;
+	};
+
+	pinctrl_usbc_vbus_en: usbc_vbus_en {
+		pinmux = <PIN_PC6__GPIO>;
+		bias-disable;
+	};
+};
+
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_mikrobus1_pwm2_default &pinctrl_mikrobus2_pwm3_default>;
+	status = "disabled"; /* Conflict with leds. */
+};
+
+&rtt {
+	atmel,rtt-rtc-time-reg = <&gpbr 0x0>;
+};
+
+&sdmmc0 {
+	bus-width = <8>;
+	non-removable;
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&vldo1>;
+	mmc-ddr-1_8v;
+	cap-mmc-highspeed;
+	cap-mmc-hw-reset;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdmmc0_default>;
+	status = "okay";
+};
+
+&sdmmc1 {
+	bus-width = <4>;
+	vmmc-supply = <&vdd_3v3>;
+	vqmmc-supply = <&vdd_3v3>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdmmc1_default>;
+	status = "okay";
+};
+
+&sdmmc2 {
+	bus-width = <4>;
+	no-1-8-v;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_sdmmc2_default>;
+};
+
+&shdwc {
+	debounce-delay-us = <976>;
+	microchip,lpm-connection = <&gmac1 &main_xtal>;
+
+	input@0 {
+		reg = <0>;
+	};
+};
+
+&spdifrx {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdifrx_default>;
+	status = "okay";
+};
+
+&spdiftx {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spdiftx_default>;
+	status = "okay";
+};
+
+&tcb0 {
+	timer0: timer@0 {
+		compatible = "atmel,tcb-timer";
+		reg = <0>;
+	};
+
+	timer1: timer@1 {
+		compatible = "atmel,tcb-timer";
+		reg = <1>;
+	};
+};
+
+&usb0 {
+	atmel,vbus-gpio = <&pioA PIN_PD11 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usba_vbus_det>;
+	phys = <&usb_phy0>;
+	phy-names = "usb";
+	status = "okay";
+};
+
+&usb1 {
+	atmel,vbus-gpio = <&pioA PIN_PC12 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbb_vbus_det>;
+	phys = <&usb_phy1>;
+	phy-names = "usb";
+	status = "disabled";
+};
+
+&usb2 {
+	num-ports = <3>;
+	atmel,vbus-gpio = <0
+			   &pioA PIN_PC11 GPIO_ACTIVE_HIGH
+			   &pioA PIN_PC6 GPIO_ACTIVE_HIGH
+			  >;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usbb_vbus_en &pinctrl_usbc_vbus_en>;
+	phys = <&usb_phy1>, <&usb_phy2>;
+	phy-names = "usb", "usb";
+	status = "okay";
+};
+
+&usb3 {
+	status = "okay";
+};
+
+&usb_phy0 {
+	status = "okay";
+};
+
+&usb_phy1 {
+	status = "okay";
+};
+
+&usb_phy2 {
+	status = "okay";
+};
+
+&vddout25 {
+	vin-supply = <&vdd_3v3>;
+	status = "okay";
+};
diff --git a/core/arch/arm/dts/fsl-lx2160a.dtsi b/core/arch/arm/dts/fsl-lx2160a.dtsi
index c5bdfc87fad4cc94b691174a2d493aa90d2fa7a4..2acdf63ff64fff8116fd3f9b972ca36c7c078c28 100644
--- a/core/arch/arm/dts/fsl-lx2160a.dtsi
+++ b/core/arch/arm/dts/fsl-lx2160a.dtsi
@@ -416,6 +416,12 @@
 		reg = <0x00000000 0x80000000 0 0x80000000>;
 	};
 
+	memory@2080000000 {
+		// DRAM space - 1, size : 126 GB DRAM
+		device_type = "memory";
+		reg = <0x00000020 0x80000000 0x0000001F 0x80000000>;
+	};
+
 	ddr1: memory-controller@1080000 {
 		compatible = "fsl,qoriq-memory-controller";
 		reg = <0x0 0x1080000 0x0 0x1000>;
diff --git a/core/arch/arm/dts/sama5d2.dtsi b/core/arch/arm/dts/sama5d2.dtsi
index 56c4dd5ca971b4154cba0d137e3e833bce3915ce..4c26d8f582e2dcd53f13357aeff901606bc920ac 100644
--- a/core/arch/arm/dts/sama5d2.dtsi
+++ b/core/arch/arm/dts/sama5d2.dtsi
@@ -745,6 +745,26 @@
 				secure-status = "okay";
 				#address-cells = <1>;
 				#size-cells = <1>;
+
+				sfc_dr0: cell@20 {
+					reg = <0x20 0x20>;
+				};
+
+				sfc_dr1: cell@24 {
+					reg = <0x24 0x20>;
+				};
+			};
+
+			die_id: die_id {
+				compatible = "optee,nvmem-die-id";
+				nvmem-cells = <&sfc_dr0>;
+				nvmem-cell-names = "die_id";
+			};
+
+			huk: huk {
+				compatible = "optee,nvmem-huk";
+				nvmem-cells = <&sfc_dr1>;
+				nvmem-cell-names = "hw_unique_key";
 			};
 
 			i2s0: i2s@f8050000 {
diff --git a/core/arch/arm/dts/sama7g5-pinfunc.h b/core/arch/arm/dts/sama7g5-pinfunc.h
new file mode 100644
index 0000000000000000000000000000000000000000..4f98cdbb00916626c9653e6c68d7afb9f26e0ce1
--- /dev/null
+++ b/core/arch/arm/dts/sama7g5-pinfunc.h
@@ -0,0 +1,927 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries
+ */
+
+#define PINMUX_PIN(no, func, ioset) \
+	(((no) & 0xffff) | (((func) & 0xf) << 16) | (((ioset) & 0xff) << 20))
+
+#define PIN_PA0				0
+#define PIN_PA0__GPIO			PINMUX_PIN(PIN_PA0, 0, 0)
+#define PIN_PA0__SDMMC0_CK		PINMUX_PIN(PIN_PA0, 1, 1)
+#define PIN_PA0__FLEXCOM0_IO0		PINMUX_PIN(PIN_PA0, 2, 1)
+#define PIN_PA0__CANTX3			PINMUX_PIN(PIN_PA0, 3, 1)
+#define PIN_PA0__PWML0			PINMUX_PIN(PIN_PA0, 5, 2)
+#define PIN_PA1				1
+#define PIN_PA1__GPIO			PINMUX_PIN(PIN_PA1, 0, 0)
+#define PIN_PA1__SDMMC0_CMD		PINMUX_PIN(PIN_PA1, 1, 1)
+#define PIN_PA1__FLEXCOM0_IO1		PINMUX_PIN(PIN_PA1, 2, 1)
+#define PIN_PA1__CANRX3			PINMUX_PIN(PIN_PA1, 3, 1)
+#define PIN_PA1__D14			PINMUX_PIN(PIN_PA1, 4, 1)
+#define PIN_PA1__PWMH0			PINMUX_PIN(PIN_PA1, 5, 3)
+#define PIN_PA2				2
+#define PIN_PA2__GPIO			PINMUX_PIN(PIN_PA2, 0, 0)
+#define PIN_PA2__SDMMC0_RSTN		PINMUX_PIN(PIN_PA2, 1, 1)
+#define PIN_PA2__FLEXCOM0_IO2		PINMUX_PIN(PIN_PA2, 2, 1)
+#define PIN_PA2__PDMC1_CLK		PINMUX_PIN(PIN_PA2, 3, 1)
+#define PIN_PA2__D15			PINMUX_PIN(PIN_PA2, 4, 1)
+#define PIN_PA2__PWMH1			PINMUX_PIN(PIN_PA2, 5, 3)
+#define PIN_PA2__FLEXCOM1_IO0		PINMUX_PIN(PIN_PA2, 6, 3)
+#define PIN_PA3				3
+#define PIN_PA3__GPIO			PINMUX_PIN(PIN_PA3, 0, 0)
+#define PIN_PA3__SDMMC0_DAT0		PINMUX_PIN(PIN_PA3, 1, 1)
+#define PIN_PA3__FLEXCOM0_IO3		PINMUX_PIN(PIN_PA3, 2, 1)
+#define PIN_PA3__PDMC1_DS0		PINMUX_PIN(PIN_PA3, 3, 1)
+#define PIN_PA3__NWR1_NBS1		PINMUX_PIN(PIN_PA3, 4, 1)
+#define PIN_PA3__PWML3			PINMUX_PIN(PIN_PA3, 5, 3)
+#define PIN_PA3__FLEXCOM1_IO1		PINMUX_PIN(PIN_PA3, 6, 3)
+#define PIN_PA4				4
+#define PIN_PA4__GPIO			PINMUX_PIN(PIN_PA4, 0, 0)
+#define PIN_PA4__SDMMC0_DAT1		PINMUX_PIN(PIN_PA4, 1, 1)
+#define PIN_PA4__FLEXCOM0_IO4		PINMUX_PIN(PIN_PA4, 2, 1)
+#define PIN_PA4__PDMC1_DS1		PINMUX_PIN(PIN_PA4, 3, 1)
+#define PIN_PA4__NCS2			PINMUX_PIN(PIN_PA4, 4, 1)
+#define PIN_PA4__PWMH3			PINMUX_PIN(PIN_PA4, 5, 3)
+#define PIN_PA4__FLEXCOM2_IO0		PINMUX_PIN(PIN_PA4, 6, 3)
+#define PIN_PA5				5
+#define PIN_PA5__GPIO			PINMUX_PIN(PIN_PA5, 0, 0)
+#define PIN_PA5__SDMMC0_DAT2		PINMUX_PIN(PIN_PA5, 1, 1)
+#define PIN_PA5__FLEXCOM1_IO0		PINMUX_PIN(PIN_PA5, 2, 1)
+#define PIN_PA5__CANTX2			PINMUX_PIN(PIN_PA5, 3, 1)
+#define PIN_PA5__A23			PINMUX_PIN(PIN_PA5, 4, 1)
+#define PIN_PA5__PWMEXTRG0		PINMUX_PIN(PIN_PA5, 5, 3)
+#define PIN_PA5__FLEXCOM2_IO1		PINMUX_PIN(PIN_PA5, 6, 3)
+#define PIN_PA6				6
+#define PIN_PA6__GPIO			PINMUX_PIN(PIN_PA6, 0, 0)
+#define PIN_PA6__SDMMC0_DAT3		PINMUX_PIN(PIN_PA6, 1, 1)
+#define PIN_PA6__FLEXCOM1_IO1		PINMUX_PIN(PIN_PA6, 2, 1)
+#define PIN_PA6__CANRX2			PINMUX_PIN(PIN_PA6, 3, 1)
+#define PIN_PA6__A24			PINMUX_PIN(PIN_PA6, 4, 1)
+#define PIN_PA6__PWMEXTRG1		PINMUX_PIN(PIN_PA6, 5, 3)
+#define PIN_PA6__FLEXCOM3_IO0		PINMUX_PIN(PIN_PA6, 6, 3)
+#define PIN_PA7				7
+#define PIN_PA7__GPIO			PINMUX_PIN(PIN_PA7, 0, 0)
+#define PIN_PA7__SDMMC0_DAT4		PINMUX_PIN(PIN_PA7, 1, 1)
+#define PIN_PA7__FLEXCOM2_IO0		PINMUX_PIN(PIN_PA7, 2, 1)
+#define PIN_PA7__CANTX1			PINMUX_PIN(PIN_PA7, 3, 1)
+#define PIN_PA7__NWAIT			PINMUX_PIN(PIN_PA7, 4, 1)
+#define PIN_PA7__PWMFI0			PINMUX_PIN(PIN_PA7, 5, 3)
+#define PIN_PA7__FLEXCOM3_IO1		PINMUX_PIN(PIN_PA7, 6, 3)
+#define PIN_PA8				8
+#define PIN_PA8__GPIO			PINMUX_PIN(PIN_PA8, 0, 0)
+#define PIN_PA8__SDMMC0_DAT5		PINMUX_PIN(PIN_PA8, 1, 1)
+#define PIN_PA8__FLEXCOM2_IO1		PINMUX_PIN(PIN_PA8, 2, 1)
+#define PIN_PA8__CANRX1			PINMUX_PIN(PIN_PA8, 3, 1)
+#define PIN_PA8__NCS0			PINMUX_PIN(PIN_PA8, 4, 1)
+#define PIN_PA8__PWMIF1			PINMUX_PIN(PIN_PA8, 5, 3)
+#define PIN_PA8__FLEXCOM4_IO0		PINMUX_PIN(PIN_PA8, 6, 3)
+#define PIN_PA9				9
+#define PIN_PA9__GPIO			PINMUX_PIN(PIN_PA9, 0, 0)
+#define PIN_PA9__SDMMC0_DAT6		PINMUX_PIN(PIN_PA9, 1, 1)
+#define PIN_PA9__FLEXCOM2_IO2		PINMUX_PIN(PIN_PA9, 2, 1)
+#define PIN_PA9__CANTX0			PINMUX_PIN(PIN_PA9, 3, 1)
+#define PIN_PA9__SMCK			PINMUX_PIN(PIN_PA9, 4, 1)
+#define PIN_PA9__SPDIF_RX		PINMUX_PIN(PIN_PA9, 5, 1)
+#define PIN_PA9__FLEXCOM4_IO1		PINMUX_PIN(PIN_PA9, 6, 3)
+#define PIN_PA10			10
+#define PIN_PA10__GPIO			PINMUX_PIN(PIN_PA10, 0, 0)
+#define PIN_PA10__SDMMC0_DAT7		PINMUX_PIN(PIN_PA10, 1, 1)
+#define PIN_PA10__FLEXCOM2_IO3		PINMUX_PIN(PIN_PA10, 2, 1)
+#define PIN_PA10__CANRX0		PINMUX_PIN(PIN_PA10, 3, 1)
+#define PIN_PA10__NCS1			PINMUX_PIN(PIN_PA10, 4, 1)
+#define PIN_PA10__SPDIF_TX		PINMUX_PIN(PIN_PA10, 5, 1)
+#define PIN_PA10__FLEXCOM5_IO0		PINMUX_PIN(PIN_PA10, 6, 3)
+#define PIN_PA11			11
+#define PIN_PA11__GPIO			PINMUX_PIN(PIN_PA11, 0, 0)
+#define PIN_PA11__SDMMC0_DS		PINMUX_PIN(PIN_PA11, 1, 1)
+#define PIN_PA11__FLEXCOM2_IO4		PINMUX_PIN(PIN_PA11, 2, 1)
+#define PIN_PA11__A0_NBS0		PINMUX_PIN(PIN_PA11, 4, 1)
+#define PIN_PA11__TIOA0			PINMUX_PIN(PIN_PA11, 5, 1)
+#define PIN_PA11__FLEXCOM5_IO1		PINMUX_PIN(PIN_PA11, 6, 3)
+#define PIN_PA12			12
+#define PIN_PA12__GPIO			PINMUX_PIN(PIN_PA12, 0, 0)
+#define PIN_PA12__SDMMC0_WP		PINMUX_PIN(PIN_PA12, 1, 1)
+#define PIN_PA12__FLEXCOM1_IO3		PINMUX_PIN(PIN_PA12, 2, 1)
+#define PIN_PA12__FLEXCOM3_IO5		PINMUX_PIN(PIN_PA12, 4, 1)
+#define PIN_PA12__PWML2			PINMUX_PIN(PIN_PA12, 5, 3)
+#define PIN_PA12__FLEXCOM6_IO0		PINMUX_PIN(PIN_PA12, 6, 3)
+#define PIN_PA13			13
+#define PIN_PA13__GPIO			PINMUX_PIN(PIN_PA13, 0, 0)
+#define PIN_PA13__SDMMC0_1V8SEL		PINMUX_PIN(PIN_PA13, 1, 1)
+#define PIN_PA13__FLEXCOM1_IO2		PINMUX_PIN(PIN_PA13, 2, 1)
+#define PIN_PA13__FLEXCOM3_IO6		PINMUX_PIN(PIN_PA13, 4, 1)
+#define PIN_PA13__PWMH2			PINMUX_PIN(PIN_PA13, 5, 3)
+#define PIN_PA13__FLEXCOM6_IO1		PINMUX_PIN(PIN_PA13, 6, 3)
+#define PIN_PA14			14
+#define PIN_PA14__GPIO			PINMUX_PIN(PIN_PA14, 0, 0)
+#define PIN_PA14__SDMMC0_CD		PINMUX_PIN(PIN_PA14, 1, 1)
+#define PIN_PA14__FLEXCOM1_IO4		PINMUX_PIN(PIN_PA14, 2, 1)
+#define PIN_PA14__A25			PINMUX_PIN(PIN_PA14, 4, 1)
+#define PIN_PA14__PWML1			PINMUX_PIN(PIN_PA14, 5, 3)
+#define PIN_PA15			15
+#define PIN_PA15__GPIO			PINMUX_PIN(PIN_PA15, 0, 0)
+#define PIN_PA15__G0_TXEN		PINMUX_PIN(PIN_PA15, 1, 1)
+#define PIN_PA15__FLEXCOM3_IO0		PINMUX_PIN(PIN_PA15, 2, 1)
+#define PIN_PA15__ISC_MCK		PINMUX_PIN(PIN_PA15, 3, 1)
+#define PIN_PA15__A1			PINMUX_PIN(PIN_PA15, 4, 1)
+#define PIN_PA15__TIOB0			PINMUX_PIN(PIN_PA15, 5, 1)
+#define PIN_PA16			16
+#define PIN_PA16__GPIO			PINMUX_PIN(PIN_PA16, 0, 0)
+#define PIN_PA16__G0_TX0		PINMUX_PIN(PIN_PA16, 1, 1)
+#define PIN_PA16__FLEXCOM3_IO1		PINMUX_PIN(PIN_PA16, 2, 1)
+#define PIN_PA16__ISC_D0		PINMUX_PIN(PIN_PA16, 3, 1)
+#define PIN_PA16__A2			PINMUX_PIN(PIN_PA16, 4, 1)
+#define PIN_PA16__TCLK0			PINMUX_PIN(PIN_PA16, 5, 1)
+#define PIN_PA17			17
+#define PIN_PA17__GPIO			PINMUX_PIN(PIN_PA17, 0, 0)
+#define PIN_PA17__G0_TX1		PINMUX_PIN(PIN_PA17, 1, 1)
+#define PIN_PA17__FLEXCOM3_IO2		PINMUX_PIN(PIN_PA17, 2, 1)
+#define PIN_PA17__ISC_D1		PINMUX_PIN(PIN_PA17, 3, 1)
+#define PIN_PA17__A3			PINMUX_PIN(PIN_PA17, 4, 1)
+#define PIN_PA17__TIOA1			PINMUX_PIN(PIN_PA17, 5, 1)
+#define PIN_PA18			18
+#define PIN_PA18__GPIO			PINMUX_PIN(PIN_PA18, 0, 0)
+#define PIN_PA18__G0_RXDV		PINMUX_PIN(PIN_PA18, 1, 1)
+#define PIN_PA18__FLEXCOM3_IO3		PINMUX_PIN(PIN_PA18, 2, 1)
+#define PIN_PA18__ISC_D2		PINMUX_PIN(PIN_PA18, 3, 1)
+#define PIN_PA18__A4			PINMUX_PIN(PIN_PA18, 4, 1)
+#define PIN_PA18__TIOB1			PINMUX_PIN(PIN_PA18, 5, 1)
+#define PIN_PA19			19
+#define PIN_PA19__GPIO			PINMUX_PIN(PIN_PA19, 0, 0)
+#define PIN_PA19__G0_RX0		PINMUX_PIN(PIN_PA19, 1, 1)
+#define PIN_PA19__FLEXCOM3_IO4		PINMUX_PIN(PIN_PA19, 2, 1)
+#define PIN_PA19__ISC_D3		PINMUX_PIN(PIN_PA19, 3, 1)
+#define PIN_PA19__A5			PINMUX_PIN(PIN_PA19, 4, 1)
+#define PIN_PA19__TCLK1			PINMUX_PIN(PIN_PA19, 5, 1)
+#define PIN_PA20			20
+#define PIN_PA20__GPIO			PINMUX_PIN(PIN_PA20, 0, 0)
+#define PIN_PA20__G0_RX1		PINMUX_PIN(PIN_PA20, 1, 1)
+#define PIN_PA20__FLEXCOM4_IO0		PINMUX_PIN(PIN_PA20, 2, 1)
+#define PIN_PA20__ISC_D4		PINMUX_PIN(PIN_PA20, 3, 1)
+#define PIN_PA20__A6			PINMUX_PIN(PIN_PA20, 4, 1)
+#define PIN_PA20__TIOA2			PINMUX_PIN(PIN_PA20, 5, 1)
+#define PIN_PA21			21
+#define PIN_PA21__GPIO			PINMUX_PIN(PIN_PA21, 0, 0)
+#define PIN_PA21__G0_RXER		PINMUX_PIN(PIN_PA21, 1, 1)
+#define PIN_PA21__FLEXCOM4_IO1		PINMUX_PIN(PIN_PA21, 2, 1)
+#define PIN_PA21__ISC_D5		PINMUX_PIN(PIN_PA21, 3, 1)
+#define PIN_PA21__A7			PINMUX_PIN(PIN_PA21, 4, 1)
+#define PIN_PA21__TIOB2			PINMUX_PIN(PIN_PA21, 5, 1)
+#define PIN_PA22			22
+#define PIN_PA22__GPIO			PINMUX_PIN(PIN_PA22, 0, 0)
+#define PIN_PA22__G0_MDC		PINMUX_PIN(PIN_PA22, 1, 1)
+#define PIN_PA22__FLEXCOM4_IO2		PINMUX_PIN(PIN_PA22, 2, 1)
+#define PIN_PA22__ISC_D6		PINMUX_PIN(PIN_PA22, 3, 1)
+#define PIN_PA22__A8			PINMUX_PIN(PIN_PA22, 4, 1)
+#define PIN_PA22__TCLK2			PINMUX_PIN(PIN_PA22, 5, 1)
+#define PIN_PA23			23
+#define PIN_PA23__GPIO			PINMUX_PIN(PIN_PA23, 0, 0)
+#define PIN_PA23__G0_MDIO		PINMUX_PIN(PIN_PA23, 1, 1)
+#define PIN_PA23__FLEXCOM4_IO3		PINMUX_PIN(PIN_PA23, 2, 1)
+#define PIN_PA23__ISC_D7		PINMUX_PIN(PIN_PA23, 3, 1)
+#define PIN_PA23__A9			PINMUX_PIN(PIN_PA23, 4, 1)
+#define PIN_PA24			24
+#define PIN_PA24__GPIO			PINMUX_PIN(PIN_PA24, 0, 0)
+#define PIN_PA24__G0_TXCK		PINMUX_PIN(PIN_PA24, 1, 1)
+#define PIN_PA24__FLEXCOM4_IO4		PINMUX_PIN(PIN_PA24, 2, 1)
+#define PIN_PA24__ISC_HSYNC		PINMUX_PIN(PIN_PA24, 3, 1)
+#define PIN_PA24__A10			PINMUX_PIN(PIN_PA24, 4, 1)
+#define PIN_PA24__FLEXCOM0_IO5		PINMUX_PIN(PIN_PA24, 5, 1)
+#define PIN_PA25			25
+#define PIN_PA25__GPIO			PINMUX_PIN(PIN_PA25, 0, 0)
+#define PIN_PA25__G0_125CK		PINMUX_PIN(PIN_PA25, 1, 1)
+#define PIN_PA25__FLEXCOM5_IO4		PINMUX_PIN(PIN_PA25, 2, 1)
+#define PIN_PA25__ISC_VSYNC		PINMUX_PIN(PIN_PA25, 3, 1)
+#define PIN_PA25__A11			PINMUX_PIN(PIN_PA25, 4, 1)
+#define PIN_PA25__FLEXCOM0_IO6		PINMUX_PIN(PIN_PA25, 5, 1)
+#define PIN_PA25__FLEXCOM7_IO0		PINMUX_PIN(PIN_PA25, 6, 3)
+#define PIN_PA26			26
+#define PIN_PA26__GPIO			PINMUX_PIN(PIN_PA26, 0, 0)
+#define PIN_PA26__G0_TX2		PINMUX_PIN(PIN_PA26, 1, 1)
+#define PIN_PA26__FLEXCOM5_IO2		PINMUX_PIN(PIN_PA26, 2, 1)
+#define PIN_PA26__ISC_FIELD		PINMUX_PIN(PIN_PA26, 3, 1)
+#define PIN_PA26__A12			PINMUX_PIN(PIN_PA26, 4, 1)
+#define PIN_PA26__TF0			PINMUX_PIN(PIN_PA26, 5, 1)
+#define PIN_PA26__FLEXCOM7_IO1		PINMUX_PIN(PIN_PA26, 6, 3)
+#define PIN_PA27			27
+#define PIN_PA27__GPIO			PINMUX_PIN(PIN_PA27, 0, 0)
+#define PIN_PA27__G0_TX3		PINMUX_PIN(PIN_PA27, 1, 1)
+#define PIN_PA27__FLEXCOM5_IO3		PINMUX_PIN(PIN_PA27, 2, 1)
+#define PIN_PA27__ISC_PCK		PINMUX_PIN(PIN_PA27, 3, 1)
+#define PIN_PA27__A13			PINMUX_PIN(PIN_PA27, 4, 1)
+#define PIN_PA27__TK0			PINMUX_PIN(PIN_PA27, 5, 1)
+#define PIN_PA27__FLEXCOM8_IO0		PINMUX_PIN(PIN_PA27, 6, 3)
+#define PIN_PA28			28
+#define PIN_PA28__GPIO			PINMUX_PIN(PIN_PA28, 0, 0)
+#define PIN_PA28__G0_RX2		PINMUX_PIN(PIN_PA28, 1, 1)
+#define PIN_PA28__FLEXCOM5_IO0		PINMUX_PIN(PIN_PA28, 2, 1)
+#define PIN_PA28__ISC_D8		PINMUX_PIN(PIN_PA28, 3, 1)
+#define PIN_PA28__A14			PINMUX_PIN(PIN_PA28, 4, 1)
+#define PIN_PA28__RD0			PINMUX_PIN(PIN_PA28, 5, 1)
+#define PIN_PA28__FLEXCOM8_IO1		PINMUX_PIN(PIN_PA28, 6, 3)
+#define PIN_PA29			29
+#define PIN_PA29__GPIO			PINMUX_PIN(PIN_PA29, 0, 0)
+#define PIN_PA29__G0_RX3		PINMUX_PIN(PIN_PA29, 1, 1)
+#define PIN_PA29__FLEXCOM5_IO1		PINMUX_PIN(PIN_PA29, 2, 1)
+#define PIN_PA29__ISC_D9		PINMUX_PIN(PIN_PA29, 3, 1)
+#define PIN_PA29__A15			PINMUX_PIN(PIN_PA29, 4, 1)
+#define PIN_PA29__RF0			PINMUX_PIN(PIN_PA29, 5, 1)
+#define PIN_PA29__FLEXCOM9_IO0		PINMUX_PIN(PIN_PA29, 6, 3)
+#define PIN_PA30			30
+#define PIN_PA30__GPIO			PINMUX_PIN(PIN_PA30, 0, 0)
+#define PIN_PA30__G0_RXCK		PINMUX_PIN(PIN_PA30, 1, 1)
+#define PIN_PA30__FLEXCOM6_IO4		PINMUX_PIN(PIN_PA30, 2, 1)
+#define PIN_PA30__ISC_D10		PINMUX_PIN(PIN_PA30, 3, 1)
+#define PIN_PA30__A16			PINMUX_PIN(PIN_PA30, 4, 1)
+#define PIN_PA30__RK0			PINMUX_PIN(PIN_PA30, 5, 1)
+#define PIN_PA30__FLEXCOM9_IO1		PINMUX_PIN(PIN_PA30, 6, 3)
+#define PIN_PA31			31
+#define PIN_PA31__GPIO			PINMUX_PIN(PIN_PA31, 0, 0)
+#define PIN_PA31__G0_TXER		PINMUX_PIN(PIN_PA31, 1, 1)
+#define PIN_PA31__FLEXCOM6_IO2		PINMUX_PIN(PIN_PA31, 2, 1)
+#define PIN_PA31__ISC_D11		PINMUX_PIN(PIN_PA31, 3, 1)
+#define PIN_PA31__A17			PINMUX_PIN(PIN_PA31, 4, 1)
+#define PIN_PA31__TD0			PINMUX_PIN(PIN_PA31, 5, 1)
+#define PIN_PA31__FLEXCOM10_IO0		PINMUX_PIN(PIN_PA31, 6, 3)
+#define PIN_PB0				32
+#define PIN_PB0__GPIO			PINMUX_PIN(PIN_PB0, 0, 0)
+#define PIN_PB0__G0_COL			PINMUX_PIN(PIN_PB0, 1, 1)
+#define PIN_PB0__FLEXCOM6_IO3		PINMUX_PIN(PIN_PB0, 2, 2)
+#define PIN_PB0__EXT_IRQ0		PINMUX_PIN(PIN_PB0, 3, 1)
+#define PIN_PB0__A18			PINMUX_PIN(PIN_PB0, 4, 1)
+#define PIN_PB0__SPDIF_RX		PINMUX_PIN(PIN_PB0, 5, 2)
+#define PIN_PB0__FLEXCOM10_IO1		PINMUX_PIN(PIN_PB0, 6, 3)
+#define PIN_PB1				33
+#define PIN_PB1__GPIO			PINMUX_PIN(PIN_PB1, 0, 0)
+#define PIN_PB1__G0_CRS			PINMUX_PIN(PIN_PB1, 1, 1)
+#define PIN_PB1__FLEXCOM6_IO1		PINMUX_PIN(PIN_PB1, 2, 2)
+#define PIN_PB1__EXT_IRQ1		PINMUX_PIN(PIN_PB1, 3, 1)
+#define PIN_PB1__A19			PINMUX_PIN(PIN_PB1, 4, 1)
+#define PIN_PB1__SPDIF_TX		PINMUX_PIN(PIN_PB1, 5, 2)
+#define PIN_PB1__FLEXCOM11_IO0		PINMUX_PIN(PIN_PB1, 6, 3)
+#define PIN_PB2				34
+#define PIN_PB2__GPIO			PINMUX_PIN(PIN_PB2, 0, 0)
+#define PIN_PB2__G0_TSUCOMP		PINMUX_PIN(PIN_PB2, 1, 1)
+#define PIN_PB2__FLEXCOM6_IO0		PINMUX_PIN(PIN_PB2, 2, 1)
+#define PIN_PB2__ADTRG			PINMUX_PIN(PIN_PB2, 3, 1)
+#define PIN_PB2__A20			PINMUX_PIN(PIN_PB2, 4, 1)
+#define PIN_PB2__FLEXCOM11_IO1		PINMUX_PIN(PIN_PB2, 6, 3)
+#define PIN_PB3				35
+#define PIN_PB3__GPIO			PINMUX_PIN(PIN_PB3, 0, 0)
+#define PIN_PB3__RF1			PINMUX_PIN(PIN_PB3, 1, 1)
+#define PIN_PB3__FLEXCOM11_IO0		PINMUX_PIN(PIN_PB3, 2, 1)
+#define PIN_PB3__PCK2			PINMUX_PIN(PIN_PB3, 3, 2)
+#define PIN_PB3__D8			PINMUX_PIN(PIN_PB3, 4, 1)
+#define PIN_PB4				36
+#define PIN_PB4__GPIO			PINMUX_PIN(PIN_PB4, 0, 0)
+#define PIN_PB4__TF1			PINMUX_PIN(PIN_PB4, 1, 1)
+#define PIN_PB4__FLEXCOM11_IO1		PINMUX_PIN(PIN_PB4, 2, 1)
+#define PIN_PB4__PCK3			PINMUX_PIN(PIN_PB4, 3, 2)
+#define PIN_PB4__D9			PINMUX_PIN(PIN_PB4, 4, 1)
+#define PIN_PB5				37
+#define PIN_PB5__GPIO			PINMUX_PIN(PIN_PB5, 0, 0)
+#define PIN_PB5__TK1			PINMUX_PIN(PIN_PB5, 1, 1)
+#define PIN_PB5__FLEXCOM11_IO2		PINMUX_PIN(PIN_PB5, 2, 1)
+#define PIN_PB5__PCK4			PINMUX_PIN(PIN_PB5, 3, 2)
+#define PIN_PB5__D10			PINMUX_PIN(PIN_PB5, 4, 1)
+#define PIN_PB6				38
+#define PIN_PB6__GPIO			PINMUX_PIN(PIN_PB6, 0, 0)
+#define PIN_PB6__RK1			PINMUX_PIN(PIN_PB6, 1, 1)
+#define PIN_PB6__FLEXCOM11_IO3		PINMUX_PIN(PIN_PB6, 2, 1)
+#define PIN_PB6__PCK5			PINMUX_PIN(PIN_PB6, 3, 2)
+#define PIN_PB6__D11			PINMUX_PIN(PIN_PB6, 4, 1)
+#define PIN_PB7				39
+#define PIN_PB7__GPIO			PINMUX_PIN(PIN_PB7, 0, 0)
+#define PIN_PB7__TD1			PINMUX_PIN(PIN_PB7, 1, 1)
+#define PIN_PB7__FLEXCOM11_IO4		PINMUX_PIN(PIN_PB7, 2, 1)
+#define PIN_PB7__FLEXCOM3_IO5		PINMUX_PIN(PIN_PB7, 3, 2)
+#define PIN_PB7__D12			PINMUX_PIN(PIN_PB7, 4, 1)
+#define PIN_PB8				40
+#define PIN_PB8__GPIO			PINMUX_PIN(PIN_PB8, 0, 0)
+#define PIN_PB8__RD1			PINMUX_PIN(PIN_PB8, 1, 1)
+#define PIN_PB8__FLEXCOM8_IO0		PINMUX_PIN(PIN_PB8, 2, 1)
+#define PIN_PB8__FLEXCOM3_IO6		PINMUX_PIN(PIN_PB8, 3, 2)
+#define PIN_PB8__D13			PINMUX_PIN(PIN_PB8, 4, 1)
+#define PIN_PB9				41
+#define PIN_PB9__GPIO			PINMUX_PIN(PIN_PB9, 0, 0)
+#define PIN_PB9__QSPI0_IO3		PINMUX_PIN(PIN_PB9, 1, 1)
+#define PIN_PB9__FLEXCOM8_IO1		PINMUX_PIN(PIN_PB9, 2, 1)
+#define PIN_PB9__PDMC0_CLK		PINMUX_PIN(PIN_PB9, 3, 1)
+#define PIN_PB9__NCS3_NANDCS		PINMUX_PIN(PIN_PB9, 4, 1)
+#define PIN_PB9__PWML0			PINMUX_PIN(PIN_PB9, 5, 2)
+#define PIN_PB10			42
+#define PIN_PB10__GPIO			PINMUX_PIN(PIN_PB10, 0, 0)
+#define PIN_PB10__QSPI0_IO2		PINMUX_PIN(PIN_PB10, 1, 1)
+#define PIN_PB10__FLEXCOM8_IO2		PINMUX_PIN(PIN_PB10, 2, 1)
+#define PIN_PB10__PDMC0_DS0		PINMUX_PIN(PIN_PB10, 3, 1)
+#define PIN_PB10__NWE_NWR0_NANDWE	PINMUX_PIN(PIN_PB10, 4, 1)
+#define PIN_PB10__PWMH0			PINMUX_PIN(PIN_PB10, 5, 2)
+#define PIN_PB11			43
+#define PIN_PB11__GPIO			PINMUX_PIN(PIN_PB11, 0, 0)
+#define PIN_PB11__QSPI0_IO1		PINMUX_PIN(PIN_PB11, 1, 1)
+#define PIN_PB11__FLEXCOM8_IO3		PINMUX_PIN(PIN_PB11, 2, 1)
+#define PIN_PB11__PDMC0_DS1		PINMUX_PIN(PIN_PB11, 3, 1)
+#define PIN_PB11__NRD_NANDOE		PINMUX_PIN(PIN_PB11, 4, 1)
+#define PIN_PB11__PWML1			PINMUX_PIN(PIN_PB11, 5, 2)
+#define PIN_PB12			44
+#define PIN_PB12__GPIO			PINMUX_PIN(PIN_PB12, 0, 0)
+#define PIN_PB12__QSPI0_IO0		PINMUX_PIN(PIN_PB12, 1, 1)
+#define PIN_PB12__FLEXCOM8_IO4		PINMUX_PIN(PIN_PB12, 2, 1)
+#define PIN_PB12__FLEXCOM6_IO5		PINMUX_PIN(PIN_PB12, 3, 1)
+#define PIN_PB12__A21_NANDALE		PINMUX_PIN(PIN_PB12, 4, 1)
+#define PIN_PB12__PWMH1			PINMUX_PIN(PIN_PB12, 5, 2)
+#define PIN_PB13			45
+#define PIN_PB13__GPIO			PINMUX_PIN(PIN_PB13, 0, 0)
+#define PIN_PB13__QSPI0_CS		PINMUX_PIN(PIN_PB13, 1, 1)
+#define PIN_PB13__FLEXCOM9_IO0		PINMUX_PIN(PIN_PB13, 2, 1)
+#define PIN_PB13__FLEXCOM6_IO6		PINMUX_PIN(PIN_PB13, 3, 1)
+#define PIN_PB13__A22_NANDCLE		PINMUX_PIN(PIN_PB13, 4, 1)
+#define PIN_PB13__PWML2			PINMUX_PIN(PIN_PB13, 5, 2)
+#define PIN_PB14			46
+#define PIN_PB14__GPIO			PINMUX_PIN(PIN_PB14, 0, 0)
+#define PIN_PB14__QSPI0_SCK		PINMUX_PIN(PIN_PB14, 1, 1)
+#define PIN_PB14__FLEXCOM9_IO1		PINMUX_PIN(PIN_PB14, 2, 1)
+#define PIN_PB14__D0			PINMUX_PIN(PIN_PB14, 4, 1)
+#define PIN_PB14__PWMH2			PINMUX_PIN(PIN_PB14, 5, 2)
+#define PIN_PB15			47
+#define PIN_PB15__GPIO			PINMUX_PIN(PIN_PB15, 0, 0)
+#define PIN_PB15__QSPI0_SCKN		PINMUX_PIN(PIN_PB15, 1, 1)
+#define PIN_PB15__FLEXCOM9_IO2		PINMUX_PIN(PIN_PB15, 2, 1)
+#define PIN_PB15__D1			PINMUX_PIN(PIN_PB15, 4, 1)
+#define PIN_PB15__PWML3			PINMUX_PIN(PIN_PB15, 5, 2)
+#define PIN_PB16			48
+#define PIN_PB16__GPIO			PINMUX_PIN(PIN_PB16, 0, 0)
+#define PIN_PB16__QSPI0_IO4		PINMUX_PIN(PIN_PB16, 1, 1)
+#define PIN_PB16__FLEXCOM9_IO3		PINMUX_PIN(PIN_PB16, 2, 1)
+#define PIN_PB16__PCK0			PINMUX_PIN(PIN_PB16, 3, 1)
+#define PIN_PB16__D2			PINMUX_PIN(PIN_PB16, 4, 1)
+#define PIN_PB16__PWMH3			PINMUX_PIN(PIN_PB16, 5, 2)
+#define PIN_PB16__EXT_IRQ0		PINMUX_PIN(PIN_PB16, 6, 2)
+#define PIN_PB17			49
+#define PIN_PB17__GPIO			PINMUX_PIN(PIN_PB17, 0, 0)
+#define PIN_PB17__QSPI0_IO5		PINMUX_PIN(PIN_PB17, 1, 1)
+#define PIN_PB17__FLEXCOM9_IO4		PINMUX_PIN(PIN_PB17, 2, 1)
+#define PIN_PB17__PCK1			PINMUX_PIN(PIN_PB17, 3, 1)
+#define PIN_PB17__D3			PINMUX_PIN(PIN_PB17, 4, 1)
+#define PIN_PB17__PWMEXTRG0		PINMUX_PIN(PIN_PB17, 5, 2)
+#define PIN_PB17__EXT_IRQ1		PINMUX_PIN(PIN_PB17, 6, 2)
+#define PIN_PB18			50
+#define PIN_PB18__GPIO			PINMUX_PIN(PIN_PB18, 0, 0)
+#define PIN_PB18__QSPI0_IO6		PINMUX_PIN(PIN_PB18, 1, 1)
+#define PIN_PB18__FLEXCOM10_IO0		PINMUX_PIN(PIN_PB18, 2, 1)
+#define PIN_PB18__PCK2			PINMUX_PIN(PIN_PB18, 3, 1)
+#define PIN_PB18__D4			PINMUX_PIN(PIN_PB18, 4, 1)
+#define PIN_PB18__PWMEXTRG1		PINMUX_PIN(PIN_PB18, 5, 2)
+#define PIN_PB19			51
+#define PIN_PB19__GPIO			PINMUX_PIN(PIN_PB19, 0, 0)
+#define PIN_PB19__QSPI0_IO7		PINMUX_PIN(PIN_PB19, 1, 1)
+#define PIN_PB19__FLEXCOM10_IO1		PINMUX_PIN(PIN_PB19, 2, 1)
+#define PIN_PB19__PCK3			PINMUX_PIN(PIN_PB19, 3, 1)
+#define PIN_PB19__D5			PINMUX_PIN(PIN_PB19, 4, 1)
+#define PIN_PB19__PWMFI0		PINMUX_PIN(PIN_PB19, 5, 2)
+#define PIN_PB20			52
+#define PIN_PB20__GPIO			PINMUX_PIN(PIN_PB20, 0, 0)
+#define PIN_PB20__QSPI0_DQS		PINMUX_PIN(PIN_PB20, 1, 1)
+#define PIN_PB20__FLEXCOM10_IO2		PINMUX_PIN(PIN_PB20, 2, 1)
+#define PIN_PB20__D6			PINMUX_PIN(PIN_PB20, 4, 1)
+#define PIN_PB20__PWMFI1		PINMUX_PIN(PIN_PB20, 5, 2)
+#define PIN_PB21			53
+#define PIN_PB21__GPIO			PINMUX_PIN(PIN_PB21, 0, 0)
+#define PIN_PB21__QSPI0_INT		PINMUX_PIN(PIN_PB21, 1, 1)
+#define PIN_PB21__FLEXCOM10_IO3		PINMUX_PIN(PIN_PB21, 2, 1)
+#define PIN_PB21__FLEXCOM9_IO5		PINMUX_PIN(PIN_PB21, 3, 1)
+#define PIN_PB21__D7			PINMUX_PIN(PIN_PB21, 4, 1)
+#define PIN_PB22			54
+#define PIN_PB22__GPIO			PINMUX_PIN(PIN_PB22, 0, 0)
+#define PIN_PB22__QSPI1_IO3		PINMUX_PIN(PIN_PB22, 1, 1)
+#define PIN_PB22__FLEXCOM10_IO4		PINMUX_PIN(PIN_PB22, 2, 1)
+#define PIN_PB22__FLEXCOM9_IO6		PINMUX_PIN(PIN_PB22, 3, 1)
+#define PIN_PB22__NANDRDY		PINMUX_PIN(PIN_PB22, 4, 1)
+#define PIN_PB23			55
+#define PIN_PB23__GPIO			PINMUX_PIN(PIN_PB23, 0, 0)
+#define PIN_PB23__QSPI1_IO2		PINMUX_PIN(PIN_PB23, 1, 1)
+#define PIN_PB23__FLEXCOM7_IO0		PINMUX_PIN(PIN_PB23, 2, 1)
+#define PIN_PB23__I2SMCC0_CK		PINMUX_PIN(PIN_PB23, 3, 1)
+#define PIN_PB23__PCK4			PINMUX_PIN(PIN_PB23, 6, 1)
+#define PIN_PB24			56
+#define PIN_PB24__GPIO			PINMUX_PIN(PIN_PB24, 0, 0)
+#define PIN_PB24__QSPI1_IO1		PINMUX_PIN(PIN_PB24, 1, 1)
+#define PIN_PB24__FLEXCOM7_IO1		PINMUX_PIN(PIN_PB24, 2, 1)
+#define PIN_PB24__I2SMCC0_WS		PINMUX_PIN(PIN_PB24, 3, 1)
+#define PIN_PB24__PCK5			PINMUX_PIN(PIN_PB24, 6, 1)
+#define PIN_PB25			57
+#define PIN_PB25__GPIO			PINMUX_PIN(PIN_PB25, 0, 0)
+#define PIN_PB25__QSPI1_IO0		PINMUX_PIN(PIN_PB25, 1, 1)
+#define PIN_PB25__FLEXCOM7_IO2		PINMUX_PIN(PIN_PB25, 2, 1)
+#define PIN_PB25__I2SMCC0_DOUT1		PINMUX_PIN(PIN_PB25, 3, 1)
+#define PIN_PB25__PCK6			PINMUX_PIN(PIN_PB25, 6, 1)
+#define PIN_PB26			58
+#define PIN_PB26__GPIO			PINMUX_PIN(PIN_PB26, 0, 0)
+#define PIN_PB26__QSPI1_CS		PINMUX_PIN(PIN_PB26, 1, 1)
+#define PIN_PB26__FLEXCOM7_IO3		PINMUX_PIN(PIN_PB26, 2, 1)
+#define PIN_PB26__I2SMCC0_DOUT0		PINMUX_PIN(PIN_PB26, 3, 1)
+#define PIN_PB26__PWMEXTRG0		PINMUX_PIN(PIN_PB26, 5, 1)
+#define PIN_PB26__PCK7			PINMUX_PIN(PIN_PB26, 6, 1)
+#define PIN_PB27			59
+#define PIN_PB27__GPIO			PINMUX_PIN(PIN_PB27, 0, 0)
+#define PIN_PB27__QSPI1_SCK		PINMUX_PIN(PIN_PB27, 1, 1)
+#define PIN_PB27__FLEXCOM7_IO4		PINMUX_PIN(PIN_PB27, 2, 1)
+#define PIN_PB27__I2SMCC0_MCK		PINMUX_PIN(PIN_PB27, 3, 1)
+#define PIN_PB27__PWMEXTRG1		PINMUX_PIN(PIN_PB27, 5, 1)
+#define PIN_PB28			60
+#define PIN_PB28__GPIO			PINMUX_PIN(PIN_PB28, 0, 0)
+#define PIN_PB28__SDMMC1_RSTN		PINMUX_PIN(PIN_PB28, 1, 1)
+#define PIN_PB28__ADTRG			PINMUX_PIN(PIN_PB28, 2, 2)
+#define PIN_PB28__PWMFI0		PINMUX_PIN(PIN_PB28, 5, 1)
+#define PIN_PB28__FLEXCOM7_IO0		PINMUX_PIN(PIN_PB28, 6, 4)
+#define PIN_PB29			61
+#define PIN_PB29__GPIO			PINMUX_PIN(PIN_PB29, 0, 0)
+#define PIN_PB29__SDMMC1_CMD		PINMUX_PIN(PIN_PB29, 1, 1)
+#define PIN_PB29__FLEXCOM3_IO2		PINMUX_PIN(PIN_PB29, 2, 2)
+#define PIN_PB29__FLEXCOM0_IO5		PINMUX_PIN(PIN_PB29, 3, 2)
+#define PIN_PB29__TIOA3			PINMUX_PIN(PIN_PB29, 4, 2)
+#define PIN_PB29__PWMFI1		PINMUX_PIN(PIN_PB29, 5, 1)
+#define PIN_PB29__FLEXCOM7_IO1		PINMUX_PIN(PIN_PB29, 6, 4)
+#define PIN_PB30			62
+#define PIN_PB30__GPIO			PINMUX_PIN(PIN_PB30, 0, 0)
+#define PIN_PB30__SDMMC1_CK		PINMUX_PIN(PIN_PB30, 1, 1)
+#define PIN_PB30__FLEXCOM3_IO3		PINMUX_PIN(PIN_PB30, 2, 2)
+#define PIN_PB30__FLEXCOM0_IO6		PINMUX_PIN(PIN_PB30, 3, 2)
+#define PIN_PB30__TIOB3			PINMUX_PIN(PIN_PB30, 4, 1)
+#define PIN_PB30__PWMH0			PINMUX_PIN(PIN_PB30, 5, 1)
+#define PIN_PB30__FLEXCOM8_IO0		PINMUX_PIN(PIN_PB30, 6, 4)
+#define PIN_PB31			63
+#define PIN_PB31__GPIO			PINMUX_PIN(PIN_PB31, 0, 0)
+#define PIN_PB31__SDMMC1_DAT0		PINMUX_PIN(PIN_PB31, 1, 1)
+#define PIN_PB31__FLEXCOM3_IO4		PINMUX_PIN(PIN_PB31, 2, 2)
+#define PIN_PB31__FLEXCOM9_IO5		PINMUX_PIN(PIN_PB31, 3, 2)
+#define PIN_PB31__TCLK3			PINMUX_PIN(PIN_PB31, 4, 1)
+#define PIN_PB31__PWML0			PINMUX_PIN(PIN_PB31, 5, 1)
+#define PIN_PB31__FLEXCOM8_IO1		PINMUX_PIN(PIN_PB31, 6, 4)
+#define PIN_PC0				64
+#define PIN_PC0__GPIO			PINMUX_PIN(PIN_PC0, 0, 0)
+#define PIN_PC0__SDMMC1_DAT1		PINMUX_PIN(PIN_PC0, 1, 1)
+#define PIN_PC0__FLEXCOM3_IO0		PINMUX_PIN(PIN_PC0, 2, 2)
+#define PIN_PC0__TIOA4			PINMUX_PIN(PIN_PC0, 4, 1)
+#define PIN_PC0__PWML1			PINMUX_PIN(PIN_PC0, 5, 1)
+#define PIN_PC0__FLEXCOM9_IO0		PINMUX_PIN(PIN_PC0, 6, 4)
+#define PIN_PC1				65
+#define PIN_PC1__GPIO			PINMUX_PIN(PIN_PC1, 0, 0)
+#define PIN_PC1__SDMMC1_DAT2		PINMUX_PIN(PIN_PC1, 1, 1)
+#define PIN_PC1__FLEXCOM3_IO1		PINMUX_PIN(PIN_PC1, 2, 2)
+#define PIN_PC1__TIOB4			PINMUX_PIN(PIN_PC1, 4, 1)
+#define PIN_PC1__PWMH1			PINMUX_PIN(PIN_PC1, 5, 1)
+#define PIN_PC1__FLEXCOM9_IO1		PINMUX_PIN(PIN_PC1, 6, 4)
+#define PIN_PC2				66
+#define PIN_PC2__GPIO			PINMUX_PIN(PIN_PC2, 0, 0)
+#define PIN_PC2__SDMMC1_DAT3		PINMUX_PIN(PIN_PC2, 1, 1)
+#define PIN_PC2__FLEXCOM4_IO0		PINMUX_PIN(PIN_PC2, 2, 2)
+#define PIN_PC2__TCLK4			PINMUX_PIN(PIN_PC2, 4, 1)
+#define PIN_PC2__PWML2			PINMUX_PIN(PIN_PC2, 5, 1)
+#define PIN_PC2__FLEXCOM10_IO0		PINMUX_PIN(PIN_PC2, 6, 4)
+#define PIN_PC3				67
+#define PIN_PC3__GPIO			PINMUX_PIN(PIN_PC3, 0, 0)
+#define PIN_PC3__SDMMC1_WP		PINMUX_PIN(PIN_PC3, 1, 1)
+#define PIN_PC3__FLEXCOM4_IO1		PINMUX_PIN(PIN_PC3, 2, 2)
+#define PIN_PC3__TIOA5			PINMUX_PIN(PIN_PC3, 4, 1)
+#define PIN_PC3__PWMH2			PINMUX_PIN(PIN_PC3, 5, 1)
+#define PIN_PC3__FLEXCOM10_IO1		PINMUX_PIN(PIN_PC3, 6, 4)
+#define PIN_PC4				68
+#define PIN_PC4__GPIO			PINMUX_PIN(PIN_PC4, 0, 0)
+#define PIN_PC4__SDMMC1_CD		PINMUX_PIN(PIN_PC4, 1, 1)
+#define PIN_PC4__FLEXCOM4_IO2		PINMUX_PIN(PIN_PC4, 2, 2)
+#define PIN_PC4__FLEXCOM9_IO6		PINMUX_PIN(PIN_PC4, 3, 2)
+#define PIN_PC4__TIOB5			PINMUX_PIN(PIN_PC4, 4, 1)
+#define PIN_PC4__PWML3			PINMUX_PIN(PIN_PC4, 5, 1)
+#define PIN_PC4__FLEXCOM11_IO0		PINMUX_PIN(PIN_PC4, 6, 4)
+#define PIN_PC5				69
+#define PIN_PC5__GPIO			PINMUX_PIN(PIN_PC5, 0, 0)
+#define PIN_PC5__SDMMC1_1V8SEL		PINMUX_PIN(PIN_PC5, 1, 1)
+#define PIN_PC5__FLEXCOM4_IO3		PINMUX_PIN(PIN_PC5, 2, 2)
+#define PIN_PC5__FLEXCOM6_IO5		PINMUX_PIN(PIN_PC5, 3, 2)
+#define PIN_PC5__TCLK5			PINMUX_PIN(PIN_PC5, 4, 1)
+#define PIN_PC5__PWMH3			PINMUX_PIN(PIN_PC5, 5, 1)
+#define PIN_PC5__FLEXCOM11_IO1		PINMUX_PIN(PIN_PC5, 6, 4)
+#define PIN_PC6				70
+#define PIN_PC6__GPIO			PINMUX_PIN(PIN_PC6, 0, 0)
+#define PIN_PC6__FLEXCOM4_IO4		PINMUX_PIN(PIN_PC6, 2, 2)
+#define PIN_PC6__FLEXCOM6_IO6		PINMUX_PIN(PIN_PC6, 3, 2)
+#define PIN_PC7				71
+#define PIN_PC7__GPIO			PINMUX_PIN(PIN_PC7, 0, 0)
+#define PIN_PC7__I2SMCC0_DIN0		PINMUX_PIN(PIN_PC7, 1, 1)
+#define PIN_PC7__FLEXCOM7_IO0		PINMUX_PIN(PIN_PC7, 2, 2)
+#define PIN_PC8				72
+#define PIN_PC8__GPIO			PINMUX_PIN(PIN_PC8, 0, 0)
+#define PIN_PC8__I2SMCC0_DIN1		PINMUX_PIN(PIN_PC8, 1, 1)
+#define PIN_PC8__FLEXCOM7_IO1		PINMUX_PIN(PIN_PC8, 2, 2)
+#define PIN_PC9				73
+#define PIN_PC9__GPIO			PINMUX_PIN(PIN_PC9, 0, 0)
+#define PIN_PC9__I2SMCC0_DOUT3		PINMUX_PIN(PIN_PC9, 1, 1)
+#define PIN_PC9__FLEXCOM7_IO2		PINMUX_PIN(PIN_PC9, 2, 2)
+#define PIN_PC9__FLEXCOM1_IO0		PINMUX_PIN(PIN_PC9, 6, 4)
+#define PIN_PC10			74
+#define PIN_PC10__GPIO			PINMUX_PIN(PIN_PC10, 0, 0)
+#define PIN_PC10__I2SMCC0_DOUT2		PINMUX_PIN(PIN_PC10, 1, 1)
+#define PIN_PC10__FLEXCOM7_IO3		PINMUX_PIN(PIN_PC10, 2, 2)
+#define PIN_PC10__FLEXCOM1_IO1		PINMUX_PIN(PIN_PC10, 6, 4)
+#define PIN_PC11			75
+#define PIN_PC11__GPIO			PINMUX_PIN(PIN_PC11, 0, 0)
+#define PIN_PC11__I2SMCC1_CK		PINMUX_PIN(PIN_PC11, 1, 1)
+#define PIN_PC11__FLEXCOM7_IO4		PINMUX_PIN(PIN_PC11, 2, 2)
+#define PIN_PC11__FLEXCOM2_IO0		PINMUX_PIN(PIN_PC11, 6, 4)
+#define PIN_PC12			76
+#define PIN_PC12__GPIO			PINMUX_PIN(PIN_PC12, 0, 0)
+#define PIN_PC12__I2SMCC1_WS		PINMUX_PIN(PIN_PC12, 1, 1)
+#define PIN_PC12__FLEXCOM8_IO2		PINMUX_PIN(PIN_PC12, 2, 2)
+#define PIN_PC12__FLEXCOM2_IO1		PINMUX_PIN(PIN_PC12, 6, 4)
+#define PIN_PC13			77
+#define PIN_PC13__GPIO			PINMUX_PIN(PIN_PC13, 0, 0)
+#define PIN_PC13__I2SMCC1_MCK		PINMUX_PIN(PIN_PC13, 1, 1)
+#define PIN_PC13__FLEXCOM8_IO1		PINMUX_PIN(PIN_PC13, 2, 2)
+#define PIN_PC13__FLEXCOM3_IO0		PINMUX_PIN(PIN_PC13, 6, 4)
+#define PIN_PC14			78
+#define PIN_PC14__GPIO			PINMUX_PIN(PIN_PC14, 0, 0)
+#define PIN_PC14__I2SMCC1_DOUT0		PINMUX_PIN(PIN_PC14, 1, 1)
+#define PIN_PC14__FLEXCOM8_IO0		PINMUX_PIN(PIN_PC14, 2, 2)
+#define PIN_PC14__FLEXCOM3_IO1		PINMUX_PIN(PIN_PC14, 6, 4)
+#define PIN_PC15			79
+#define PIN_PC15__GPIO			PINMUX_PIN(PIN_PC15, 0, 0)
+#define PIN_PC15__I2SMCC1_DOUT1		PINMUX_PIN(PIN_PC15, 1, 1)
+#define PIN_PC15__FLEXCOM8_IO3		PINMUX_PIN(PIN_PC15, 2, 2)
+#define PIN_PC15__FLEXCOM4_IO0		PINMUX_PIN(PIN_PC15, 6, 4)
+#define PIN_PC16			80
+#define PIN_PC16__GPIO			PINMUX_PIN(PIN_PC16, 0, 0)
+#define PIN_PC16__I2SMCC1_DOUT2		PINMUX_PIN(PIN_PC16, 1, 1)
+#define PIN_PC16__FLEXCOM8_IO4		PINMUX_PIN(PIN_PC16, 2, 2)
+#define PIN_PC16__FLEXCOM3_IO1		PINMUX_PIN(PIN_PC16, 6, 4)
+#define PIN_PC17			81
+#define PIN_PC17__GPIO			PINMUX_PIN(PIN_PC17, 0, 0)
+#define PIN_PC17__I2SMCC1_DOUT3		PINMUX_PIN(PIN_PC17, 1, 1)
+#define PIN_PC17__EXT_IRQ0		PINMUX_PIN(PIN_PC17, 2, 3)
+#define PIN_PC17__FLEXCOM5_IO0		PINMUX_PIN(PIN_PC17, 6, 4)
+#define PIN_PC18			82
+#define PIN_PC18__GPIO			PINMUX_PIN(PIN_PC18, 0, 0)
+#define PIN_PC18__I2SMCC1_DIN0		PINMUX_PIN(PIN_PC18, 1, 1)
+#define PIN_PC18__FLEXCOM9_IO0		PINMUX_PIN(PIN_PC18, 2, 2)
+#define PIN_PC18__FLEXCOM5_IO1		PINMUX_PIN(PIN_PC18, 6, 4)
+#define PIN_PC19			83
+#define PIN_PC19__GPIO			PINMUX_PIN(PIN_PC19, 0, 0)
+#define PIN_PC19__I2SMCC1_DIN1		PINMUX_PIN(PIN_PC19, 1, 1)
+#define PIN_PC19__FLEXCOM9_IO1		PINMUX_PIN(PIN_PC19, 2, 2)
+#define PIN_PC19__FLEXCOM6_IO0		PINMUX_PIN(PIN_PC19, 6, 4)
+#define PIN_PC20			84
+#define PIN_PC20__GPIO			PINMUX_PIN(PIN_PC20, 0, 0)
+#define PIN_PC20__I2SMCC1_DIN2		PINMUX_PIN(PIN_PC20, 1, 1)
+#define PIN_PC20__FLEXCOM9_IO4		PINMUX_PIN(PIN_PC20, 2, 2)
+#define PIN_PC20__FLEXCOM6_IO1		PINMUX_PIN(PIN_PC20, 6, 4)
+#define PIN_PC21			85
+#define PIN_PC21__GPIO			PINMUX_PIN(PIN_PC21, 0, 0)
+#define PIN_PC21__I2SMCC1_DIN3		PINMUX_PIN(PIN_PC21, 1, 1)
+#define PIN_PC21__FLEXCOM9_IO2		PINMUX_PIN(PIN_PC21, 2, 2)
+#define PIN_PC21__D3			PINMUX_PIN(PIN_PC21, 4, 2)
+#define PIN_PC21__FLEXCOM6_IO0		PINMUX_PIN(PIN_PC21, 6, 5)
+#define PIN_PC22			86
+#define PIN_PC22__GPIO			PINMUX_PIN(PIN_PC22, 0, 0)
+#define PIN_PC22__I2SMCC0_DIN2		PINMUX_PIN(PIN_PC22, 1, 1)
+#define PIN_PC22__FLEXCOM9_IO3		PINMUX_PIN(PIN_PC22, 2, 2)
+#define PIN_PC22__D4			PINMUX_PIN(PIN_PC22, 4, 2)
+#define PIN_PC22__FLEXCOM6_IO1		PINMUX_PIN(PIN_PC22, 6, 5)
+#define PIN_PC23			87
+#define PIN_PC23__GPIO			PINMUX_PIN(PIN_PC23, 0, 0)
+#define PIN_PC23__I2SMCC0_DIN3		PINMUX_PIN(PIN_PC23, 1, 1)
+#define PIN_PC23__FLEXCOM0_IO5		PINMUX_PIN(PIN_PC23, 2, 3)
+#define PIN_PC23__D5			PINMUX_PIN(PIN_PC23, 4, 2)
+#define PIN_PC23__FLEXCOM7_IO0		PINMUX_PIN(PIN_PC23, 6, 5)
+#define PIN_PC24			88
+#define PIN_PC24__GPIO			PINMUX_PIN(PIN_PC24, 0, 0)
+#define PIN_PC24__FLEXCOM0_IO6		PINMUX_PIN(PIN_PC24, 2, 3)
+#define PIN_PC24__EXT_IRQ1		PINMUX_PIN(PIN_PC24, 3, 3)
+#define PIN_PC24__D6			PINMUX_PIN(PIN_PC24, 4, 2)
+#define PIN_PC24__FLEXCOM7_IO1		PINMUX_PIN(PIN_PC24, 6, 5)
+#define PIN_PC25			89
+#define PIN_PC25__GPIO			PINMUX_PIN(PIN_PC25, 0, 0)
+#define PIN_PC25__NTRST			PINMUX_PIN(PIN_PC25, 1, 1)
+#define PIN_PC26			90
+#define PIN_PC26__GPIO			PINMUX_PIN(PIN_PC26, 0, 0)
+#define PIN_PC26__TCK_SWCLK		PINMUX_PIN(PIN_PC26, 1, 1)
+#define PIN_PC27			91
+#define PIN_PC27__GPIO			PINMUX_PIN(PIN_PC27, 0, 0)
+#define PIN_PC27__TMS_SWDIO		PINMUX_PIN(PIN_PC27, 1, 1)
+#define PIN_PC28			92
+#define PIN_PC28__GPIO			PINMUX_PIN(PIN_PC28, 0, 0)
+#define PIN_PC28__TDI			PINMUX_PIN(PIN_PC28, 1, 1)
+#define PIN_PC29			93
+#define PIN_PC29__GPIO			PINMUX_PIN(PIN_PC29, 0, 0)
+#define PIN_PC29__TDO			PINMUX_PIN(PIN_PC29, 1, 1)
+#define PIN_PC30			94
+#define PIN_PC30__GPIO			PINMUX_PIN(PIN_PC30, 0, 0)
+#define PIN_PC30__FLEXCOM10_IO0		PINMUX_PIN(PIN_PC30, 2, 2)
+#define PIN_PC31			95
+#define PIN_PC31__GPIO			PINMUX_PIN(PIN_PC31, 0, 0)
+#define PIN_PC31__FLEXCOM10_IO1		PINMUX_PIN(PIN_PC31, 2, 2)
+#define PIN_PD0				96
+#define PIN_PD0__GPIO			PINMUX_PIN(PIN_PD0, 0, 0)
+#define PIN_PD0__FLEXCOM11_IO0		PINMUX_PIN(PIN_PD0, 2, 2)
+#define PIN_PD1				97
+#define PIN_PD1__GPIO			PINMUX_PIN(PIN_PD1, 0, 0)
+#define PIN_PD1__FLEXCOM11_IO1		PINMUX_PIN(PIN_PD1, 2, 2)
+#define PIN_PD2				98
+#define PIN_PD2__GPIO			PINMUX_PIN(PIN_PD2, 0, 0)
+#define PIN_PD2__SDMMC2_RSTN		PINMUX_PIN(PIN_PD2, 1, 1)
+#define PIN_PD2__PCK0			PINMUX_PIN(PIN_PD2, 2, 2)
+#define PIN_PD2__CANTX4			PINMUX_PIN(PIN_PD2, 3, 1)
+#define PIN_PD2__D7			PINMUX_PIN(PIN_PD2, 4, 2)
+#define PIN_PD2__TIOA0			PINMUX_PIN(PIN_PD2, 5, 2)
+#define PIN_PD2__FLEXCOM8_IO0		PINMUX_PIN(PIN_PD2, 6, 5)
+#define PIN_PD3				99
+#define PIN_PD3__GPIO			PINMUX_PIN(PIN_PD3, 0, 0)
+#define PIN_PD3__SDMMC2_CMD		PINMUX_PIN(PIN_PD3, 1, 1)
+#define PIN_PD3__FLEXCOM0_IO0		PINMUX_PIN(PIN_PD3, 2, 2)
+#define PIN_PD3__CANRX4			PINMUX_PIN(PIN_PD3, 3, 1)
+#define PIN_PD3__NANDRDY		PINMUX_PIN(PIN_PD3, 4, 2)
+#define PIN_PD3__TIOB0			PINMUX_PIN(PIN_PD3, 5, 2)
+#define PIN_PD3__FLEXCOM8_IO1		PINMUX_PIN(PIN_PD3, 6, 5)
+#define PIN_PD4				100
+#define PIN_PD4__GPIO			PINMUX_PIN(PIN_PD4, 0, 0)
+#define PIN_PD4__SDMMC2_CK		PINMUX_PIN(PIN_PD4, 1, 1)
+#define PIN_PD4__FLEXCOM0_IO1		PINMUX_PIN(PIN_PD4, 2, 2)
+#define PIN_PD4__CANTX5			PINMUX_PIN(PIN_PD4, 3, 1)
+#define PIN_PD4__NCS3_NANDCS		PINMUX_PIN(PIN_PD4, 4, 2)
+#define PIN_PD4__TCLK0			PINMUX_PIN(PIN_PD4, 5, 2)
+#define PIN_PD4__FLEXCOM9_IO0		PINMUX_PIN(PIN_PD4, 6, 5)
+#define PIN_PD5				101
+#define PIN_PD5__GPIO			PINMUX_PIN(PIN_PD5, 0, 0)
+#define PIN_PD5__SDMMC2_DAT0		PINMUX_PIN(PIN_PD5, 1, 1)
+#define PIN_PD5__FLEXCOM0_IO2		PINMUX_PIN(PIN_PD5, 2, 2)
+#define PIN_PD5__CANRX5			PINMUX_PIN(PIN_PD5, 3, 1)
+#define PIN_PD5__NWE_NWR0_NANDWE	PINMUX_PIN(PIN_PD5, 4, 2)
+#define PIN_PD5__TIOA1			PINMUX_PIN(PIN_PD5, 5, 2)
+#define PIN_PD5__FLEXCOM9_IO1		PINMUX_PIN(PIN_PD5, 6, 5)
+#define PIN_PD6				102
+#define PIN_PD6__GPIO			PINMUX_PIN(PIN_PD6, 0, 0)
+#define PIN_PD6__SDMMC2_DAT1		PINMUX_PIN(PIN_PD6, 1, 1)
+#define PIN_PD6__FLEXCOM0_IO3		PINMUX_PIN(PIN_PD6, 2, 2)
+#define PIN_PD6__SPDIF_RX		PINMUX_PIN(PIN_PD6, 3, 3)
+#define PIN_PD6__NRD_NANDOE		PINMUX_PIN(PIN_PD6, 4, 2)
+#define PIN_PD6__TIOB1			PINMUX_PIN(PIN_PD6, 5, 2)
+#define PIN_PD6__FLEXCOM10_IO0		PINMUX_PIN(PIN_PD6, 6, 5)
+#define PIN_PD7				103
+#define PIN_PD7__GPIO			PINMUX_PIN(PIN_PD7, 0, 0)
+#define PIN_PD7__SDMMC2_DAT2		PINMUX_PIN(PIN_PD7, 1, 1)
+#define PIN_PD7__FLEXCOM0_IO4		PINMUX_PIN(PIN_PD7, 2, 2)
+#define PIN_PD7__SPDIF_TX		PINMUX_PIN(PIN_PD7, 2, 2)
+#define PIN_PD7__A21_NANDALE		PINMUX_PIN(PIN_PD7, 4, 2)
+#define PIN_PD7__TCLK1			PINMUX_PIN(PIN_PD7, 5, 2)
+#define PIN_PD7__FLEXCOM10_IO1		PINMUX_PIN(PIN_PD7, 6, 5)
+#define PIN_PD8				104
+#define PIN_PD8__GPIO			PINMUX_PIN(PIN_PD8, 0, 0)
+#define PIN_PD8__SDMMC2_DAT3		PINMUX_PIN(PIN_PD8, 1, 1)
+#define PIN_PD8__I2SMCC0_DIN0		PINMUX_PIN(PIN_PD8, 3, 1)
+#define PIN_PD8__A11_NANDCLE		PINMUX_PIN(PIN_PD8, 4, 2)
+#define PIN_PD8__TIOA2			PINMUX_PIN(PIN_PD8, 5, 2)
+#define PIN_PD8__FLEXCOM11_IO0		PINMUX_PIN(PIN_PD8, 6, 5)
+#define PIN_PD9				105
+#define PIN_PD9__GPIO			PINMUX_PIN(PIN_PD9, 0, 0)
+#define PIN_PD9__SDMMC2_WP		PINMUX_PIN(PIN_PD9, 1, 1)
+#define PIN_PD9__I2SMCC0_DIN1		PINMUX_PIN(PIN_PD9, 3, 2)
+#define PIN_PD9__D0			PINMUX_PIN(PIN_PD9, 4, 2)
+#define PIN_PD9__TIOB2			PINMUX_PIN(PIN_PD9, 5, 2)
+#define PIN_PD9__FLEXCOM11_IO1		PINMUX_PIN(PIN_PD9, 6, 5)
+#define PIN_PD10			106
+#define PIN_PD10__GPIO			PINMUX_PIN(PIN_PD10, 0, 0)
+#define PIN_PD10__SDMMC2_CD		PINMUX_PIN(PIN_PD10, 1, 1)
+#define PIN_PD10__PCK6			PINMUX_PIN(PIN_PD10, 2, 2)
+#define PIN_PD10__I2SMCC0_DIN2		PINMUX_PIN(PIN_PD10, 3, 2)
+#define PIN_PD10__D1			PINMUX_PIN(PIN_PD10, 4, 2)
+#define PIN_PD10__TCLK2			PINMUX_PIN(PIN_PD10, 5, 2)
+#define PIN_PD10__FLEXCOM0_IO0		PINMUX_PIN(PIN_PD10, 6, 3)
+#define PIN_PD11			107
+#define PIN_PD11__GPIO			PINMUX_PIN(PIN_PD11, 0, 0)
+#define PIN_PD11__SDMMC2_1V8SEL		PINMUX_PIN(PIN_PD11, 1, 1)
+#define PIN_PD11__PCK7			PINMUX_PIN(PIN_PD11, 2, 2)
+#define PIN_PD11__I2SMCC0_DIN3		PINMUX_PIN(PIN_PD11, 3, 2)
+#define PIN_PD11__D2			PINMUX_PIN(PIN_PD11, 4, 2)
+#define PIN_PD11__TIOA3			PINMUX_PIN(PIN_PD11, 5, 2)
+#define PIN_PD11__FLEXCOM0_IO1		PINMUX_PIN(PIN_PD11, 6, 3)
+#define PIN_PD12			108
+#define PIN_PD12__GPIO			PINMUX_PIN(PIN_PD12, 0, 0)
+#define PIN_PD12__PCK1			PINMUX_PIN(PIN_PD12, 1, 2)
+#define PIN_PD12__FLEXCOM1_IO0		PINMUX_PIN(PIN_PD12, 2, 2)
+#define PIN_PD12__CANTX0		PINMUX_PIN(PIN_PD12, 4, 2)
+#define PIN_PD12__TIOB3			PINMUX_PIN(PIN_PD12, 5, 2)
+#define PIN_PD13			109
+#define PIN_PD13__GPIO			PINMUX_PIN(PIN_PD13, 0, 0)
+#define PIN_PD13__I2SMCC0_CK		PINMUX_PIN(PIN_PD13, 1, 2)
+#define PIN_PD13__FLEXCOM1_IO1		PINMUX_PIN(PIN_PD13, 2, 2)
+#define PIN_PD13__PWML0			PINMUX_PIN(PIN_PD13, 3, 4)
+#define PIN_PD13__CANRX0		PINMUX_PIN(PIN_PD13, 4, 2)
+#define PIN_PD13__TCLK3			PINMUX_PIN(PIN_PD13, 5, 2)
+#define PIN_PD14			110
+#define PIN_PD14__GPIO			PINMUX_PIN(PIN_PD14, 0, 0)
+#define PIN_PD14__I2SMCC0_MCK		PINMUX_PIN(PIN_PD14, 1, 2)
+#define PIN_PD14__FLEXCOM1_IO2		PINMUX_PIN(PIN_PD14, 2, 2)
+#define PIN_PD14__PWMH0			PINMUX_PIN(PIN_PD14, 3, 4)
+#define PIN_PD14__CANTX1		PINMUX_PIN(PIN_PD14, 4, 2)
+#define PIN_PD14__TIOA4			PINMUX_PIN(PIN_PD14, 5, 2)
+#define PIN_PD14__FLEXCOM2_IO0		PINMUX_PIN(PIN_PD14, 6, 5)
+#define PIN_PD15			111
+#define PIN_PD15__GPIO			PINMUX_PIN(PIN_PD15, 0, 0)
+#define PIN_PD15__I2SMCC0_WS		PINMUX_PIN(PIN_PD15, 1, 2)
+#define PIN_PD15__FLEXCOM1_IO3		PINMUX_PIN(PIN_PD15, 2, 2)
+#define PIN_PD15__PWML1			PINMUX_PIN(PIN_PD15, 3, 4)
+#define PIN_PD15__CANRX1		PINMUX_PIN(PIN_PD15, 4, 2)
+#define PIN_PD15__TIOB4			PINMUX_PIN(PIN_PD15, 5, 2)
+#define PIN_PD15__FLEXCOM2_IO1		PINMUX_PIN(PIN_PD15, 6, 5)
+#define PIN_PD16			112
+#define PIN_PD16__GPIO			PINMUX_PIN(PIN_PD16, 0, 0)
+#define PIN_PD16__I2SMCC0_DOUT0		PINMUX_PIN(PIN_PD16, 1, 2)
+#define PIN_PD16__FLEXCOM1_IO4		PINMUX_PIN(PIN_PD16, 2, 2)
+#define PIN_PD16__PWMH1			PINMUX_PIN(PIN_PD16, 3, 4)
+#define PIN_PD16__CANTX2		PINMUX_PIN(PIN_PD16, 4, 2)
+#define PIN_PD16__TCLK4			PINMUX_PIN(PIN_PD16, 5, 2)
+#define PIN_PD16__FLEXCOM3_IO0		PINMUX_PIN(PIN_PD16, 6, 5)
+#define PIN_PD17			113
+#define PIN_PD17__GPIO			PINMUX_PIN(PIN_PD17, 0, 0)
+#define PIN_PD17__I2SMCC0_DOUT1		PINMUX_PIN(PIN_PD17, 1, 2)
+#define PIN_PD17__FLEXCOM2_IO0		PINMUX_PIN(PIN_PD17, 2, 2)
+#define PIN_PD17__PWML2			PINMUX_PIN(PIN_PD17, 3, 4)
+#define PIN_PD17__CANRX2		PINMUX_PIN(PIN_PD17, 4, 2)
+#define PIN_PD17__TIOA5			PINMUX_PIN(PIN_PD17, 5, 2)
+#define PIN_PD17__FLEXCOM3_IO1		PINMUX_PIN(PIN_PD17, 6, 5)
+#define PIN_PD18			114
+#define PIN_PD18__GPIO			PINMUX_PIN(PIN_PD18, 0, 0)
+#define PIN_PD18__I2SMCC0_DOUT2		PINMUX_PIN(PIN_PD18, 1, 2)
+#define PIN_PD18__FLEXCOM2_IO1		PINMUX_PIN(PIN_PD18, 2, 2)
+#define PIN_PD18__PWMH2			PINMUX_PIN(PIN_PD18, 3, 4)
+#define PIN_PD18__CANTX3		PINMUX_PIN(PIN_PD18, 4, 2)
+#define PIN_PD18__TIOB5			PINMUX_PIN(PIN_PD18, 5, 2)
+#define PIN_PD18__FLEXCOM4_IO0		PINMUX_PIN(PIN_PD18, 6, 5)
+#define PIN_PD19			115
+#define PIN_PD19__GPIO			PINMUX_PIN(PIN_PD19, 0, 0)
+#define PIN_PD19__I2SMCC0_DOUT3		PINMUX_PIN(PIN_PD19, 1, 2)
+#define PIN_PD19__FLEXCOM2_IO2		PINMUX_PIN(PIN_PD19, 2, 2)
+#define PIN_PD19__PWML3			PINMUX_PIN(PIN_PD19, 3, 4)
+#define PIN_PD19__CANRX3		PINMUX_PIN(PIN_PD19, 4, 2)
+#define PIN_PD19__TCLK5			PINMUX_PIN(PIN_PD19, 5, 2)
+#define PIN_PD19__FLEXCOM4_IO1		PINMUX_PIN(PIN_PD19, 6, 5)
+#define PIN_PD20			116
+#define PIN_PD20__GPIO			PINMUX_PIN(PIN_PD20, 0, 0)
+#define PIN_PD20__PCK0			PINMUX_PIN(PIN_PD20, 1, 3)
+#define PIN_PD20__FLEXCOM2_IO3		PINMUX_PIN(PIN_PD20, 2, 2)
+#define PIN_PD20__PWMH3			PINMUX_PIN(PIN_PD20, 3, 4)
+#define PIN_PD20__CANTX4		PINMUX_PIN(PIN_PD20, 4, 2)
+#define PIN_PD20__FLEXCOM5_IO0		PINMUX_PIN(PIN_PD20, 6, 5)
+#define PIN_PD21			117
+#define PIN_PD21__GPIO			PINMUX_PIN(PIN_PD21, 0, 0)
+#define PIN_PD21__PCK1			PINMUX_PIN(PIN_PD21, 1, 3)
+#define PIN_PD21__FLEXCOM2_IO4		PINMUX_PIN(PIN_PD21, 2, 2)
+#define PIN_PD21__CANRX4		PINMUX_PIN(PIN_PD21, 4, 2)
+#define PIN_PD21__FLEXCOM5_IO1		PINMUX_PIN(PIN_PD21, 6, 5)
+#define PIN_PD21__G1_TXEN		PINMUX_PIN(PIN_PD21, 7, 1)
+#define PIN_PD22			118
+#define PIN_PD22__GPIO			PINMUX_PIN(PIN_PD22, 0, 0)
+#define PIN_PD22__PDMC0_CLK		PINMUX_PIN(PIN_PD22, 1, 2)
+#define PIN_PD22__PWMEXTRG0		PINMUX_PIN(PIN_PD22, 3, 4)
+#define PIN_PD22__RD1			PINMUX_PIN(PIN_PD22, 4, 2)
+#define PIN_PD22__CANTX5		PINMUX_PIN(PIN_PD22, 6, 2)
+#define PIN_PD22__G1_TX0		PINMUX_PIN(PIN_PD22, 7, 1)
+#define PIN_PD23			119
+#define PIN_PD23__GPIO			PINMUX_PIN(PIN_PD23, 0, 0)
+#define PIN_PD23__PDMC0_DS0		PINMUX_PIN(PIN_PD23, 1, 2)
+#define PIN_PD23__PWMEXTRG1		PINMUX_PIN(PIN_PD23, 3, 4)
+#define PIN_PD23__RF1			PINMUX_PIN(PIN_PD23, 4, 2)
+#define PIN_PD23__ISC_MCK		PINMUX_PIN(PIN_PD23, 5, 2)
+#define PIN_PD23__CANRX5		PINMUX_PIN(PIN_PD23, 6, 2)
+#define PIN_PD23__G1_TX1		PINMUX_PIN(PIN_PD23, 7, 1)
+#define PIN_PD24			120
+#define PIN_PD24__GPIO			PINMUX_PIN(PIN_PD24, 0, 0)
+#define PIN_PD24__PDMC0_DS1		PINMUX_PIN(PIN_PD24, 1, 2)
+#define PIN_PD24__PWMFI0		PINMUX_PIN(PIN_PD24, 3, 4)
+#define PIN_PD24__RK1			PINMUX_PIN(PIN_PD24, 4, 2)
+#define PIN_PD24__ISC_D0		PINMUX_PIN(PIN_PD24, 5, 2)
+#define PIN_PD24__G1_RXDV		PINMUX_PIN(PIN_PD24, 7, 1)
+#define PIN_PD25			121
+#define PIN_PD25__GPIO			PINMUX_PIN(PIN_PD25, 0, 0)
+#define PIN_PD25__PDMC1_CLK		PINMUX_PIN(PIN_PD25, 1, 2)
+#define PIN_PD25__FLEXCOM5_IO0		PINMUX_PIN(PIN_PD25, 2, 2)
+#define PIN_PD25__PWMFI1		PINMUX_PIN(PIN_PD25, 3, 4)
+#define PIN_PD25__TD1			PINMUX_PIN(PIN_PD25, 4, 2)
+#define PIN_PD25__ISC_D1		PINMUX_PIN(PIN_PD25, 5, 2)
+#define PIN_PD25__G1_RX0		PINMUX_PIN(PIN_PD25, 7, 1)
+#define PIN_PD26			122
+#define PIN_PD26__GPIO			PINMUX_PIN(PIN_PD26, 0, 0)
+#define PIN_PD26__PDMC1_DS0		PINMUX_PIN(PIN_PD26, 1, 2)
+#define PIN_PD26__FLEXCOM5_IO1		PINMUX_PIN(PIN_PD26, 2, 2)
+#define PIN_PD26__ADTRG			PINMUX_PIN(PIN_PD26, 3, 3)
+#define PIN_PD26__TF1			PINMUX_PIN(PIN_PD26, 4, 2)
+#define PIN_PD26__ISC_D2		PINMUX_PIN(PIN_PD26, 5, 2)
+#define PIN_PD26__G1_RX1		PINMUX_PIN(PIN_PD26, 7, 1)
+#define PIN_PD27			123
+#define PIN_PD27__GPIO			PINMUX_PIN(PIN_PD27, 0, 0)
+#define PIN_PD27__PDMC1_DS1		PINMUX_PIN(PIN_PD27, 1, 2)
+#define PIN_PD27__FLEXCOM5_IO2		PINMUX_PIN(PIN_PD27, 2, 2)
+#define PIN_PD27__TIOA0			PINMUX_PIN(PIN_PD27, 3, 3)
+#define PIN_PD27__TK1			PINMUX_PIN(PIN_PD27, 4, 2)
+#define PIN_PD27__ISC_D3		PINMUX_PIN(PIN_PD27, 5, 2)
+#define PIN_PD27__G1_RXER		PINMUX_PIN(PIN_PD27, 7, 1)
+#define PIN_PD28			124
+#define PIN_PD28__GPIO			PINMUX_PIN(PIN_PD28, 0, 0)
+#define PIN_PD28__RD0			PINMUX_PIN(PIN_PD28, 1, 2)
+#define PIN_PD28__FLEXCOM5_IO3		PINMUX_PIN(PIN_PD28, 2, 2)
+#define PIN_PD28__TIOB0			PINMUX_PIN(PIN_PD28, 3, 3)
+#define PIN_PD28__I2SMCC1_CK		PINMUX_PIN(PIN_PD28, 4, 2)
+#define PIN_PD28__ISC_D4		PINMUX_PIN(PIN_PD28, 5, 2)
+#define PIN_PD28__PWML3			PINMUX_PIN(PIN_PD28, 6, 5)
+#define PIN_PD28__G1_MDC		PINMUX_PIN(PIN_PD28, 7, 1)
+#define PIN_PD29			125
+#define PIN_PD29__GPIO			PINMUX_PIN(PIN_PD29, 0, 0)
+#define PIN_PD29__RF0			PINMUX_PIN(PIN_PD29, 1, 2)
+#define PIN_PD29__FLEXCOM5_IO4		PINMUX_PIN(PIN_PD29, 2, 2)
+#define PIN_PD29__TCLK0			PINMUX_PIN(PIN_PD29, 3, 3)
+#define PIN_PD29__I2SMCC1_WS		PINMUX_PIN(PIN_PD29, 4, 2)
+#define PIN_PD29__ISC_D5		PINMUX_PIN(PIN_PD29, 5, 2)
+#define PIN_PD29__PWMH3			PINMUX_PIN(PIN_PD29, 6, 5)
+#define PIN_PD29__G1_MDIO		PINMUX_PIN(PIN_PD29, 7, 1)
+#define PIN_PD30			126
+#define PIN_PD30__GPIO			PINMUX_PIN(PIN_PD30, 0, 0)
+#define PIN_PD30__RK0			PINMUX_PIN(PIN_PD30, 1, 2)
+#define PIN_PD30__FLEXCOM6_IO0		PINMUX_PIN(PIN_PD30, 2, 2)
+#define PIN_PD30__TIOA1			PINMUX_PIN(PIN_PD30, 3, 3)
+#define PIN_PD30__I2SMCC1_MCK		PINMUX_PIN(PIN_PD30, 4, 2)
+#define PIN_PD30__ISC_D6		PINMUX_PIN(PIN_PD30, 5, 2)
+#define PIN_PD30__PWMEXTRG0		PINMUX_PIN(PIN_PD30, 6, 5)
+#define PIN_PD30__G1_TXCK		PINMUX_PIN(PIN_PD30, 7, 1)
+#define PIN_PD31			127
+#define PIN_PD31__GPIO			PINMUX_PIN(PIN_PD31, 0, 0)
+#define PIN_PD31__TD0			PINMUX_PIN(PIN_PD31, 1, 2)
+#define PIN_PD31__FLEXCOM6_IO1		PINMUX_PIN(PIN_PD31, 2, 2)
+#define PIN_PD31__TIOB1			PINMUX_PIN(PIN_PD31, 3, 3)
+#define PIN_PD31__I2SMCC1_DOUT0		PINMUX_PIN(PIN_PD31, 4, 2)
+#define PIN_PD31__ISC_D7		PINMUX_PIN(PIN_PD31, 5, 2)
+#define PIN_PD31__PWM_EXTRG1		PINMUX_PIN(PIN_PD31, 6, 5)
+#define PIN_PD31__G1_TX2		PINMUX_PIN(PIN_PD31, 7, 1)
+#define PIN_PE0				128
+#define PIN_PE0__GPIO			PINMUX_PIN(PIN_PE0, 0, 0)
+#define PIN_PE0__TF0			PINMUX_PIN(PIN_PE0, 1, 2)
+#define PIN_PE0__FLEXCOM6_IO2		PINMUX_PIN(PIN_PE0, 2, 2)
+#define PIN_PE0__TCLK1			PINMUX_PIN(PIN_PE0, 3, 3)
+#define PIN_PE0__I2SMCC1_DOUT1		PINMUX_PIN(PIN_PE0, 4, 2)
+#define PIN_PE0__ISC_HSYNC		PINMUX_PIN(PIN_PE0, 5, 2)
+#define PIN_PE0__PWMFI0			PINMUX_PIN(PIN_PE0, 6, 5)
+#define PIN_PE0__G1_TX3			PINMUX_PIN(PIN_PE0, 7, 1)
+#define PIN_PE1				129
+#define PIN_PE1__GPIO			PINMUX_PIN(PIN_PE1, 0, 0)
+#define PIN_PE1__TK0			PINMUX_PIN(PIN_PE1, 1, 2)
+#define PIN_PE1__FLEXCOM6_IO3		PINMUX_PIN(PIN_PE1, 2, 2)
+#define PIN_PE1__TIOA2			PINMUX_PIN(PIN_PE1, 3, 3)
+#define PIN_PE1__I2SMCC1_DOUT2		PINMUX_PIN(PIN_PE1, 4, 2)
+#define PIN_PE1__ISC_VSYNC		PINMUX_PIN(PIN_PE1, 5, 2)
+#define PIN_PE1__PWMFI1			PINMUX_PIN(PIN_PE1, 6, 5)
+#define PIN_PE1__G1_RX2			PINMUX_PIN(PIN_PE1, 7, 1)
+#define PIN_PE2				130
+#define PIN_PE2__GPIO			PINMUX_PIN(PIN_PE2, 0, 0)
+#define PIN_PE2__PWML0			PINMUX_PIN(PIN_PE2, 1, 5)
+#define PIN_PE2__FLEXCOM6_IO4		PINMUX_PIN(PIN_PE2, 2, 2)
+#define PIN_PE2__TIOB2			PINMUX_PIN(PIN_PE2, 3, 3)
+#define PIN_PE2__I2SMCC1_DOUT3		PINMUX_PIN(PIN_PE2, 4, 2)
+#define PIN_PE2__ISC_FIELD		PINMUX_PIN(PIN_PE2, 5, 2)
+#define PIN_PE2__G1_RX3			PINMUX_PIN(PIN_PE2, 7, 1)
+#define PIN_PE3				131
+#define PIN_PE3__GPIO			PINMUX_PIN(PIN_PE3, 0, 0)
+#define PIN_PE3__PWMH0			PINMUX_PIN(PIN_PE3, 1, 5)
+#define PIN_PE3__FLEXCOM0_IO0		PINMUX_PIN(PIN_PE3, 2, 4)
+#define PIN_PE3__TCLK2			PINMUX_PIN(PIN_PE3, 3, 3)
+#define PIN_PE3__I2SMCC1_DIN0		PINMUX_PIN(PIN_PE3, 4, 2)
+#define PIN_PE3__ISC_PCK		PINMUX_PIN(PIN_PE3, 5, 2)
+#define PIN_PE3__G1_RXCK		PINMUX_PIN(PIN_PE3, 7, 1)
+#define PIN_PE4				132
+#define PIN_PE4__GPIO			PINMUX_PIN(PIN_PE4, 0, 0)
+#define PIN_PE4__PWML1			PINMUX_PIN(PIN_PE4, 1, 5)
+#define PIN_PE4__FLEXCOM0_IO1		PINMUX_PIN(PIN_PE4, 2, 4)
+#define PIN_PE4__TIOA3			PINMUX_PIN(PIN_PE4, 3, 3)
+#define PIN_PE4__I2SMCC1_DIN1		PINMUX_PIN(PIN_PE4, 4, 2)
+#define PIN_PE4__ISC_D8			PINMUX_PIN(PIN_PE4, 5, 2)
+#define PIN_PE4__G1_TXER		PINMUX_PIN(PIN_PE4, 7, 1)
+#define PIN_PE5				133
+#define PIN_PE5__GPIO			PINMUX_PIN(PIN_PE5, 0, 0)
+#define PIN_PE5__PWMH1			PINMUX_PIN(PIN_PE5, 1, 5)
+#define PIN_PE5__FLEXCOM0_IO2		PINMUX_PIN(PIN_PE5, 2, 4)
+#define PIN_PE5__TIOB3			PINMUX_PIN(PIN_PE5, 3, 3)
+#define PIN_PE5__I2SMCC1_DIN2		PINMUX_PIN(PIN_PE5, 4, 2)
+#define PIN_PE5__ISC_D9			PINMUX_PIN(PIN_PE5, 5, 2)
+#define PIN_PE5__G1_COL			PINMUX_PIN(PIN_PE5, 7, 1)
+#define PIN_PE6				134
+#define PIN_PE6__GPIO			PINMUX_PIN(PIN_PE6, 0, 0)
+#define PIN_PE6__PWML2			PINMUX_PIN(PIN_PE6, 1, 5)
+#define PIN_PE6__FLEXCOM0_IO3		PINMUX_PIN(PIN_PE6, 2, 4)
+#define PIN_PE6__TCLK3			PINMUX_PIN(PIN_PE6, 3, 3)
+#define PIN_PE6__I2SMCC1_DIN3		PINMUX_PIN(PIN_PE6, 4, 2)
+#define PIN_PE6__ISC_D10		PINMUX_PIN(PIN_PE6, 5, 2)
+#define PIN_PE6__G1_CRS			PINMUX_PIN(PIN_PE6, 7, 1)
+#define PIN_PE7				135
+#define PIN_PE7__GPIO			PINMUX_PIN(PIN_PE7, 0, 0)
+#define PIN_PE7__PWMH2			PINMUX_PIN(PIN_PE7, 1, 5)
+#define PIN_PE7__FLEXCOM0_IO4		PINMUX_PIN(PIN_PE7, 2, 4)
+#define PIN_PE7__TIOA4			PINMUX_PIN(PIN_PE7, 3, 3)
+#define PIN_PE7__ISC_D11		PINMUX_PIN(PIN_PE7, 5, 2)
+#define PIN_PE7__G1_TSUCOMP		PINMUX_PIN(PIN_PE7, 7, 1)
diff --git a/core/arch/arm/dts/sama7g5.dtsi b/core/arch/arm/dts/sama7g5.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..e7c1ff48069684d9211668c62d863751effb8f94
--- /dev/null
+++ b/core/arch/arm/dts/sama7g5.dtsi
@@ -0,0 +1,1222 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ *  sama7g5.dtsi - Device Tree Include file for SAMA7G5 family SoC
+ *
+ *  Copyright (C) 2020 Microchip Technology, Inc. and its subsidiaries
+ *
+ *  Author: Eugen Hristev <eugen.hristev@microchip.com>
+ *  Author: Claudiu Beznea <claudiu.beznea@microchip.com>
+ */
+
+#include <dt-bindings/clock/at91.h>
+#include <dt-bindings/dma/at91.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+
+/ {
+	model = "Microchip SAMA7G5 family SoC";
+	compatible = "microchip,sama7g5";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			clocks = <&pmc PMC_TYPE_CORE PMC_CPUPLL>;
+			clock-names = "cpu";
+			operating-points-v2 = <&cpu_opp_table>;
+			#cooling-cells = <2>; /* min followed by max */
+		};
+	};
+
+	cpu_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-90000000 {
+			opp-hz = /bits/ 64 <90000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-250000000 {
+			opp-hz = /bits/ 64 <250000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-600000000 {
+			opp-hz = /bits/ 64 <600000000>;
+			opp-microvolt = <1050000 1050000 1225000>;
+			clock-latency-ns = <320000>;
+			opp-suspend;
+		};
+
+		opp-800000000 {
+			opp-hz = /bits/ 64 <800000000>;
+			opp-microvolt = <1150000 1125000 1225000>;
+			clock-latency-ns = <320000>;
+		};
+
+		opp-1000000002 {
+			opp-hz = /bits/ 64 <1000000002>;
+			opp-microvolt = <1250000 1225000 1300000>;
+			clock-latency-ns = <320000>;
+		};
+	};
+
+	thermal-zones {
+		cpu_thermal: cpu-thermal {
+			polling-delay-passive = <1000>;
+			polling-delay = <5000>;
+			thermal-sensors = <&thermal_sensor>;
+
+			trips {
+				cpu_normal: cpu-alert0 {
+					temperature = <90000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+
+				cpu_hot: cpu-alert1 {
+					temperature = <95000>;
+					hysteresis = <0>;
+					type = "passive";
+				};
+
+				cpu_critical: cpu-critical {
+					temperature = <100000>;
+					hysteresis = <0>;
+					type = "critical";
+				};
+			};
+
+			cooling-maps {
+				map0 {
+					trip = <&cpu_normal>;
+				};
+
+				map1 {
+					trip = <&cpu_hot>;
+				};
+			};
+		};
+	};
+
+	clocks {
+		slow_xtal: slow_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+		};
+
+		main_xtal: main_xtal {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+		};
+
+		usb_clk: usb_clk {
+			compatible = "fixed-clock";
+			#clock-cells = <0>;
+			clock-frequency = <48000000>;
+		};
+	};
+
+	utmi_clk: utmi-clk {
+		compatible = "microchip,sama7g5-utmi-clk";
+		sfr-phandle = <&sfr>;
+		#clock-cells = <1>;
+		clocks = <&pmc PMC_TYPE_CORE PMC_UTMI>;
+		clock-names = "utmi_clk";
+		reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
+		status = "disabled";
+	};
+
+	utmi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		usb_phy0: phy@0 {
+			compatible = "microchip,sama7g5-usb-phy";
+			sfr-phandle = <&sfr>;
+			reg = <0>;
+			clock-names = "utmi_clk";
+			status = "disabled";
+			#phy-cells = <0>;
+		};
+
+		usb_phy1: phy@1 {
+			compatible = "microchip,sama7g5-usb-phy";
+			sfr-phandle = <&sfr>;
+			reg = <1>;
+			clock-names = "utmi_clk";
+			status = "disabled";
+			#phy-cells = <0>;
+		};
+
+		usb_phy2: phy@2 {
+			compatible = "microchip,sama7g5-usb-phy";
+			sfr-phandle = <&sfr>;
+			reg = <2>;
+			clock-names = "utmi_clk";
+			status = "disabled";
+			#phy-cells = <0>;
+		};
+	};
+
+	vddout25: fixed-regulator-vddout25 {
+		compatible = "regulator-fixed";
+
+		regulator-name = "VDDOUT25";
+		regulator-min-microvolt = <2500000>;
+		regulator-max-microvolt = <2500000>;
+		regulator-boot-on;
+		status = "disabled";
+	};
+
+	ns_sram: sram@100000 {
+		compatible = "atmel,sama5d2-sram", "mmio-sram";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x100000 0x3400>;
+		ranges;
+		status = "disabled";
+		secure-status = "okay";
+	};
+
+	thermal_sensor: thermal-sensor {
+		compatible = "generic-adc-thermal";
+		#thermal-sensor-cells = <0>;
+		io-channel-names = "sensor-channel";
+		status = "disabled";
+	};
+
+	soc {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		usb0: gadget@200000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "microchip,sama7g5-udc";
+			reg = <0x00200000 0x100000
+			       0xe0814000 0x400>;
+			interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 104>, <&usb_clk>;
+			clock-names = "pclk", "hclk";
+			status = "disabled";
+		};
+
+		usb1: gadget@300000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "microchip,sama7g5-udc";
+			reg = <0x00300000 0x100000
+			       0xe0818000 0x400>;
+			interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 105>, <&usb_clk>;
+			clock-names = "pclk", "hclk";
+			status = "disabled";
+		};
+
+		usb2: ohci@400000 {
+			compatible = "microchip,sama7g5-ohci", "usb-ohci";
+			reg = <0x00400000 0x100000>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			clock-names = "ohci_clk", "hclk", "uhpck";
+			status = "disabled";
+		};
+
+		usb3: ehci@500000 {
+			compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
+			reg = <0x00500000 0x100000>;
+			interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&usb_clk>, <&pmc PMC_TYPE_PERIPHERAL 106>;
+			clock-names = "usb_clk", "ehci_clk";
+			status = "disabled";
+		};
+
+		nfc_sram: sram@600000 {
+			compatible = "mmio-sram";
+			no-memory-wc;
+			reg = <0x00600000 0x2400>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0x00600000 0x2400>;
+		};
+
+		nfc_io: nfc-io@10000000 {
+			compatible = "atmel,sama5d3-nfc-io", "syscon";
+			reg = <0x10000000 0x8000000>;
+		};
+
+		ebi: ebi@40000000 {
+			compatible = "atmel,sama5d3-ebi";
+			#address-cells = <2>;
+			#size-cells = <1>;
+			atmel,smc = <&hsmc>;
+			reg = <0x40000000 0x20000000>;
+			ranges = <0x0 0x0 0x40000000 0x8000000
+				  0x1 0x0 0x48000000 0x8000000
+				  0x2 0x0 0x50000000 0x8000000
+				  0x3 0x0 0x58000000 0x8000000>;
+			clocks = <&pmc PMC_TYPE_CORE PMC_MCK1>;
+			status = "disabled";
+
+			nand_controller: nand-controller {
+				compatible = "atmel,sama5d3-nand-controller";
+				atmel,nfc-sram = <&nfc_sram>;
+				atmel,nfc-io = <&nfc_io>;
+				ecc-engine = <&pmecc>;
+				#address-cells = <2>;
+				#size-cells = <1>;
+				ranges;
+				status = "disabled";
+			};
+		};
+
+		securam: sram@e0000000 {
+			compatible = "microchip,sama7g5-securam", "atmel,sama5d2-securam", "mmio-sram";
+			reg = <0xe0000000 0x4000>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 18>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0 0xe0000000 0x4000>;
+			no-memory-wc;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		secumod: secumod@e0004000 {
+			compatible = "microchip,sama7g5-secumod", "atmel,sama5d2-secumod", "syscon";
+			reg = <0xe0004000 0x4000>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		sfrbu: sfr@e0008000 {
+			compatible = "microchip,sama7g5-sfrbu", "atmel,sama5d2-sfrbu", "syscon";
+			reg = <0xe0008000 0x20>;
+		};
+
+		pioA: pinctrl@e0014000 {
+			compatible = "microchip,sama7g5-pinctrl";
+			reg = <0xe0014000 0x800>;
+			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 11>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		pmc: pmc@e0018000 {
+			compatible = "microchip,sama7g5-pmc", "syscon";
+			reg = <0xe0018000 0x200>;
+			interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+			#clock-cells = <2>;
+			clocks = <&clk32k 1>, <&clk32k 0>, <&main_xtal>;
+			clock-names = "td_slck", "md_slck", "main_xtal";
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		reset_controller: reset-controller@e001d000 {
+			compatible = "microchip,sama7g5-rstc";
+			reg = <0xe001d000 0xc>, <0xe001d0e4 0x4>;
+			#reset-cells = <1>;
+			clocks = <&clk32k 0>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		shdwc: shdwc@e001d010 {
+			compatible = "microchip,sama7g5-shdwc", "syscon";
+			reg = <0xe001d010 0x10>;
+			clocks = <&clk32k 0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			atmel,wakeup-rtc-timer;
+			atmel,wakeup-rtt-timer;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		rtt: rtc@e001d020 {
+			compatible = "microchip,sama7g5-rtt", "microchip,sam9x60-rtt", "atmel,at91sam9260-rtt";
+			reg = <0xe001d020 0x30>;
+			interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk32k 0>;
+		};
+
+		clk32k: clock-controller@e001d050 {
+			compatible = "microchip,sama7g5-sckc", "microchip,sam9x60-sckc";
+			reg = <0xe001d050 0x4>;
+			clocks = <&slow_xtal>;
+			#clock-cells = <1>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		gpbr: gpbr@e001d060 {
+			compatible = "microchip,sama7g5-gpbr", "syscon";
+			reg = <0xe001d060 0x48>;
+		};
+
+		rtc: rtc@e001d0a8 {
+			compatible = "microchip,sama7g5-rtc", "microchip,sam9x60-rtc";
+			reg = <0xe001d0a8 0x30>;
+			interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk32k 1>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		ps_wdt: watchdog@e001d180 {
+			compatible = "microchip,sama7g5-wdt";
+			reg = <0xe001d180 0x24>;
+			interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&clk32k 0>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		chipid@e0020000 {
+			compatible = "microchip,sama7g5-chipid";
+			reg = <0xe0020000 0x8>;
+		};
+
+		tcb1: timer@e0800000 {
+			compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xe0800000 0x100>;
+			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 91>, <&pmc PMC_TYPE_PERIPHERAL 92>, <&pmc PMC_TYPE_PERIPHERAL 93>, <&clk32k 1>;
+			clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk";
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		hsmc: hsmc@e0808000 {
+			compatible = "atmel,sama5d2-smc", "syscon", "simple-mfd";
+			reg = <0xe0808000 0x1000>;
+			interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 21>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+
+			pmecc: ecc-engine@e0808070 {
+				compatible = "atmel,sama5d2-pmecc";
+				reg = <0xe0808070 0x490>,
+				      <0xe0808500 0x200>;
+			};
+		};
+
+		qspi0: spi@e080c000 {
+			compatible = "microchip,sama7g5-ospi";
+			reg = <0xe080c000 0x400>, <0x20000000 0x10000000>;
+			reg-names = "qspi_base", "qspi_mmap";
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(41)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(40)>;
+			dma-names = "tx", "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 78>, <&pmc PMC_TYPE_GCK 78>;
+			clock-names = "pclk", "gclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 78>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <133000000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		qspi1: spi@e0810000 {
+			compatible = "microchip,sama7g5-qspi";
+			reg = <0xe0810000 0x400>, <0x30000000 0x10000000>;
+			reg-names = "qspi_base", "qspi_mmap";
+			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(43)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(42)>;
+			dma-names = "tx", "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 79>, <&pmc PMC_TYPE_GCK 79>;
+			clock-names = "pclk", "gclk";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
+		can0: can@e0828000 {
+			compatible = "bosch,m_can";
+			reg = <0xe0828000 0x100>, <0x100000 0x7800>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 61>, <&pmc PMC_TYPE_GCK 61>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 61>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0x3400 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		can1: can@e082c000 {
+			compatible = "bosch,m_can";
+			reg = <0xe082c000 0x100>, <0x100000 0xbc00>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 62>, <&pmc PMC_TYPE_GCK 62>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 62>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0x7800 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		can2: can@e0830000 {
+			compatible = "bosch,m_can";
+			reg = <0xe0830000 0x100>, <0x100000 0x10000>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 63>, <&pmc PMC_TYPE_GCK 63>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 63>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0xbc00 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		can3: can@e0834000 {
+			compatible = "bosch,m_can";
+			reg = <0xe0834000 0x100>, <0x110000 0x4400>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 64>, <&pmc PMC_TYPE_GCK 64>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 64>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0x0 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		can4: can@e0838000 {
+			compatible = "bosch,m_can";
+			reg = <0xe0838000 0x100>, <0x110000 0x8800>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 65>, <&pmc PMC_TYPE_GCK 65>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 65>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0x4400 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		can5: can@e083c000 {
+			compatible = "bosch,m_can";
+			reg = <0xe083c000 0x100>, <0x110000 0xcc00>;
+			reg-names = "m_can", "message_ram";
+			interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "int0", "int1";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 66>, <&pmc PMC_TYPE_GCK 66>;
+			clock-names = "hclk", "cclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 66>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clock-rates = <40000000>;
+			bosch,mram-cfg = <0x8800 0 0 64 0 0 32 32>;
+			status = "disabled";
+		};
+
+		adc: adc@e1000000 {
+			compatible = "microchip,sama7g5-adc";
+			reg = <0xe1000000 0x200>;
+			interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_GCK 26>;
+			assigned-clocks = <&pmc PMC_TYPE_GCK 26>;
+			assigned-clock-rates = <100000000>;
+			clock-names = "adc_clk";
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(0)>;
+			dma-names = "rx";
+			atmel,min-sample-rate-hz = <200000>;
+			atmel,max-sample-rate-hz = <20000000>;
+			atmel,startup-time-ms = <4>;
+			#io-channel-cells = <1>;
+			nvmem-cells = <&temperature_calib>;
+			nvmem-cell-names = "temperature_calib";
+			status = "disabled";
+		};
+
+		sdmmc0: mmc@e1204000 {
+			compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+			reg = <0xe1204000 0x4000>;
+			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 80>, <&pmc PMC_TYPE_GCK 80>;
+			clock-names = "hclock", "multclk";
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clocks = <&pmc PMC_TYPE_GCK 80>;
+			assigned-clock-rates = <200000000>;
+			microchip,sdcal-inverted;
+			status = "disabled";
+		};
+
+		sdmmc1: mmc@e1208000 {
+			compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+			reg = <0xe1208000 0x4000>;
+			interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 81>, <&pmc PMC_TYPE_GCK 81>;
+			clock-names = "hclock", "multclk";
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clocks = <&pmc PMC_TYPE_GCK 81>;
+			assigned-clock-rates = <200000000>;
+			microchip,sdcal-inverted;
+			status = "disabled";
+		};
+
+		sdmmc2: mmc@e120c000 {
+			compatible = "microchip,sama7g5-sdhci", "microchip,sam9x60-sdhci";
+			reg = <0xe120c000 0x4000>;
+			interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 82>, <&pmc PMC_TYPE_GCK 82>;
+			clock-names = "hclock", "multclk";
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_SYSPLL>;
+			assigned-clocks = <&pmc PMC_TYPE_GCK 82>;
+			assigned-clock-rates = <200000000>;
+			microchip,sdcal-inverted;
+			status = "disabled";
+		};
+
+		csi2host: csi2host@e1400000 {
+			compatible = "snps,dw-csi";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xe1400000 0x7FF>;
+			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 33>, <&pmc PMC_TYPE_GCK 33>;
+			clock-names = "perclk", "phyclk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 33>;
+			assigned-clock-rates = <26600000>;
+			snps,output-type = <1>;
+			phys = <&csi_dphy>;
+			status = "disabled";
+
+			port@1 {
+				reg = <1>;
+				csi2host_in: endpoint {
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				csi2host_out: endpoint {
+				};
+			};
+		};
+
+		csi_dphy: dphy@e1400040 {
+			compatible = "snps,dw-dphy-rx";
+			#phy-cells = <0>;
+			bus-width = <8>;
+			snps,dphy-frequency = <900000>;
+			snps,phy_type = <0>;
+			reg = <0xe1400040 0x20>;
+			status = "disabled";
+		};
+
+		csi2dc: csi2dc@e1404000 {
+			compatible = "microchip,sama7g5-csi2dc";
+			reg = <0xe1404000 0x500>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 34>, <&xisc>;
+			clock-names = "pclk", "scck";
+			assigned-clocks = <&xisc>;
+			assigned-clock-rates = <266000000>;
+			status = "disabled";
+
+			ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				port@0 {
+					reg = <0>;
+					csi2dc_in: endpoint {
+					};
+				};
+
+				port@1 {
+					reg = <1>;
+					csi2dc_out: endpoint {
+						bus-width = <14>;
+						hsync-active = <1>;
+						vsync-active = <1>;
+						remote-endpoint = <&xisc_in>;
+					};
+				};
+			};
+		};
+
+		xisc: xisc@e1408000 {
+			compatible = "microchip,sama7g5-isc";
+			reg = <0xe1408000 0x2000>;
+			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 56>;
+			clock-names = "hclock";
+			#clock-cells = <0>;
+			clock-output-names = "isc-mck";
+			status = "disabled";
+
+			port {
+				xisc_in: endpoint {
+					bus-type = <5>; /* Parallel */
+					bus-width = <14>;
+					hsync-active = <1>;
+					vsync-active = <1>;
+					remote-endpoint = <&csi2dc_out>;
+				};
+			};
+		};
+
+		pwm: pwm@e1604000 {
+			compatible = "microchip,sama7g5-pwm", "atmel,sama5d2-pwm";
+			reg = <0xe1604000 0x4000>;
+			interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+			#pwm-cells = <3>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 77>;
+			status = "disabled";
+		};
+
+		pdmc0: sound@e1608000 {
+			compatible = "microchip,sama7g5-pdmc";
+			reg = <0xe1608000 0x1000>;
+			interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
+			#sound-dai-cells = <0>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(37)>;
+			dma-names = "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 68>, <&pmc PMC_TYPE_GCK 68>;
+			clock-names = "pclk", "gclk";
+			sound-name-prefix = "PDMC0";
+			status = "disabled";
+		};
+
+		pdmc1: sound@e160c000 {
+			compatible = "microchip,sama7g5-pdmc";
+			reg = <0xe160c000 0x1000>;
+			interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+			#sound-dai-cells = <0>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(38)>;
+			dma-names = "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 69>, <&pmc PMC_TYPE_GCK 69>;
+			clock-names = "pclk", "gclk";
+			sound-name-prefix = "PDMC1";
+			status = "disabled";
+		};
+
+		asrc: sound@e1610000 {
+			compatible = "microchip,sama7g5-asrc";
+			reg = <0xe1610000 0x1000>;
+			interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+			#sound-dai-cells = <1>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(55)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(56)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(57)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(58)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(59)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(60)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(61)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(62)>;
+			dma-names = "rx0", "tx0", "rx1", "tx1",
+				    "rx2", "tx2", "rx3", "tx3";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 30>, <&pmc PMC_TYPE_GCK 30>;
+			clock-names = "pclk", "gclk";
+			microchip,triggers = <&i2s0>, <&i2s1>, <&pdmc0>, <&pdmc1>,
+					     <&ssc0>, <&ssc1>, <&spdiftx>, <&spdifrx>;
+			microchip,trigger-indexes = <1>, <2>, <3>, <4>, <5>, <8>, <9>, <10>;
+			assigned-clocks = <&pmc PMC_TYPE_GCK 30>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_AUDIOPMCPLL>;
+			status = "disabled";
+		};
+
+		spdifrx: spdifrx@e1614000 {
+			#sound-dai-cells = <0>;
+			compatible = "microchip,sama7g5-spdifrx";
+			reg = <0xe1614000 0x4000>;
+			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(49)>;
+			dma-names = "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 84>, <&pmc PMC_TYPE_GCK 84>;
+			clock-names = "pclk", "gclk";
+			status = "disabled";
+			sound-name-prefix = "SPDIFRX0";
+		};
+
+		spdiftx: spdiftx@e1618000 {
+			#sound-dai-cells = <0>;
+			compatible = "microchip,sama7g5-spdiftx";
+			reg = <0xe1618000 0x4000>;
+			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(50)>;
+			dma-names = "tx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 85>, <&pmc PMC_TYPE_GCK 85>;
+			clock-names = "pclk", "gclk";
+			sound-name-prefix = "SPDIFTX0";
+		};
+
+		i2s0: i2s@e161c000 {
+			compatible = "microchip,sama7g5-i2smcc";
+			#sound-dai-cells = <0>;
+			reg = <0xe161c000 0x4000>;
+			interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(34)>, <&dma0 AT91_XDMAC_DT_PERID(33)>;
+			dma-names = "tx", "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 57>, <&pmc PMC_TYPE_GCK 57>;
+			clock-names = "pclk", "gclk";
+			sound-name-prefix = "I2SMCC0";
+			status = "disabled";
+		};
+
+		i2s1: i2s@e1620000 {
+			compatible = "microchip,sama7g5-i2smcc";
+			#sound-dai-cells = <0>;
+			reg = <0xe1620000 0x4000>;
+			interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(36)>, <&dma0 AT91_XDMAC_DT_PERID(35)>;
+			dma-names = "tx", "rx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 58>, <&pmc PMC_TYPE_GCK 58>;
+			clock-names = "pclk", "gclk";
+			sound-name-prefix = "I2SMCC1";
+			status = "disabled";
+		};
+
+		sfr: sfr@e1624000 {
+			compatible = "microchip,sama7g5-sfr", "syscon";
+			reg = <0xe1624000 0x4000>;
+		};
+
+		eic: interrupt-controller@e1628000 {
+			compatible = "microchip,sama7g5-eic";
+			reg = <0xe1628000 0xec>;
+			interrupt-parent = <&gic>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 37>;
+			clock-names = "pclk";
+			status = "disabled";
+		};
+
+		pit64b0: timer@e1800000 {
+			compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b";
+			reg = <0xe1800000 0x4000>;
+			interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 70>, <&pmc PMC_TYPE_GCK 70>;
+			clock-names = "pclk", "gclk";
+		};
+
+		pit64b1: timer@e1804000 {
+			compatible = "microchip,sama7g5-pit64b", "microchip,sam9x60-pit64b";
+			reg = <0xe1804000 0x4000>;
+			interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 71>, <&pmc PMC_TYPE_GCK 71>;
+			clock-names = "pclk", "gclk";
+		};
+
+		ssc0: sound@e180c000 {
+			compatible = "atmel,at91sam9g45-ssc";
+			reg = <0xe180c000 0x1000>;
+			#sound-dai-cells = <0>;
+			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(44)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(45)>;
+			dma-names = "rx", "tx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 86>;
+			clock-names = "pclk";
+			sound-name-prefix = "SSC0";
+			status = "disabled";
+		};
+
+		aes: crypto@e1810000 {
+			compatible = "atmel,at91sam9g46-aes";
+			reg = <0xe1810000 0x100>;
+			interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 27>;
+			clock-names = "aes_clk";
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(1)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(2)>;
+			dma-names = "tx", "rx";
+			status = "okay";
+		};
+
+		sha: crypto@e1814000 {
+			compatible = "atmel,at91sam9g46-sha";
+			reg = <0xe1814000 0x100>;
+			interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 83>;
+			clock-names = "sha_clk";
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(48)>;
+			dma-names = "tx";
+			status = "okay";
+		};
+
+		flx0: flexcom@e1818000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe1818000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 38>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe1818000 0x800>;
+			status = "disabled";
+
+			uart0: serial@200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0x200 0x200>;
+				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 38>;
+				clock-names = "usart";
+				dmas = <&dma1 AT91_XDMAC_DT_PERID(6)>,
+					<&dma1 AT91_XDMAC_DT_PERID(5)>;
+				dma-names = "tx", "rx";
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+
+		flx1: flexcom@e181c000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe181c000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 39>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe181c000 0x800>;
+			status = "disabled";
+
+			i2c1: i2c@600 {
+				compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+				reg = <0x600 0x200>;
+				interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 39>;
+				atmel,fifo-size = <32>;
+				dmas = <&dma0 AT91_XDMAC_DT_PERID(8)>,
+					<&dma0 AT91_XDMAC_DT_PERID(7)>;
+				dma-names = "tx", "rx";
+				status = "disabled";
+			};
+		};
+
+		flx3: flexcom@e1824000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe1824000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 41>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe1824000 0x800>;
+			status = "disabled";
+
+			uart3: serial@200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0x200 0x200>;
+				interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 41>;
+				clock-names = "usart";
+				dmas = <&dma1 AT91_XDMAC_DT_PERID(12)>,
+					<&dma1 AT91_XDMAC_DT_PERID(11)>;
+				dma-names = "tx", "rx";
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				status = "disabled";
+			};
+		};
+
+		ssc1: sound@e200c000 {
+			compatible = "atmel,at91sam9g45-ssc";
+			reg = <0xe200c000 0x1000>;
+			#sound-dai-cells = <0>;
+			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(46)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(47)>;
+			dma-names = "rx", "tx";
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 87>;
+			clock-names = "pclk";
+			sound-name-prefix = "SSC1";
+			status = "disabled";
+		};
+
+		trng: rng@e2010000 {
+			compatible = "microchip,sama7g5-trng", "atmel,at91sam9g45-trng";
+			reg = <0xe2010000 0x100>;
+			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 97>;
+			status = "disabled";
+			secure-status = "okay";
+		};
+
+		tdes: crypto@e2014000 {
+			compatible = "atmel,at91sam9g46-tdes";
+			reg = <0xe2014000 0x100>;
+			interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 96>;
+			clock-names = "tdes_clk";
+			dmas = <&dma0 AT91_XDMAC_DT_PERID(54)>,
+			       <&dma0 AT91_XDMAC_DT_PERID(53)>;
+			dma-names = "tx", "rx";
+			status = "okay";
+		};
+
+		flx4: flexcom@e2018000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe2018000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 42>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe2018000 0x800>;
+			status = "disabled";
+
+			uart4: serial@200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0x200 0x200>;
+				interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 42>;
+				clock-names = "usart";
+				dmas = <&dma1 AT91_XDMAC_DT_PERID(14)>,
+					<&dma1 AT91_XDMAC_DT_PERID(13)>;
+				dma-names = "tx", "rx";
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				atmel,fifo-size = <16>;
+				status = "disabled";
+			};
+		};
+
+		flx7: flexcom@e2024000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe2024000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 45>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe2024000 0x800>;
+			status = "disabled";
+
+			uart7: serial@200 {
+				compatible = "atmel,at91sam9260-usart";
+				reg = <0x200 0x200>;
+				interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 45>;
+				clock-names = "usart";
+				dmas = <&dma1 AT91_XDMAC_DT_PERID(20)>,
+					<&dma1 AT91_XDMAC_DT_PERID(19)>;
+				dma-names = "tx", "rx";
+				atmel,use-dma-rx;
+				atmel,use-dma-tx;
+				atmel,fifo-size = <16>;
+				status = "disabled";
+			};
+		};
+
+		gmac0: ethernet@e2800000 {
+			compatible = "microchip,sama7g5-gem";
+			reg = <0xe2800000 0x1000>;
+			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_PERIPHERAL 51>, <&pmc PMC_TYPE_GCK 51>, <&pmc PMC_TYPE_GCK 53>;
+			clock-names = "pclk", "hclk", "tx_clk", "tsu_clk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 51>;
+			assigned-clock-rates = <125000000>;
+			assigned-clock-parents = <&pmc PMC_TYPE_CORE PMC_ETHPLL>;
+			status = "disabled";
+		};
+
+		gmac1: ethernet@e2804000 {
+			compatible = "microchip,sama7g5-emac";
+			reg = <0xe2804000 0x1000>;
+			interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH
+				      GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_PERIPHERAL 52>, <&pmc PMC_TYPE_GCK 54>;
+			clock-names = "pclk", "hclk", "tsu_clk";
+			assigned-clocks = <&pmc PMC_TYPE_GCK 54>;
+			assigned-clock-rates = <200000000>;
+			status = "disabled";
+		};
+
+		dma0: dma-controller@e2808000 {
+			compatible = "microchip,sama7g5-dma";
+			reg = <0xe2808000 0x1000>;
+			interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 22>;
+			clock-names = "dma_clk";
+			status = "disabled";
+		};
+
+		dma1: dma-controller@e280c000 {
+			compatible = "microchip,sama7g5-dma";
+			reg = <0xe280c000 0x1000>;
+			interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 23>;
+			clock-names = "dma_clk";
+			status = "disabled";
+		};
+
+		/* Place dma2 here despite it's address */
+		dma2: dma-controller@e1200000 {
+			compatible = "microchip,sama7g5-dma";
+			reg = <0xe1200000 0x1000>;
+			interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+			#dma-cells = <1>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 24>;
+			clock-names = "dma_clk";
+			dma-requests = <0>;
+			status = "disabled";
+		};
+
+		tcb0: timer@e2814000 {
+			compatible = "atmel,sama5d2-tcb", "simple-mfd", "syscon";
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0xe2814000 0x100>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 88>, <&pmc PMC_TYPE_PERIPHERAL 89>, <&pmc PMC_TYPE_PERIPHERAL 90>, <&clk32k 1>;
+			clock-names = "t0_clk", "t1_clk", "t2_clk", "slow_clk";
+		};
+
+		flx8: flexcom@e2818000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe2818000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 46>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe2818000 0x800>;
+			status = "disabled";
+
+			i2c8: i2c@600 {
+				compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+				reg = <0x600 0x200>;
+				interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 46>;
+				atmel,fifo-size = <32>;
+				dmas = <&dma0 AT91_XDMAC_DT_PERID(22)>,
+					<&dma0 AT91_XDMAC_DT_PERID(21)>;
+				dma-names = "tx", "rx";
+				status = "disabled";
+			};
+		};
+
+		flx9: flexcom@e281c000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe281c000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe281c000 0x800>;
+			status = "disabled";
+
+			i2c9: i2c@600 {
+				compatible = "microchip,sama7g5-i2c", "microchip,sam9x60-i2c";
+				reg = <0x600 0x200>;
+				interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 47>;
+				atmel,fifo-size = <32>;
+				dmas = <&dma0 AT91_XDMAC_DT_PERID(24)>,
+					<&dma0 AT91_XDMAC_DT_PERID(23)>;
+				dma-names = "tx", "rx";
+				status = "disabled";
+			};
+		};
+
+		flx11: flexcom@e2824000 {
+			compatible = "atmel,sama5d2-flexcom";
+			reg = <0xe2824000 0x200>;
+			clocks = <&pmc PMC_TYPE_PERIPHERAL 49>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0x0 0xe2824000 0x800>;
+			status = "disabled";
+
+			spi11: spi@400 {
+				compatible = "atmel,at91rm9200-spi";
+				reg = <0x400 0x200>;
+				interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&pmc PMC_TYPE_PERIPHERAL 49>;
+				clock-names = "spi_clk";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				atmel,fifo-size = <32>;
+				dmas = <&dma0 AT91_XDMAC_DT_PERID(28)>,
+					    <&dma0 AT91_XDMAC_DT_PERID(27)>;
+				dma-names = "tx", "rx";
+				status = "disabled";
+			};
+		};
+
+		uddrc: uddrc@e3800000 {
+			compatible = "microchip,sama7g5-uddrc";
+			reg = <0xe3800000 0x4000>;
+		};
+
+		ddr3phy: ddr3phy@e3804000 {
+			compatible = "microchip,sama7g5-ddr3phy";
+			reg = <0xe3804000 0x1000>;
+		};
+
+		otpc: efuse@e8c00000 {
+			compatible = "microchip,sama7g5-otpc", "syscon";
+			reg = <0xe8c00000 0x100>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			temperature_calib: calib@1 {
+				status = "disabled";
+			};
+		};
+
+		gic: interrupt-controller@e8c11000 {
+			compatible = "arm,cortex-a7-gic";
+			#interrupt-cells = <3>;
+			#address-cells = <0>;
+			interrupt-controller;
+			reg = <0xe8c11000 0x1000>,
+				<0xe8c12000 0x2000>;
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp13-pinctrl.dtsi b/core/arch/arm/dts/stm32mp13-pinctrl.dtsi
index 6bf84198769eb816d256916bb37b43a41a95abff..fc7289df298a4e61c7a8ab15ab5125df66d5fade 100644
--- a/core/arch/arm/dts/stm32mp13-pinctrl.dtsi
+++ b/core/arch/arm/dts/stm32mp13-pinctrl.dtsi
@@ -27,13 +27,13 @@
 
 	uart4_pins_a: uart4-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('D', 6, AF8)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX_NSEC('D', 6, AF8)>; /* UART4_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 8, AF8)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('D', 8, AF8)>; /* UART4_RX */
 			bias-disable;
 		};
 	};
diff --git a/core/arch/arm/dts/stm32mp131.dtsi b/core/arch/arm/dts/stm32mp131.dtsi
index 3ddfaab8ce23365b2dd7779c4e43b44d7cb63f2c..3077249375cf20b2a63c1f49ae05608303772515 100644
--- a/core/arch/arm/dts/stm32mp131.dtsi
+++ b/core/arch/arm/dts/stm32mp131.dtsi
@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
 #include <dt-bindings/clock/stm32mp13-clks.h>
 #include <dt-bindings/clock/stm32mp13-clksrc.h>
+#include <dt-bindings/firewall/stm32mp13-etzpc.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/regulator/st,stm32mp13-regulator.h>
 #include <dt-bindings/reset/stm32mp13-resets.h>
@@ -276,6 +277,7 @@
 			reg = <0x5c00a000 0x400>;
 			interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
 			clocks = <&rcc RTCAPB>;
+			st,backup-zones = <10 5 17>;
 		};
 
 		pinctrl: pin-controller@50002000 {
@@ -290,6 +292,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOA>;
 				reg = <0x0 0x400>;
 				st,bank-name = "GPIOA";
@@ -302,6 +305,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOB>;
 				reg = <0x1000 0x400>;
 				st,bank-name = "GPIOB";
@@ -314,6 +318,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOC>;
 				reg = <0x2000 0x400>;
 				st,bank-name = "GPIOC";
@@ -326,6 +331,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOD>;
 				reg = <0x3000 0x400>;
 				st,bank-name = "GPIOD";
@@ -338,6 +344,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOE>;
 				reg = <0x4000 0x400>;
 				st,bank-name = "GPIOE";
@@ -350,6 +357,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOF>;
 				reg = <0x5000 0x400>;
 				st,bank-name = "GPIOF";
@@ -362,6 +370,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOG>;
 				reg = <0x6000 0x400>;
 				st,bank-name = "GPIOG";
@@ -374,6 +383,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOH>;
 				reg = <0x7000 0x400>;
 				st,bank-name = "GPIOH";
@@ -386,6 +396,7 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				clocks = <&rcc GPIOI>;
 				reg = <0x8000 0x400>;
 				st,bank-name = "GPIOI";
@@ -395,11 +406,12 @@
 		};
 
 		etzpc: etzpc@5c007000 {
-			compatible = "st,stm32-etzpc", "firewall-bus";
+			compatible = "st,stm32-etzpc", "simple-bus";
 			reg = <0x5C007000 0x400>;
 			clocks = <&rcc TZPC>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#access-controller-cells = <1>;
 
 			adc_2: adc@48004000 {
 				reg = <0x48004000 0x400>;
@@ -411,6 +423,7 @@
 				#interrupt-cells = <1>;
 				#address-cells = <1>;
 				#size-cells = <0>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_ADC2_ID>;
 				status = "disabled";
 
 				adc2: adc@0 {
@@ -451,6 +464,7 @@
 				interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc USART1_K>;
 				resets = <&rcc USART1_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART1_ID>;
 				status = "disabled";
 			};
 
@@ -460,6 +474,7 @@
 				interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc USART2_K>;
 				resets = <&rcc USART2_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART2_ID>;
 				status = "disabled";
 			};
 
@@ -472,6 +487,7 @@
 				#size-cells = <0>;
 				st,syscfg-fmp = <&syscfg 0x4 0x4>;
 				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C3_ID>;
 				status = "disabled";
 			};
 
@@ -484,6 +500,7 @@
 				#size-cells = <0>;
 				st,syscfg-fmp = <&syscfg 0x4 0x8>;
 				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C4_ID>;
 				status = "disabled";
 			};
 
@@ -496,6 +513,7 @@
 				#size-cells = <0>;
 				st,syscfg-fmp = <&syscfg 0x4 0x10>;
 				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C5_ID>;
 				status = "disabled";
 			};
 
@@ -507,6 +525,8 @@
 				interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc TIM12_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM12_ID>;
+				status = "disabled";
 
 				counter {
 					compatible = "st,stm32-timer-counter";
@@ -521,6 +541,7 @@
 				reg = <0x4c008000 0x400>;
 				clocks = <&rcc TIM13_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM13_ID>;
 				status = "disabled";
 			};
 
@@ -531,6 +552,7 @@
 				reg = <0x4c009000 0x400>;
 				clocks = <&rcc TIM14_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM14_ID>;
 				status = "disabled";
 			};
 
@@ -542,6 +564,7 @@
 				interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc TIM15_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM15_ID>;
 				status = "disabled";
 
 				counter {
@@ -557,8 +580,8 @@
 				reg = <0x4c00b000 0x400>;
 				clocks = <&rcc TIM16_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM16_ID>;
 				status = "disabled";
-
 			};
 
 			timers17: timer@4c00c000 {
@@ -568,6 +591,7 @@
 				reg = <0x4c00c000 0x400>;
 				clocks = <&rcc TIM17_K>;
 				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM17_ID>;
 				status = "disabled";
 			};
 
@@ -579,6 +603,7 @@
 				interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc LPTIM2_K>;
 				clock-names = "mux";
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM2_ID>;
 				status = "disabled";
 			};
 
@@ -590,6 +615,7 @@
 				interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc LPTIM3_K>;
 				clock-names = "mux";
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM3_ID>;
 				status = "disabled";
 
 				counter {
@@ -605,6 +631,7 @@
 				regulator-min-microvolt = <1650000>;
 				regulator-max-microvolt = <2500000>;
 				clocks = <&rcc VREF>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_VREFBUF_ID>;
 				status = "disabled";
 			};
 
@@ -614,6 +641,7 @@
 				interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc HASH1>;
 				resets = <&rcc HASH1_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_HASH_ID>;
 				status = "disabled";
 			};
 
@@ -622,6 +650,7 @@
 				reg = <0x54004000 0x400>;
 				clocks = <&rcc RNG1_K>;
 				resets = <&rcc RNG1_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_RNG_ID>;
 				status = "disabled";
 			};
 
@@ -631,12 +660,14 @@
 				interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
 				clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
 				clock-names = "pclk", "lsi";
+				access-controllers = <&etzpc STM32MP1_ETZPC_IWDG1_ID>;
 				status = "disabled";
 			};
 
 			stgen: stgen@5c008000 {
 				compatible = "st,stm32-stgen";
 				reg = <0x5C008000 0x1000>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_STGENC_ID>;
 			};
 		};
 	};
diff --git a/core/arch/arm/dts/stm32mp135.dtsi b/core/arch/arm/dts/stm32mp135.dtsi
index 1e790f9df1b792466bc1161aa4f670cae6f2ed1a..ca795da52aa2260219c34b13d97ac679beccb05b 100644
--- a/core/arch/arm/dts/stm32mp135.dtsi
+++ b/core/arch/arm/dts/stm32mp135.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
@@ -17,6 +17,7 @@
 				clocks = <&rcc LTDC_PX>;
 				clock-names = "lcd";
 				resets = <&rcc LTDC_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LTDC_ID>;
 				status = "disabled";
 			};
 		};
diff --git a/core/arch/arm/dts/stm32mp135f-dk.dts b/core/arch/arm/dts/stm32mp135f-dk.dts
index 7357601bac99d47039438ab454f13ab51e15c28f..5a47916a6c0da7dedd48bf80bc824c42a47c7ed1 100644
--- a/core/arch/arm/dts/stm32mp135f-dk.dts
+++ b/core/arch/arm/dts/stm32mp135f-dk.dts
@@ -1,12 +1,13 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2023 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
 /dts-v1/;
 
 #include <dt-bindings/clock/stm32mp13-clksrc.h>
+#include <dt-bindings/firewall/stm32mp13-tzc400.h>
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/gpio/stm32mp_gpio.h>
 #include <dt-bindings/regulator/st,stm32mp13-regulator.h>
@@ -40,6 +41,7 @@
 		optee_framebuffer: optee-framebuffer@dd000000 {
 			/* Secure framebuffer memory */
 			reg = <0xdd000000 0x1000000>;
+			st,protreg = <DT_TZC_REGION_S_RDWR 0>;
 			no-map;
 		};
 	};
@@ -61,21 +63,6 @@
 	};
 };
 
-&adc_2 {
-	vdda-supply = <&vdd_adc>;
-	vref-supply = <&vdd_adc>;
-	status = "okay";
-
-	adc2: adc@0 {
-		status = "okay";
-
-		channel@15 {
-			reg = <15>;
-			label = "vbat";
-		};
-	};
-};
-
 &bsec {
 	board_id: board_id@f0 {
 		reg = <0xf0 0x4>;
@@ -83,6 +70,51 @@
 	};
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_ADC1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_ADC2_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DCMIPP_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRLPHY_ID, DECPROT_NS_R_S_W, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_ETH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_ETH2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_FMC_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C3_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C5_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_LPTIM2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_LPTIM3_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_LTDC_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_MCE_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_OTG_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_PKA_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_QSPI_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SAES_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SDMMC1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SDMMC2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI5_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SRAM1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SRAM2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SRAM3_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM12_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM13_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM14_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM15_ID, DECPROT_S_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM16_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_TIM17_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_USART2_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_USBPHYCTRL_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_VREFBUF_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>;
+};
+
 &gpiob {
 	st,protreg = <TZPROT(9)>;
 };
@@ -467,6 +499,10 @@
 	vddsd2-supply = <&vdd>;
 };
 
+&tzc400 {
+	memory-region = <&optee_framebuffer>;
+};
+
 &uart4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart4_pins_a>;
diff --git a/core/arch/arm/dts/stm32mp13xc.dtsi b/core/arch/arm/dts/stm32mp13xc.dtsi
index 4527f1105efa99172f1d29b7ec8529b3fba6c0c7..b073f8442dc56c01add6e01a4c3c9b615ce26e64 100644
--- a/core/arch/arm/dts/stm32mp13xc.dtsi
+++ b/core/arch/arm/dts/stm32mp13xc.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
@@ -11,6 +11,7 @@
 		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&rcc CRYP1>;
 		resets = <&rcc CRYP1_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_CRYP_ID>;
 		status = "disabled";
 	};
 
@@ -18,8 +19,10 @@
 		compatible = "st,stm32mp13-saes";
 		reg = <0x54005000 0x400>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&rcc SAES_K>;
+		clocks = <&rcc SAES_K>, <&rcc RNG1_K>;
+		clock-names = "bus", "rng";
 		resets = <&rcc SAES_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_SAES_ID>;
 		status = "disabled";
 	};
 
@@ -29,6 +32,7 @@
 		interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&rcc PKA>;
 		resets = <&rcc PKA_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_PKA_ID>;
 		status = "disabled";
 	};
 };
diff --git a/core/arch/arm/dts/stm32mp13xf.dtsi b/core/arch/arm/dts/stm32mp13xf.dtsi
index 4527f1105efa99172f1d29b7ec8529b3fba6c0c7..b073f8442dc56c01add6e01a4c3c9b615ce26e64 100644
--- a/core/arch/arm/dts/stm32mp13xf.dtsi
+++ b/core/arch/arm/dts/stm32mp13xf.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2021-2022 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2021-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
@@ -11,6 +11,7 @@
 		interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&rcc CRYP1>;
 		resets = <&rcc CRYP1_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_CRYP_ID>;
 		status = "disabled";
 	};
 
@@ -18,8 +19,10 @@
 		compatible = "st,stm32mp13-saes";
 		reg = <0x54005000 0x400>;
 		interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
-		clocks = <&rcc SAES_K>;
+		clocks = <&rcc SAES_K>, <&rcc RNG1_K>;
+		clock-names = "bus", "rng";
 		resets = <&rcc SAES_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_SAES_ID>;
 		status = "disabled";
 	};
 
@@ -29,6 +32,7 @@
 		interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
 		clocks = <&rcc PKA>;
 		resets = <&rcc PKA_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_PKA_ID>;
 		status = "disabled";
 	};
 };
diff --git a/core/arch/arm/dts/stm32mp15-pinctrl.dtsi b/core/arch/arm/dts/stm32mp15-pinctrl.dtsi
index 7edff9ca8199e051a67672b5cfa54366ba18a6a3..7806110a4c3a5fc5706659519c8b3540453e64f8 100644
--- a/core/arch/arm/dts/stm32mp15-pinctrl.dtsi
+++ b/core/arch/arm/dts/stm32mp15-pinctrl.dtsi
@@ -1830,356 +1830,356 @@
 
 	uart4_pins_a: uart4-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX_NSEC('G', 11, AF6)>; /* UART4_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 2, AF8)>; /* UART4_RX */
 			bias-disable;
 		};
 	};
 
 	uart4_idle_pins_a: uart4-idle-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('G', 11, ANALOG)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX_NSEC('G', 11, ANALOG)>; /* UART4_TX */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 2, AF8)>; /* UART4_RX */
 			bias-disable;
 		};
 	};
 
 	uart4_sleep_pins_a: uart4-sleep-0 {
 		pins {
-			pinmux = <STM32_PINMUX('G', 11, ANALOG)>, /* UART4_TX */
-				 <STM32_PINMUX('B', 2, ANALOG)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('G', 11, ANALOG)>, /* UART4_TX */
+				 <STM32_PINMUX_NSEC('B', 2, ANALOG)>; /* UART4_RX */
 		};
 	};
 
 	uart4_pins_b: uart4-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('D', 1, AF8)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX_NSEC('D', 1, AF8)>; /* UART4_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 2, AF8)>; /* UART4_RX */
 			bias-disable;
 		};
 	};
 
 	uart4_pins_c: uart4-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+			pinmux = <STM32_PINMUX_NSEC('G', 11, AF6)>; /* UART4_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 2, AF8)>; /* UART4_RX */
 			bias-disable;
 		};
 	};
 
 	uart7_pins_a: uart7-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_TX */
+			pinmux = <STM32_PINMUX_NSEC('E', 8, AF7)>; /* UART7_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('E', 7, AF7)>, /* UART7_RX */
-				 <STM32_PINMUX('E', 10, AF7)>, /* UART7_CTS */
-				 <STM32_PINMUX('E', 9, AF7)>; /* UART7_RTS */
+			pinmux = <STM32_PINMUX_NSEC('E', 7, AF7)>, /* UART7_RX */
+				 <STM32_PINMUX_NSEC('E', 10, AF7)>, /* UART7_CTS */
+				 <STM32_PINMUX_NSEC('E', 9, AF7)>; /* UART7_RTS */
 			bias-disable;
 		};
 	};
 
 	uart7_pins_b: uart7-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('F', 7, AF7)>; /* UART7_TX */
+			pinmux = <STM32_PINMUX_NSEC('F', 7, AF7)>; /* UART7_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('F', 6, AF7)>; /* UART7_RX */
+			pinmux = <STM32_PINMUX_NSEC('F', 6, AF7)>; /* UART7_RX */
 			bias-disable;
 		};
 	};
 
 	uart7_pins_c: uart7-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 8, AF7)>; /* UART7_TX */
+			pinmux = <STM32_PINMUX_NSEC('E', 8, AF7)>; /* UART7_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* UART7_RX */
+			pinmux = <STM32_PINMUX_NSEC('E', 7, AF7)>; /* UART7_RX */
 			bias-pull-up;
 		};
 	};
 
 	uart7_idle_pins_c: uart7-idle-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 8, ANALOG)>; /* UART7_TX */
+			pinmux = <STM32_PINMUX_NSEC('E', 8, ANALOG)>; /* UART7_TX */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('E', 7, AF7)>; /* UART7_RX */
+			pinmux = <STM32_PINMUX_NSEC('E', 7, AF7)>; /* UART7_RX */
 			bias-pull-up;
 		};
 	};
 
 	uart7_sleep_pins_c: uart7-sleep-2 {
 		pins {
-			pinmux = <STM32_PINMUX('E', 8, ANALOG)>, /* UART7_TX */
-				 <STM32_PINMUX('E', 7, ANALOG)>; /* UART7_RX */
+			pinmux = <STM32_PINMUX_NSEC('E', 8, ANALOG)>, /* UART7_TX */
+				 <STM32_PINMUX_NSEC('E', 7, ANALOG)>; /* UART7_RX */
 		};
 	};
 
 	uart8_pins_a: uart8-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('E', 1, AF8)>; /* UART8_TX */
+			pinmux = <STM32_PINMUX_NSEC('E', 1, AF8)>; /* UART8_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('E', 0, AF8)>; /* UART8_RX */
+			pinmux = <STM32_PINMUX_NSEC('E', 0, AF8)>; /* UART8_RX */
 			bias-disable;
 		};
 	};
 
 	uart8_rtscts_pins_a: uart8rtscts-0 {
 		pins {
-			pinmux = <STM32_PINMUX('G', 7, AF8)>, /* UART8_RTS */
-				 <STM32_PINMUX('G', 10, AF8)>; /* UART8_CTS */
+			pinmux = <STM32_PINMUX_NSEC('G', 7, AF8)>, /* UART8_RTS */
+				 <STM32_PINMUX_NSEC('G', 10, AF8)>; /* UART8_CTS */
 			bias-disable;
 		};
 	};
 
 	usart2_pins_a: usart2-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
-				 <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
+			pinmux = <STM32_PINMUX_NSEC('F', 5, AF7)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('D', 4, AF7)>; /* USART2_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 6, AF7)>, /* USART2_RX */
-				 <STM32_PINMUX('D', 3, AF7)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('D', 6, AF7)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('D', 3, AF7)>; /* USART2_CTS_NSS */
 			bias-disable;
 		};
 	};
 
 	usart2_sleep_pins_a: usart2-sleep-0 {
 		pins {
-			pinmux = <STM32_PINMUX('F', 5, ANALOG)>, /* USART2_TX */
-				 <STM32_PINMUX('D', 4, ANALOG)>, /* USART2_RTS */
-				 <STM32_PINMUX('D', 6, ANALOG)>, /* USART2_RX */
-				 <STM32_PINMUX('D', 3, ANALOG)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('F', 5, ANALOG)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('D', 4, ANALOG)>, /* USART2_RTS */
+				 <STM32_PINMUX_NSEC('D', 6, ANALOG)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('D', 3, ANALOG)>; /* USART2_CTS_NSS */
 		};
 	};
 
 	usart2_pins_b: usart2-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('F', 5, AF7)>, /* USART2_TX */
-				 <STM32_PINMUX('A', 1, AF7)>; /* USART2_RTS */
+			pinmux = <STM32_PINMUX_NSEC('F', 5, AF7)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('A', 1, AF7)>; /* USART2_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('F', 4, AF7)>, /* USART2_RX */
-				 <STM32_PINMUX('E', 15, AF7)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('F', 4, AF7)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('E', 15, AF7)>; /* USART2_CTS_NSS */
 			bias-disable;
 		};
 	};
 
 	usart2_sleep_pins_b: usart2-sleep-1 {
 		pins {
-			pinmux = <STM32_PINMUX('F', 5, ANALOG)>, /* USART2_TX */
-				 <STM32_PINMUX('A', 1, ANALOG)>, /* USART2_RTS */
-				 <STM32_PINMUX('F', 4, ANALOG)>, /* USART2_RX */
-				 <STM32_PINMUX('E', 15, ANALOG)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('F', 5, ANALOG)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('A', 1, ANALOG)>, /* USART2_RTS */
+				 <STM32_PINMUX_NSEC('F', 4, ANALOG)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('E', 15, ANALOG)>; /* USART2_CTS_NSS */
 		};
 	};
 
 	usart2_pins_c: usart2-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('D', 5, AF7)>, /* USART2_TX */
-				 <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
+			pinmux = <STM32_PINMUX_NSEC('D', 5, AF7)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('D', 4, AF7)>; /* USART2_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 6, AF7)>, /* USART2_RX */
-				 <STM32_PINMUX('D', 3, AF7)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('D', 6, AF7)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('D', 3, AF7)>; /* USART2_CTS_NSS */
 			bias-disable;
 		};
 	};
 
 	usart2_idle_pins_c: usart2-idle-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('D', 5, ANALOG)>, /* USART2_TX */
-				 <STM32_PINMUX('D', 3, ANALOG)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('D', 5, ANALOG)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('D', 3, ANALOG)>; /* USART2_CTS_NSS */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 4, AF7)>; /* USART2_RTS */
+			pinmux = <STM32_PINMUX_NSEC('D', 4, AF7)>; /* USART2_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins3 {
-			pinmux = <STM32_PINMUX('D', 6, AF7)>; /* USART2_RX */
+			pinmux = <STM32_PINMUX_NSEC('D', 6, AF7)>; /* USART2_RX */
 			bias-disable;
 		};
 	};
 
 	usart2_sleep_pins_c: usart2-sleep-2 {
 		pins {
-			pinmux = <STM32_PINMUX('D', 5, ANALOG)>, /* USART2_TX */
-				 <STM32_PINMUX('D', 4, ANALOG)>, /* USART2_RTS */
-				 <STM32_PINMUX('D', 6, ANALOG)>, /* USART2_RX */
-				 <STM32_PINMUX('D', 3, ANALOG)>; /* USART2_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('D', 5, ANALOG)>, /* USART2_TX */
+				 <STM32_PINMUX_NSEC('D', 4, ANALOG)>, /* USART2_RTS */
+				 <STM32_PINMUX_NSEC('D', 6, ANALOG)>, /* USART2_RX */
+				 <STM32_PINMUX_NSEC('D', 3, ANALOG)>; /* USART2_CTS_NSS */
 		};
 	};
 
 	usart3_pins_a: usart3-0 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, AF7)>; /* USART3_TX */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, AF7)>; /* USART3_TX */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 12, AF8)>; /* USART3_RX */
 			bias-disable;
 		};
 	};
 
 	usart3_pins_b: usart3-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, AF7)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, AF8)>; /* USART3_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
-				 <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('B', 12, AF8)>, /* USART3_RX */
+				 <STM32_PINMUX_NSEC('I', 10, AF8)>; /* USART3_CTS_NSS */
 			bias-pull-up;
 		};
 	};
 
 	usart3_idle_pins_b: usart3-idle-1 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('I', 10, ANALOG)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('I', 10, ANALOG)>; /* USART3_CTS_NSS */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX_NSEC('G', 8, AF8)>; /* USART3_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins3 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 12, AF8)>; /* USART3_RX */
 			bias-pull-up;
 		};
 	};
 
 	usart3_sleep_pins_b: usart3-sleep-1 {
 		pins {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, ANALOG)>, /* USART3_RTS */
-				 <STM32_PINMUX('I', 10, ANALOG)>, /* USART3_CTS_NSS */
-				 <STM32_PINMUX('B', 12, ANALOG)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, ANALOG)>, /* USART3_RTS */
+				 <STM32_PINMUX_NSEC('I', 10, ANALOG)>, /* USART3_CTS_NSS */
+				 <STM32_PINMUX_NSEC('B', 12, ANALOG)>; /* USART3_RX */
 		};
 	};
 
 	usart3_pins_c: usart3-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, AF7)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, AF8)>; /* USART3_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
-				 <STM32_PINMUX('B', 13, AF7)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('B', 12, AF8)>, /* USART3_RX */
+				 <STM32_PINMUX_NSEC('B', 13, AF7)>; /* USART3_CTS_NSS */
 			bias-pull-up;
 		};
 	};
 
 	usart3_idle_pins_c: usart3-idle-2 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('B', 13, ANALOG)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('B', 13, ANALOG)>; /* USART3_CTS_NSS */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX_NSEC('G', 8, AF8)>; /* USART3_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins3 {
-			pinmux = <STM32_PINMUX('B', 12, AF8)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 12, AF8)>; /* USART3_RX */
 			bias-pull-up;
 		};
 	};
 
 	usart3_sleep_pins_c: usart3-sleep-2 {
 		pins {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, ANALOG)>, /* USART3_RTS */
-				 <STM32_PINMUX('B', 13, ANALOG)>, /* USART3_CTS_NSS */
-				 <STM32_PINMUX('B', 12, ANALOG)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, ANALOG)>, /* USART3_RTS */
+				 <STM32_PINMUX_NSEC('B', 13, ANALOG)>, /* USART3_CTS_NSS */
+				 <STM32_PINMUX_NSEC('B', 12, ANALOG)>; /* USART3_RX */
 		};
 	};
 
 	usart3_pins_d: usart3-3 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, AF7)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, AF8)>; /* USART3_RTS */
 			bias-disable;
 			drive-push-pull;
 			slew-rate = <0>;
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 9, AF7)>, /* USART3_RX */
-				 <STM32_PINMUX('D', 11, AF7)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('D', 9, AF7)>, /* USART3_RX */
+				 <STM32_PINMUX_NSEC('D', 11, AF7)>; /* USART3_CTS_NSS */
 			bias-disable;
 		};
 	};
 
 	usart3_idle_pins_d: usart3-idle-3 {
 		pins1 {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, ANALOG)>, /* USART3_RTS */
-				 <STM32_PINMUX('D', 11, ANALOG)>; /* USART3_CTS_NSS */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, ANALOG)>, /* USART3_RTS */
+				 <STM32_PINMUX_NSEC('D', 11, ANALOG)>; /* USART3_CTS_NSS */
 		};
 		pins2 {
-			pinmux = <STM32_PINMUX('D', 9, AF7)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('D', 9, AF7)>; /* USART3_RX */
 			bias-disable;
 		};
 	};
 
 	usart3_sleep_pins_d: usart3-sleep-3 {
 		pins {
-			pinmux = <STM32_PINMUX('B', 10, ANALOG)>, /* USART3_TX */
-				 <STM32_PINMUX('G', 8, ANALOG)>, /* USART3_RTS */
-				 <STM32_PINMUX('D', 11, ANALOG)>, /* USART3_CTS_NSS */
-				 <STM32_PINMUX('D', 9, ANALOG)>; /* USART3_RX */
+			pinmux = <STM32_PINMUX_NSEC('B', 10, ANALOG)>, /* USART3_TX */
+				 <STM32_PINMUX_NSEC('G', 8, ANALOG)>, /* USART3_RTS */
+				 <STM32_PINMUX_NSEC('D', 11, ANALOG)>, /* USART3_CTS_NSS */
+				 <STM32_PINMUX_NSEC('D', 9, ANALOG)>; /* USART3_RX */
 		};
 	};
 
@@ -2214,6 +2214,23 @@
 	};
 
 	i2c4_pins_a: i2c4-0 {
+		pins {
+			pinmux = <STM32_PINMUX_NSEC('Z', 4, AF6)>, /* I2C4_SCL */
+				 <STM32_PINMUX_NSEC('Z', 5, AF6)>; /* I2C4_SDA */
+			bias-disable;
+			drive-open-drain;
+			slew-rate = <0>;
+		};
+	};
+
+	i2c4_sleep_pins_a: i2c4-sleep-0 {
+		pins {
+			pinmux = <STM32_PINMUX_NSEC('Z', 4, ANALOG)>, /* I2C4_SCL */
+				 <STM32_PINMUX_NSEC('Z', 5, ANALOG)>; /* I2C4_SDA */
+		};
+	};
+
+	i2c4_secure_pins_a: i2c4-sec-0 {
 		pins {
 			pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
 				 <STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
@@ -2223,7 +2240,7 @@
 		};
 	};
 
-	i2c4_sleep_pins_a: i2c4-sleep-0 {
+	i2c4_secure_sleep_pins_a: i2c4-sec-sleep-0 {
 		pins {
 			pinmux = <STM32_PINMUX('Z', 4, ANALOG)>, /* I2C4_SCL */
 				 <STM32_PINMUX('Z', 5, ANALOG)>; /* I2C4_SDA */
diff --git a/core/arch/arm/dts/stm32mp151.dtsi b/core/arch/arm/dts/stm32mp151.dtsi
index d6729c8c1fd1e237e7269c0ed8f2f63260b60799..ea0a1c6c19887dfea9c24c348a046ac51337c466 100644
--- a/core/arch/arm/dts/stm32mp151.dtsi
+++ b/core/arch/arm/dts/stm32mp151.dtsi
@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2017-2024 - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/stm32mp1-clks.h>
 #include <dt-bindings/reset/stm32mp1-resets.h>
+#include <dt-bindings/firewall/stm32mp15-etzpc.h>
 
 / {
 	#address-cells = <1>;
@@ -122,1704 +123,1782 @@
 		interrupt-parent = <&intc>;
 		ranges;
 
-		timers2: timer@40000000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40000000 0x400>;
-			clocks = <&rcc TIM2_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 18 0x400 0x1>,
-			       <&dmamux1 19 0x400 0x1>,
-			       <&dmamux1 20 0x400 0x1>,
-			       <&dmamux1 21 0x400 0x1>,
-			       <&dmamux1 22 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4", "up";
+		ipcc: mailbox@4c001000 {
+			compatible = "st,stm32mp1-ipcc";
+			#mbox-cells = <1>;
+			reg = <0x4c001000 0x400>;
+			st,proc-id = <0>;
+			interrupts-extended =
+				<&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+				<&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				<&exti 61 1>;
+			interrupt-names = "rx", "tx", "wakeup";
+			clocks = <&rcc IPCC>;
+			wakeup-source;
 			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@1 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <1>;
-				status = "disabled";
-			};
-
-			counter {
-				compatible = "st,stm32-timer-counter";
-				status = "disabled";
-			};
 		};
 
-		timers3: timer@40001000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40001000 0x400>;
-			clocks = <&rcc TIM3_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 23 0x400 0x1>,
-			       <&dmamux1 24 0x400 0x1>,
-			       <&dmamux1 25 0x400 0x1>,
-			       <&dmamux1 26 0x400 0x1>,
-			       <&dmamux1 27 0x400 0x1>,
-			       <&dmamux1 28 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
-			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@2 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <2>;
-				status = "disabled";
-			};
-
-			counter {
-				compatible = "st,stm32-timer-counter";
-				status = "disabled";
-			};
+		rcc: rcc@50000000 {
+			compatible = "st,stm32mp1-rcc", "syscon";
+			reg = <0x50000000 0x1000>;
+			#clock-cells = <1>;
+			#reset-cells = <1>;
 		};
 
-		timers4: timer@40002000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40002000 0x400>;
-			clocks = <&rcc TIM4_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 29 0x400 0x1>,
-			       <&dmamux1 30 0x400 0x1>,
-			       <&dmamux1 31 0x400 0x1>,
-			       <&dmamux1 32 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4";
-			status = "disabled";
+		pwr_regulators: pwr@50001000 {
+			compatible = "st,stm32mp1,pwr-reg";
+			reg = <0x50001000 0x10>;
 
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
+			reg11: reg11 {
+				regulator-name = "reg11";
+				regulator-min-microvolt = <1100000>;
+				regulator-max-microvolt = <1100000>;
 			};
 
-			timer@3 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <3>;
-				status = "disabled";
+			reg18: reg18 {
+				regulator-name = "reg18";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
 			};
 
-			counter {
-				compatible = "st,stm32-timer-counter";
-				status = "disabled";
+			usb33: usb33 {
+				regulator-name = "usb33";
+				regulator-min-microvolt = <3300000>;
+				regulator-max-microvolt = <3300000>;
 			};
 		};
 
-		timers5: timer@40003000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40003000 0x400>;
-			clocks = <&rcc TIM5_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 55 0x400 0x1>,
-			       <&dmamux1 56 0x400 0x1>,
-			       <&dmamux1 57 0x400 0x1>,
-			       <&dmamux1 58 0x400 0x1>,
-			       <&dmamux1 59 0x400 0x1>,
-			       <&dmamux1 60 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
-			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@4 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <4>;
-				status = "disabled";
-			};
-
-			counter {
-				compatible = "st,stm32-timer-counter";
-				status = "disabled";
-			};
+		pwr_mcu: pwr_mcu@50001014 {
+			compatible = "st,stm32mp151-pwr-mcu", "syscon";
+			reg = <0x50001014 0x4>;
 		};
 
-		timers6: timer@40004000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40004000 0x400>;
-			clocks = <&rcc TIM6_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 69 0x400 0x1>;
-			dma-names = "up";
-			status = "disabled";
-
-			timer@5 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <5>;
-				status = "disabled";
-			};
+		exti: interrupt-controller@5000d000 {
+			compatible = "st,stm32mp1-exti", "syscon";
+			interrupt-controller;
+			#interrupt-cells = <2>;
+			reg = <0x5000d000 0x400>;
 		};
 
-		timers7: timer@40005000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40005000 0x400>;
-			clocks = <&rcc TIM7_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 70 0x400 0x1>;
-			dma-names = "up";
-			status = "disabled";
-
-			timer@6 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <6>;
-				status = "disabled";
-			};
+		syscfg: syscon@50020000 {
+			compatible = "st,stm32mp157-syscfg", "syscon";
+			reg = <0x50020000 0x400>;
+			clocks = <&rcc SYSCFG>;
 		};
 
-		timers12: timer@40006000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40006000 0x400>;
-			clocks = <&rcc TIM12_K>;
-			clock-names = "int";
+		dts: thermal@50028000 {
+			compatible = "st,stm32-thermal";
+			reg = <0x50028000 0x100>;
+			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc TMPSENS>;
+			clock-names = "pclk";
+			#thermal-sensor-cells = <0>;
 			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@11 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <11>;
-				status = "disabled";
-			};
 		};
 
-		timers13: timer@40007000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40007000 0x400>;
-			clocks = <&rcc TIM13_K>;
-			clock-names = "int";
-			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@12 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <12>;
-				status = "disabled";
-			};
+		mdma1: dma-controller@58000000 {
+			compatible = "st,stm32h7-mdma";
+			reg = <0x58000000 0x1000>;
+			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc MDMA>;
+			resets = <&rcc MDMA_R>;
+			#dma-cells = <5>;
+			dma-channels = <32>;
+			dma-requests = <48>;
 		};
 
-		timers14: timer@40008000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x40008000 0x400>;
-			clocks = <&rcc TIM14_K>;
-			clock-names = "int";
+		sdmmc1: mmc@58005000 {
+			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+			arm,primecell-periphid = <0x00253180>;
+			reg = <0x58005000 0x1000>;
+			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cmd_irq";
+			clocks = <&rcc SDMMC1_K>;
+			clock-names = "apb_pclk";
+			resets = <&rcc SDMMC1_R>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			max-frequency = <120000000>;
 			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			timer@13 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <13>;
-				status = "disabled";
-			};
 		};
 
-		lptimer1: timer@40009000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-lptimer";
-			reg = <0x40009000 0x400>;
-			interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LPTIM1_K>;
-			clock-names = "mux";
-			wakeup-source;
+		sdmmc2: mmc@58007000 {
+			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+			arm,primecell-periphid = <0x00253180>;
+			reg = <0x58007000 0x1000>;
+			interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "cmd_irq";
+			clocks = <&rcc SDMMC2_K>;
+			clock-names = "apb_pclk";
+			resets = <&rcc SDMMC2_R>;
+			cap-sd-highspeed;
+			cap-mmc-highspeed;
+			max-frequency = <120000000>;
 			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm-lp";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-
-			trigger@0 {
-				compatible = "st,stm32-lptimer-trigger";
-				reg = <0>;
-				status = "disabled";
-			};
-
-			counter {
-				compatible = "st,stm32-lptimer-counter";
-				status = "disabled";
-			};
 		};
 
-		spi2: spi@4000b000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x4000b000 0x400>;
-			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI2_K>;
-			resets = <&rcc SPI2_R>;
-			dmas = <&dmamux1 39 0x400 0x05>,
-			       <&dmamux1 40 0x400 0x05>;
-			dma-names = "rx", "tx";
+		crc1: crc@58009000 {
+			compatible = "st,stm32f7-crc";
+			reg = <0x58009000 0x400>;
+			clocks = <&rcc CRC1>;
 			status = "disabled";
 		};
 
-		i2s2: audio-controller@4000b000 {
-			compatible = "st,stm32h7-i2s";
-			#sound-dai-cells = <0>;
-			reg = <0x4000b000 0x400>;
-			interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&dmamux1 39 0x400 0x01>,
-			       <&dmamux1 40 0x400 0x01>;
-			dma-names = "rx", "tx";
+		usbh_ohci: usb@5800c000 {
+			compatible = "generic-ohci";
+			reg = <0x5800c000 0x1000>;
+			clocks = <&usbphyc>, <&rcc USBH>;
+			resets = <&rcc USBH_R>;
+			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
-		spi3: spi@4000c000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x4000c000 0x400>;
-			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI3_K>;
-			resets = <&rcc SPI3_R>;
-			dmas = <&dmamux1 61 0x400 0x05>,
-			       <&dmamux1 62 0x400 0x05>;
-			dma-names = "rx", "tx";
+		usbh_ehci: usb@5800d000 {
+			compatible = "generic-ehci";
+			reg = <0x5800d000 0x1000>;
+			clocks = <&usbphyc>, <&rcc USBH>;
+			resets = <&rcc USBH_R>;
+			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+			companion = <&usbh_ohci>;
 			status = "disabled";
 		};
 
-		i2s3: audio-controller@4000c000 {
-			compatible = "st,stm32h7-i2s";
-			#sound-dai-cells = <0>;
-			reg = <0x4000c000 0x400>;
-			interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&dmamux1 61 0x400 0x01>,
-			       <&dmamux1 62 0x400 0x01>;
-			dma-names = "rx", "tx";
+		ltdc: display-controller@5a001000 {
+			compatible = "st,stm32-ltdc";
+			reg = <0x5a001000 0x400>;
+			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+				     <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc LTDC_PX>;
+			clock-names = "lcd";
+			resets = <&rcc LTDC_R>;
 			status = "disabled";
-		};
 
-		spdifrx: audio-controller@4000d000 {
-			compatible = "st,stm32h7-spdifrx";
-			#sound-dai-cells = <0>;
-			reg = <0x4000d000 0x400>;
-			clocks = <&rcc SPDIF_K>;
-			clock-names = "kclk";
-			interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&dmamux1 93 0x400 0x01>,
-			       <&dmamux1 94 0x400 0x01>;
-			dma-names = "rx", "rx-ctrl";
-			status = "disabled";
+			port {
+				#address-cells = <1>;
+				#size-cells = <0>;
+			};
 		};
 
-		usart2: serial@4000e000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x4000e000 0x400>;
-			interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc USART2_K>;
-			wakeup-source;
-			dmas = <&dmamux1 43 0x400 0x15>,
-			       <&dmamux1 44 0x400 0x11>;
-			dma-names = "rx", "tx";
+		iwdg2: watchdog@5a002000 {
+			compatible = "st,stm32mp1-iwdg";
+			reg = <0x5a002000 0x400>;
+			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+			clock-names = "pclk", "lsi";
 			status = "disabled";
 		};
 
-		usart3: serial@4000f000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x4000f000 0x400>;
-			interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc USART3_K>;
-			wakeup-source;
-			dmas = <&dmamux1 45 0x400 0x15>,
-			       <&dmamux1 46 0x400 0x11>;
-			dma-names = "rx", "tx";
+		usbphyc: usbphyc@5a006000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			#clock-cells = <0>;
+			compatible = "st,stm32mp1-usbphyc";
+			reg = <0x5a006000 0x1000>;
+			clocks = <&rcc USBPHY_K>;
+			resets = <&rcc USBPHY_R>;
+			vdda1v1-supply = <&reg11>;
+			vdda1v8-supply = <&reg18>;
 			status = "disabled";
-		};
 
-		uart4: serial@40010000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x40010000 0x400>;
-			interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc UART4_K>;
-			wakeup-source;
-			dmas = <&dmamux1 63 0x400 0x15>,
-			       <&dmamux1 64 0x400 0x11>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
+			usbphyc_port0: usb-phy@0 {
+				#phy-cells = <0>;
+				reg = <0>;
+			};
 
-		uart5: serial@40011000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x40011000 0x400>;
-			interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc UART5_K>;
-			wakeup-source;
-			dmas = <&dmamux1 65 0x400 0x15>,
-			       <&dmamux1 66 0x400 0x11>;
-			dma-names = "rx", "tx";
-			status = "disabled";
+			usbphyc_port1: usb-phy@1 {
+				#phy-cells = <1>;
+				reg = <1>;
+			};
 		};
 
-		i2c1: i2c@40012000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x40012000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C1_K>;
-			resets = <&rcc I2C1_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x1>;
-			wakeup-source;
-			i2c-analog-filter;
+		rtc: rtc@5c004000 {
+			compatible = "st,stm32mp1-rtc";
+			reg = <0x5c004000 0x400>;
+			clocks = <&rcc RTCAPB>, <&rcc RTC>;
+			clock-names = "pclk", "rtc_ck";
+			interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>;
 			status = "disabled";
 		};
 
-		i2c2: i2c@40013000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x40013000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C2_K>;
-			resets = <&rcc I2C2_R>;
+		bsec: efuse@5c005000 {
+			compatible = "st,stm32mp15-bsec";
+			reg = <0x5c005000 0x400>;
 			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x2>;
-			wakeup-source;
-			i2c-analog-filter;
-			status = "disabled";
-		};
-
-		i2c3: i2c@40014000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x40014000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C3_K>;
-			resets = <&rcc I2C3_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x4>;
-			wakeup-source;
-			i2c-analog-filter;
-			status = "disabled";
-		};
+			#size-cells = <1>;
 
-		i2c5: i2c@40015000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x40015000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C5_K>;
-			resets = <&rcc I2C5_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x10>;
-			wakeup-source;
-			i2c-analog-filter;
-			status = "disabled";
+			cfg0_otp: cfg0_otp@0 {
+				reg = <0x0 0x1>;
+			};
+			part_number_otp: part_number_otp@4 {
+				reg = <0x4 0x1>;
+			};
+			monotonic_otp: monotonic_otp@10 {
+				reg = <0x10 0x4>;
+			};
+			nand_otp: nand_otp@24 {
+				reg = <0x24 0x4>;
+			};
+			uid_otp: uid_otp@34 {
+				reg = <0x34 0xc>;
+			};
+			package_otp: package_otp@40 {
+				reg = <0x40 0x4>;
+			};
+			hw2_otp: hw2_otp@48 {
+				reg = <0x48 0x4>;
+			};
+			ts_cal1: calib@5c {
+				reg = <0x5c 0x2>;
+			};
+			ts_cal2: calib@5e {
+				reg = <0x5e 0x2>;
+			};
+			pkh_otp: pkh_otp@60 {
+				reg = <0x60 0x20>;
+			};
+			ethernet_mac_address: mac@e4 {
+				reg = <0xe4 0x8>;
+				st,non-secure-otp;
+			};
 		};
 
-		cec: cec@40016000 {
-			compatible = "st,stm32-cec";
-			reg = <0x40016000 0x400>;
-			interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc CEC_K>, <&rcc CEC>;
-			clock-names = "cec", "hdmi-cec";
-			status = "disabled";
+		tamp: tamp@5c00a000 {
+			compatible = "st,stm32-tamp", "syscon", "simple-mfd";
+			reg = <0x5c00a000 0x400>;
+			clocks = <&rcc RTCAPB>;
+			st,backup-zones = <10 5 17>;
 		};
 
-		dac: dac@40017000 {
-			compatible = "st,stm32h7-dac-core";
-			reg = <0x40017000 0x400>;
-			clocks = <&rcc DAC12>;
-			clock-names = "pclk";
+		/*
+		 * Break node order to solve dependency probe issue between
+		 * pinctrl and exti.
+		 */
+		pinctrl: pinctrl@50002000 {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
+			#size-cells = <1>;
+			compatible = "st,stm32mp157-pinctrl";
+			ranges = <0 0x50002000 0xa400>;
+			interrupt-parent = <&exti>;
+			st,syscfg = <&exti 0x60 0xff>;
+			pins-are-numbered;
 
-			dac1: dac@1 {
-				compatible = "st,stm32-dac";
-				#io-channel-cells = <1>;
-				reg = <1>;
+			gpioa: gpio@50002000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x0 0x400>;
+				clocks = <&rcc GPIOA>;
+				st,bank-name = "GPIOA";
 				status = "disabled";
 			};
 
-			dac2: dac@2 {
-				compatible = "st,stm32-dac";
-				#io-channel-cells = <1>;
-				reg = <2>;
+			gpiob: gpio@50003000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x1000 0x400>;
+				clocks = <&rcc GPIOB>;
+				st,bank-name = "GPIOB";
 				status = "disabled";
 			};
-		};
-
-		uart7: serial@40018000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x40018000 0x400>;
-			interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc UART7_K>;
-			wakeup-source;
-			dmas = <&dmamux1 79 0x400 0x15>,
-			       <&dmamux1 80 0x400 0x11>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		uart8: serial@40019000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x40019000 0x400>;
-			interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc UART8_K>;
-			wakeup-source;
-			dmas = <&dmamux1 81 0x400 0x15>,
-			       <&dmamux1 82 0x400 0x11>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		timers1: timer@44000000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x44000000 0x400>;
-			clocks = <&rcc TIM1_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 11 0x400 0x1>,
-			       <&dmamux1 12 0x400 0x1>,
-			       <&dmamux1 13 0x400 0x1>,
-			       <&dmamux1 14 0x400 0x1>,
-			       <&dmamux1 15 0x400 0x1>,
-			       <&dmamux1 16 0x400 0x1>,
-			       <&dmamux1 17 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4",
-				    "up", "trig", "com";
-			status = "disabled";
 
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
+			gpioc: gpio@50004000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x2000 0x400>;
+				clocks = <&rcc GPIOC>;
+				st,bank-name = "GPIOC";
 				status = "disabled";
 			};
 
-			timer@0 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <0>;
+			gpiod: gpio@50005000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x3000 0x400>;
+				clocks = <&rcc GPIOD>;
+				st,bank-name = "GPIOD";
 				status = "disabled";
 			};
 
-			counter {
-				compatible = "st,stm32-timer-counter";
+			gpioe: gpio@50006000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x4000 0x400>;
+				clocks = <&rcc GPIOE>;
+				st,bank-name = "GPIOE";
 				status = "disabled";
 			};
-		};
-
-		timers8: timer@44001000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x44001000 0x400>;
-			clocks = <&rcc TIM8_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 47 0x400 0x1>,
-			       <&dmamux1 48 0x400 0x1>,
-			       <&dmamux1 49 0x400 0x1>,
-			       <&dmamux1 50 0x400 0x1>,
-			       <&dmamux1 51 0x400 0x1>,
-			       <&dmamux1 52 0x400 0x1>,
-			       <&dmamux1 53 0x400 0x1>;
-			dma-names = "ch1", "ch2", "ch3", "ch4",
-				    "up", "trig", "com";
-			status = "disabled";
 
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
+			gpiof: gpio@50007000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x5000 0x400>;
+				clocks = <&rcc GPIOF>;
+				st,bank-name = "GPIOF";
 				status = "disabled";
 			};
 
-			timer@7 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <7>;
+			gpiog: gpio@50008000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x6000 0x400>;
+				clocks = <&rcc GPIOG>;
+				st,bank-name = "GPIOG";
 				status = "disabled";
 			};
 
-			counter {
-				compatible = "st,stm32-timer-counter";
+			gpioh: gpio@50009000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x7000 0x400>;
+				clocks = <&rcc GPIOH>;
+				st,bank-name = "GPIOH";
 				status = "disabled";
 			};
-		};
-
-		usart6: serial@44003000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x44003000 0x400>;
-			interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc USART6_K>;
-			wakeup-source;
-			dmas = <&dmamux1 71 0x400 0x15>,
-			       <&dmamux1 72 0x400 0x11>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		spi1: spi@44004000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x44004000 0x400>;
-			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI1_K>;
-			resets = <&rcc SPI1_R>;
-			dmas = <&dmamux1 37 0x400 0x05>,
-			       <&dmamux1 38 0x400 0x05>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		i2s1: audio-controller@44004000 {
-			compatible = "st,stm32h7-i2s";
-			#sound-dai-cells = <0>;
-			reg = <0x44004000 0x400>;
-			interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&dmamux1 37 0x400 0x01>,
-			       <&dmamux1 38 0x400 0x01>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		spi4: spi@44005000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x44005000 0x400>;
-			interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI4_K>;
-			resets = <&rcc SPI4_R>;
-			dmas = <&dmamux1 83 0x400 0x05>,
-			       <&dmamux1 84 0x400 0x05>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
-
-		timers15: timer@44006000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x44006000 0x400>;
-			clocks = <&rcc TIM15_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 105 0x400 0x1>,
-			       <&dmamux1 106 0x400 0x1>,
-			       <&dmamux1 107 0x400 0x1>,
-			       <&dmamux1 108 0x400 0x1>;
-			dma-names = "ch1", "up", "trig", "com";
-			status = "disabled";
 
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
+			gpioi: gpio@5000a000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x8000 0x400>;
+				clocks = <&rcc GPIOI>;
+				st,bank-name = "GPIOI";
 				status = "disabled";
 			};
 
-			timer@14 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <14>;
+			gpioj: gpio@5000b000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0x9000 0x400>;
+				clocks = <&rcc GPIOJ>;
+				st,bank-name = "GPIOJ";
 				status = "disabled";
 			};
-		};
-
-		timers16: timer@44007000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x44007000 0x400>;
-			clocks = <&rcc TIM16_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 109 0x400 0x1>,
-			       <&dmamux1 110 0x400 0x1>;
-			dma-names = "ch1", "up";
-			status = "disabled";
 
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
-			timer@15 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <15>;
+			gpiok: gpio@5000c000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				reg = <0xa000 0x400>;
+				clocks = <&rcc GPIOK>;
+				st,bank-name = "GPIOK";
 				status = "disabled";
 			};
 		};
 
-		timers17: timer@44008000 {
+		pinctrl_z: pinctrl@54004000 {
 			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-timers";
-			reg = <0x44008000 0x400>;
-			clocks = <&rcc TIM17_K>;
-			clock-names = "int";
-			dmas = <&dmamux1 111 0x400 0x1>,
-			       <&dmamux1 112 0x400 0x1>;
-			dma-names = "ch1", "up";
-			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm";
-				#pwm-cells = <3>;
-				status = "disabled";
-			};
+			#size-cells = <1>;
+			compatible = "st,stm32mp157-z-pinctrl";
+			ranges = <0 0x54004000 0x400>;
+			pins-are-numbered;
+			interrupt-parent = <&exti>;
+			st,syscfg = <&exti 0x60 0xff>;
 
-			timer@16 {
-				compatible = "st,stm32h7-timer-trigger";
-				reg = <16>;
+			gpioz: gpio@54004000 {
+				gpio-controller;
+				#gpio-cells = <2>;
+				interrupt-controller;
+				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
+				reg = <0 0x400>;
+				clocks = <&rcc GPIOZ>;
+				st,bank-name = "GPIOZ";
+				st,bank-ioport = <11>;
 				status = "disabled";
 			};
 		};
 
-		spi5: spi@44009000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x44009000 0x400>;
-			interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI5_K>;
-			resets = <&rcc SPI5_R>;
-			dmas = <&dmamux1 85 0x400 0x05>,
-			       <&dmamux1 86 0x400 0x05>;
-			dma-names = "rx", "tx";
-			status = "disabled";
+		tzc400: tzc@5c006000 {
+			compatible = "st,stm32mp1-tzc";
+			reg = <0x5c006000 0x1000>;
+			interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc TZC1>, <&rcc TZC2>;
+			st,mem-map = <0xc0000000 0x40000000>;
 		};
 
-		sai1: sai@4400a000 {
-			compatible = "st,stm32h7-sai";
+		etzpc: etzpc@5c007000 {
+			compatible = "st,stm32-etzpc", "simple-bus";
+			reg = <0x5C007000 0x400>;
+			clocks = <&rcc TZPC>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-			ranges = <0 0x4400a000 0x400>;
-			reg = <0x4400a000 0x4>, <0x4400a3f0 0x10>;
-			interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&rcc SAI1_R>;
-			status = "disabled";
+			#access-controller-cells = <1>;
 
-			sai1a: audio-controller@4400a004 {
-				#sound-dai-cells = <0>;
+			timers2: timer@40000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40000000 0x400>;
+				clocks = <&rcc TIM2_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 18 0x400 0x1>,
+				       <&dmamux1 19 0x400 0x1>,
+				       <&dmamux1 20 0x400 0x1>,
+				       <&dmamux1 21 0x400 0x1>,
+				       <&dmamux1 22 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4", "up";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM2_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-				compatible = "st,stm32-sai-sub-a";
-				reg = <0x4 0x20>;
-				clocks = <&rcc SAI1_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 87 0x400 0x01>;
-				status = "disabled";
-			};
+				timer@1 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <1>;
+					status = "disabled";
+				};
 
-			sai1b: audio-controller@4400a024 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x20>;
-				clocks = <&rcc SAI1_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 88 0x400 0x01>;
-				status = "disabled";
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
 			};
-		};
 
-		sai2: sai@4400b000 {
-			compatible = "st,stm32h7-sai";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x4400b000 0x400>;
-			reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>;
-			interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&rcc SAI2_R>;
-			status = "disabled";
+			timers3: timer@40001000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40001000 0x400>;
+				clocks = <&rcc TIM3_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 23 0x400 0x1>,
+				       <&dmamux1 24 0x400 0x1>,
+				       <&dmamux1 25 0x400 0x1>,
+				       <&dmamux1 26 0x400 0x1>,
+				       <&dmamux1 27 0x400 0x1>,
+				       <&dmamux1 28 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM3_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			sai2a: audio-controller@4400b004 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-a";
-				reg = <0x4 0x20>;
-				clocks = <&rcc SAI2_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 89 0x400 0x01>;
-				status = "disabled";
-			};
+				timer@2 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <2>;
+					status = "disabled";
+				};
 
-			sai2b: audio-controller@4400b024 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x20>;
-				clocks = <&rcc SAI2_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 90 0x400 0x01>;
-				status = "disabled";
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
 			};
-		};
 
-		sai3: sai@4400c000 {
-			compatible = "st,stm32h7-sai";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x4400c000 0x400>;
-			reg = <0x4400c000 0x4>, <0x4400c3f0 0x10>;
-			interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&rcc SAI3_R>;
-			status = "disabled";
+			timers4: timer@40002000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40002000 0x400>;
+				clocks = <&rcc TIM4_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 29 0x400 0x1>,
+				       <&dmamux1 30 0x400 0x1>,
+				       <&dmamux1 31 0x400 0x1>,
+				       <&dmamux1 32 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM4_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			sai3a: audio-controller@4400c004 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-a";
-				reg = <0x04 0x20>;
-				clocks = <&rcc SAI3_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 113 0x400 0x01>;
-				status = "disabled";
-			};
+				timer@3 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <3>;
+					status = "disabled";
+				};
 
-			sai3b: audio-controller@4400c024 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x20>;
-				clocks = <&rcc SAI3_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 114 0x400 0x01>;
-				status = "disabled";
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
 			};
-		};
 
-		dfsdm: dfsdm@4400d000 {
-			compatible = "st,stm32mp1-dfsdm";
-			reg = <0x4400d000 0x800>;
-			clocks = <&rcc DFSDM_K>;
-			clock-names = "dfsdm";
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
+			timers5: timer@40003000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40003000 0x400>;
+				clocks = <&rcc TIM5_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 55 0x400 0x1>,
+				       <&dmamux1 56 0x400 0x1>,
+				       <&dmamux1 57 0x400 0x1>,
+				       <&dmamux1 58 0x400 0x1>,
+				       <&dmamux1 59 0x400 0x1>,
+				       <&dmamux1 60 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM5_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			dfsdm0: filter@0 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <0>;
-				interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 101 0x400 0x01>;
-				dma-names = "rx";
-				status = "disabled";
+				timer@4 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <4>;
+					status = "disabled";
+				};
+
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
 			};
 
-			dfsdm1: filter@1 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <1>;
-				interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 102 0x400 0x01>;
-				dma-names = "rx";
-				status = "disabled";
+			timers6: timer@40004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40004000 0x400>;
+				clocks = <&rcc TIM6_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 69 0x400 0x1>;
+				dma-names = "up";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM6_ID>;
+				status = "disabled";
+
+				timer@5 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <5>;
+					status = "disabled";
+				};
 			};
 
-			dfsdm2: filter@2 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <2>;
-				interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 103 0x400 0x01>;
-				dma-names = "rx";
-				status = "disabled";
+			timers7: timer@40005000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40005000 0x400>;
+				clocks = <&rcc TIM7_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 70 0x400 0x1>;
+				dma-names = "up";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM7_ID>;
+				status = "disabled";
+
+				timer@6 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <6>;
+					status = "disabled";
+				};
 			};
 
-			dfsdm3: filter@3 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <3>;
-				interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 104 0x400 0x01>;
-				dma-names = "rx";
+			timers12: timer@40006000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40006000 0x400>;
+				clocks = <&rcc TIM12_K>;
+				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM12_ID>;
 				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer@11 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <11>;
+					status = "disabled";
+				};
 			};
 
-			dfsdm4: filter@4 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <4>;
-				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 91 0x400 0x01>;
-				dma-names = "rx";
+			timers13: timer@40007000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40007000 0x400>;
+				clocks = <&rcc TIM13_K>;
+				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM13_ID>;
 				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer@12 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <12>;
+					status = "disabled";
+				};
 			};
 
-			dfsdm5: filter@5 {
-				compatible = "st,stm32-dfsdm-adc";
-				#io-channel-cells = <1>;
-				reg = <5>;
-				interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&dmamux1 92 0x400 0x01>;
-				dma-names = "rx";
+			timers14: timer@40008000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x40008000 0x400>;
+				clocks = <&rcc TIM14_K>;
+				clock-names = "int";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM14_ID>;
 				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+
+				timer@13 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <13>;
+					status = "disabled";
+				};
 			};
-		};
 
-		dma1: dma-controller@48000000 {
-			compatible = "st,stm32-dma";
-			reg = <0x48000000 0x400>;
-			interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc DMA1>;
-			resets = <&rcc DMA1_R>;
-			#dma-cells = <4>;
-			st,mem2mem;
-			dma-requests = <8>;
-		};
+			lptimer1: timer@40009000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-lptimer";
+				reg = <0x40009000 0x400>;
+				interrupts-extended = <&exti 47 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc LPTIM1_K>;
+				clock-names = "mux";
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM1_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-		dma2: dma-controller@48001000 {
-			compatible = "st,stm32-dma";
-			reg = <0x48001000 0x400>;
-			interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc DMA2>;
-			resets = <&rcc DMA2_R>;
-			#dma-cells = <4>;
-			st,mem2mem;
-			dma-requests = <8>;
-		};
+				trigger@0 {
+					compatible = "st,stm32-lptimer-trigger";
+					reg = <0>;
+					status = "disabled";
+				};
 
-		dmamux1: dma-router@48002000 {
-			compatible = "st,stm32h7-dmamux";
-			reg = <0x48002000 0x40>;
-			#dma-cells = <3>;
-			dma-requests = <128>;
-			dma-masters = <&dma1 &dma2>;
-			dma-channels = <16>;
-			clocks = <&rcc DMAMUX>;
-			resets = <&rcc DMAMUX_R>;
-		};
+				counter {
+					compatible = "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
+			};
 
-		adc: adc@48003000 {
-			compatible = "st,stm32mp1-adc-core";
-			reg = <0x48003000 0x400>;
-			interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc ADC12>, <&rcc ADC12_K>;
-			clock-names = "bus", "adc";
-			interrupt-controller;
-			st,syscfg = <&syscfg>;
-			#interrupt-cells = <1>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
+			spi2: spi@4000b000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x4000b000 0x400>;
+				interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI2_K>;
+				resets = <&rcc SPI2_R>;
+				dmas = <&dmamux1 39 0x400 0x05>,
+				       <&dmamux1 40 0x400 0x05>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI2_ID>;
+				status = "disabled";
+			};
 
-			adc1: adc@0 {
-				compatible = "st,stm32mp1-adc";
-				#io-channel-cells = <1>;
-				reg = <0x0>;
-				interrupt-parent = <&adc>;
-				interrupts = <0>;
-				dmas = <&dmamux1 9 0x400 0x01>;
-				dma-names = "rx";
+			i2s2: audio-controller@4000b000 {
+				compatible = "st,stm32h7-i2s";
+				#sound-dai-cells = <0>;
+				reg = <0x4000b000 0x400>;
+				interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 39 0x400 0x01>,
+				       <&dmamux1 40 0x400 0x01>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI2_ID>;
 				status = "disabled";
 			};
 
-			adc2: adc@100 {
-				compatible = "st,stm32mp1-adc";
-				#io-channel-cells = <1>;
-				reg = <0x100>;
-				interrupt-parent = <&adc>;
-				interrupts = <1>;
-				dmas = <&dmamux1 10 0x400 0x01>;
-				dma-names = "rx";
+			spi3: spi@4000c000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x4000c000 0x400>;
+				interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI3_K>;
+				resets = <&rcc SPI3_R>;
+				dmas = <&dmamux1 61 0x400 0x05>,
+				       <&dmamux1 62 0x400 0x05>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI3_ID>;
 				status = "disabled";
 			};
-		};
 
-		sdmmc3: mmc@48004000 {
-			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
-			arm,primecell-periphid = <0x00253180>;
-			reg = <0x48004000 0x400>;
-			interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "cmd_irq";
-			clocks = <&rcc SDMMC3_K>;
-			clock-names = "apb_pclk";
-			resets = <&rcc SDMMC3_R>;
-			cap-sd-highspeed;
-			cap-mmc-highspeed;
-			max-frequency = <120000000>;
-			status = "disabled";
-		};
+			i2s3: audio-controller@4000c000 {
+				compatible = "st,stm32h7-i2s";
+				#sound-dai-cells = <0>;
+				reg = <0x4000c000 0x400>;
+				interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 61 0x400 0x01>,
+				       <&dmamux1 62 0x400 0x01>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI3_ID>;
+				status = "disabled";
+			};
 
-		usbotg_hs: usb-otg@49000000 {
-			compatible = "st,stm32mp15-hsotg", "snps,dwc2";
-			reg = <0x49000000 0x10000>;
-			clocks = <&rcc USBO_K>;
-			clock-names = "otg";
-			resets = <&rcc USBO_R>;
-			reset-names = "dwc2";
-			interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
-			g-rx-fifo-size = <512>;
-			g-np-tx-fifo-size = <32>;
-			g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
-			dr_mode = "otg";
-			otg-rev = <0x200>;
-			usb33d-supply = <&usb33>;
-			status = "disabled";
-		};
+			spdifrx: audio-controller@4000d000 {
+				compatible = "st,stm32h7-spdifrx";
+				#sound-dai-cells = <0>;
+				reg = <0x4000d000 0x400>;
+				clocks = <&rcc SPDIF_K>;
+				clock-names = "kclk";
+				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 93 0x400 0x01>,
+				       <&dmamux1 94 0x400 0x01>;
+				dma-names = "rx", "rx-ctrl";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPDIFRX_ID>;
+				status = "disabled";
+			};
+
+			usart2: serial@4000e000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x4000e000 0x400>;
+				interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc USART2_K>;
+				wakeup-source;
+				dmas = <&dmamux1 43 0x400 0x15>,
+				       <&dmamux1 44 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART2_ID>;
+				status = "disabled";
+			};
+
+			usart3: serial@4000f000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x4000f000 0x400>;
+				interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc USART3_K>;
+				wakeup-source;
+				dmas = <&dmamux1 45 0x400 0x15>,
+				       <&dmamux1 46 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART3_ID>;
+				status = "disabled";
+			};
+
+			uart4: serial@40010000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x40010000 0x400>;
+				interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc UART4_K>;
+				wakeup-source;
+				dmas = <&dmamux1 63 0x400 0x15>,
+				       <&dmamux1 64 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_UART4_ID>;
+				status = "disabled";
+			};
+
+			uart5: serial@40011000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x40011000 0x400>;
+				interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc UART5_K>;
+				wakeup-source;
+				dmas = <&dmamux1 65 0x400 0x15>,
+				       <&dmamux1 66 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_UART5_ID>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@40012000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x40012000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C1_K>;
+				resets = <&rcc I2C1_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x1>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C1_ID>;
+				status = "disabled";
+			};
 
-		ipcc: mailbox@4c001000 {
-			compatible = "st,stm32mp1-ipcc";
-			#mbox-cells = <1>;
-			reg = <0x4c001000 0x400>;
-			st,proc-id = <0>;
-			interrupts-extended =
-				<&intc GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
-				<&intc GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
-				<&exti 61 1>;
-			interrupt-names = "rx", "tx", "wakeup";
-			clocks = <&rcc IPCC>;
-			wakeup-source;
-			status = "disabled";
-		};
+			i2c2: i2c@40013000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x40013000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C2_K>;
+				resets = <&rcc I2C2_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x2>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C2_ID>;
+				status = "disabled";
+			};
 
-		dcmi: dcmi@4c006000 {
-			compatible = "st,stm32-dcmi";
-			reg = <0x4c006000 0x400>;
-			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&rcc CAMITF_R>;
-			clocks = <&rcc DCMI>;
-			clock-names = "mclk";
-			dmas = <&dmamux1 75 0x400 0x01>;
-			dma-names = "tx";
-			status = "disabled";
-		};
+			i2c3: i2c@40014000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x40014000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C3_K>;
+				resets = <&rcc I2C3_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x4>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C3_ID>;
+				status = "disabled";
+			};
 
-		rcc: rcc@50000000 {
-			compatible = "st,stm32mp1-rcc", "syscon";
-			reg = <0x50000000 0x1000>;
-			#clock-cells = <1>;
-			#reset-cells = <1>;
-		};
+			i2c5: i2c@40015000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x40015000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C5_K>;
+				resets = <&rcc I2C5_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x10>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C5_ID>;
+				status = "disabled";
+			};
 
-		pwr_regulators: pwr@50001000 {
-			compatible = "st,stm32mp1,pwr-reg";
-			reg = <0x50001000 0x10>;
+			cec: cec@40016000 {
+				compatible = "st,stm32-cec";
+				reg = <0x40016000 0x400>;
+				interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CEC_K>, <&rcc CEC>;
+				clock-names = "cec", "hdmi-cec";
+				access-controllers = <&etzpc STM32MP1_ETZPC_CEC_ID>;
+				status = "disabled";
+			};
 
-			reg11: reg11 {
-				regulator-name = "reg11";
-				regulator-min-microvolt = <1100000>;
-				regulator-max-microvolt = <1100000>;
+			dac: dac@40017000 {
+				compatible = "st,stm32h7-dac-core";
+				reg = <0x40017000 0x400>;
+				clocks = <&rcc DAC12>;
+				clock-names = "pclk";
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_DAC_ID>;
+				status = "disabled";
+
+				dac1: dac@1 {
+					compatible = "st,stm32-dac";
+					#io-channel-cells = <1>;
+					reg = <1>;
+					status = "disabled";
+				};
+
+				dac2: dac@2 {
+					compatible = "st,stm32-dac";
+					#io-channel-cells = <1>;
+					reg = <2>;
+					status = "disabled";
+				};
 			};
 
-			reg18: reg18 {
-				regulator-name = "reg18";
-				regulator-min-microvolt = <1800000>;
-				regulator-max-microvolt = <1800000>;
+			uart7: serial@40018000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x40018000 0x400>;
+				interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc UART7_K>;
+				wakeup-source;
+				dmas = <&dmamux1 79 0x400 0x15>,
+				       <&dmamux1 80 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_UART7_ID>;
+				status = "disabled";
 			};
 
-			usb33: usb33 {
-				regulator-name = "usb33";
-				regulator-min-microvolt = <3300000>;
-				regulator-max-microvolt = <3300000>;
+			uart8: serial@40019000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x40019000 0x400>;
+				interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc UART8_K>;
+				wakeup-source;
+				dmas = <&dmamux1 81 0x400 0x15>,
+				       <&dmamux1 82 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_UART8_ID>;
+				status = "disabled";
 			};
-		};
 
-		pwr_mcu: pwr_mcu@50001014 {
-			compatible = "st,stm32mp151-pwr-mcu", "syscon";
-			reg = <0x50001014 0x4>;
-		};
+			timers1: timer@44000000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x44000000 0x400>;
+				clocks = <&rcc TIM1_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 11 0x400 0x1>,
+				       <&dmamux1 12 0x400 0x1>,
+				       <&dmamux1 13 0x400 0x1>,
+				       <&dmamux1 14 0x400 0x1>,
+				       <&dmamux1 15 0x400 0x1>,
+				       <&dmamux1 16 0x400 0x1>,
+				       <&dmamux1 17 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4",
+					    "up", "trig", "com";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM1_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-		exti: interrupt-controller@5000d000 {
-			compatible = "st,stm32mp1-exti", "syscon";
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			reg = <0x5000d000 0x400>;
-		};
+				timer@0 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <0>;
+					status = "disabled";
+				};
 
-		syscfg: syscon@50020000 {
-			compatible = "st,stm32mp157-syscfg", "syscon";
-			reg = <0x50020000 0x400>;
-			clocks = <&rcc SYSCFG>;
-		};
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
+			};
 
-		lptimer2: timer@50021000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-lptimer";
-			reg = <0x50021000 0x400>;
-			interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LPTIM2_K>;
-			clock-names = "mux";
-			wakeup-source;
-			status = "disabled";
+			timers8: timer@44001000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x44001000 0x400>;
+				clocks = <&rcc TIM8_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 47 0x400 0x1>,
+				       <&dmamux1 48 0x400 0x1>,
+				       <&dmamux1 49 0x400 0x1>,
+				       <&dmamux1 50 0x400 0x1>,
+				       <&dmamux1 51 0x400 0x1>,
+				       <&dmamux1 52 0x400 0x1>,
+				       <&dmamux1 53 0x400 0x1>;
+				dma-names = "ch1", "ch2", "ch3", "ch4",
+					    "up", "trig", "com";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM8_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			pwm {
-				compatible = "st,stm32-pwm-lp";
-				#pwm-cells = <3>;
-				status = "disabled";
+				timer@7 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <7>;
+					status = "disabled";
+				};
+
+				counter {
+					compatible = "st,stm32-timer-counter";
+					status = "disabled";
+				};
 			};
 
-			trigger@1 {
-				compatible = "st,stm32-lptimer-trigger";
-				reg = <1>;
+			usart6: serial@44003000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x44003000 0x400>;
+				interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc USART6_K>;
+				wakeup-source;
+				dmas = <&dmamux1 71 0x400 0x15>,
+				       <&dmamux1 72 0x400 0x11>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART6_ID>;
 				status = "disabled";
 			};
 
-			counter {
-				compatible = "st,stm32-lptimer-counter";
+			spi1: spi@44004000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x44004000 0x400>;
+				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI1_K>;
+				resets = <&rcc SPI1_R>;
+				dmas = <&dmamux1 37 0x400 0x05>,
+				       <&dmamux1 38 0x400 0x05>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI1_ID>;
 				status = "disabled";
 			};
-		};
-
-		lptimer3: timer@50022000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32-lptimer";
-			reg = <0x50022000 0x400>;
-			interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LPTIM3_K>;
-			clock-names = "mux";
-			wakeup-source;
-			status = "disabled";
 
-			pwm {
-				compatible = "st,stm32-pwm-lp";
-				#pwm-cells = <3>;
+			i2s1: audio-controller@44004000 {
+				compatible = "st,stm32h7-i2s";
+				#sound-dai-cells = <0>;
+				reg = <0x44004000 0x400>;
+				interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&dmamux1 37 0x400 0x01>,
+				       <&dmamux1 38 0x400 0x01>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI1_ID>;
 				status = "disabled";
 			};
 
-			trigger@2 {
-				compatible = "st,stm32-lptimer-trigger";
-				reg = <2>;
+			spi4: spi@44005000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x44005000 0x400>;
+				interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI4_K>;
+				resets = <&rcc SPI4_R>;
+				dmas = <&dmamux1 83 0x400 0x05>,
+				       <&dmamux1 84 0x400 0x05>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI4_ID>;
 				status = "disabled";
 			};
-		};
 
-		lptimer4: timer@50023000 {
-			compatible = "st,stm32-lptimer";
-			reg = <0x50023000 0x400>;
-			interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LPTIM4_K>;
-			clock-names = "mux";
-			wakeup-source;
-			status = "disabled";
+			timers15: timer@44006000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x44006000 0x400>;
+				clocks = <&rcc TIM15_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 105 0x400 0x1>,
+				       <&dmamux1 106 0x400 0x1>,
+				       <&dmamux1 107 0x400 0x1>,
+				       <&dmamux1 108 0x400 0x1>;
+				dma-names = "ch1", "up", "trig", "com";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM15_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			pwm {
-				compatible = "st,stm32-pwm-lp";
-				#pwm-cells = <3>;
-				status = "disabled";
+				timer@14 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <14>;
+					status = "disabled";
+				};
 			};
-		};
 
-		lptimer5: timer@50024000 {
-			compatible = "st,stm32-lptimer";
-			reg = <0x50024000 0x400>;
-			interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LPTIM5_K>;
-			clock-names = "mux";
-			wakeup-source;
-			status = "disabled";
-
-			pwm {
-				compatible = "st,stm32-pwm-lp";
-				#pwm-cells = <3>;
-				status = "disabled";
+			timers16: timer@44007000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x44007000 0x400>;
+				clocks = <&rcc TIM16_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 109 0x400 0x1>,
+				       <&dmamux1 110 0x400 0x1>;
+				dma-names = "ch1", "up";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM16_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
+				timer@15 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <15>;
+					status = "disabled";
+				};
 			};
-		};
 
-		vrefbuf: vrefbuf@50025000 {
-			compatible = "st,stm32-vrefbuf";
-			reg = <0x50025000 0x8>;
-			regulator-min-microvolt = <1500000>;
-			regulator-max-microvolt = <2500000>;
-			clocks = <&rcc VREF>;
-			status = "disabled";
-		};
+			timers17: timer@44008000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-timers";
+				reg = <0x44008000 0x400>;
+				clocks = <&rcc TIM17_K>;
+				clock-names = "int";
+				dmas = <&dmamux1 111 0x400 0x1>,
+				       <&dmamux1 112 0x400 0x1>;
+				dma-names = "ch1", "up";
+				access-controllers = <&etzpc STM32MP1_ETZPC_TIM17_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-		sai4: sai@50027000 {
-			compatible = "st,stm32h7-sai";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			ranges = <0 0x50027000 0x400>;
-			reg = <0x50027000 0x4>, <0x500273f0 0x10>;
-			interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
-			resets = <&rcc SAI4_R>;
-			status = "disabled";
+				timer@16 {
+					compatible = "st,stm32h7-timer-trigger";
+					reg = <16>;
+					status = "disabled";
+				};
+			};
 
-			sai4a: audio-controller@50027004 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-a";
-				reg = <0x04 0x20>;
-				clocks = <&rcc SAI4_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 99 0x400 0x01>;
+			spi5: spi@44009000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x44009000 0x400>;
+				interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI5_K>;
+				resets = <&rcc SPI5_R>;
+				dmas = <&dmamux1 85 0x400 0x05>,
+				       <&dmamux1 86 0x400 0x05>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI5_ID>;
 				status = "disabled";
 			};
 
-			sai4b: audio-controller@50027024 {
-				#sound-dai-cells = <0>;
-				compatible = "st,stm32-sai-sub-b";
-				reg = <0x24 0x20>;
-				clocks = <&rcc SAI4_K>;
-				clock-names = "sai_ck";
-				dmas = <&dmamux1 100 0x400 0x01>;
-				status = "disabled";
+			sai1: sai@4400a000 {
+				compatible = "st,stm32h7-sai";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x4400a000 0x400>;
+				reg = <0x4400a000 0x4>, <0x4400a3f0 0x10>;
+				interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&rcc SAI1_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_SAI1_ID>;
+				status = "disabled";
+
+				sai1a: audio-controller@4400a004 {
+					#sound-dai-cells = <0>;
+
+					compatible = "st,stm32-sai-sub-a";
+					reg = <0x4 0x20>;
+					clocks = <&rcc SAI1_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 87 0x400 0x01>;
+					status = "disabled";
+				};
+
+				sai1b: audio-controller@4400a024 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-b";
+					reg = <0x24 0x20>;
+					clocks = <&rcc SAI1_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 88 0x400 0x01>;
+					status = "disabled";
+				};
 			};
-		};
 
-		dts: thermal@50028000 {
-			compatible = "st,stm32-thermal";
-			reg = <0x50028000 0x100>;
-			interrupts = <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc TMPSENS>;
-			clock-names = "pclk";
-			#thermal-sensor-cells = <0>;
-			status = "disabled";
-		};
+			sai2: sai@4400b000 {
+				compatible = "st,stm32h7-sai";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x4400b000 0x400>;
+				reg = <0x4400b000 0x4>, <0x4400b3f0 0x10>;
+				interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&rcc SAI2_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_SAI2_ID>;
+				status = "disabled";
+
+				sai2a: audio-controller@4400b004 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-a";
+					reg = <0x4 0x20>;
+					clocks = <&rcc SAI2_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 89 0x400 0x01>;
+					status = "disabled";
+				};
 
-		hash1: hash@54002000 {
-			compatible = "st,stm32f756-hash";
-			reg = <0x54002000 0x400>;
-			interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc HASH1>;
-			resets = <&rcc HASH1_R>;
-			dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0>;
-			dma-names = "in";
-			dma-maxburst = <2>;
-			status = "disabled";
-		};
+				sai2b: audio-controller@4400b024 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-b";
+					reg = <0x24 0x20>;
+					clocks = <&rcc SAI2_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 90 0x400 0x01>;
+					status = "disabled";
+				};
+			};
 
-		rng1: rng@54003000 {
-			compatible = "st,stm32-rng";
-			reg = <0x54003000 0x400>;
-			clocks = <&rcc RNG1_K>;
-			resets = <&rcc RNG1_R>;
-			status = "disabled";
-		};
+			sai3: sai@4400c000 {
+				compatible = "st,stm32h7-sai";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x4400c000 0x400>;
+				reg = <0x4400c000 0x4>, <0x4400c3f0 0x10>;
+				interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&rcc SAI3_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_SAI3_ID>;
+				status = "disabled";
+
+				sai3a: audio-controller@4400c004 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-a";
+					reg = <0x04 0x20>;
+					clocks = <&rcc SAI3_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 113 0x400 0x01>;
+					status = "disabled";
+				};
 
-		mdma1: dma-controller@58000000 {
-			compatible = "st,stm32h7-mdma";
-			reg = <0x58000000 0x1000>;
-			interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc MDMA>;
-			resets = <&rcc MDMA_R>;
-			#dma-cells = <5>;
-			dma-channels = <32>;
-			dma-requests = <48>;
-		};
-
-		fmc: memory-controller@58002000 {
-			#address-cells = <2>;
-			#size-cells = <1>;
-			compatible = "st,stm32mp1-fmc2-ebi";
-			reg = <0x58002000 0x1000>;
-			clocks = <&rcc FMC_K>;
-			resets = <&rcc FMC_R>;
-			status = "disabled";
-
-			ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
-				 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
-				 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
-				 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
-				 <4 0 0x80000000 0x10000000>; /* NAND */
+				sai3b: audio-controller@4400c024 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-b";
+					reg = <0x24 0x20>;
+					clocks = <&rcc SAI3_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 114 0x400 0x01>;
+					status = "disabled";
+				};
+			};
 
-			nand-controller@4,0 {
+			dfsdm: dfsdm@4400d000 {
+				compatible = "st,stm32mp1-dfsdm";
+				reg = <0x4400d000 0x800>;
+				clocks = <&rcc DFSDM_K>;
+				clock-names = "dfsdm";
 				#address-cells = <1>;
 				#size-cells = <0>;
-				compatible = "st,stm32mp1-fmc2-nfc";
-				reg = <4 0x00000000 0x1000>,
-				      <4 0x08010000 0x1000>,
-				      <4 0x08020000 0x1000>,
-				      <4 0x01000000 0x1000>,
-				      <4 0x09010000 0x1000>,
-				      <4 0x09020000 0x1000>;
-				interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
-				dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
-				       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
-				       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
-				dma-names = "tx", "rx", "ecc";
+				access-controllers = <&etzpc STM32MP1_ETZPC_DFSDM_ID>;
 				status = "disabled";
-			};
-		};
 
-		qspi: spi@58003000 {
-			compatible = "st,stm32f469-qspi";
-			reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
-			reg-names = "qspi", "qspi_mm";
-			interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
-			dmas = <&mdma1 22 0x2 0x10100002 0x0 0x0>,
-			       <&mdma1 22 0x2 0x10100008 0x0 0x0>;
-			dma-names = "tx", "rx";
-			clocks = <&rcc QSPI_K>;
-			resets = <&rcc QSPI_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			status = "disabled";
-		};
+				dfsdm0: filter@0 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <0>;
+					interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 101 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-		sdmmc1: mmc@58005000 {
-			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
-			arm,primecell-periphid = <0x00253180>;
-			reg = <0x58005000 0x1000>;
-			interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "cmd_irq";
-			clocks = <&rcc SDMMC1_K>;
-			clock-names = "apb_pclk";
-			resets = <&rcc SDMMC1_R>;
-			cap-sd-highspeed;
-			cap-mmc-highspeed;
-			max-frequency = <120000000>;
-			status = "disabled";
-		};
+				dfsdm1: filter@1 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <1>;
+					interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 102 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-		sdmmc2: mmc@58007000 {
-			compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
-			arm,primecell-periphid = <0x00253180>;
-			reg = <0x58007000 0x1000>;
-			interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "cmd_irq";
-			clocks = <&rcc SDMMC2_K>;
-			clock-names = "apb_pclk";
-			resets = <&rcc SDMMC2_R>;
-			cap-sd-highspeed;
-			cap-mmc-highspeed;
-			max-frequency = <120000000>;
-			status = "disabled";
-		};
+				dfsdm2: filter@2 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <2>;
+					interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 103 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-		crc1: crc@58009000 {
-			compatible = "st,stm32f7-crc";
-			reg = <0x58009000 0x400>;
-			clocks = <&rcc CRC1>;
-			status = "disabled";
-		};
+				dfsdm3: filter@3 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <3>;
+					interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 104 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-		ethernet0: ethernet@5800a000 {
-			compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
-			reg = <0x5800a000 0x2000>;
-			reg-names = "stmmaceth";
-			interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "macirq";
-			clock-names = "stmmaceth",
-				      "mac-clk-tx",
-				      "mac-clk-rx",
-				      "eth-ck",
-				      "ptp_ref",
-				      "ethstp";
-			clocks = <&rcc ETHMAC>,
-				 <&rcc ETHTX>,
-				 <&rcc ETHRX>,
-				 <&rcc ETHCK_K>,
-				 <&rcc ETHPTP_K>,
-				 <&rcc ETHSTP>;
-			st,syscon = <&syscfg 0x4>;
-			snps,mixed-burst;
-			snps,pbl = <2>;
-			snps,en-tx-lpi-clockgating;
-			snps,axi-config = <&stmmac_axi_config_0>;
-			snps,tso;
-			status = "disabled";
+				dfsdm4: filter@4 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <4>;
+					interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 91 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-			stmmac_axi_config_0: stmmac-axi-config {
-				snps,wr_osr_lmt = <0x7>;
-				snps,rd_osr_lmt = <0x7>;
-				snps,blen = <0 0 0 0 16 8 4>;
+				dfsdm5: filter@5 {
+					compatible = "st,stm32-dfsdm-adc";
+					#io-channel-cells = <1>;
+					reg = <5>;
+					interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&dmamux1 92 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 			};
-		};
-
-		usbh_ohci: usb@5800c000 {
-			compatible = "generic-ohci";
-			reg = <0x5800c000 0x1000>;
-			clocks = <&usbphyc>, <&rcc USBH>;
-			resets = <&rcc USBH_R>;
-			interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-			status = "disabled";
-		};
 
-		usbh_ehci: usb@5800d000 {
-			compatible = "generic-ehci";
-			reg = <0x5800d000 0x1000>;
-			clocks = <&usbphyc>, <&rcc USBH>;
-			resets = <&rcc USBH_R>;
-			interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-			companion = <&usbh_ohci>;
-			status = "disabled";
-		};
-
-		ltdc: display-controller@5a001000 {
-			compatible = "st,stm32-ltdc";
-			reg = <0x5a001000 0x400>;
-			interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc LTDC_PX>;
-			clock-names = "lcd";
-			resets = <&rcc LTDC_R>;
-			status = "disabled";
-
-			port {
+			dma1: dma-controller@48000000 {
+				compatible = "st,stm32-dma";
+				reg = <0x48000000 0x400>;
+				interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc DMA1>;
+				resets = <&rcc DMA1_R>;
+				#dma-cells = <4>;
+				st,mem2mem;
+				dma-requests = <8>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_DMA1_ID>;
+				status = "disabled";
+			};
+
+			dma2: dma-controller@48001000 {
+				compatible = "st,stm32-dma";
+				reg = <0x48001000 0x400>;
+				interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc DMA2>;
+				resets = <&rcc DMA2_R>;
+				#dma-cells = <4>;
+				st,mem2mem;
+				dma-requests = <8>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_DMA2_ID>;
+				status = "disabled";
+			};
+
+			dmamux1: dma-router@48002000 {
+				compatible = "st,stm32h7-dmamux";
+				reg = <0x48002000 0x40>;
+				#dma-cells = <3>;
+				dma-requests = <128>;
+				dma-masters = <&dma1 &dma2>;
+				dma-channels = <16>;
+				clocks = <&rcc DMAMUX>;
+				resets = <&rcc DMAMUX_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_DMAMUX_ID>;
+				status = "disabled";
+			};
+
+			adc: adc@48003000 {
+				compatible = "st,stm32mp1-adc-core";
+				reg = <0x48003000 0x400>;
+				interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc ADC12>, <&rcc ADC12_K>;
+				clock-names = "bus", "adc";
+				interrupt-controller;
+				st,syscfg = <&syscfg>;
+				#interrupt-cells = <1>;
 				#address-cells = <1>;
 				#size-cells = <0>;
-			};
-		};
-
-		iwdg2: watchdog@5a002000 {
-			compatible = "st,stm32mp1-iwdg";
-			reg = <0x5a002000 0x400>;
-			interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
-			clock-names = "pclk", "lsi";
-			status = "disabled";
-		};
-
-		usbphyc: usbphyc@5a006000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			#clock-cells = <0>;
-			compatible = "st,stm32mp1-usbphyc";
-			reg = <0x5a006000 0x1000>;
-			clocks = <&rcc USBPHY_K>;
-			resets = <&rcc USBPHY_R>;
-			vdda1v1-supply = <&reg11>;
-			vdda1v8-supply = <&reg18>;
-			status = "disabled";
-
-			usbphyc_port0: usb-phy@0 {
-				#phy-cells = <0>;
-				reg = <0>;
-			};
+				access-controllers = <&etzpc STM32MP1_ETZPC_ADC_ID>;
+				status = "disabled";
+
+				adc1: adc@0 {
+					compatible = "st,stm32mp1-adc";
+					#io-channel-cells = <1>;
+					reg = <0x0>;
+					interrupt-parent = <&adc>;
+					interrupts = <0>;
+					dmas = <&dmamux1 9 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 
-			usbphyc_port1: usb-phy@1 {
-				#phy-cells = <1>;
-				reg = <1>;
+				adc2: adc@100 {
+					compatible = "st,stm32mp1-adc";
+					#io-channel-cells = <1>;
+					reg = <0x100>;
+					interrupt-parent = <&adc>;
+					interrupts = <1>;
+					dmas = <&dmamux1 10 0x400 0x01>;
+					dma-names = "rx";
+					status = "disabled";
+				};
 			};
-		};
-
-		usart1: serial@5c000000 {
-			compatible = "st,stm32h7-uart";
-			reg = <0x5c000000 0x400>;
-			interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc USART1_K>;
-			wakeup-source;
-			status = "disabled";
-		};
-
-		spi6: spi@5c001000 {
-			#address-cells = <1>;
-			#size-cells = <0>;
-			compatible = "st,stm32h7-spi";
-			reg = <0x5c001000 0x400>;
-			interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc SPI6_K>;
-			resets = <&rcc SPI6_R>;
-			dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>,
-			       <&mdma1 35 0x0 0x40002 0x0 0x0>;
-			dma-names = "rx", "tx";
-			status = "disabled";
-		};
 
-		i2c4: i2c@5c002000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x5c002000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C4_K>;
-			resets = <&rcc I2C4_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x8>;
-			wakeup-source;
-			i2c-analog-filter;
-			status = "disabled";
-		};
-
-		iwdg1: watchdog@5c003000 {
-			compatible = "st,stm32mp1-iwdg";
-			reg = <0x5C003000 0x400>;
-			interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
-			clock-names = "pclk", "lsi";
-			status = "disabled";
-		};
-
-		rtc: rtc@5c004000 {
-			compatible = "st,stm32mp1-rtc";
-			reg = <0x5c004000 0x400>;
-			clocks = <&rcc RTCAPB>, <&rcc RTC>;
-			clock-names = "pclk", "rtc_ck";
-			interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>;
-			status = "disabled";
-		};
+			sdmmc3: mmc@48004000 {
+				compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell";
+				arm,primecell-periphid = <0x00253180>;
+				reg = <0x48004000 0x400>;
+				interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "cmd_irq";
+				clocks = <&rcc SDMMC3_K>;
+				clock-names = "apb_pclk";
+				resets = <&rcc SDMMC3_R>;
+				cap-sd-highspeed;
+				cap-mmc-highspeed;
+				max-frequency = <120000000>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_SDMMC3_ID>;
+				status = "disabled";
+			};
+
+			usbotg_hs: usb-otg@49000000 {
+				compatible = "st,stm32mp15-hsotg", "snps,dwc2";
+				reg = <0x49000000 0x10000>;
+				clocks = <&rcc USBO_K>;
+				clock-names = "otg";
+				resets = <&rcc USBO_R>;
+				reset-names = "dwc2";
+				interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+				g-rx-fifo-size = <512>;
+				g-np-tx-fifo-size = <32>;
+				g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
+				dr_mode = "otg";
+				otg-rev = <0x200>;
+				usb33d-supply = <&usb33>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_OTG_ID>;
+				status = "disabled";
+			};
+
+			dcmi: dcmi@4c006000 {
+				compatible = "st,stm32-dcmi";
+				reg = <0x4c006000 0x400>;
+				interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&rcc CAMITF_R>;
+				clocks = <&rcc DCMI>;
+				clock-names = "mclk";
+				dmas = <&dmamux1 75 0x400 0x01>;
+				dma-names = "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_DCMI_ID>;
+				status = "disabled";
+			};
+
+			lptimer2: timer@50021000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-lptimer";
+				reg = <0x50021000 0x400>;
+				interrupts-extended = <&exti 48 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc LPTIM2_K>;
+				clock-names = "mux";
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM2_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-		bsec: efuse@5c005000 {
-			compatible = "st,stm32mp15-bsec";
-			reg = <0x5c005000 0x400>;
-			#address-cells = <1>;
-			#size-cells = <1>;
+				trigger@1 {
+					compatible = "st,stm32-lptimer-trigger";
+					reg = <1>;
+					status = "disabled";
+				};
 
-			cfg0_otp: cfg0_otp@0 {
-				reg = <0x0 0x1>;
-			};
-			part_number_otp: part_number_otp@4 {
-				reg = <0x4 0x1>;
-			};
-			monotonic_otp: monotonic_otp@10 {
-				reg = <0x10 0x4>;
-			};
-			nand_otp: nand_otp@24 {
-				reg = <0x24 0x4>;
-			};
-			uid_otp: uid_otp@34 {
-				reg = <0x34 0xc>;
-			};
-			package_otp: package_otp@40 {
-				reg = <0x40 0x4>;
-			};
-			hw2_otp: hw2_otp@48 {
-				reg = <0x48 0x4>;
-			};
-			ts_cal1: calib@5c {
-				reg = <0x5c 0x2>;
-			};
-			ts_cal2: calib@5e {
-				reg = <0x5e 0x2>;
-			};
-			pkh_otp: pkh_otp@60 {
-				reg = <0x60 0x20>;
-			};
-			ethernet_mac_address: mac@e4 {
-				reg = <0xe4 0x8>;
-				st,non-secure-otp;
+				counter {
+					compatible = "st,stm32-lptimer-counter";
+					status = "disabled";
+				};
 			};
-		};
-
-		etzpc: etzpc@5c007000 {
-			compatible = "st,stm32-etzpc";
-			reg = <0x5C007000 0x400>;
-			clocks = <&rcc TZPC>;
-			status = "disabled";
-			secure-status = "okay";
-		};
-
-		i2c6: i2c@5c009000 {
-			compatible = "st,stm32mp15-i2c";
-			reg = <0x5c009000 0x400>;
-			interrupt-names = "event", "error";
-			interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc I2C6_K>;
-			resets = <&rcc I2C6_R>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			st,syscfg-fmp = <&syscfg 0x4 0x20>;
-			wakeup-source;
-			i2c-analog-filter;
-			status = "disabled";
-		};
 
-		tamp: tamp@5c00a000 {
-			compatible = "st,stm32-tamp", "syscon", "simple-mfd";
-			reg = <0x5c00a000 0x400>;
-			clocks = <&rcc RTCAPB>;
-		};
-
-		/*
-		 * Break node order to solve dependency probe issue between
-		 * pinctrl and exti.
-		 */
-		pinctrl: pinctrl@50002000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "st,stm32mp157-pinctrl";
-			ranges = <0 0x50002000 0xa400>;
-			interrupt-parent = <&exti>;
-			st,syscfg = <&exti 0x60 0xff>;
-			pins-are-numbered;
+			lptimer3: timer@50022000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32-lptimer";
+				reg = <0x50022000 0x400>;
+				interrupts-extended = <&exti 50 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc LPTIM3_K>;
+				clock-names = "mux";
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM3_ID>;
+				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 
-			gpioa: gpio@50002000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x0 0x400>;
-				clocks = <&rcc GPIOA>;
-				st,bank-name = "GPIOA";
-				status = "disabled";
+				trigger@2 {
+					compatible = "st,stm32-lptimer-trigger";
+					reg = <2>;
+					status = "disabled";
+				};
 			};
 
-			gpiob: gpio@50003000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x1000 0x400>;
-				clocks = <&rcc GPIOB>;
-				st,bank-name = "GPIOB";
+			lptimer4: timer@50023000 {
+				compatible = "st,stm32-lptimer";
+				reg = <0x50023000 0x400>;
+				interrupts-extended = <&exti 52 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc LPTIM4_K>;
+				clock-names = "mux";
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM4_ID>;
 				status = "disabled";
-			};
 
-			gpioc: gpio@50004000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x2000 0x400>;
-				clocks = <&rcc GPIOC>;
-				st,bank-name = "GPIOC";
-				status = "disabled";
+				pwm {
+					compatible = "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 			};
 
-			gpiod: gpio@50005000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x3000 0x400>;
-				clocks = <&rcc GPIOD>;
-				st,bank-name = "GPIOD";
+			lptimer5: timer@50024000 {
+				compatible = "st,stm32-lptimer";
+				reg = <0x50024000 0x400>;
+				interrupts-extended = <&exti 53 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc LPTIM5_K>;
+				clock-names = "mux";
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_LPTIM5_ID>;
 				status = "disabled";
+
+				pwm {
+					compatible = "st,stm32-pwm-lp";
+					#pwm-cells = <3>;
+					status = "disabled";
+				};
 			};
 
-			gpioe: gpio@50006000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x4000 0x400>;
-				clocks = <&rcc GPIOE>;
-				st,bank-name = "GPIOE";
+			vrefbuf: vrefbuf@50025000 {
+				compatible = "st,stm32-vrefbuf";
+				reg = <0x50025000 0x8>;
+				regulator-min-microvolt = <1500000>;
+				regulator-max-microvolt = <2500000>;
+				clocks = <&rcc VREF>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_VREFBUF_ID>;
 				status = "disabled";
 			};
 
-			gpiof: gpio@50007000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x5000 0x400>;
-				clocks = <&rcc GPIOF>;
-				st,bank-name = "GPIOF";
-				status = "disabled";
+			sai4: sai@50027000 {
+				compatible = "st,stm32h7-sai";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0 0x50027000 0x400>;
+				reg = <0x50027000 0x4>, <0x500273f0 0x10>;
+				interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+				resets = <&rcc SAI4_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_SAI4_ID>;
+				status = "disabled";
+
+				sai4a: audio-controller@50027004 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-a";
+					reg = <0x04 0x20>;
+					clocks = <&rcc SAI4_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 99 0x400 0x01>;
+					status = "disabled";
+				};
+
+				sai4b: audio-controller@50027024 {
+					#sound-dai-cells = <0>;
+					compatible = "st,stm32-sai-sub-b";
+					reg = <0x24 0x20>;
+					clocks = <&rcc SAI4_K>;
+					clock-names = "sai_ck";
+					dmas = <&dmamux1 100 0x400 0x01>;
+					status = "disabled";
+				};
 			};
 
-			gpiog: gpio@50008000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x6000 0x400>;
-				clocks = <&rcc GPIOG>;
-				st,bank-name = "GPIOG";
-				status = "disabled";
+			hash1: hash@54002000 {
+				compatible = "st,stm32f756-hash";
+				reg = <0x54002000 0x400>;
+				interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc HASH1>;
+				resets = <&rcc HASH1_R>;
+				dmas = <&mdma1 31 0x2 0x1000A02 0x0 0x0>;
+				dma-names = "in";
+				dma-maxburst = <2>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_HASH1_ID>;
+				status = "disabled";
+			};
+
+			rng1: rng@54003000 {
+				compatible = "st,stm32-rng";
+				reg = <0x54003000 0x400>;
+				clocks = <&rcc RNG1_K>;
+				resets = <&rcc RNG1_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_RNG1_ID>;
+				status = "disabled";
+			};
+
+			fmc: memory-controller@58002000 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "st,stm32mp1-fmc2-ebi";
+				reg = <0x58002000 0x1000>;
+				clocks = <&rcc FMC_K>;
+				resets = <&rcc FMC_R>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_FMC_ID>;
+				status = "disabled";
+
+				ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
+					 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
+					 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
+					 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
+					 <4 0 0x80000000 0x10000000>; /* NAND */
+
+				nand-controller@4,0 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible = "st,stm32mp1-fmc2-nfc";
+					reg = <4 0x00000000 0x1000>,
+					      <4 0x08010000 0x1000>,
+					      <4 0x08020000 0x1000>,
+					      <4 0x01000000 0x1000>,
+					      <4 0x09010000 0x1000>,
+					      <4 0x09020000 0x1000>;
+					interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+					dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+					       <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+					       <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+					dma-names = "tx", "rx", "ecc";
+					status = "disabled";
+				};
 			};
 
-			gpioh: gpio@50009000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x7000 0x400>;
-				clocks = <&rcc GPIOH>;
-				st,bank-name = "GPIOH";
-				status = "disabled";
+			qspi: spi@58003000 {
+				compatible = "st,stm32f469-qspi";
+				reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
+				reg-names = "qspi", "qspi_mm";
+				interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+				dmas = <&mdma1 22 0x2 0x10100002 0x0 0x0>,
+				<&mdma1 22 0x2 0x10100008 0x0 0x0>;
+				dma-names = "tx", "rx";
+				clocks = <&rcc QSPI_K>;
+				resets = <&rcc QSPI_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				access-controllers = <&etzpc STM32MP1_ETZPC_QSPI_ID>;
+				status = "disabled";
+			};
+
+			ethernet0: ethernet@5800a000 {
+				compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
+				reg = <0x5800a000 0x2000>;
+				reg-names = "stmmaceth";
+				interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+				interrupt-names = "macirq";
+				clock-names = "stmmaceth",
+					      "mac-clk-tx",
+					      "mac-clk-rx",
+					      "eth-ck",
+					      "ptp_ref",
+					      "ethstp";
+				clocks = <&rcc ETHMAC>,
+					 <&rcc ETHTX>,
+					 <&rcc ETHRX>,
+					 <&rcc ETHCK_K>,
+					 <&rcc ETHPTP_K>,
+					 <&rcc ETHSTP>;
+				st,syscon = <&syscfg 0x4>;
+				snps,mixed-burst;
+				snps,pbl = <2>;
+				snps,en-tx-lpi-clockgating;
+				snps,axi-config = <&stmmac_axi_config_0>;
+				snps,tso;
+				access-controllers = <&etzpc STM32MP1_ETZPC_ETH_ID>;
+				status = "disabled";
+
+				stmmac_axi_config_0: stmmac-axi-config {
+					snps,wr_osr_lmt = <0x7>;
+					snps,rd_osr_lmt = <0x7>;
+					snps,blen = <0 0 0 0 16 8 4>;
+				};
 			};
 
-			gpioi: gpio@5000a000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x8000 0x400>;
-				clocks = <&rcc GPIOI>;
-				st,bank-name = "GPIOI";
+			usart1: serial@5c000000 {
+				compatible = "st,stm32h7-uart";
+				reg = <0x5c000000 0x400>;
+				interrupts-extended = <&exti 26 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc USART1_K>;
+				wakeup-source;
+				access-controllers = <&etzpc STM32MP1_ETZPC_USART1_ID>;
 				status = "disabled";
 			};
 
-			gpioj: gpio@5000b000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0x9000 0x400>;
-				clocks = <&rcc GPIOJ>;
-				st,bank-name = "GPIOJ";
+			spi6: spi@5c001000 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				compatible = "st,stm32h7-spi";
+				reg = <0x5c001000 0x400>;
+				interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc SPI6_K>;
+				resets = <&rcc SPI6_R>;
+				dmas = <&mdma1 34 0x0 0x40008 0x0 0x0>,
+				       <&mdma1 35 0x0 0x40002 0x0 0x0>;
+				dma-names = "rx", "tx";
+				access-controllers = <&etzpc STM32MP1_ETZPC_SPI6_ID>;
+				status = "disabled";
+			};
+
+			i2c4: i2c@5c002000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x5c002000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C4_K>;
+				resets = <&rcc I2C4_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x8>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C4_ID>;
 				status = "disabled";
 			};
 
-			gpiok: gpio@5000c000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0xa000 0x400>;
-				clocks = <&rcc GPIOK>;
-				st,bank-name = "GPIOK";
+			iwdg1: watchdog@5c003000 {
+				compatible = "st,stm32mp1-iwdg";
+				reg = <0x5C003000 0x400>;
+				interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc IWDG1>, <&rcc CK_LSI>;
+				clock-names = "pclk", "lsi";
+				access-controllers = <&etzpc STM32MP1_ETZPC_IWDG1_ID>;
 				status = "disabled";
 			};
-		};
-
-		pinctrl_z: pinctrl@54004000 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "st,stm32mp157-z-pinctrl";
-			ranges = <0 0x54004000 0x400>;
-			pins-are-numbered;
-			interrupt-parent = <&exti>;
-			st,syscfg = <&exti 0x60 0xff>;
 
-			gpioz: gpio@54004000 {
-				gpio-controller;
-				#gpio-cells = <2>;
-				interrupt-controller;
-				#interrupt-cells = <2>;
-				reg = <0 0x400>;
-				clocks = <&rcc GPIOZ>;
-				st,bank-name = "GPIOZ";
-				st,bank-ioport = <11>;
+			i2c6: i2c@5c009000 {
+				compatible = "st,stm32mp15-i2c";
+				reg = <0x5c009000 0x400>;
+				interrupt-names = "event", "error";
+				interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+					     <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc I2C6_K>;
+				resets = <&rcc I2C6_R>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				st,syscfg-fmp = <&syscfg 0x4 0x20>;
+				wakeup-source;
+				i2c-analog-filter;
+				access-controllers = <&etzpc STM32MP1_ETZPC_I2C6_ID>;
 				status = "disabled";
 			};
 		};
diff --git a/core/arch/arm/dts/stm32mp153.dtsi b/core/arch/arm/dts/stm32mp153.dtsi
index 486084e0b80b5df0fc3c581641918c90c23dbe2a..3578195afc3e2a2754967e445eec5f6bc821ec13 100644
--- a/core/arch/arm/dts/stm32mp153.dtsi
+++ b/core/arch/arm/dts/stm32mp153.dtsi
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2019-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
@@ -28,32 +28,34 @@
 			     <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
 			     <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
 	};
+};
 
-	soc {
-		m_can1: can@4400e000 {
-			compatible = "bosch,m_can";
-			reg = <0x4400e000 0x400>, <0x44011000 0x1400>;
-			reg-names = "m_can", "message_ram";
-			interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "int0", "int1";
-			clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
-			clock-names = "hclk", "cclk";
-			bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
-			status = "disabled";
-		};
+&etzpc {
+	m_can1: can@4400e000 {
+		compatible = "bosch,m_can";
+		reg = <0x4400e000 0x400>, <0x44011000 0x1400>;
+		reg-names = "m_can", "message_ram";
+		interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_TT_FDCAN_ID>;
+		status = "disabled";
+	};
 
-		m_can2: can@4400f000 {
-			compatible = "bosch,m_can";
-			reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
-			reg-names = "m_can", "message_ram";
-			interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
-				     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
-			interrupt-names = "int0", "int1";
-			clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
-			clock-names = "hclk", "cclk";
-			bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
-			status = "disabled";
-		};
+	m_can2: can@4400f000 {
+		compatible = "bosch,m_can";
+		reg = <0x4400f000 0x400>, <0x44011000 0x2800>;
+		reg-names = "m_can", "message_ram";
+		interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
+			     <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+		interrupt-names = "int0", "int1";
+		clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>;
+		clock-names = "hclk", "cclk";
+		bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_TT_FDCAN_ID>;
+		status = "disabled";
 	};
 };
diff --git a/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts
index 8236375389bf0e088aee2dd3eaa6fc8625e9b429..2d0cad2ca9d21686596516f811cc6eb3b00d2e76 100644
--- a/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts
+++ b/core/arch/arm/dts/stm32mp157a-dk1-scmi.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2023
+ * Copyright (C) STMicroelectronics 2023-2024
  */
 
 /dts-v1/;
@@ -12,6 +12,21 @@
 	compatible = "st,stm32mp157a-dk1-scmi", "st,stm32mp157";
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
+
 &rcc {
 	compatible = "st,stm32mp1-rcc-secure";
 	status = "okay";
diff --git a/core/arch/arm/dts/stm32mp157a-dk1.dts b/core/arch/arm/dts/stm32mp157a-dk1.dts
index 294746da4ff279e66f3d390458ad777332cc190e..6ce8c6ae2247c91e20c11da99219931882b4c6f3 100644
--- a/core/arch/arm/dts/stm32mp157a-dk1.dts
+++ b/core/arch/arm/dts/stm32mp157a-dk1.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2019-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
@@ -36,3 +36,18 @@
 		reg = <0xf0 0x10>;
 	};
 };
+
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
diff --git a/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts
index e80e2a47c1e3ede6fe99bbc067b6596eea9aa737..30436d148af7c0709679361a61b94b4d9ee50869 100644
--- a/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts
+++ b/core/arch/arm/dts/stm32mp157c-dk2-scmi.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2023
+ * Copyright (C) STMicroelectronics 2023-2024
  */
 
 /dts-v1/;
@@ -12,6 +12,22 @@
 	compatible = "st,stm32mp157c-dk2-scmi", "st,stm32mp157";
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
+
 &rcc {
 	compatible = "st,stm32mp1-rcc-secure";
 	status = "okay";
diff --git a/core/arch/arm/dts/stm32mp157c-dk2.dts b/core/arch/arm/dts/stm32mp157c-dk2.dts
index dfb8f9830fd61235084ec7e285792d0788eaac80..471a062e2a0c6f48e3b1370e5f140ca3cc75af06 100644
--- a/core/arch/arm/dts/stm32mp157c-dk2.dts
+++ b/core/arch/arm/dts/stm32mp157c-dk2.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2019-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
@@ -74,6 +74,22 @@
 	};
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
+
 &i2c1 {
 	touchscreen@38 {
 		compatible = "focaltech,ft6236";
diff --git a/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts
index 19cf9bc6b9368a5ec5c3c1f1fd4da979639e367c..5c2c172984b470cdb0377bd84a3bbacc6ca3f6c7 100644
--- a/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts
+++ b/core/arch/arm/dts/stm32mp157c-ed1-scmi.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2023
+ * Copyright (C) STMicroelectronics 2023-2024
  */
 /dts-v1/;
 
@@ -11,6 +11,22 @@
 	compatible = "st,stm32mp157c-ed1-scmi", "st,stm32mp157";
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
+
 &iwdg1 {
 	timeout-sec = <32>;
 };
diff --git a/core/arch/arm/dts/stm32mp157c-ed1.dts b/core/arch/arm/dts/stm32mp157c-ed1.dts
index c0b4e1a294d69e8b8b1da94de7cdb51d666c4742..1fef2864a3230162ab0ed2ba394244a877b4313e 100644
--- a/core/arch/arm/dts/stm32mp157c-ed1.dts
+++ b/core/arch/arm/dts/stm32mp157c-ed1.dts
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2017-2024 - All Rights Reserved
  * Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
  */
 /dts-v1/;
@@ -94,6 +94,7 @@
 		gpios-states = <0>;
 		states = <1800000 0x1>,
 			 <2900000 0x0>;
+		status = "disabled";
 	};
 
 	vin: vin {
@@ -152,6 +153,22 @@
 	status = "disabled";
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_S_RW, DECPROT_LOCK)>;
+};
+
 &gpu {
 	contiguous-area = <&gpu_reserved>;
 };
@@ -161,6 +178,7 @@
 };
 
 &i2c4 {
+	compatible = "st,stm32mp15-i2c-non-secure";
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c4_pins_a>;
 	pinctrl-1 = <&i2c4_sleep_pins_a>;
diff --git a/core/arch/arm/dts/stm32mp15xc.dtsi b/core/arch/arm/dts/stm32mp15xc.dtsi
index b06a55a2fa188dfb7f5212f887d6e80e01b20e9a..0cc03124bacf2c1433b8eb755d0653757f8a1c4f 100644
--- a/core/arch/arm/dts/stm32mp15xc.dtsi
+++ b/core/arch/arm/dts/stm32mp15xc.dtsi
@@ -1,18 +1,17 @@
 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 /*
- * Copyright (C) STMicroelectronics 2019 - All Rights Reserved
+ * Copyright (C) STMicroelectronics 2019-2024 - All Rights Reserved
  * Author: Alexandre Torgue <alexandre.torgue@st.com> for STMicroelectronics.
  */
 
-/ {
-	soc {
-		cryp1: cryp@54001000 {
-			compatible = "st,stm32mp1-cryp";
-			reg = <0x54001000 0x400>;
-			interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-			clocks = <&rcc CRYP1>;
-			resets = <&rcc CRYP1_R>;
-			status = "disabled";
-		};
+&etzpc {
+	cryp1: cryp@54001000 {
+		compatible = "st,stm32mp1-cryp";
+		reg = <0x54001000 0x400>;
+		interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&rcc CRYP1>;
+		resets = <&rcc CRYP1_R>;
+		access-controllers = <&etzpc STM32MP1_ETZPC_CRYP1_ID>;
+		status = "disabled";
 	};
 };
diff --git a/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi b/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi
index b4fc6da5b4a43fa5972b785088b26f9cb1d5128b..be1c35bddf974e7b385daebc4697aceba0bb7843 100644
--- a/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dhcom-som.dtsi
@@ -147,6 +147,22 @@
 	};
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_NS_RW, DECPROT_LOCK)>;
+};
+
 &fmc {
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&fmc_pins_b>;
diff --git a/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi b/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi
index 76c54b006d8712e49a29b60ff3e1938e0e67d9c5..62237dc7f6342bb41a4bc70119b46ba8f21bbd9a 100644
--- a/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dhcor-avenger96.dtsi
@@ -84,6 +84,7 @@
 		gpios-states = <0>;
 		states = <1800000 0x1>,
 			 <2900000 0x0>;
+		status = "disabled";
 	};
 
 	sound {
diff --git a/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi b/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi
index 312f3870a6c7c71af55717eefc7294f3cf719616..6a793e9837a304d63b691311f9a4f5c432fb023a 100644
--- a/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dhcor-som.dtsi
@@ -72,6 +72,22 @@
 	status = "okay";
 };
 
+&etzpc {
+	st,decprot =
+		<DECPROT(STM32MP1_ETZPC_USART1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_SPI6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C4_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_I2C6_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_RNG1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_HASH1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_CRYP1_ID, DECPROT_NS_RW, DECPROT_UNLOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRCTRL_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_DDRPHYC_ID, DECPROT_NS_R_S_W, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_STGENC_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_BKPSRAM_ID, DECPROT_S_RW, DECPROT_LOCK)>,
+		<DECPROT(STM32MP1_ETZPC_IWDG1_ID, DECPROT_NS_RW, DECPROT_LOCK)>;
+};
+
 &i2c4 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&i2c4_pins_a>;
diff --git a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
index af5a0534455a43ba0f30232150ff6a2d5f55a497..8500a96eea273968d13f77cc0a9cfca2f2e548de 100644
--- a/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
+++ b/core/arch/arm/dts/stm32mp15xx-dkx.dtsi
@@ -242,6 +242,7 @@
 };
 
 &i2c4 {
+	compatible = "st,stm32mp15-i2c-non-secure";
 	pinctrl-names = "default", "sleep";
 	pinctrl-0 = <&i2c4_pins_a>;
 	pinctrl-1 = <&i2c4_sleep_pins_a>;
@@ -742,5 +743,5 @@
 	regulator-min-microvolt = <2500000>;
 	regulator-max-microvolt = <2500000>;
 	vdda-supply = <&vdd>;
-	status = "okay";
+	status = "disabled";
 };
diff --git a/core/arch/arm/dts/stm32mp25-pinctrl.dtsi b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi
index 5bd27767fbf5974dcbd14dd25e0aa8e167b975eb..0fa9d60e28ffd76cd18d3740a1915e18097b1d60 100644
--- a/core/arch/arm/dts/stm32mp25-pinctrl.dtsi
+++ b/core/arch/arm/dts/stm32mp25-pinctrl.dtsi
@@ -5,3 +5,30 @@
  */
 #include <dt-bindings/pinctrl/stm32-pinfunc.h>
 
+&pinctrl {
+	usart2_pins_a: usart2-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX_NSEC('A', 4, AF6)>; /* USART2_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX_NSEC('A', 8, AF8)>; /* USART2_RX */
+			bias-disable;
+		};
+	};
+
+	usart2_secure_pins_a: usart2-sec-0 {
+		pins1 {
+			pinmux = <STM32_PINMUX('A', 4, AF6)>; /* USART2_TX */
+			bias-disable;
+			drive-push-pull;
+			slew-rate = <0>;
+		};
+		pins2 {
+			pinmux = <STM32_PINMUX('A', 8, AF8)>; /* USART2_RX */
+			bias-disable;
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp251.dtsi b/core/arch/arm/dts/stm32mp251.dtsi
index edbf84679c5a646d97cd2328e6c3fe28b87d449c..c6e8d622c45c428c287132f1109d2cac86f7d386 100644
--- a/core/arch/arm/dts/stm32mp251.dtsi
+++ b/core/arch/arm/dts/stm32mp251.dtsi
@@ -4,7 +4,13 @@
  * Author: Alexandre Torgue <alexandre.torgue@foss.st.com> for STMicroelectronics.
  */
 
+#include <dt-bindings/clock/st,stm32mp25-rcc.h>
+#include <dt-bindings/firewall/stm32mp25-rif.h>
+#include <dt-bindings/firewall/stm32mp25-rifsc.h>
+#include <dt-bindings/firewall/stm32mp25-risaf.h>
+#include <dt-bindings/firewall/stm32mp25-risab.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/st,stm32mp25-rcc.h>
 
 / {
 	#address-cells = <2>;
@@ -75,12 +81,10 @@
 			clock-frequency = <0>;
 		};
 
-		clocks {
-			clk_rcbsec: clk-rcbsec {
-				#clock-cells = <0>;
-				compatible = "fixed-clock";
-				clock-frequency = <64000000>;
-			};
+		clk_rcbsec: clk-rcbsec {
+			#clock-cells = <0>;
+			compatible = "fixed-clock";
+			clock-frequency = <64000000>;
 		};
 	};
 
@@ -91,13 +95,181 @@
 		interrupt-parent = <&intc>;
 		ranges = <0x0 0x0 0x0 0x80000000>;
 
+		hpdma1: dma-controller@40400000 {
+			compatible = "st,stm32-dma3";
+			reg = <0x40400000 0x1000>;
+			clocks = <&rcc CK_BUS_HPDMA1>;
+			resets = <&rcc HPDMA1_R>;
+			#dma-cells = <4>;
+			status = "disabled";
+		};
+
+		hpdma2: dma-controller@40410000 {
+			compatible = "st,stm32-dma3";
+			reg = <0x40410000 0x1000>;
+			clocks = <&rcc CK_BUS_HPDMA2>;
+			resets = <&rcc HPDMA2_R>;
+			#dma-cells = <4>;
+			status = "disabled";
+		};
+
+		hpdma3: dma-controller@40420000 {
+			compatible = "st,stm32-dma3";
+			reg = <0x40420000 0x1000>;
+			clocks = <&rcc CK_BUS_HPDMA3>;
+			resets = <&rcc HPDMA3_R>;
+			#dma-cells = <4>;
+			status = "disabled";
+		};
+
+		ipcc1: mailbox@40490000 {
+			compatible = "st,stm32mp25-ipcc";
+			reg = <0x40490000 0x400>;
+			interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+			interrupt-names = "rx";
+			clocks = <&rcc CK_BUS_IPCC1>;
+			status = "disabled";
+		};
+
 		rifsc: rifsc@42080000 {
+			compatible = "st,stm32mp25-rifsc", "simple-bus";
 			reg = <0x42080000 0x1000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#access-controller-cells = <1>;
 
 			usart2: serial@400e0000 {
+				compatible = "st,stm32h7-uart";
 				reg = <0x400e0000 0x400>;
+				interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&rcc CK_KER_USART2>;
+				access-controllers = <&rifsc STM32MP25_RIFSC_USART2_ID>;
+				status = "disabled";
+			};
+
+			rng: rng@42020000 {
+				compatible = "st,stm32mp25-rng";
+				reg = <0x42020000 0x400>;
+				clocks = <&clk_rcbsec>, <&rcc CK_BUS_RNG>;
+				clock-names = "rng_clk", "rng_hclk";
+				resets = <&rcc RNG_R>;
+				access-controllers = <&rifsc STM32MP25_RIFSC_RNG_ID>;
+			};
+		};
+
+		iac: iac@42090000 {
+			compatible = "st,stm32mp25-iac";
+			reg = <0x42090000 0x400>;
+			interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+		};
+
+		risaf1: risaf@420a0000 {
+			compatible = "st,stm32mp25-risaf";
+			reg = <0x420a0000 0x1000>;
+			clocks = <&rcc CK_BUS_BKPSRAM>;
+			st,mem-map = <0x0 0x42000000 0x0 0x2000>;
+		};
+
+		risaf2: risaf@420b0000 {
+			compatible = "st,stm32mp25-risaf";
+			reg = <0x420b0000 0x1000>;
+			clocks = <&rcc CK_KER_OSPI1>;
+			st,mem-map = <0x0 0x60000000 0x0 0x10000000>;
+			status = "disabled";
+		};
+
+		risaf4: risaf@420d0000 {
+			compatible = "st,stm32mp25-risaf-enc";
+			reg = <0x420d0000 0x1000>;
+			clocks = <&rcc CK_BUS_RISAF4>;
+			st,mem-map = <0x0 0x80000000 0x1 0x00000000>;
+		};
+
+		risaf5: risaf@420e0000 {
+			compatible = "st,stm32mp25-risaf";
+			reg = <0x420e0000 0x1000>;
+			clocks = <&rcc CK_BUS_PCIE>;
+			st,mem-map = <0x0 0x10000000 0x0 0x10000000>;
+			status = "disabled";
+		};
+
+		risab1: risab@420f0000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x420f0000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa000000 0x20000>;
+			#access-controller-cells = <1>;
+		};
+
+		risab2: risab@42100000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x42100000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa020000 0x20000>;
+			#access-controller-cells = <1>;
+		};
+
+		risab3: risab@42110000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x42110000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa040000 0x20000>;
+			#access-controller-cells = <1>;
+		};
+
+		risab4: risab@42120000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x42120000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa060000 0x20000>;
+			#access-controller-cells = <1>;
+		};
+
+		risab5: risab@42130000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x42130000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa080000 0x20000>;
+			#access-controller-cells = <1>;
+		};
+
+		risab6: risab@42140000 {
+			compatible = "st,stm32mp25-risab";
+			reg = <0x42140000 0x1000>;
+			clocks = <&rcc CK_ICN_LS_MCU>;
+			st,mem-map = <0xa0a0000 0x20000>;
+			#access-controller-cells = <1>;
+			status = "disabled";
+		};
+
+		serc: serc@44080000 {
+			compatible = "st,stm32mp25-serc";
+			reg = <0x44080000 0x1000>;
+			interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc CK_BUS_SERC>;
+		};
+
+		rcc: rcc@44200000 {
+			compatible = "st,stm32mp25-rcc", "syscon";
+			reg = <0x44200000 0x10000>;
+			interrupts = <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>;
+
+			#clock-cells = <1>;
+			#reset-cells = <1>;
+			clocks = <&clk_hse>, <&clk_hsi>, <&clk_lse>,
+				 <&clk_lsi>, <&clk_msi>, <&clk_i2sin>;
+			clock-names = "clk-hse", "clk-hsi", "clk-lse",
+				      "clk-lsi", "clk-msi", "clk-i2sin";
+
+			hsi_calibration: hsi-calibration {
+				compatible = "st,hsi-cal";
+				st,cal_hsi_dev = <31>;
+				st,cal_hsi_ref = <1953>;
+				status = "disabled";
+			};
+
+			msi_calibration: msi-calibration {
+				compatible = "st,msi-cal";
 				status = "disabled";
 			};
 		};
@@ -114,7 +286,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x0 0x400>;
+				clocks = <&rcc CK_BUS_GPIOA>;
 				st,bank-name = "GPIOA";
 				status = "disabled";
 			};
@@ -124,7 +298,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x10000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOB>;
 				st,bank-name = "GPIOB";
 				status = "disabled";
 			};
@@ -134,7 +310,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x20000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOC>;
 				st,bank-name = "GPIOC";
 				status = "disabled";
 			};
@@ -144,7 +322,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x30000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOD>;
 				st,bank-name = "GPIOD";
 				status = "disabled";
 			};
@@ -154,7 +334,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x40000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOE>;
 				st,bank-name = "GPIOE";
 				status = "disabled";
 			};
@@ -164,7 +346,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x50000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOF>;
 				st,bank-name = "GPIOF";
 				status = "disabled";
 			};
@@ -174,7 +358,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x60000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOG>;
 				st,bank-name = "GPIOG";
 				status = "disabled";
 			};
@@ -184,7 +370,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x70000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOH>;
 				st,bank-name = "GPIOH";
 				status = "disabled";
 			};
@@ -194,7 +382,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x80000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOI>;
 				st,bank-name = "GPIOI";
 				status = "disabled";
 			};
@@ -204,7 +394,9 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0x90000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOJ>;
 				st,bank-name = "GPIOJ";
 				status = "disabled";
 			};
@@ -214,12 +406,25 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0xa0000 0x400>;
+				clocks = <&rcc CK_BUS_GPIOK>;
 				st,bank-name = "GPIOK";
 				status = "disabled";
 			};
 		};
 
+		tamp: tamp@46010000 {
+			compatible = "st,stm32mp25-tamp";
+			reg = <0x46010000 0x400>;
+			clocks = <&rcc CK_BUS_RTC>;
+			interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges;
+			st,backup-zones = <24 24 24 24 12 12 8>;
+		};
+
 		pinctrl_z: pinctrl-z@46200000 {
 			#address-cells = <1>;
 			#size-cells = <1>;
@@ -232,11 +437,44 @@
 				#gpio-cells = <2>;
 				interrupt-controller;
 				#interrupt-cells = <2>;
+				#access-controller-cells = <1>;
 				reg = <0 0x400>;
+				clocks = <&rcc CK_BUS_GPIOZ>;
 				st,bank-name = "GPIOZ";
 				st,bank-ioport = <11>;
 				status = "disabled";
 			};
 		};
+
+		hsem: hwspinlock@46240000 {
+			compatible = "st,stm32mp25-hsem";
+			reg = <0x46240000 0x400>;
+			interrupts = <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&rcc CK_BUS_HSEM>;
+			status = "disabled";
+		};
+
+		ipcc2: mailbox@46250000 {
+			compatible = "st,stm32mp25-ipcc";
+			reg = <0x46250000 0x400>;
+			clocks = <&rcc CK_BUS_IPCC2>;
+			status = "disabled";
+		};
+
+		fmc: memory-controller@48200000 {
+			#address-cells = <2>;
+			#size-cells = <1>;
+			compatible = "st,stm32mp25-fmc2-ebi";
+			reg = <0x48200000 0x400>;
+			clocks = <&rcc CK_KER_FMC>;
+			resets = <&rcc FMC_R>;
+			status = "disabled";
+
+			ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */
+				 <1 0 0x64000000 0x04000000>, /* EBI CS 2 */
+				 <2 0 0x68000000 0x04000000>, /* EBI CS 3 */
+				 <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */
+				 <4 0 0x80000000 0x10000000>; /* NAND */
+		};
 	};
 };
diff --git a/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..a5a2f918f746f37f96be2a537ca2e913aa6c0d2b
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rcc.dtsi
@@ -0,0 +1,199 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+&clk_hse {
+	clock-frequency = <40000000>;
+};
+
+&clk_hsi {
+	clock-frequency = <64000000>;
+};
+
+&clk_lse {
+	clock-frequency = <32768>;
+};
+
+&clk_lsi {
+	clock-frequency = <32000>;
+};
+
+&clk_msi {
+	clock-frequency = <16000000>;
+};
+
+&rcc {
+	st,busclk = <
+		DIV_CFG(DIV_LSMCU, 1)
+		DIV_CFG(DIV_APB1, 0)
+		DIV_CFG(DIV_APB2, 0)
+		DIV_CFG(DIV_APB3, 0)
+		DIV_CFG(DIV_APB4, 0)
+		DIV_CFG(DIV_APBDBG, 0)
+	>;
+
+	st,flexgen = <
+		FLEXGEN_CFG(0, XBAR_SRC_PLL4, 0, 2)
+		FLEXGEN_CFG(1, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(2, XBAR_SRC_PLL4, 0, 1)
+		FLEXGEN_CFG(3, XBAR_SRC_PLL4, 0, 2)
+		FLEXGEN_CFG(4, XBAR_SRC_PLL4, 0, 3)
+		FLEXGEN_CFG(5, XBAR_SRC_PLL4, 0, 2)
+		FLEXGEN_CFG(6, XBAR_SRC_PLL4, 0, 1)
+		FLEXGEN_CFG(7, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(8, XBAR_SRC_HSI_KER, 0, 0)
+		FLEXGEN_CFG(9, XBAR_SRC_HSI_KER, 0, 0)
+		FLEXGEN_CFG(10, XBAR_SRC_PLL7, 0, 16)
+		FLEXGEN_CFG(11, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(12, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(13, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(14, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(15, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(16, XBAR_SRC_PLL4, 0, 23)
+		FLEXGEN_CFG(17, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(18, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(19, XBAR_SRC_HSI_KER, 0, 3)
+		FLEXGEN_CFG(20, XBAR_SRC_HSI_KER, 0, 0)
+		FLEXGEN_CFG(21, XBAR_SRC_HSI_KER, 0, 0)
+		FLEXGEN_CFG(22, XBAR_SRC_HSI_KER, 0, 0)
+		FLEXGEN_CFG(23, XBAR_SRC_PLL7, 0, 16)
+		FLEXGEN_CFG(24, XBAR_SRC_PLL7, 0, 16)
+		FLEXGEN_CFG(25, XBAR_SRC_PLL7, 0, 16)
+		FLEXGEN_CFG(26, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(27, XBAR_SRC_PLL8, 0, 3)
+		FLEXGEN_CFG(28, XBAR_SRC_PLL8, 0, 21)
+		FLEXGEN_CFG(29, XBAR_SRC_PLL5, 0, 1)
+		FLEXGEN_CFG(30, XBAR_SRC_HSE_KER, 0, 1)
+		FLEXGEN_CFG(31, XBAR_SRC_PLL5, 0, 19)
+		FLEXGEN_CFG(32, XBAR_SRC_PLL5, 0, 19)
+		FLEXGEN_CFG(33, XBAR_SRC_HSE_KER, 0, 0)
+		FLEXGEN_CFG(34, XBAR_SRC_PLL4, 0, 59)
+		FLEXGEN_CFG(35, XBAR_SRC_HSI_KER, 0, 3)
+		FLEXGEN_CFG(36, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(37, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(38, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(39, XBAR_SRC_MSI_KER, 0, 0)
+		FLEXGEN_CFG(40, XBAR_SRC_LSE, 0, 0)
+		FLEXGEN_CFG(41, XBAR_SRC_PLL4, 0, 11)
+		FLEXGEN_CFG(42, XBAR_SRC_PLL7, 0, 16)
+		FLEXGEN_CFG(43, XBAR_SRC_PLL4, 0, 23)
+		FLEXGEN_CFG(44, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(45, XBAR_SRC_PLL4, 0, 2)
+		FLEXGEN_CFG(46, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(47, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(48, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(49, XBAR_SRC_PLL5, 0, 3)
+		FLEXGEN_CFG(51, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(52, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(53, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(54, XBAR_SRC_PLL6, 0, 3)
+		FLEXGEN_CFG(55, XBAR_SRC_PLL6, 0, 3)
+		FLEXGEN_CFG(56, XBAR_SRC_PLL4, 0, 5)
+		FLEXGEN_CFG(57, XBAR_SRC_HSE_KER, 0, 1)
+		FLEXGEN_CFG(58, XBAR_SRC_HSE_KER, 0, 1)
+		FLEXGEN_CFG(59, XBAR_SRC_PLL4, 0, 1)
+		FLEXGEN_CFG(60, XBAR_SRC_PLL4, 0, 23)
+		FLEXGEN_CFG(61, XBAR_SRC_PLL4, 0, 7)
+		FLEXGEN_CFG(62, XBAR_SRC_PLL4, 0, 7)
+		FLEXGEN_CFG(63, XBAR_SRC_PLL4, 0, 2)
+	>;
+
+	st,kerclk = <
+		MUX_CFG(MUX_ADC12, MUX_ADC12_FLEX46)
+		MUX_CFG(MUX_USB2PHY1, MUX_USB2PHY1_FLEX57)
+		MUX_CFG(MUX_USB2PHY2, MUX_USB2PHY2_FLEX58)
+		MUX_CFG(MUX_USB3PCIEPHY, MUX_USB3PCIEPHY_HSE)
+		MUX_CFG(MUX_DSIPHY, MUX_DSIPHY_FLEX28)
+		MUX_CFG(MUX_DSIBLANE, MUX_DSIBLANE_DSIPHY)
+		MUX_CFG(MUX_LVDSPHY, MUX_LVDSPHY_FLEX32)
+		MUX_CFG(MUX_DTS, MUX_DTS_HSE)
+		MUX_CFG(MUX_RTC, MUX_RTC_LSE)
+		MUX_CFG(MUX_D3PER, MUX_D3PER_MSI)
+		MCO_CFG(MCO1, MUX_MCO1_FLEX61, MCO_OFF)
+		MCO_CFG(MCO2, MUX_MCO2_FLEX62, MCO_OFF)
+	>;
+
+	pll1: st,pll-1 {
+		st,pll = <&pll1_cfg_1200Mhz>;
+
+		pll1_cfg_1200Mhz: pll1-cfg-1200Mhz {
+			cfg = <30 1 1 1>;
+			src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>;
+		};
+
+		pll1_cfg_1500Mhz: pll1-cfg-1500Mhz {
+			cfg = <75 2 1 1>;
+			src = <MUX_CFG(MUX_MUXSEL5, MUXSEL_HSE)>;
+		};
+	};
+
+	pll2: st,pll-2 {
+		st,pll = <&pll2_cfg_600Mhz>;
+
+		pll2_cfg_600Mhz: pll2-cfg-600Mhz {
+			cfg = <30 1 1 2>;
+			src = <MUX_CFG(MUX_MUXSEL6, MUXSEL_HSE)>;
+		};
+	};
+
+	pll3: st,pll-3 {
+		st,pll = <&pll3_cfg_800Mhz>;
+
+		pll3_cfg_800Mhz: pll3-cfg-800Mhz {
+			cfg = <20 1 1 1>;
+			src = <MUX_CFG(MUX_MUXSEL7, MUXSEL_HSE)>;
+		};
+
+		pll3_cfg_900Mhz: pll3-cfg-900Mhz {
+			cfg = <45 2 1 1>;
+			src = <MUX_CFG(MUX_MUXSEL7, MUXSEL_HSE)>;
+		};
+	};
+
+	pll4: st,pll-4 {
+		st,pll = <&pll4_cfg_1200Mhz>;
+
+		pll4_cfg_1200Mhz: pll4-cfg-1200Mhz {
+			cfg = <30 1 1 1>;
+			src = <MUX_CFG(MUX_MUXSEL0, MUXSEL_HSE)>;
+		};
+	};
+
+	pll5: st,pll-5 {
+		st,pll = <&pll5_cfg_532Mhz>;
+
+		pll5_cfg_532Mhz: pll5-cfg-532Mhz {
+			cfg = <133 5 1 2>;
+			src = <MUX_CFG(MUX_MUXSEL1, MUXSEL_HSE)>;
+		};
+	};
+
+	pll6: st,pll-6 {
+		st,pll = <&pll6_cfg_500Mhz>;
+
+		pll6_cfg_500Mhz: pll6-cfg-500Mhz {
+			cfg = <25 1 1 2>;
+			src = <MUX_CFG(MUX_MUXSEL2, MUXSEL_HSE)>;
+		};
+	};
+
+	pll7: st,pll-7 {
+		st,pll = <&pll7_cfg_835_51172Mhz>;
+
+		pll7_cfg_835_51172Mhz: pll7-cfg-835-51172Mhz {
+			cfg = <167 4 1 2>;
+			src = <MUX_CFG(MUX_MUXSEL3, MUXSEL_HSE)>;
+			frac = < 0x1A3337 >;
+		};
+	};
+
+	pll8: st,pll-8 {
+		st,pll = <&pll8_cfg_594Mhz>;
+
+		pll8_cfg_594Mhz: pll8-cfg-594Mhz {
+			cfg = <297 5 1 4>;
+			src = <MUX_CFG(MUX_MUXSEL4, MUXSEL_HSE)>;
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-resmem.dtsi b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-resmem.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..4b397c2927a17d2b452f77122448d0d773597feb
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-resmem.dtsi
@@ -0,0 +1,137 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+/ {
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		/* Internal RAM reserved memory declaration */
+		tfa_bl31: tfa-bl31@a000000 {
+			reg = <0x0 0xa000000 0x0 0x20000>;
+			no-map;
+		};
+
+		hpdma_lli: hpdma-lli@a020000 {
+			reg = <0x0 0xa020000 0x0 0x20000>;
+			no-map;
+		};
+
+		bsec_mirror: bsec-mirror@a040000 {
+			reg = <0x0 0xa040000 0x0 0x1000>;
+			no-map;
+		};
+
+		cm33_sram1: cm33-sram1@a041000 {
+			reg = <0x0 0xa041000 0x0 0x1f000>;
+			no-map;
+		};
+
+		cm33_sram2: cm33-sram2@a060000 {
+			reg = <0x0 0xa060000 0x0 0x20000>;
+			no-map;
+		};
+
+		cm33_retram: cm33-retram@a080000 {
+			reg = <0x0 0xa080000 0x0 0x1f000>;
+			no-map;
+		};
+
+		ddr_param: ddr-param@a09f000 {
+			reg = <0x0 0xa09f000 0x0 0x1000>;
+			no-map;
+		};
+
+		/* PCIe reserved memory declaration */
+		pcie_device: pcie-device@10000000 {
+			reg = <0x0 0x10000000 0x0 0x10000000>;
+			no-map;
+		};
+
+		/* Backup RAM reserved memory declaration */
+		bl31_lowpower: bl31-lowpower@42000000 {
+			reg = <0x0 0x42000000 0x0 0x1000>;
+			no-map;
+		};
+
+		tfm_its: tfm-its@42001000 {
+			reg = <0x0 0x42001000 0x0 0x1000>;
+			no-map;
+		};
+
+		/* Octo Memory Manager reserved memory declaration */
+		mm_ospi1: mm-ospi@60000000 {
+			reg = <0x0 0x60000000 0x0 0x10000000>;
+			no-map;
+		};
+
+		/* DDR reserved memory declaration */
+		tfm_code: tfm-code@80000000 {
+			reg = <0x0 0x80000000 0x0 0x100000>;
+			no-map;
+		};
+
+		cm33_cube_fw: cm33-cube-fw@80100000 {
+			reg = <0x0 0x80100000 0x0 0x800000>;
+			no-map;
+		};
+
+		tfm_data: tfm-data@80900000 {
+			reg = <0x0 0x80900000 0x0 0x100000>;
+			no-map;
+		};
+
+		cm33_cube_data: cm33-cube-data@80a00000 {
+			reg = <0x0 0x80a00000 0x0 0x800000>;
+			no-map;
+		};
+
+		ipc_shmem: ipc-shmem@81200000 {
+			reg = <0x0 0x81200000 0x0 0x100000>;
+			no-map;
+		};
+
+		spare1: spare1@81300000 {
+			reg = <0x0 0x81300000 0x0 0xcc0000>;
+			no-map;
+		};
+
+		bl31_context: bl31-context@81fc0000 {
+			reg = <0x0 0x81fc0000 0x0 0x40000>;
+			no-map;
+		};
+
+		op_tee: op-tee@82000000 {
+			reg = <0x0 0x82000000 0x0 0x2000000>;
+			no-map;
+		};
+
+		linuxkernel1: linuxkernel1@84000000 {
+			reg = <0x0 0x84000000 0x0 0x76800000>;
+			no-map;
+		};
+
+		gpu_reserved: gpu-reserved@fa800000 {
+			reg = <0x0 0xfa800000 0x0 0x4000000>;
+			no-map;
+		};
+
+		ltdc_sec_layer: ltdc-sec-layer@fe800000 {
+			reg = <0x0 0xfe800000 0x0 0x800000>;
+			no-map;
+		};
+
+		ltdc_sec_rotation: ltdc-sec-rotation@ff000000 {
+			reg = <0x0 0xff000000 0x0 0x1000000>;
+			no-map;
+		};
+
+		linuxkernel2: linuxkernel2@100000000 {
+			reg = <0x1 0x00000000 0x0 0x80000000>;
+			no-map;
+		};
+	};
+};
diff --git a/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi
new file mode 100644
index 0000000000000000000000000000000000000000..9346cbece0718d8191b0ba6108daa517875c3621
--- /dev/null
+++ b/core/arch/arm/dts/stm32mp257f-ev1-ca35tdcid-rif.dtsi
@@ -0,0 +1,772 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+/* Break alphabetical to group RIF configuration by feature to ease DT readability */
+
+&rifsc {
+	st,protreg = <
+		RIFPROT(STM32MP25_RIFSC_TIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM10_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM11_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM13_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM14_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM15_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM16_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM17_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_TIM20_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LPTIM1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_LPTIM2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LPTIM3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LPTIM4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LPTIM5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPI8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SPDIFRX_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USART2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USART3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UART4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UART5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USART6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UART7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UART8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UART9_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LPUART1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C6_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I2C7_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_I2C8_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SAI1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SAI2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SAI3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SAI4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_MDF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ADF1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_FDCAN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_HDP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ADC12_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ADC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ETH1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ETH2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ETHSW_DEIP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ETHSW_ACM_CFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USBH_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_USB3DR_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_COMBOPHY_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_PCIE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_UCPD1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_STGEN_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_SDMMC1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SDMMC2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SDMMC3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_GPU_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LTDC_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LTDC_L0L1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LTDC_L2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LTDC_ROT_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_DSI_CMN_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_DSI_TRIG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_DSI_RDFIFO_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_LVDS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_CSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_DCMIPP_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_DCMI_PSSI_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_VDEC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_VENC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_RNG_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_PKA_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_SAES_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_HASH_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_CRYP1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_CRYP2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_IWDG1_ID, RIF_UNUSED, RIF_LOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_IWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_IWDG3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_IWDG4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_IWDG5_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_WWDG1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_WWDG2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_VREFBUF_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_DTS_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_RAMCFG_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_CRC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_SERC_ID, RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(STM32MP25_RIFSC_GICV2M_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I3C1_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I3C2_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I3C3_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_I3C4_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(STM32MP25_RIFSC_ICACHE_DCACHE_ID, RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+	st,rimu = <
+		RIMUPROT(RIMU_ID(0), RIF_CID1, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
+		RIMUPROT(RIMU_ID(1), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(2), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(3), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(4), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(5), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(6), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(7), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(8), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(9), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(10), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(11), RIF_CID0, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
+		RIMUPROT(RIMU_ID(12), RIF_CID0, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
+		RIMUPROT(RIMU_ID(13), RIF_CID0, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_M)
+		RIMUPROT(RIMU_ID(14), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+		RIMUPROT(RIMU_ID(15), RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CIDSEL_P)
+	>;
+	st,glocked = <RIFSC_RIMU_GLOCK>;
+};
+
+&tamp {
+	st,protreg = <
+		RIFPROT(RIF_TAMP_RESOURCE(0), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_TAMP_RESOURCE(1), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_TAMP_RESOURCE(2), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+	>;
+	st,backup-zones = <24 24 24 24 12 12 8>;
+};
+
+&gpioa {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpiob {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpioc {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpiod {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&gpioe {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpiof {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpiog {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpioh {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpioi {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpioj {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpiok {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&gpioz {
+	st,protreg = <
+		RIFPROT(RIF_IOPORT_PIN(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_IOPORT_PIN(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IOPORT_PIN(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&hpdma1 {
+	st,protreg = <
+		RIFPROT(RIF_HPDMA_CHANNEL(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&hpdma2 {
+	st,protreg = <
+		RIFPROT(RIF_HPDMA_CHANNEL(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&hpdma3 {
+	st,protreg = <
+		RIFPROT(RIF_HPDMA_CHANNEL(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_HPDMA_CHANNEL(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&rcc {
+	st,protreg = <
+		RIFPROT(RIF_RCC_RESOURCE(69), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(64), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(65), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(66), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(67), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(68), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(70), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(71), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(72), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_RCC_RESOURCE(73), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(74), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(75), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(76), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(77), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(78), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(79), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(80), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(81), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(82), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(83), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(84), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(85), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(86), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(87), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(88), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(89), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(90), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(91), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(92), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(93), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(94), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(95), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(96), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(97), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(98), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(99), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(100), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(101), RIF_CID1_BF, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(102), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_RCC_RESOURCE(103), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(104), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(105), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(106), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(108), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(109), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(110), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_RCC_RESOURCE(111), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_RCC_RESOURCE(112), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(113), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(0), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(1), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(2), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(3), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(4), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(5), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(6), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(7), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(8), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(9), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(10), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(11), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(12), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(13), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(14), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(15), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(16), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(17), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(18), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(19), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(20), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(21), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(22), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(23), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(24), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(25), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(26), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(27), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(28), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(29), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(30), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(31), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(32), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(33), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(34), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(35), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(36), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(37), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(38), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(39), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(40), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(41), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(42), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(43), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(44), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(45), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(46), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(47), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(48), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(49), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(50), EMPTY_SEMWL, RIF_UNLOCK, RIF_NSEC, RIF_PRIV, RIF_UNUSED, RIF_SEM_EN, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(51), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(52), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(53), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(54), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(55), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(56), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(57), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(58), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(59), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(60), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(61), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(62), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_RCC_RESOURCE(63), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&ipcc1 {
+	st,protreg = <
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(13), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(14), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(15), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(16), RIF_UNUSED, RIF_UNLOCK, RIF_SEC, RIF_PRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(16), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID2, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&ipcc2 {
+	st,protreg = <
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU1_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID3, RIF_SEM_DIS, RIF_CFEN)
+		RIFPROT(RIF_IPCC_CPU2_CHANNEL(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_CID1, RIF_SEM_DIS, RIF_CFEN)
+	>;
+};
+
+&hsem {
+	st,proccid = <1 RIF_CID1>, <2 RIF_CID2>, <3 RIF_CID3>;
+	st,protreg = <
+		RIFPROT(RIF_HSEM_RESOURCE(0), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(1), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(2), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(3), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(4), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(5), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(6), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(7), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(8), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(9), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(10), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(11), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(12), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(13), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(14), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+		RIFPROT(RIF_HSEM_RESOURCE(15), RIF_UNUSED, RIF_UNLOCK, RIF_NSEC, RIF_NPRIV, RIF_UNUSED, RIF_SEM_DIS, RIF_CFDIS)
+	>;
+};
+
+&tfa_bl31 {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_SEC, RIF_UNUSED, RIF_CFEN, RIF_CID1_BF, RIF_CID1_BF, RIF_CID1_BF)>;
+};
+
+&hpdma_lli {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_NSEC, RIF_PRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&bsec_mirror {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_SEC, RIF_NPRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&cm33_sram1 {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_NSEC, RIF_NPRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&cm33_sram2 {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_NSEC, RIF_NPRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&cm33_retram {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_SEC, RIF_NPRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&ddr_param {
+	st,protreg = <RISABPROT(RIF_DDCID_DIS, RIF_UNUSED, RIF_SEC, RIF_NPRIV, RIF_CFDIS, RIF_UNUSED, RIF_UNUSED, RIF_UNUSED)>;
+};
+
+&risab1 {
+	memory-region = <&tfa_bl31>;
+};
+
+&risab2 {
+	memory-region = <&hpdma_lli>;
+};
+
+&risab3 {
+	st,srwiad;
+	memory-region = <&bsec_mirror>, <&cm33_sram1>;
+};
+
+&risab4 {
+	st,srwiad;
+	memory-region = <&cm33_sram2>;
+};
+
+&risab5 {
+	st,srwiad;
+	memory-region = <&cm33_retram>, <&ddr_param>;
+};
+
+&mm_ospi1 {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(1), RIF_CID1_BF | RIF_CID2_BF, RIF_CID1_BF | RIF_CID2_BF, 0, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&risaf2 {
+	memory-region = <&mm_ospi1>;
+};
+
+&pcie_device {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(1), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&risaf5 {
+	memory-region = <&pcie_device>;
+};
+
+&bl31_lowpower {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(1), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_CID1_BF, RIF_SEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&tfm_its {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(2), RIF_CID2_BF, RIF_CID2_BF, RIF_CID2_BF, RIF_SEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&risaf1 {
+	memory-region = <&bl31_lowpower>, <&tfm_its>;
+};
+
+&tfm_code {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(1), RIF_CID2_BF, RIF_CID2_BF, RIF_UNUSED, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
+};
+
+&cm33_cube_fw {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(2), RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&tfm_data {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(3), RIF_CID2_BF, RIF_CID2_BF, RIF_UNUSED, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
+};
+
+&cm33_cube_data {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(4), RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&ipc_shmem {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(5), RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&spare1 {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(6), RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_CID0_BF|RIF_CID1_BF|RIF_CID2_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&bl31_context {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(7), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
+};
+
+&op_tee {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(8), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_SEC, RIF_ENC_EN, RIF_BREN_EN)>;
+};
+
+&linuxkernel1 {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(9), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&gpu_reserved {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(10), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&ltdc_sec_layer {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(13), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&ltdc_sec_rotation {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(14), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&linuxkernel2 {
+	st,protreg = <RISAFPROT(RISAF_REG_ID(15), RIF_CID0_BF|RIF_CID1_BF, RIF_CID0_BF|RIF_CID1_BF, RIF_UNUSED, RIF_NSEC, RIF_ENC_DIS, RIF_BREN_EN)>;
+};
+
+&risaf4 {
+	memory-region = <&tfm_code>, <&cm33_cube_fw>, <&tfm_data>, <&cm33_cube_data>, <&ipc_shmem>, <&spare1>, <&bl31_context>, <&op_tee>, <&linuxkernel1>, <&gpu_reserved>, <&ltdc_sec_layer>, <&ltdc_sec_rotation>, <&linuxkernel2>;
+};
diff --git a/core/arch/arm/dts/stm32mp257f-ev1.dts b/core/arch/arm/dts/stm32mp257f-ev1.dts
index 3219c1e12f8d1495442ce7c220b917064699d854..8d173f12bc04296873e2579642e6936c1c28390f 100644
--- a/core/arch/arm/dts/stm32mp257f-ev1.dts
+++ b/core/arch/arm/dts/stm32mp257f-ev1.dts
@@ -5,10 +5,13 @@
  */
 
 /dts-v1/;
-
-#include "stm32mp25-pinctrl.dtsi"
+#include <dt-bindings/clock/stm32mp25-clksrc.h>
 #include "stm32mp257.dtsi"
+#include "stm32mp257f-ev1-ca35tdcid-rcc.dtsi"
+#include "stm32mp257f-ev1-ca35tdcid-resmem.dtsi"
+#include "stm32mp257f-ev1-ca35tdcid-rif.dtsi"
 #include "stm32mp25xf.dtsi"
+#include "stm32mp25-pinctrl.dtsi"
 #include "stm32mp25xxai-pinctrl.dtsi"
 
 / {
@@ -28,3 +31,41 @@
 		reg = <0x0 0x80000000 0x1 0x00000000>;
 	};
 };
+
+&hpdma1 {
+	status = "okay";
+};
+
+&hpdma2 {
+	status = "okay";
+};
+
+&hpdma3 {
+	status = "okay";
+};
+
+&hsem {
+	status = "okay";
+};
+
+&ipcc1 {
+	status = "okay";
+};
+
+&ipcc2 {
+	status = "okay";
+};
+
+&risaf2 {
+	status = "okay";
+};
+
+&risaf5 {
+	status = "okay";
+};
+
+&usart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&usart2_pins_a>;
+	status = "okay";
+};
diff --git a/core/arch/arm/include/arm.h b/core/arch/arm/include/arm.h
index 43504ba5b05ab501b0c8817c676497c8b8786f4d..49c5cd0dd95c8e20a1be6002050f30de8bb35471 100644
--- a/core/arch/arm/include/arm.h
+++ b/core/arch/arm/include/arm.h
@@ -76,6 +76,15 @@
 #define MPIDR_AARCH32_AFF_MASK	(MPIDR_AFF0_MASK | MPIDR_AFF1_MASK | \
 				 MPIDR_AFF2_MASK)
 
+/* MPIDR definitions for VCPU */
+#define MPIDR_VCPU_MASK		ULL(0xffffff)
+
+/* ID_ISAR5 Cryptography Extension masks */
+#define ID_ISAR5_AES		GENMASK_32(7, 4)
+#define ID_ISAR5_SHA1		GENMASK_32(11, 8)
+#define ID_ISAR5_SHA2		GENMASK_32(15, 12)
+#define ID_ISAR5_CRC32		GENMASK_32(19, 16)
+
 /* CLIDR definitions */
 #define CLIDR_LOUIS_SHIFT	U(21)
 #define CLIDR_LOC_SHIFT		U(24)
@@ -174,11 +183,74 @@ static inline unsigned int feat_pan_implemented(void)
 
 static inline bool feat_crc32_implemented(void)
 {
+#ifdef ARM32
+	return read_id_isar5() & ID_ISAR5_CRC32;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_CRC32;
+#endif
+}
+
+static inline bool feat_aes_implemented(void)
+{
+#ifdef ARM32
+	return read_id_isar5() & ID_ISAR5_AES;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_AES;
+#endif
+}
+
+static inline bool feat_sha1_implemented(void)
+{
+#ifdef ARM32
+	return read_id_isar5() & ID_ISAR5_SHA1;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA1;
+#endif
+}
+
+static inline bool feat_sha256_implemented(void)
+{
+#ifdef ARM32
+	return read_id_isar5() & ID_ISAR5_SHA2;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2;
+#endif
+}
+
+static inline bool feat_sha512_implemented(void)
+{
+#ifdef ARM32
+	return false;
+#else
+	return ((read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA2) >>
+		ID_AA64ISAR0_SHA2_SHIFT) == ID_AA64ISAR0_SHA2_FEAT_SHA512;
+#endif
+}
+
+static inline bool feat_sha3_implemented(void)
+{
+#ifdef ARM32
+	return false;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_SHA3;
+#endif
+}
+
+static inline bool feat_sm3_implemented(void)
+{
+#ifdef ARM32
+	return false;
+#else
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM3;
+#endif
+}
+
+static inline bool feat_sm4_implemented(void)
+{
 #ifdef ARM32
 	return false;
 #else
-	return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_EL1_CRC32_SHIFT) &
-		ID_AA64ISAR0_EL1_CRC32_MASK) == FEAT_CRC32_IMPLEMENTED;
+	return read_id_aa64isar0_el1() & ID_AA64ISAR0_SM4;
 #endif
 }
 
diff --git a/core/arch/arm/include/arm64.h b/core/arch/arm/include/arm64.h
index 23a21c41c42e6b86a941b2b05515dadf9b09f4f8..c72b5cd7bbd3d315c72c28fcbb8b35387b7cb108 100644
--- a/core/arch/arm/include/arm64.h
+++ b/core/arch/arm/include/arm64.h
@@ -57,6 +57,14 @@
 #define DAIFBIT_ALL			(DAIFBIT_FIQ | DAIFBIT_IRQ | \
 					 DAIFBIT_ABT | DAIFBIT_DBG)
 
+#if defined(CFG_CORE_IRQ_IS_NATIVE_INTR)
+#define DAIFBIT_NATIVE_INTR		DAIFBIT_IRQ
+#define DAIFBIT_FOREIGN_INTR		DAIFBIT_FIQ
+#else
+#define DAIFBIT_NATIVE_INTR		DAIFBIT_FIQ
+#define DAIFBIT_FOREIGN_INTR		DAIFBIT_IRQ
+#endif
+
 #define DAIF_F_SHIFT		U(6)
 #define DAIF_F			BIT32(6)
 #define DAIF_I			BIT32(7)
@@ -249,11 +257,6 @@
 #define FEAT_PAN2_IMPLEMENTED		U(0x2)
 #define FEAT_PAN3_IMPLEMENTED		U(0x3)
 
-#define ID_AA64ISAR0_EL1_CRC32_MASK	UL(0xf)
-#define ID_AA64ISAR0_EL1_CRC32_SHIFT	U(16)
-#define FEAT_CRC32_NOT_IMPLEMENTED	U(0x0)
-#define FEAT_CRC32_IMPLEMENTED		U(0x1)
-
 #define ID_AA64ISAR1_GPI_SHIFT		U(28)
 #define ID_AA64ISAR1_GPI_MASK		U(0xf)
 #define ID_AA64ISAR1_GPI_NI		U(0x0)
@@ -286,6 +289,22 @@
 
 #define GCR_EL1_RRND				BIT64(16)
 
+/* ID_AA64ISAR0_EL1, AArch64 Instruction Set Attribute Register 0 */
+#define ID_AA64ISAR0_AES	GENMASK_64(7, 4)
+#define ID_AA64ISAR0_SHA1	GENMASK_64(11, 8)
+#define ID_AA64ISAR0_SHA2	GENMASK_64(15, 12)
+#define ID_AA64ISAR0_CRC32	GENMASK_64(19, 16)
+#define ID_AA64ISAR0_ATOMIC	GENMASK_64(23, 20)
+#define ID_AA64ISAR0_TME	GENMASK_64(27, 24)
+#define ID_AA64ISAR0_RDM	GENMASK_64(31, 28)
+#define ID_AA64ISAR0_SHA3	GENMASK_64(35, 32)
+#define ID_AA64ISAR0_SM3	GENMASK_64(39, 36)
+#define ID_AA64ISAR0_SM4	GENMASK_64(43, 40)
+
+#define ID_AA64ISAR0_SHA2_SHIFT		U(12)
+#define ID_AA64ISAR0_SHA2_FEAT_SHA256	U(1)
+#define ID_AA64ISAR0_SHA2_FEAT_SHA512	U(2)
+
 #ifndef __ASSEMBLER__
 static inline __noprof void isb(void)
 {
@@ -433,8 +452,15 @@ static inline __noprof void write_##reg(type val)		\
 
 DEFINE_U32_REG_READWRITE_FUNCS(cpacr_el1)
 DEFINE_U32_REG_READWRITE_FUNCS(daif)
+#ifdef __clang__
+DEFINE_REG_READ_FUNC_(fpcr, uint32_t, S3_3_c4_c4_0)
+DEFINE_REG_WRITE_FUNC_(fpcr, uint32_t, S3_3_c4_c4_0)
+DEFINE_REG_READ_FUNC_(fpsr, uint32_t, S3_3_c4_c4_1)
+DEFINE_REG_WRITE_FUNC_(fpsr, uint32_t, S3_3_c4_c4_1)
+#else
 DEFINE_U32_REG_READWRITE_FUNCS(fpcr)
 DEFINE_U32_REG_READWRITE_FUNCS(fpsr)
+#endif
 
 DEFINE_U32_REG_READ_FUNC(ctr_el0)
 #define read_ctr() read_ctr_el0()
@@ -451,6 +477,8 @@ DEFINE_REG_READ_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
 DEFINE_REG_WRITE_FUNC_(cntps_ctl, uint32_t, cntps_ctl_el1)
 DEFINE_REG_READ_FUNC_(cntps_tval, uint32_t, cntps_tval_el1)
 DEFINE_REG_WRITE_FUNC_(cntps_tval, uint32_t, cntps_tval_el1)
+DEFINE_REG_READ_FUNC_(cntps_cval, uint64_t, cntps_cval_el1)
+DEFINE_REG_WRITE_FUNC_(cntps_cval, uint64_t, cntps_cval_el1)
 
 DEFINE_REG_READ_FUNC_(pmccntr, uint64_t, pmccntr_el0)
 
diff --git a/core/arch/arm/include/ffa.h b/core/arch/arm/include/ffa.h
index 1a7baccfb1f21c4dcacdb73a3f14a196f2498c0f..cb094b47634187b9f73c81971a52f1d4781101f6 100644
--- a/core/arch/arm/include/ffa.h
+++ b/core/arch/arm/include/ffa.h
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: BSD-3-Clause */
 /*
  * Copyright (c) 2020, Linaro Limited
- * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2024, Arm Limited. All rights reserved.
  */
 
 #ifndef __FFA_H
@@ -23,6 +23,7 @@
 #define FFA_DENIED		-6
 #define FFA_RETRY		-7
 #define FFA_ABORTED		-8
+#define FFA_NO_DATA		-9
 
 /* FFA_VERSION helpers */
 #define FFA_VERSION_MAJOR		U(1)
@@ -95,6 +96,19 @@
 #define FFA_FEATURES_FUNC_ID_MASK	BIT32(31)
 #define FFA_FEATURES_FEATURE_ID_MASK	GENMASK_32(7, 0)
 
+/* Flags used in calls to FFA_NOTIFICATION_GET interface  */
+#define FFA_NOTIF_FLAG_BITMAP_SP	BIT(0)
+#define FFA_NOTIF_FLAG_BITMAP_VM	BIT(1)
+#define FFA_NOTIF_FLAG_BITMAP_SPM	BIT(2)
+#define FFA_NOTIF_FLAG_BITMAP_HYP	BIT(3)
+
+/* Flags used in calls to FFA_NOTIFICATION_INFO_GET interface */
+#define FFA_NOTIF_INFO_GET_MORE_FLAG		BIT(0)
+#define FFA_NOTIF_INFO_GET_ID_LIST_SHIFT	12
+#define FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT	7
+#define FFA_NOTIF_INFO_GET_ID_COUNT_MASK	0x1F
+
+/* Feature IDs used with FFA_FEATURES */
 #define FFA_FEATURE_NOTIF_PEND_INTR	U(0x1)
 #define FFA_FEATURE_SCHEDULE_RECV_INTR	U(0x2)
 #define FFA_FEATURE_MANAGED_EXIT_INTR	U(0x3)
@@ -223,6 +237,12 @@
 #define FFA_CONSOLE_LOG_32_MAX_MSG_LEN	U(24)
 #define FFA_CONSOLE_LOG_64_MAX_MSG_LEN	U(48)
 
+/* Memory transaction type in FFA_MEM_RETRIEVE_RESP flags */
+#define FFA_MEMORY_TRANSACTION_TYPE_MASK	GENMASK_32(4, 3)
+#define FFA_MEMORY_TRANSACTION_TYPE_SHARE	SHIFT_U32(1, 3)
+#define FFA_MEMORY_TRANSACTION_TYPE_LEND	SHIFT_U32(2, 3)
+#define FFA_MEMORY_TRANSACTION_TYPE_DONATE	SHIFT_U32(3, 3)
+
 #ifndef __ASSEMBLER__
 /* Constituent memory region descriptor */
 struct ffa_address_range {
diff --git a/core/arch/arm/include/hafnium.h b/core/arch/arm/include/hafnium.h
deleted file mode 100644
index 542ae8f3ccf980b7c517e047fe72bed71b2915ce..0000000000000000000000000000000000000000
--- a/core/arch/arm/include/hafnium.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Copyright 2018 The Hafnium Authors.
- * Copyright (c) 2022, Linaro Limited
- */
-
-#ifndef __HAFNIUM_H
-#define __HAFNIUM_H
-
-/*
- * This is based on inc/vmapi/hf/abi.h and inc/vmapi/hf/types.h from the
- * Hafnium source tree.
- */
-
-/*
- * Enables a given interrupt ID, returns 0 on success or -1 if the
- * interrupt ID is invalid.
- */
-#define HF_INTERRUPT_ENABLE	0xff03
-
-/*
- * Returns the ID of the next pending interrupt, and acknowledges it (i.e.
- * marks it as no longer pending). Returns HF_INVALID_INTID if there are no
- * pending interrupts.
- */
-#define HF_INTERRUPT_GET	0xff04
-
-/*
- * Drops the current interrupt priority and deactivate the given interrupt
- * ID.
- */
-#define HF_INTERRUPT_DEACTIVATE	0xff08
-
-/* Interrupt ID returned when there is no interrupt pending. */
-#define HF_INVALID_INTID	0xffffffff
-
-/* The virtual interrupt ID used for managed exit. */
-#define HF_MANAGED_EXIT_INTID	4
-
-#define HF_INTERRUPT_TYPE_IRQ	0
-#define HF_INTERRUPT_TYPE_FIQ	1
-#define HF_ENABLE		1
-#define HF_DISABLE		0
-
-#endif /*__HAFNIUM_H*/
diff --git a/core/arch/arm/include/kernel/delay_arch.h b/core/arch/arm/include/kernel/delay_arch.h
index 12a2080ff029f5590200ab34aecf444ca96f24ce..4008e694d8d8b7e77b150c065212366a00425725 100644
--- a/core/arch/arm/include/kernel/delay_arch.h
+++ b/core/arch/arm/include/kernel/delay_arch.h
@@ -30,23 +30,18 @@
 #ifndef __KERNEL_DELAY_ARCH_H
 #define __KERNEL_DELAY_ARCH_H
 
+#ifdef CFG_CORE_HAS_GENERIC_TIMER
 #include <arm.h>
-#include <stdbool.h>
 #include <stdint.h>
 
-static inline uint64_t arm_cnt_us2cnt(uint32_t us)
+static inline unsigned int delay_cnt_freq(void)
 {
-	return ((uint64_t)us * (uint64_t)read_cntfrq()) / 1000000ULL;
+	return read_cntfrq();
 }
 
-static inline uint64_t timeout_init_us(uint32_t us)
+static inline uint64_t delay_cnt_read(void)
 {
-	return barrier_read_counter_timer() + arm_cnt_us2cnt(us);
+	return barrier_read_counter_timer();
 }
-
-static inline bool timeout_elapsed(uint64_t expire)
-{
-	return barrier_read_counter_timer() > expire;
-}
-
+#endif /* CFG_CORE_HAS_GENERIC_TIMER */
 #endif
diff --git a/core/arch/arm/include/kernel/secure_partition.h b/core/arch/arm/include/kernel/secure_partition.h
index 9924148cb790288535ce67bf3792d71bae4c8148..f8374ba576e0f04dee8307da11f809976205e07d 100644
--- a/core/arch/arm/include/kernel/secure_partition.h
+++ b/core/arch/arm/include/kernel/secure_partition.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (c) 2020-2023, Arm Limited.
+ * Copyright (c) 2020-2024, Arm Limited.
  */
 #ifndef __KERNEL_SECURE_PARTITION_H
 #define __KERNEL_SECURE_PARTITION_H
@@ -33,6 +33,7 @@ struct sp_session {
 	TEE_UUID ffa_uuid;
 	uint32_t ns_int_mode;
 	uint32_t ns_int_mode_inherited;
+	uint32_t props;
 	TAILQ_ENTRY(sp_session) link;
 };
 
diff --git a/core/arch/arm/include/kernel/spmc_sp_handler.h b/core/arch/arm/include/kernel/spmc_sp_handler.h
index d43ee40cd0ae052f51754102fb88dd43b61cef78..4ee0d3357f3f35632831a1fd9e051a3bc61ccccc 100644
--- a/core/arch/arm/include/kernel/spmc_sp_handler.h
+++ b/core/arch/arm/include/kernel/spmc_sp_handler.h
@@ -23,7 +23,7 @@ bool ffa_mem_reclaim(struct thread_smc_args *args,
 #ifdef CFG_SECURE_PARTITION
 void spmc_sp_start_thread(struct thread_smc_args *args);
 int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans,
-		      struct ffa_rxtx *rxtx, size_t blen,
+		      struct ffa_rxtx *rxtx, size_t blen, size_t flen,
 		      uint64_t *global_handle, struct sp_session *owner_sp);
 void spmc_sp_set_to_preempted(struct ts_session *ts_sess);
 int spmc_sp_resume_from_preempted(uint16_t endpoint_id);
@@ -35,7 +35,7 @@ static inline void spmc_sp_start_thread(struct thread_smc_args *args __unused)
 static inline int
 spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans __unused,
 		  struct ffa_rxtx *rxtx __unused, size_t blen __unused,
-		  uint64_t *global_handle __unused,
+		  size_t flen __unused, uint64_t *global_handle __unused,
 		  struct sp_session *owner_sp __unused)
 {
 	return FFA_NOT_SUPPORTED;
diff --git a/core/arch/arm/include/kernel/stmm_sp.h b/core/arch/arm/include/kernel/stmm_sp.h
index f9da6a027a9dda55bb1b8f134716aff5558355e7..7f300c450858ccccd7afc7e4857c10df2b124e93 100644
--- a/core/arch/arm/include/kernel/stmm_sp.h
+++ b/core/arch/arm/include/kernel/stmm_sp.h
@@ -137,7 +137,6 @@ struct stmm_ctx {
 	struct thread_ctx_regs regs;
 	vaddr_t ns_comm_buf_addr;
 	unsigned int ns_comm_buf_size;
-	bool is_initializing;
 };
 
 extern const struct ts_ops stmm_sp_ops;
@@ -154,8 +153,21 @@ static inline struct stmm_ctx *to_stmm_ctx(struct ts_ctx *ctx)
 }
 
 #ifdef CFG_WITH_STMM_SP
+/*
+ * Setup session context for the StMM application
+ * @uuid: TA UUID
+ * @sess: Session for which to setup the StMM context
+ *
+ * This function must be called with tee_ta_mutex locked.
+ */
 TEE_Result stmm_init_session(const TEE_UUID *uuid,
 			     struct tee_ta_session *s);
+
+/*
+ * Finalize session context initialization the StMM application
+ * @sess: Session for which to finalize StMM context
+ */
+TEE_Result stmm_complete_session(struct tee_ta_session *s);
 #else
 static inline TEE_Result
 stmm_init_session(const TEE_UUID *uuid __unused,
@@ -163,6 +175,12 @@ stmm_init_session(const TEE_UUID *uuid __unused,
 {
 	return TEE_ERROR_ITEM_NOT_FOUND;
 }
+
+static inline TEE_Result
+stmm_complete_session(struct tee_ta_session *s __unused)
+{
+	return TEE_ERROR_GENERIC;
+}
 #endif
 
 #ifdef CFG_WITH_STMM_SP
diff --git a/core/arch/arm/include/kernel/thread_private_arch.h b/core/arch/arm/include/kernel/thread_private_arch.h
index d5b188429c360824be35ffc73d16c6a95cd444e1..11a32a17b820bc6c3e88953c516c67a6944819fc 100644
--- a/core/arch/arm/include/kernel/thread_private_arch.h
+++ b/core/arch/arm/include/kernel/thread_private_arch.h
@@ -38,22 +38,18 @@
 
 #ifdef ARM64
 #if (defined(__clang__) && !defined(__OPTIMIZE_SIZE__)) || \
-	defined(CFG_CORE_SANITIZE_KADDRESS)
+	defined(CFG_CORE_SANITIZE_KADDRESS) || defined(CFG_NS_VIRTUALIZATION)
 #define STACK_TMP_SIZE		(4096 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA)
 #else
 #define STACK_TMP_SIZE		(2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA)
 #endif
-#if defined(CFG_CORE_SANITIZE_KADDRESS)
+#if defined(CFG_CORE_SANITIZE_KADDRESS) || defined(CFG_CORE_DEBUG_CHECK_STACKS)
 #define STACK_THREAD_SIZE	(10240 + CFG_STACK_THREAD_EXTRA)
 #else
 #define STACK_THREAD_SIZE	(8192 + CFG_STACK_THREAD_EXTRA)
 #endif
 
-#if TRACE_LEVEL > 0
-#define STACK_ABT_SIZE		3072
-#else
-#define STACK_ABT_SIZE		1024
-#endif
+#define STACK_ABT_SIZE		4096
 #endif /*ARM64*/
 
 #ifdef CFG_CORE_DEBUG_CHECK_STACKS
diff --git a/core/arch/arm/include/kernel/thread_spmc.h b/core/arch/arm/include/kernel/thread_spmc.h
index 672bc2cc82ebfb5c80f18d223fbf6cbdab6cc7e9..7a03f4002a9aa42bfc6d456a33e38c3cdceab55d 100644
--- a/core/arch/arm/include/kernel/thread_spmc.h
+++ b/core/arch/arm/include/kernel/thread_spmc.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (c) 2021, Arm Limited.
+ * Copyright (c) 2021-2024, Arm Limited.
  * Copyright (c) 2023, Linaro Limited
  */
 #ifndef __KERNEL_THREAD_SPMC_H
@@ -11,8 +11,30 @@
 #include <kernel/panic.h>
 #include <kernel/thread.h>
 
-/* FF-A endpoint base ID when OP-TEE is used as a S-EL1 endpoint */
-#define SPMC_ENDPOINT_ID        0x8001
+/* The FF-A ID of Secure World components should be between these limits */
+#define FFA_SWD_ID_MIN	0x8000
+#define FFA_SWD_ID_MAX	UINT16_MAX
+
+/*
+ * OP-TEE FF-A partition ID. This is valid both when
+ * - the SPMC is implemented by OP-TEE and the core OP-TEE functionality runs
+ *   in a logical SP that resides at the same exception level as the SPMC, or,
+ * - the SPMC is at a higher EL and OP-TEE is running as a standalone S-EL1 SP.
+ */
+extern uint16_t optee_endpoint_id;
+
+/*
+ * FF-A ID of the SPMC. This is valid both when the SPMC is implemented in
+ * OP-TEE or at a higher EL.
+ */
+extern uint16_t spmc_id;
+
+#if defined(CFG_CORE_SEL1_SPMC)
+/* FF-A ID of the SPMD. This is only valid when OP-TEE is the S-EL1 SPMC. */
+extern uint16_t spmd_id;
+#endif
+
+#define SPMC_CORE_SEL1_MAX_SHM_COUNT	64
 
 struct ffa_rxtx {
 	void *rx;
@@ -23,6 +45,7 @@ struct ffa_rxtx {
 	bool tx_is_mine;
 };
 
+void spmc_handle_spm_id_get(struct thread_smc_args *args);
 void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *buf);
 void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *buf);
 void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *buf);
diff --git a/core/arch/arm/include/mm/core_mmu_arch.h b/core/arch/arm/include/mm/core_mmu_arch.h
index d8154d7efdff7e44ca5a6e50748c6c875882e90f..803c9c42ece5f34659cf63acd6d2e53dc7021a9d 100644
--- a/core/arch/arm/include/mm/core_mmu_arch.h
+++ b/core/arch/arm/include/mm/core_mmu_arch.h
@@ -137,15 +137,6 @@ struct core_mmu_user_map {
 };
 #endif
 
-#ifdef CFG_WITH_LPAE
-bool core_mmu_user_va_range_is_defined(void);
-#else
-static inline bool __noprof core_mmu_user_va_range_is_defined(void)
-{
-	return true;
-}
-#endif
-
 /* Cache maintenance operation type */
 enum cache_op {
 	DCACHE_CLEAN,
@@ -172,9 +163,6 @@ static inline TEE_Result cache_op_outer(enum cache_op op __unused,
 }
 #endif
 
-/* Do section mapping, not support on LPAE */
-void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb);
-
 #if defined(ARM64)
 unsigned int core_mmu_arm64_get_pa_width(void);
 #endif
diff --git a/core/arch/arm/include/optee_ffa.h b/core/arch/arm/include/optee_ffa.h
index 8db02650be578b26141d302bd2338b853020851d..d61c625e9c79fea2ca84a37581f9caba2c8ed776 100644
--- a/core/arch/arm/include/optee_ffa.h
+++ b/core/arch/arm/include/optee_ffa.h
@@ -93,6 +93,8 @@
 #define OPTEE_FFA_SEC_CAP_ARG_OFFSET	BIT(0)
 /* OP-TEE supports asynchronous notification via FF-A */
 #define OPTEE_FFA_SEC_CAP_ASYNC_NOTIF	BIT(1)
+/* OP-TEE supports probing for RPMB device if needed */
+#define OPTEE_FFA_SEC_CAP_RPMB_PROBE	BIT(2)
 
 #define OPTEE_FFA_EXCHANGE_CAPABILITIES OPTEE_FFA_BLOCKING_CALL(2)
 
@@ -117,7 +119,8 @@
  *
  * Call register usage:
  * w3:    Service ID, OPTEE_FFA_ENABLE_ASYNC_NOTIF
- * w4:	  Notification value to request bottom half processing
+ * w4:	  Notification value to request bottom half processing, should be
+ *	  less than OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE
  * w5-w7: Not used (MBZ)
  *
  * Return register usage:
@@ -126,6 +129,8 @@
  */
 #define OPTEE_FFA_ENABLE_ASYNC_NOTIF	OPTEE_FFA_BLOCKING_CALL(5)
 
+#define OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE	64
+
 /*
  * Call with struct optee_msg_arg as argument in the supplied shared memory
  * with a zero internal offset and normal cached memory attributes.
diff --git a/core/arch/arm/include/sm/optee_smc.h b/core/arch/arm/include/sm/optee_smc.h
index fe9aff0e1fc29135c7dda790d6372bcba324b7b8..acae757abdf85c12f25240f4c873a6c1bb7a6158 100644
--- a/core/arch/arm/include/sm/optee_smc.h
+++ b/core/arch/arm/include/sm/optee_smc.h
@@ -316,6 +316,8 @@
 #define OPTEE_SMC_SEC_CAP_ASYNC_NOTIF		BIT(5)
 /* Secure world supports pre-allocating RPC arg struct */
 #define OPTEE_SMC_SEC_CAP_RPC_ARG		BIT(6)
+/* Secure world supports probing for RPMB device if needed */
+#define OPTEE_SMC_SEC_CAP_RPMB_PROBE		BIT(7)
 
 #define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES	U(9)
 #define OPTEE_SMC_EXCHANGE_CAPABILITIES \
diff --git a/core/arch/arm/kernel/abort.c b/core/arch/arm/kernel/abort.c
index 72fbfc84f628b2fd57c93eba17468e3c0c829e4f..c5d5c917c1cce8ea5c94c4b3fac25c15dee8f89d 100644
--- a/core/arch/arm/kernel/abort.c
+++ b/core/arch/arm/kernel/abort.c
@@ -13,9 +13,7 @@
 #include <kernel/user_mode_ctx.h>
 #include <memtag.h>
 #include <mm/core_mmu.h>
-#include <mm/mobj.h>
 #include <mm/tee_pager.h>
-#include <tee/tee_svc.h>
 #include <trace.h>
 #include <unw/unwind.h>
 
diff --git a/core/arch/arm/kernel/boot.c b/core/arch/arm/kernel/boot.c
index 275eb8cfb242b0a69bf8d5172abe5e30144ce232..52899add58c7990499b316276b41c2d7bc693824 100644
--- a/core/arch/arm/kernel/boot.c
+++ b/core/arch/arm/kernel/boot.c
@@ -33,10 +33,10 @@
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <mm/fobj.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_mm.h>
 #include <mm/tee_pager.h>
 #include <sm/psci.h>
-#include <stdio.h>
 #include <trace.h>
 #include <utee_defines.h>
 #include <util.h>
@@ -80,7 +80,12 @@ uint32_t sem_cpu_sync[CFG_TEE_CORE_NB_CORE];
 DECLARE_KEEP_PAGER(sem_cpu_sync);
 #endif
 
-static void *manifest_dt __nex_bss;
+/*
+ * Must not be in .bss since it's initialized and used from assembly before
+ * .bss is cleared.
+ */
+vaddr_t boot_cached_mem_end __nex_data = 1;
+
 static unsigned long boot_arg_fdt __nex_bss;
 static unsigned long boot_arg_nsec_entry __nex_bss;
 static unsigned long boot_arg_pageable_part __nex_bss;
@@ -189,6 +194,59 @@ static void init_vfp_nsec(void)
 }
 #endif
 
+static void check_crypto_extensions(void)
+{
+	bool ce_supported = true;
+
+	if (!feat_aes_implemented() &&
+	    IS_ENABLED(CFG_CRYPTO_AES_ARM_CE)) {
+		EMSG("AES instructions are not supported");
+		ce_supported = false;
+	}
+
+	if (!feat_sha1_implemented() &&
+	    IS_ENABLED(CFG_CRYPTO_SHA1_ARM_CE)) {
+		EMSG("SHA1 instructions are not supported");
+		ce_supported = false;
+	}
+
+	if (!feat_sha256_implemented() &&
+	    IS_ENABLED(CFG_CRYPTO_SHA256_ARM_CE)) {
+		EMSG("SHA256 instructions are not supported");
+		ce_supported = false;
+	}
+
+	/* Check aarch64 specific instructions */
+	if (IS_ENABLED(CFG_ARM64_core)) {
+		if (!feat_sha512_implemented() &&
+		    IS_ENABLED(CFG_CRYPTO_SHA512_ARM_CE)) {
+			EMSG("SHA512 instructions are not supported");
+			ce_supported = false;
+		}
+
+		if (!feat_sha3_implemented() &&
+		    IS_ENABLED(CFG_CRYPTO_SHA3_ARM_CE)) {
+			EMSG("SHA3 instructions are not supported");
+			ce_supported = false;
+		}
+
+		if (!feat_sm3_implemented() &&
+		    IS_ENABLED(CFG_CRYPTO_SM3_ARM_CE)) {
+			EMSG("SM3 instructions are not supported");
+			ce_supported = false;
+		}
+
+		if (!feat_sm4_implemented() &&
+		    IS_ENABLED(CFG_CRYPTO_SM4_ARM_CE)) {
+			EMSG("SM4 instructions are not supported");
+			ce_supported = false;
+		}
+	}
+
+	if (!ce_supported)
+		panic("HW doesn't support CE instructions");
+}
+
 #if defined(CFG_WITH_VFP)
 
 #ifdef ARM32
@@ -322,50 +380,42 @@ static void init_asan(void)
 /* Called from entry_a64.S only when MEMTAG is configured */
 void boot_init_memtag(void)
 {
-	paddr_t base = 0;
-	paddr_size_t size = 0;
-
 	memtag_init_ops(feat_mte_implemented());
-	core_mmu_get_secure_memory(&base, &size);
-	memtag_set_tags((void *)(vaddr_t)base, size, 0);
+}
+
+static TEE_Result mmap_clear_memtag(struct tee_mmap_region *map,
+				    void *ptr __unused)
+{
+	switch (map->type) {
+	case MEM_AREA_NEX_RAM_RO:
+	case MEM_AREA_SEC_RAM_OVERALL:
+		DMSG("Clearing tags for VA %#"PRIxVA"..%#"PRIxVA,
+		     map->va, map->va + map->size - 1);
+		memtag_set_tags((void *)map->va, map->size, 0);
+		break;
+	default:
+		break;
+	}
+
+	return TEE_SUCCESS;
+}
+
+/* Called from entry_a64.S only when MEMTAG is configured */
+void boot_clear_memtag(void)
+{
+	core_mmu_for_each_map(NULL, mmap_clear_memtag);
 }
 #endif
 
 #ifdef CFG_WITH_PAGER
 
 #ifdef CFG_CORE_SANITIZE_KADDRESS
-static void carve_out_asan_mem(tee_mm_pool_t *pool)
+static void carve_out_asan_mem(void)
 {
-	const size_t s = pool->hi - pool->lo;
-	tee_mm_entry_t *mm;
-	paddr_t apa = ASAN_MAP_PA;
-	size_t asz = ASAN_MAP_SZ;
-
-	if (core_is_buffer_outside(apa, asz, pool->lo, s))
-		return;
-
-	/* Reserve the shadow area */
-	if (!core_is_buffer_inside(apa, asz, pool->lo, s)) {
-		if (apa < pool->lo) {
-			/*
-			 * ASAN buffer is overlapping with the beginning of
-			 * the pool.
-			 */
-			asz -= pool->lo - apa;
-			apa = pool->lo;
-		} else {
-			/*
-			 * ASAN buffer is overlapping with the end of the
-			 * pool.
-			 */
-			asz = pool->hi - apa;
-		}
-	}
-	mm = tee_mm_alloc2(pool, apa, asz);
-	assert(mm);
+	nex_phys_mem_partial_carve_out(ASAN_MAP_PA, ASAN_MAP_SZ);
 }
 #else
-static void carve_out_asan_mem(tee_mm_pool_t *pool __unused)
+static void carve_out_asan_mem(void)
 {
 }
 #endif
@@ -379,7 +429,7 @@ static void print_pager_pool_size(void)
 		stats.npages_all * SMALL_PAGE_SIZE / 1024);
 }
 
-static void init_vcore(tee_mm_pool_t *mm_vcore)
+static void init_virt_pool(tee_mm_pool_t *virt_pool)
 {
 	const vaddr_t begin = VCORE_START_VA;
 	size_t size = TEE_RAM_VA_SIZE;
@@ -390,9 +440,9 @@ static void init_vcore(tee_mm_pool_t *mm_vcore)
 		size = ASAN_MAP_PA - begin;
 #endif
 
-	if (!tee_mm_init(mm_vcore, begin, size, SMALL_PAGE_SHIFT,
+	if (!tee_mm_init(virt_pool, begin, size, SMALL_PAGE_SHIFT,
 			 TEE_MM_POOL_NO_FLAGS))
-		panic("tee_mm_vcore init failed");
+		panic("core_virt_mem_pool init failed");
 }
 
 /*
@@ -448,7 +498,7 @@ static struct fobj *ro_paged_alloc(tee_mm_entry_t *mm, void *hashes,
 #endif
 }
 
-static void init_runtime(unsigned long pageable_part)
+static void init_pager_runtime(unsigned long pageable_part)
 {
 	size_t n;
 	size_t init_size = (size_t)(__init_end - __init_start);
@@ -473,12 +523,6 @@ static void init_runtime(unsigned long pageable_part)
 
 	tmp_hashes = __init_end + embdata->hashes_offset;
 
-	init_asan();
-
-	/* Add heap2 first as heap1 may be too small as initial bget pool */
-	malloc_add_pool(__heap2_start, __heap2_end - __heap2_start);
-	malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
-
 	/*
 	 * This needs to be initialized early to support address lookup
 	 * in MEM_AREA_TEE_RAM
@@ -492,17 +536,17 @@ static void init_runtime(unsigned long pageable_part)
 	asan_memcpy_unchecked(hashes, tmp_hashes, hash_size);
 
 	/*
-	 * Need tee_mm_sec_ddr initialized to be able to allocate secure
-	 * DDR below.
+	 * The pager is about the be enabled below, eventual temporary boot
+	 * memory allocation must be removed now.
 	 */
-	core_mmu_init_ta_ram();
+	boot_mem_release_tmp_alloc();
 
-	carve_out_asan_mem(&tee_mm_sec_ddr);
+	carve_out_asan_mem();
 
-	mm = tee_mm_alloc(&tee_mm_sec_ddr, pageable_size);
+	mm = nex_phys_mem_ta_alloc(pageable_size);
 	assert(mm);
-	paged_store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM,
-				   pageable_size);
+	paged_store = phys_to_virt(tee_mm_get_smem(mm),
+				   MEM_AREA_SEC_RAM_OVERALL, pageable_size);
 	/*
 	 * Load pageable part in the dedicated allocated area:
 	 * - Move pageable non-init part into pageable area. Note bootloader
@@ -547,7 +591,7 @@ static void init_runtime(unsigned long pageable_part)
 	 * Initialize the virtual memory pool used for main_mmu_l2_ttb which
 	 * is supplied to tee_pager_init() below.
 	 */
-	init_vcore(&tee_mm_vcore);
+	init_virt_pool(&core_virt_mem_pool);
 
 	/*
 	 * Assign alias area for pager end of the small page block the rest
@@ -555,9 +599,9 @@ static void init_runtime(unsigned long pageable_part)
 	 * we're guaranteed to not need more than the physical amount of
 	 * TZSRAM.
 	 */
-	mm = tee_mm_alloc2(&tee_mm_vcore,
-			   (vaddr_t)tee_mm_vcore.lo +
-			   tee_mm_vcore.size - TZSRAM_SIZE,
+	mm = tee_mm_alloc2(&core_virt_mem_pool,
+			   (vaddr_t)core_virt_mem_pool.lo +
+			   core_virt_mem_pool.size - TZSRAM_SIZE,
 			   TZSRAM_SIZE);
 	assert(mm);
 	tee_pager_set_alias_area(mm);
@@ -566,7 +610,7 @@ static void init_runtime(unsigned long pageable_part)
 	 * Claim virtual memory which isn't paged.
 	 * Linear memory (flat map core memory) ends there.
 	 */
-	mm = tee_mm_alloc2(&tee_mm_vcore, VCORE_UNPG_RX_PA,
+	mm = tee_mm_alloc2(&core_virt_mem_pool, VCORE_UNPG_RX_PA,
 			   (vaddr_t)(__pageable_start - VCORE_UNPG_RX_PA));
 	assert(mm);
 
@@ -574,7 +618,7 @@ static void init_runtime(unsigned long pageable_part)
 	 * Allocate virtual memory for the pageable area and let the pager
 	 * take charge of all the pages already assigned to that memory.
 	 */
-	mm = tee_mm_alloc2(&tee_mm_vcore, (vaddr_t)__pageable_start,
+	mm = tee_mm_alloc2(&core_virt_mem_pool, (vaddr_t)__pageable_start,
 			   pageable_size);
 	assert(mm);
 	fobj = ro_paged_alloc(mm, hashes, paged_store);
@@ -597,33 +641,16 @@ static void init_runtime(unsigned long pageable_part)
 	 * This setup may happen when a the secure bootloader runs in TZRAM
 	 * and its memory can be reused by OP-TEE once boot stages complete.
 	 */
-	tee_pager_add_pages(tee_mm_vcore.lo,
-			(VCORE_UNPG_RX_PA - tee_mm_vcore.lo) / SMALL_PAGE_SIZE,
-			true);
+	tee_pager_add_pages(core_virt_mem_pool.lo,
+			    (VCORE_UNPG_RX_PA - core_virt_mem_pool.lo) /
+				SMALL_PAGE_SIZE,
+			    true);
 
 	print_pager_pool_size();
 }
-#else
-
-static void init_runtime(unsigned long pageable_part __unused)
+#else /*!CFG_WITH_PAGER*/
+static void init_pager_runtime(unsigned long pageable_part __unused)
 {
-	init_asan();
-
-	/*
-	 * By default whole OP-TEE uses malloc, so we need to initialize
-	 * it early. But, when virtualization is enabled, malloc is used
-	 * only by TEE runtime, so malloc should be initialized later, for
-	 * every virtual partition separately. Core code uses nex_malloc
-	 * instead.
-	 */
-#ifdef CFG_NS_VIRTUALIZATION
-	nex_malloc_add_pool(__nex_heap_start, __nex_heap_end -
-					      __nex_heap_start);
-#else
-	malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
-#endif
-
-	IMSG_RAW("\n");
 }
 #endif
 
@@ -805,133 +832,6 @@ static int config_psci(struct dt_descriptor *dt __unused)
 }
 #endif /*CFG_PSCI_ARM32*/
 
-#ifdef CFG_CORE_DYN_SHM
-static uint64_t get_dt_val_and_advance(const void *data, size_t *offs,
-				       uint32_t cell_size)
-{
-	uint64_t rv = 0;
-
-	if (cell_size == 1) {
-		uint32_t v;
-
-		memcpy(&v, (const uint8_t *)data + *offs, sizeof(v));
-		*offs += sizeof(v);
-		rv = fdt32_to_cpu(v);
-	} else {
-		uint64_t v;
-
-		memcpy(&v, (const uint8_t *)data + *offs, sizeof(v));
-		*offs += sizeof(v);
-		rv = fdt64_to_cpu(v);
-	}
-
-	return rv;
-}
-
-/*
- * Find all non-secure memory from DT. Memory marked inaccessible by Secure
- * World is ignored since it could not be mapped to be used as dynamic shared
- * memory.
- */
-static int get_nsec_memory_helper(void *fdt, struct core_mmu_phys_mem *mem)
-{
-	const uint8_t *prop = NULL;
-	uint64_t a = 0;
-	uint64_t l = 0;
-	size_t prop_offs = 0;
-	size_t prop_len = 0;
-	int elems_total = 0;
-	int addr_size = 0;
-	int len_size = 0;
-	int offs = 0;
-	size_t n = 0;
-	int len = 0;
-
-	addr_size = fdt_address_cells(fdt, 0);
-	if (addr_size < 0)
-		return 0;
-
-	len_size = fdt_size_cells(fdt, 0);
-	if (len_size < 0)
-		return 0;
-
-	while (true) {
-		offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type",
-						     "memory",
-						     sizeof("memory"));
-		if (offs < 0)
-			break;
-
-		if (fdt_get_status(fdt, offs) != (DT_STATUS_OK_NSEC |
-						   DT_STATUS_OK_SEC))
-			continue;
-
-		prop = fdt_getprop(fdt, offs, "reg", &len);
-		if (!prop)
-			continue;
-
-		prop_len = len;
-		for (n = 0, prop_offs = 0; prop_offs < prop_len; n++) {
-			a = get_dt_val_and_advance(prop, &prop_offs, addr_size);
-			if (prop_offs >= prop_len) {
-				n--;
-				break;
-			}
-
-			l = get_dt_val_and_advance(prop, &prop_offs, len_size);
-			if (mem) {
-				mem->type = MEM_AREA_DDR_OVERALL;
-				mem->addr = a;
-				mem->size = l;
-				mem++;
-			}
-		}
-
-		elems_total += n;
-	}
-
-	return elems_total;
-}
-
-static struct core_mmu_phys_mem *get_nsec_memory(void *fdt, size_t *nelems)
-{
-	struct core_mmu_phys_mem *mem = NULL;
-	int elems_total = 0;
-
-	elems_total = get_nsec_memory_helper(fdt, NULL);
-	if (elems_total <= 0)
-		return NULL;
-
-	mem = nex_calloc(elems_total, sizeof(*mem));
-	if (!mem)
-		panic();
-
-	elems_total = get_nsec_memory_helper(fdt, mem);
-	assert(elems_total > 0);
-
-	*nelems = elems_total;
-
-	return mem;
-}
-#endif /*CFG_CORE_DYN_SHM*/
-
-#ifdef CFG_CORE_RESERVED_SHM
-static int mark_static_shm_as_reserved(struct dt_descriptor *dt)
-{
-	vaddr_t shm_start;
-	vaddr_t shm_end;
-
-	core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &shm_start, &shm_end);
-	if (shm_start != shm_end)
-		return add_res_mem_dt_node(dt, "optee_shm",
-					   virt_to_phys((void *)shm_start),
-					   shm_end - shm_start);
-
-	DMSG("No SHM configured");
-	return -1;
-}
-#endif /*CFG_CORE_RESERVED_SHM*/
-
 static int mark_tzdram_as_reserved(struct dt_descriptor *dt)
 {
 	return add_res_mem_dt_node(dt, "optee_core", CFG_TZDRAM_START,
@@ -963,148 +863,18 @@ static void update_external_dt(void)
 static void update_external_dt(void)
 {
 }
-
-#ifdef CFG_CORE_DYN_SHM
-static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused,
-						 size_t *nelems __unused)
-{
-	return NULL;
-}
-#endif /*CFG_CORE_DYN_SHM*/
 #endif /*!CFG_DT*/
 
-#if defined(CFG_CORE_FFA)
-void *get_manifest_dt(void)
-{
-	return manifest_dt;
-}
-
-static void reinit_manifest_dt(void)
-{
-	paddr_t pa = (unsigned long)manifest_dt;
-	void *fdt = NULL;
-	int ret = 0;
-
-	if (!pa) {
-		EMSG("No manifest DT found");
-		return;
-	}
-
-	fdt = core_mmu_add_mapping(MEM_AREA_MANIFEST_DT, pa, CFG_DTB_MAX_SIZE);
-	if (!fdt)
-		panic("Failed to map manifest DT");
-
-	manifest_dt = fdt;
-
-	ret = fdt_check_full(fdt, CFG_DTB_MAX_SIZE);
-	if (ret < 0) {
-		EMSG("Invalid manifest Device Tree at %#lx: error %d", pa, ret);
-		panic();
-	}
-
-	IMSG("manifest DT found");
-}
-
-static TEE_Result release_manifest_dt(void)
-{
-	if (!manifest_dt)
-		return TEE_SUCCESS;
-
-	if (core_mmu_remove_mapping(MEM_AREA_MANIFEST_DT, manifest_dt,
-				    CFG_DTB_MAX_SIZE))
-		panic("Failed to remove temporary manifest DT mapping");
-	manifest_dt = NULL;
-
-	return TEE_SUCCESS;
-}
-
-boot_final(release_manifest_dt);
-#else
-void *get_manifest_dt(void)
-{
-	return NULL;
-}
-
-static void reinit_manifest_dt(void)
-{
-}
-#endif /*CFG_CORE_FFA*/
-
-#ifdef CFG_CORE_DYN_SHM
-static void discover_nsec_memory(void)
-{
-	struct core_mmu_phys_mem *mem;
-	const struct core_mmu_phys_mem *mem_begin = NULL;
-	const struct core_mmu_phys_mem *mem_end = NULL;
-	size_t nelems;
-	void *fdt = get_external_dt();
-
-	if (fdt) {
-		mem = get_nsec_memory(fdt, &nelems);
-		if (mem) {
-			core_mmu_set_discovered_nsec_ddr(mem, nelems);
-			return;
-		}
-
-		DMSG("No non-secure memory found in FDT");
-	}
-
-	mem_begin = phys_ddr_overall_begin;
-	mem_end = phys_ddr_overall_end;
-	nelems = mem_end - mem_begin;
-	if (nelems) {
-		/*
-		 * Platform cannot use both register_ddr() and the now
-		 * deprecated register_dynamic_shm().
-		 */
-		assert(phys_ddr_overall_compat_begin ==
-		       phys_ddr_overall_compat_end);
-	} else {
-		mem_begin = phys_ddr_overall_compat_begin;
-		mem_end = phys_ddr_overall_compat_end;
-		nelems = mem_end - mem_begin;
-		if (!nelems)
-			return;
-		DMSG("Warning register_dynamic_shm() is deprecated, please use register_ddr() instead");
-	}
-
-	mem = nex_calloc(nelems, sizeof(*mem));
-	if (!mem)
-		panic();
-
-	memcpy(mem, phys_ddr_overall_begin, sizeof(*mem) * nelems);
-	core_mmu_set_discovered_nsec_ddr(mem, nelems);
-}
-#else /*CFG_CORE_DYN_SHM*/
-static void discover_nsec_memory(void)
-{
-}
-#endif /*!CFG_CORE_DYN_SHM*/
-
-#ifdef CFG_NS_VIRTUALIZATION
-static TEE_Result virt_init_heap(void)
-{
-	/* We need to initialize pool for every virtual guest partition */
-	malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
-
-	return TEE_SUCCESS;
-}
-preinit_early(virt_init_heap);
-#endif
-
 void init_tee_runtime(void)
 {
-#ifndef CFG_WITH_PAGER
-	/* Pager initializes TA RAM early */
-	core_mmu_init_ta_ram();
-#endif
 	/*
 	 * With virtualization we call this function when creating the
 	 * OP-TEE partition instead.
 	 */
 	if (!IS_ENABLED(CFG_NS_VIRTUALIZATION))
 		call_preinitcalls();
-	call_initcalls();
+	call_early_initcalls();
+	call_service_initcalls();
 
 	/*
 	 * These two functions uses crypto_rng_read() to initialize the
@@ -1127,6 +897,8 @@ void init_tee_runtime(void)
 
 static void init_primary(unsigned long pageable_part, unsigned long nsec_entry)
 {
+	vaddr_t va = 0;
+
 	thread_init_core_local_stacks();
 	/*
 	 * Mask asynchronous exceptions before switch to the thread vector
@@ -1138,14 +910,54 @@ static void init_primary(unsigned long pageable_part, unsigned long nsec_entry)
 	thread_set_exceptions(THREAD_EXCP_ALL);
 	primary_save_cntfrq();
 	init_vfp_sec();
+
+	if (IS_ENABLED(CFG_CRYPTO_WITH_CE))
+		check_crypto_extensions();
+
+	init_asan();
+
 	/*
-	 * Pager: init_runtime() calls thread_kernel_enable_vfp() so we must
-	 * set a current thread right now to avoid a chicken-and-egg problem
-	 * (thread_init_boot_thread() sets the current thread but needs
-	 * things set by init_runtime()).
+	 * By default whole OP-TEE uses malloc, so we need to initialize
+	 * it early. But, when virtualization is enabled, malloc is used
+	 * only by TEE runtime, so malloc should be initialized later, for
+	 * every virtual partition separately. Core code uses nex_malloc
+	 * instead.
 	 */
-	thread_get_core_local()->curr_thread = 0;
-	init_runtime(pageable_part);
+#ifdef CFG_WITH_PAGER
+	/* Add heap2 first as heap1 may be too small as initial bget pool */
+	malloc_add_pool(__heap2_start, __heap2_end - __heap2_start);
+#endif
+#ifdef CFG_NS_VIRTUALIZATION
+	nex_malloc_add_pool(__nex_heap_start, __nex_heap_end -
+					      __nex_heap_start);
+#else
+	malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
+#endif
+	IMSG_RAW("\n");
+
+	core_mmu_save_mem_map();
+	core_mmu_init_phys_mem();
+	va = boot_mem_release_unused();
+	if (!IS_ENABLED(CFG_WITH_PAGER)) {
+		/*
+		 * We must update boot_cached_mem_end to reflect the memory
+		 * just unmapped by boot_mem_release_unused().
+		 */
+		assert(va && va <= boot_cached_mem_end);
+		boot_cached_mem_end = va;
+	}
+
+	if (IS_ENABLED(CFG_WITH_PAGER)) {
+		/*
+		 * Pager: init_runtime() calls thread_kernel_enable_vfp()
+		 * so we must set a current thread right now to avoid a
+		 * chicken-and-egg problem (thread_init_boot_thread() sets
+		 * the current thread but needs things set by
+		 * init_runtime()).
+		 */
+		thread_get_core_local()->curr_thread = 0;
+		init_pager_runtime(pageable_part);
+	}
 
 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
 		/*
@@ -1210,6 +1022,10 @@ void __weak boot_init_primary_late(unsigned long fdt __unused,
 #ifdef CFG_CORE_ASLR
 	DMSG("Executing at offset %#lx with virtual load address %#"PRIxVA,
 	     (unsigned long)boot_mmu_config.map_offset, VCORE_START_VA);
+#endif
+#ifdef CFG_NS_VIRTUALIZATION
+	DMSG("NS-virtualization enabled, supporting %u guests",
+	     CFG_VIRT_GUEST_COUNT);
 #endif
 	if (IS_ENABLED(CFG_MEMTAG))
 		DMSG("Memory tagging %s",
@@ -1226,12 +1042,21 @@ void __weak boot_init_primary_late(unsigned long fdt __unused,
 
 	boot_primary_init_intc();
 	init_vfp_nsec();
-	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
-		IMSG("Initializing virtualization support");
-		core_mmu_init_virtualization();
-	} else {
+	if (!IS_ENABLED(CFG_NS_VIRTUALIZATION))
 		init_tee_runtime();
-	}
+}
+
+/*
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+void __weak boot_init_primary_final(void)
+{
+	if (!IS_ENABLED(CFG_WITH_PAGER))
+		boot_mem_release_tmp_alloc();
+
+	if (!IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		call_driver_initcalls();
 	call_finalcalls();
 	IMSG("Primary CPU switching to normal world boot");
 }
@@ -1425,7 +1250,7 @@ unsigned long __weak get_aslr_seed(void)
 		goto err;
 	}
 
-	return fdt64_to_cpu(*seed);
+	return fdt64_to_cpu(fdt64_ld(seed));
 
 err:
 	/* Try platform implementation */
@@ -1552,22 +1377,25 @@ void __weak boot_save_args(unsigned long a0, unsigned long a1,
 	 *       Transfer List
 	 * a0	- DTB address or 0 (AArch64)
 	 *	- must be 0 (AArch32)
-	 * a1	- TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK
+	 * a1	- 1 << 32 | TRANSFER_LIST_SIGNATURE[0:31] (AArch64)
+	 *	- 1 << 24 | TRANSFER_LIST_SIGNATURE[0:23] (AArch32)
 	 * a2	- must be 0 (AArch64)
 	 *	- DTB address or 0 (AArch32)
 	 * a3	- Transfer list base address
 	 * a4	- Not used
 	 */
 
-	if (IS_ENABLED(CFG_TRANSFER_LIST) &&
-	    a1 == (TRANSFER_LIST_SIGNATURE | REG_CONVENTION_VER_MASK)) {
-		if (IS_ENABLED(CFG_ARM64_core)) {
+	if (IS_ENABLED(CFG_TRANSFER_LIST)) {
+		if (IS_ENABLED(CFG_ARM64_core) &&
+		    a1 == TL_HANDOFF_X1_VALUE(TL_REG_CONVENTION_VER)) {
 			boot_save_transfer_list(a2, a3, a0);
 			boot_arg_fdt = a0;
-		} else {
+		} else if (IS_ENABLED(CFG_ARM32_core) &&
+			   a1 == TL_HANDOFF_R1_VALUE(TL_REG_CONVENTION_VER)) {
 			boot_save_transfer_list(a0, a3, a2);
 			boot_arg_fdt = a2;
 		}
+
 		return;
 	}
 
@@ -1582,15 +1410,16 @@ void __weak boot_save_args(unsigned long a0, unsigned long a1,
 	if (IS_ENABLED(CFG_CORE_FFA)) {
 		if (IS_ENABLED(CFG_CORE_SEL2_SPMC) ||
 		    IS_ENABLED(CFG_CORE_EL3_SPMC))
-			manifest_dt = get_fdt_from_boot_info((void *)a0);
+			init_manifest_dt(get_fdt_from_boot_info((void *)a0));
 		else
-			manifest_dt = (void *)a0;
+			init_manifest_dt((void *)a0);
 		if (IS_ENABLED(CFG_CORE_SEL2_SPMC) &&
 		    IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE)) {
 			paddr_t base = 0;
 			size_t size = 0;
 
-			get_sec_mem_from_manifest(manifest_dt, &base, &size);
+			get_sec_mem_from_manifest(get_manifest_dt(),
+						  &base, &size);
 			core_mmu_set_secure_memory(base, size);
 		}
 	} else {
diff --git a/core/arch/arm/kernel/entry_a32.S b/core/arch/arm/kernel/entry_a32.S
index a43d36afb7c81030acce22a66e2ea6895832bef1..80ee7ed4e4f081884b1c2981b13d926cd04210b2 100644
--- a/core/arch/arm/kernel/entry_a32.S
+++ b/core/arch/arm/kernel/entry_a32.S
@@ -284,11 +284,13 @@ DECLARE_KEEP_INIT _start
 		assert_flat_mapped_range (\vbase), (\line)
 		bl	pl310_base
 		ldr	r1, \vbase
-		ldr	r2, \vend
+		ldr	r2, =\vend
+		ldr	r2, [r2]
 		bl	arm_cl2_invbypa
 #endif
 		ldr	r0, \vbase
-		ldr	r1, \vend
+		ldr	r1, =\vend
+		ldr	r1, [r1]
 		sub	r1, r1, r0
 		bl	dcache_inv_range
 	.endm
@@ -297,16 +299,19 @@ DECLARE_KEEP_INIT _start
 #if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL)
 		assert_flat_mapped_range (\vbase), (\line)
 		ldr	r0, \vbase
-		ldr	r1, \vend
+		ldr	r1, =\vend
+		ldr	r1, [r1]
 		sub	r1, r1, r0
 		bl	dcache_clean_range
 		bl	pl310_base
 		ldr	r1, \vbase
-		ldr	r2, \vend
+		ldr	r2, =\vend
+		ldr	r2, [r2]
 		bl	arm_cl2_cleaninvbypa
 #endif
 		ldr	r0, \vbase
-		ldr	r1, \vend
+		ldr	r1, =\vend
+		ldr	r1, [r1]
 		sub	r1, r1, r0
 		bl	dcache_cleaninv_range
 	.endm
@@ -349,7 +354,8 @@ UNWIND(	.cantunwind)
 	/* Copy backwards (as memmove) in case we're overlapping */
 	add	r0, r0, r2		/* __init_start + len */
 	add	r1, r1, r2		/* __data_end + len */
-	str	r0, cached_mem_end
+	ldr	r3, =boot_cached_mem_end
+	str	r0, [r3]
 	ldr	r2, =__init_start
 copy_init:
 	ldmdb	r1!, {r3, r9-r12}
@@ -360,22 +366,30 @@ copy_init:
 	/*
 	 * The binary is built as:
 	 * [Core, rodata and data] : In correct location
-	 * [struct boot_embdata + data] : Should be moved to __end, first
-	 * uint32_t tells the length of the struct + data
+	 * [struct boot_embdata + data] : Should be moved to right before
+	 * __vcore_free_end, the first uint32_t tells the length of the
+	 * struct + data
 	 */
-	ldr	r0, =__end		/* dst */
 	ldr	r1, =__data_end		/* src */
 	ldr	r2, [r1]		/* struct boot_embdata::total_len */
+	/* dst */
+	ldr	r0, =__vcore_free_end
+	sub	r0, r0, r2
+	/* round down to beginning of page */
+	mov	r3,  #(SMALL_PAGE_SIZE - 1)
+	bic	r0, r0, r3
+	ldr	r3, =boot_embdata_ptr
+	str	r0, [r3]
 	/* Copy backwards (as memmove) in case we're overlapping */
-	add	r0, r0, r2
 	add	r1, r1, r2
-	str	r0, cached_mem_end
-	ldr	r2, =__end
+	add	r2, r0, r2
+	ldr	r3, =boot_cached_mem_end
+	str	r2, [r3]
 
 copy_init:
 	ldmdb	r1!, {r3, r9-r12}
-	stmdb	r0!, {r3, r9-r12}
-	cmp	r0, r2
+	stmdb	r2!, {r3, r9-r12}
+	cmp	r2, r0
 	bgt	copy_init
 #endif
 
@@ -452,6 +466,23 @@ shadow_stack_access_ok:
 	bl	boot_save_args
 	add	sp, sp, #(2 * 4)
 
+#ifdef CFG_WITH_PAGER
+	ldr	r0, =__init_end	/* pointer to boot_embdata */
+	ldr	r1, [r0]	/* struct boot_embdata::total_len */
+	add	r0, r0, r1
+	mov_imm	r1, 0xfff
+	add	r0, r0, r1	/* round up */
+	bic	r0, r0, r1	/* to next page */
+	mov_imm r1, (TEE_RAM_PH_SIZE + TEE_RAM_START)
+	mov	r2, r1
+#else
+	ldr	r0, =__vcore_free_start
+	ldr	r1, =boot_embdata_ptr
+	ldr	r1, [r1]
+	ldr	r2, =__vcore_free_end
+#endif
+	bl	boot_mem_init
+
 #ifdef CFG_PL310
 	bl	pl310_base
 	bl	arm_cl2_config
@@ -463,7 +494,7 @@ shadow_stack_access_ok:
 	 * invalidate memory not used by OP-TEE since we may invalidate
 	 * entries used by for instance ARM Trusted Firmware.
 	 */
-	inval_cache_vrange(cached_mem_start, cached_mem_end)
+	inval_cache_vrange(cached_mem_start, boot_cached_mem_end)
 
 #if defined(CFG_PL310) && !defined(CFG_PL310_SIP_PROTOCOL)
 	/* Enable PL310 if not yet enabled */
@@ -473,6 +504,9 @@ shadow_stack_access_ok:
 
 #ifdef CFG_CORE_ASLR
 	bl	get_aslr_seed
+#ifdef CFG_CORE_ASLR_SEED
+	mov_imm	r0, CFG_CORE_ASLR_SEED
+#endif
 #else
 	mov	r0, #0
 #endif
@@ -489,12 +523,13 @@ shadow_stack_access_ok:
 	ldr	r0, =boot_mmu_config
 	ldr	r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET]
 	/*
-	 * Update cached_mem_end address with load offset since it was
+	 * Update boot_cached_mem_end address with load offset since it was
 	 * calculated before relocation.
 	 */
-	ldr	r2, cached_mem_end
+	ldr	r3, =boot_cached_mem_end
+	ldr	r2, [r3]
 	add	r2, r2, r0
-	str	r2, cached_mem_end
+	str	r2, [r3]
 
 	bl	relocate
 #endif
@@ -502,6 +537,9 @@ shadow_stack_access_ok:
 	bl	__get_core_pos
 	bl	enable_mmu
 #ifdef CFG_CORE_ASLR
+	ldr	r0, =boot_mmu_config
+	ldr	r0, [r0, #CORE_MMU_CONFIG_MAP_OFFSET]
+	bl	boot_mem_relocate
 	/*
 	 * Reinitialize console, since register_serial_console() has
 	 * previously registered a PA and with ASLR the VA is different
@@ -530,6 +568,7 @@ shadow_stack_access_ok:
 	str	r0, [r8, #THREAD_CORE_LOCAL_FLAGS]
 #endif
 	bl	boot_init_primary_late
+	bl	boot_init_primary_final
 #ifndef CFG_NS_VIRTUALIZATION
 	mov	r0, #THREAD_CLF_TMP
 	str	r0, [r8, #THREAD_CORE_LOCAL_FLAGS]
@@ -554,7 +593,7 @@ shadow_stack_access_ok:
 	 * they have turned on their D-cache, clean and invalidate the
 	 * D-cache before exiting to normal world.
 	 */
-	flush_cache_vrange(cached_mem_start, cached_mem_end)
+	flush_cache_vrange(cached_mem_start, boot_cached_mem_end)
 
 	/* release secondary boot cores and sync with them */
 	cpu_is_ready
@@ -628,9 +667,11 @@ LOCAL_DATA cached_mem_start , :
 	.word	__text_start
 END_DATA cached_mem_start
 
-LOCAL_DATA cached_mem_end , :
+#ifndef CFG_WITH_PAGER
+LOCAL_DATA boot_embdata_ptr , :
 	.skip	4
-END_DATA cached_mem_end
+END_DATA boot_embdata_ptr
+#endif
 
 LOCAL_FUNC unhandled_cpu , :
 	wfi
@@ -644,7 +685,8 @@ LOCAL_FUNC relocate , :
 #ifdef CFG_WITH_PAGER
 	ldr	r12, =__init_end
 #else
-	ldr	r12, =__end
+	ldr	r12, =boot_embdata_ptr
+	ldr	r12, [r12]
 #endif
 	ldr	r2, [r12, #BOOT_EMBDATA_RELOC_OFFSET]
 	ldr	r3, [r12, #BOOT_EMBDATA_RELOC_LEN]
diff --git a/core/arch/arm/kernel/entry_a64.S b/core/arch/arm/kernel/entry_a64.S
index 480ba7060046d7dc79dd3680a46605e8fce0e3b0..04dc781e144e21817042e354fc96767e5df32ad9 100644
--- a/core/arch/arm/kernel/entry_a64.S
+++ b/core/arch/arm/kernel/entry_a64.S
@@ -136,7 +136,7 @@
 11:
 	.endm
 
-	.macro init_pauth_per_cpu
+	.macro init_pauth_secondary_cpu
 		msr	spsel, #1
 		ldp	x0, x1, [sp, #THREAD_CORE_LOCAL_KEYS]
 		msr	spsel, #0
@@ -200,7 +200,7 @@ FUNC _start , :
 	/* Copy backwards (as memmove) in case we're overlapping */
 	add	x0, x0, x2		/* __init_start + len */
 	add	x1, x1, x2		/* __data_end + len */
-	adr	x3, cached_mem_end
+	adr_l	x3, boot_cached_mem_end
 	str	x0, [x3]
 	adr	x2, __init_start
 copy_init:
@@ -212,23 +212,30 @@ copy_init:
 	/*
 	 * The binary is built as:
 	 * [Core, rodata and data] : In correct location
-	 * [struct boot_embdata + data] : Should be moved to __end, first
-	 * uint32_t tells the length of the struct + data
+	 * [struct boot_embdata + data] : Should be moved to right before
+	 * __vcore_free_end, the first uint32_t tells the length of the
+	 * struct + data
 	 */
-	adr_l	x0, __end		/* dst */
 	adr_l	x1, __data_end		/* src */
 	ldr	w2, [x1]		/* struct boot_embdata::total_len */
+	/* dst */
+	adr_l	x0, __vcore_free_end
+	sub	x0, x0, x2
+	/* round down to beginning of page */
+	bic	x0, x0, #(SMALL_PAGE_SIZE - 1)
+	adr_l	x3, boot_embdata_ptr
+	str	x0, [x3]
+
 	/* Copy backwards (as memmove) in case we're overlapping */
-	add	x0, x0, x2
 	add	x1, x1, x2
-	adr	x3, cached_mem_end
-	str	x0, [x3]
-	adr_l	x2, __end
+	add	x2, x0, x2
+	adr_l	x3, boot_cached_mem_end
+	str	x2, [x3]
 
 copy_init:
 	ldp	x3, x4, [x1, #-16]!
-	stp	x3, x4, [x0, #-16]!
-	cmp	x0, x2
+	stp	x3, x4, [x2, #-16]!
+	cmp	x2, x0
 	b.gt	copy_init
 #endif
 
@@ -289,7 +296,8 @@ clear_nex_bss:
 	 * entries used by for instance ARM Trusted Firmware.
 	 */
 	adr_l	x0, __text_start
-	ldr	x1, cached_mem_end
+	adr_l	x1, boot_cached_mem_end
+	ldr	x1, [x1]
 	sub	x1, x1, x0
 	bl	dcache_cleaninv_range
 
@@ -303,6 +311,22 @@ clear_nex_bss:
 	mov	x4, xzr
 	bl	boot_save_args
 
+#ifdef CFG_WITH_PAGER
+	adr_l	x0, __init_end	/* pointer to boot_embdata */
+	ldr	w1, [x0]	/* struct boot_embdata::total_len */
+	add	x0, x0, x1
+	add	x0, x0, #0xfff	/* round up */
+	bic	x0, x0, #0xfff  /* to next page */
+	mov_imm x1, (TEE_RAM_PH_SIZE + TEE_RAM_START)
+	mov	x2, x1
+#else
+	adr_l	x0, __vcore_free_start
+	adr_l	x1, boot_embdata_ptr
+	ldr	x1, [x1]
+	adr_l	x2, __vcore_free_end;
+#endif
+	bl	boot_mem_init
+
 #ifdef CFG_MEMTAG
 	/*
 	 * If FEAT_MTE2 is available, initializes the memtag callbacks.
@@ -314,6 +338,9 @@ clear_nex_bss:
 
 #ifdef CFG_CORE_ASLR
 	bl	get_aslr_seed
+#ifdef CFG_CORE_ASLR_SEED
+	mov_imm	x0, CFG_CORE_ASLR_SEED
+#endif
 #else
 	mov	x0, #0
 #endif
@@ -330,10 +357,10 @@ clear_nex_bss:
 	ldr	x0, boot_mmu_config + CORE_MMU_CONFIG_MAP_OFFSET
 	cbz	x0, 1f
 	/*
-	 * Update cached_mem_end address with load offset since it was
+	 * Update boot_cached_mem_end address with load offset since it was
 	 * calculated before relocation.
 	 */
-	adr	x5, cached_mem_end
+	adr_l	x5, boot_cached_mem_end
 	ldr	x6, [x5]
 	add	x6, x6, x0
 	str	x6, [x5]
@@ -345,6 +372,9 @@ clear_nex_bss:
 	bl	__get_core_pos
 	bl	enable_mmu
 #ifdef CFG_CORE_ASLR
+	adr_l	x0, boot_mmu_config
+	ldr	x0, [x0, #CORE_MMU_CONFIG_MAP_OFFSET]
+	bl	boot_mem_relocate
 	/*
 	 * Reinitialize console, since register_serial_console() has
 	 * previously registered a PA and with ASLR the VA is different
@@ -353,6 +383,10 @@ clear_nex_bss:
 	bl	console_init
 #endif
 
+#ifdef CFG_MEMTAG
+	bl	boot_clear_memtag
+#endif
+
 #ifdef CFG_NS_VIRTUALIZATION
 	/*
 	 * Initialize partition tables for each partition to
@@ -378,13 +412,27 @@ clear_nex_bss:
 #endif
 	bl	boot_init_primary_late
 #ifdef CFG_CORE_PAUTH
-	init_pauth_per_cpu
+	adr_l	x0, threads
+	ldp	x1, x2, [x0, #THREAD_CTX_KEYS]
+	write_apiakeyhi x1
+	write_apiakeylo x2
+	mrs	x0, sctlr_el1
+	orr	x0, x0, #SCTLR_ENIA
+	msr	sctlr_el1, x0
+	isb
 #endif
+	bl	boot_init_primary_final
 
 #ifndef CFG_NS_VIRTUALIZATION
 	mov	x0, #THREAD_CLF_TMP
 	str     w0, [x24, #THREAD_CORE_LOCAL_FLAGS]
 	mov	sp, x23
+#ifdef CFG_CORE_PAUTH
+	ldp	x0, x1, [x24, #THREAD_CORE_LOCAL_KEYS]
+	write_apiakeyhi x0
+	write_apiakeylo x1
+	isb
+#endif
 #endif
 
 #ifdef _CFG_CORE_STACK_PROTECTOR
@@ -406,7 +454,8 @@ clear_nex_bss:
 	 * D-cache before exiting to normal world.
 	 */
 	adr_l	x0, __text_start
-	ldr	x1, cached_mem_end
+	adr_l	x1, boot_cached_mem_end
+	ldr	x1, [x1]
 	sub	x1, x1, x0
 	bl	dcache_cleaninv_range
 
@@ -447,11 +496,13 @@ clear_nex_bss:
 END_FUNC _start
 DECLARE_KEEP_INIT _start
 
+#ifndef CFG_WITH_PAGER
 	.section .identity_map.data
 	.balign	8
-LOCAL_DATA cached_mem_end , :
+LOCAL_DATA boot_embdata_ptr , :
 	.skip	8
-END_DATA cached_mem_end
+END_DATA boot_embdata_ptr
+#endif
 
 #if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE)
 LOCAL_FUNC relocate , :
@@ -462,7 +513,8 @@ LOCAL_FUNC relocate , :
 #ifdef CFG_WITH_PAGER
 	adr_l	x6, __init_end
 #else
-	adr_l	x6, __end
+	adr_l	x6, boot_embdata_ptr
+	ldr	x6, [x6]
 #endif
 	ldp	w2, w3, [x6, #BOOT_EMBDATA_RELOC_OFFSET]
 
@@ -615,7 +667,7 @@ FUNC cpu_on_handler , :
 	init_memtag_per_cpu
 #endif
 #ifdef CFG_CORE_PAUTH
-	init_pauth_per_cpu
+	init_pauth_secondary_cpu
 #endif
 
 	mov	x0, x19
diff --git a/core/arch/arm/kernel/generic_timer.c b/core/arch/arm/kernel/generic_timer.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d101fcc69d13b53143a0445eb734d08a7669530
--- /dev/null
+++ b/core/arch/arm/kernel/generic_timer.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <arm.h>
+#include <kernel/callout.h>
+#include <kernel/timer.h>
+
+static void timer_disable(const struct callout_timer_desc *desc __unused)
+{
+	write_cntps_ctl(0);
+}
+
+static void timer_set_next(const struct callout_timer_desc *desc __unused,
+			   uint64_t ctrval)
+{
+	write_cntps_cval(ctrval);
+	write_cntps_ctl(1);
+}
+
+static uint64_t
+timer_ms_to_ticks(const struct callout_timer_desc *desc __unused,
+		  uint32_t timeout_ms)
+{
+	uint64_t freq = read_cntfrq();
+
+	return (freq * timeout_ms) / 1000;
+}
+
+static uint64_t timer_now(const struct callout_timer_desc *desc __unused)
+{
+	return barrier_read_counter_timer();
+}
+
+static struct itr_handler timer_itr __nex_bss;
+static const struct callout_timer_desc timer_desc
+__relrodata_unpaged("timer_desc") = {
+	.disable_timeout = timer_disable,
+	.set_next_timeout = timer_set_next,
+	.ms_to_ticks = timer_ms_to_ticks,
+	.get_now = timer_now,
+	.is_per_cpu = true,
+};
+DECLARE_KEEP_PAGER(timer_desc);
+
+static enum itr_return timer_itr_cb(struct itr_handler *h __unused)
+{
+	callout_service_cb();
+
+	return ITRR_HANDLED;
+}
+DECLARE_KEEP_PAGER(timer_itr_cb);
+
+void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number)
+{
+	timer_itr = (struct itr_handler){
+		.it = itr_number,
+		.flags = ITRF_TRIGGER_LEVEL,
+		.handler = timer_itr_cb,
+	};
+
+	if (interrupt_add_handler_with_chip(itr_chip, &timer_itr))
+		panic();
+
+	interrupt_enable(timer_itr.chip, timer_itr.it);
+	callout_service_init(&timer_desc);
+}
diff --git a/core/arch/arm/kernel/kern.ld.S b/core/arch/arm/kernel/kern.ld.S
index 500c2d2f8a8c3b3aac9fad2f93652727450927fe..03ae13045d56e2a3754d4e7ddd1d6c45b9c349e7 100644
--- a/core/arch/arm/kernel/kern.ld.S
+++ b/core/arch/arm/kernel/kern.ld.S
@@ -157,13 +157,13 @@ SECTIONS
 	}
 
 	/* .ARM.exidx is sorted, so has to go in its own output section.  */
-	.ARM.exidx : {
+	.ARM.exidx : ALIGN(8) {
 		__exidx_start = .;
 		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
 		__exidx_end = .;
 	}
 
-	.ARM.extab : {
+	.ARM.extab : ALIGN(8) {
 		__extab_start = .;
 		*(.ARM.extab*)
 		__extab_end = .;
@@ -279,8 +279,11 @@ SECTIONS
 		. = ALIGN(8);
 		__nozi_stack_end = .;
 	}
-
-#ifdef CFG_WITH_PAGER
+#ifndef CFG_WITH_PAGER
+	. = ALIGN(SMALL_PAGE_SIZE);
+	__flatmap_free_start = .;
+	__flatmap_unpg_rw_size = __flatmap_free_start - __flatmap_unpg_rw_start;
+#else
 	.heap2 (NOLOAD) : {
 		__heap2_start = .;
 		/*
@@ -374,7 +377,10 @@ SECTIONS
 	ASSERT(TEE_LOAD_ADDR < (TEE_RAM_START + TEE_RAM_PH_SIZE),
 		"Load address after end of physical memory")
 	ASSERT((TEE_RAM_START + TEE_RAM_PH_SIZE - __init_end) >
-		SMALL_PAGE_SIZE, "Too few free pages to initialize paging")
+		SMALL_PAGE_SIZE * 2 +
+		(__pageable_end - __pageable_start) / 4096 * 32 +
+		SIZEOF(.rel) / 2 + SIZEOF(.rela) / 3 ,
+		"Too few free pages to initialize paging")
 
 
 #endif /*CFG_WITH_PAGER*/
@@ -406,8 +412,8 @@ SECTIONS
 	_end_of_ram = .;
 
 #ifndef CFG_WITH_PAGER
-	__flatmap_unpg_rw_size = _end_of_ram - __flatmap_unpg_rw_start;
 	__get_tee_init_end = .;
+	__flatmap_free_size = _end_of_ram - __flatmap_free_start;
 #endif
 
 	/*
@@ -458,6 +464,12 @@ __vcore_unpg_rw_start = __flatmap_unpg_rw_start;
 __vcore_unpg_rw_size = __flatmap_unpg_rw_size;
 __vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size;
 
+#ifndef CFG_WITH_PAGER
+__vcore_free_start = __flatmap_free_start;
+__vcore_free_size = __flatmap_free_size;
+__vcore_free_end = __flatmap_free_start + __flatmap_free_size;
+#endif
+
 #ifdef CFG_NS_VIRTUALIZATION
 /* Nexus read-write memory */
 __vcore_nex_rw_start = __flatmap_nex_rw_start;
@@ -466,28 +478,21 @@ __vcore_nex_rw_end = __vcore_nex_rw_start + __vcore_nex_rw_size;
 #endif
 
 #ifdef CFG_WITH_PAGER
-/*
- * Core init mapping shall cover up to end of the physical RAM.
- * This is required since the hash table is appended to the
- * binary data after the firmware build sequence.
- */
-#define __FLATMAP_PAGER_TRAILING_SPACE	\
-	(TEE_RAM_START + TEE_RAM_PH_SIZE - \
-		(__flatmap_init_ro_start + __flatmap_init_ro_size))
-
 /* Paged/init read-only memories */
 __vcore_init_rx_start = __flatmap_init_rx_start;
-__vcore_init_ro_start = __flatmap_init_ro_start;
 #ifdef CFG_CORE_RODATA_NOEXEC
 __vcore_init_rx_size = __flatmap_init_rx_size;
-__vcore_init_ro_size = __flatmap_init_ro_size + __FLATMAP_PAGER_TRAILING_SPACE;
+__vcore_init_ro_start = __flatmap_init_ro_start;
+__vcore_init_ro_size = __flatmap_init_ro_size;
 #else
-__vcore_init_rx_size = __flatmap_init_rx_size + __flatmap_init_ro_size +
-		       __FLATMAP_PAGER_TRAILING_SPACE;
+__vcore_init_rx_size = __flatmap_init_rx_size + __flatmap_init_ro_size;
+__vcore_init_ro_start = __vcore_init_rx_end;
 __vcore_init_ro_size = 0;
 #endif /* CFG_CORE_RODATA_NOEXEC */
 __vcore_init_rx_end = __vcore_init_rx_start + __vcore_init_rx_size;
 __vcore_init_ro_end = __vcore_init_ro_start + __vcore_init_ro_size;
+ASSERT(__vcore_init_ro_start == __vcore_init_rx_end,
+       "__vcore_init_ro_start should follow __vcore_init_rx_end")
 #endif /* CFG_WITH_PAGER */
 
 #ifdef CFG_CORE_SANITIZE_KADDRESS
diff --git a/core/arch/arm/kernel/link.mk b/core/arch/arm/kernel/link.mk
index 49e9f4fa18a5ba563b77f3ee587d90b3edc502a1..11fe79d982ceb06b490049fe7feda12daba6d241 100644
--- a/core/arch/arm/kernel/link.mk
+++ b/core/arch/arm/kernel/link.mk
@@ -140,38 +140,6 @@ $(link-script-pp): $(link-script) $(link-script-extra-deps)
 	$(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \
 		$(link-script-cppflags) $< -o $@
 
-define update-buildcount
-	@$(cmd-echo-silent) '  UPD     $(1)'
-	$(q)if [ ! -f $(1) ]; then \
-		mkdir -p $(dir $(1)); \
-		echo 1 >$(1); \
-	else \
-		expr 0`cat $(1)` + 1 >$(1); \
-	fi
-endef
-
-# filter-out to workaround objdump warning
-version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \
-			$(platform-cflags) $(cflagscore))
-# SOURCE_DATE_EPOCH defined for reproducible builds
-ifneq ($(SOURCE_DATE_EPOCH),)
-date-opts = -d @$(SOURCE_DATE_EPOCH)
-endif
-DATE_STR = `LC_ALL=C date -u $(date-opts)`
-BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount`
-CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'`
-define gen-version-o
-	$(call update-buildcount,$(link-out-dir)/.buildcount)
-	@$(cmd-echo-silent) '  GEN     $(link-out-dir)/version.o'
-	$(q)echo -e "const char core_v_str[] =" \
-		"\"$(TEE_IMPL_VERSION) \"" \
-		"\"($(CORE_CC_VERSION)) \"" \
-		"\"#$(BUILD_COUNT_STR) \"" \
-		"\"$(DATE_STR) \"" \
-		"\"$(CFG_KERN_LINKER_ARCH)\";\n" \
-		| $(CCcore) $(version-o-cflags) \
-			-xc - -c -o $(link-out-dir)/version.o
-endef
 $(link-out-dir)/version.o:
 	$(call gen-version-o)
 
diff --git a/core/arch/arm/kernel/link_dummies_paged.c b/core/arch/arm/kernel/link_dummies_paged.c
index 4e9f090d019c16ba76f40a39ad7f9832a9ee23f2..84de15dd1b43ed2aed156b54d08d09dccf13b7e0 100644
--- a/core/arch/arm/kernel/link_dummies_paged.c
+++ b/core/arch/arm/kernel/link_dummies_paged.c
@@ -13,12 +13,24 @@
 #include <mm/fobj.h>
 #include <mm/mobj.h>
 #include <tee_api_types.h>
-#include <tee/entry_std.h>
 
 void __section(".text.dummy.call_preinitcalls") call_preinitcalls(void)
 {
 }
 
+void __section(".text.dummy.call_early_initcalls") call_early_initcalls(void)
+{
+}
+
+void __section(".text.dummy.call_service_initcalls")
+call_service_initcalls(void)
+{
+}
+
+void __section(".text.dummy.call_driver_initcalls") call_driver_initcalls(void)
+{
+}
+
 void __section(".text.dummy.call_initcalls") call_initcalls(void)
 {
 }
@@ -33,6 +45,11 @@ boot_init_primary_late(unsigned long fdt __unused,
 {
 }
 
+void __section(".text.dummy.boot_init_primary_final")
+boot_init_primary_final(void)
+{
+}
+
 uint32_t __section(".text.dummy.__thread_std_smc_entry")
 __thread_std_smc_entry(uint32_t a0 __unused, uint32_t a1 __unused,
 		       uint32_t a2 __unused, uint32_t a3 __unused,
diff --git a/core/arch/arm/kernel/link_dummy.ld b/core/arch/arm/kernel/link_dummy.ld
index 1393088bd844357dc652c642ff3688f7f6ce7653..cd87c2cf003eec51673962cfb67bf299f73681d9 100644
--- a/core/arch/arm/kernel/link_dummy.ld
+++ b/core/arch/arm/kernel/link_dummy.ld
@@ -100,6 +100,9 @@ __vcore_unpg_rw_start = .;
 __vcore_unpg_rx_end = .;
 __vcore_unpg_rx_size = .;
 __vcore_unpg_rx_start = .;
+__vcore_free_start = .;
+__vcore_free_size = .;
+__vcore_free_end = .;
 PROVIDE(core_v_str = 0);
 PROVIDE(tee_entry_std = 0);
 PROVIDE(init_teecore = 0);
diff --git a/core/arch/arm/kernel/misc_a64.S b/core/arch/arm/kernel/misc_a64.S
index 3e70a0da91493611aacc288866acf04b2df3bd5b..2334fb062f31f6f27127011a723b07e34fe8aa7a 100644
--- a/core/arch/arm/kernel/misc_a64.S
+++ b/core/arch/arm/kernel/misc_a64.S
@@ -17,6 +17,10 @@ END_FUNC __get_core_pos
 /* size_t get_core_pos_mpidr(uint32_t mpidr); */
 /* Let platforms override this if needed */
 WEAK_FUNC get_core_pos_mpidr , :
+#if CFG_CORE_SEL2_SPMC
+	mov	x1, #MPIDR_VCPU_MASK
+	and	x0, x0, x1
+#else /* CFG_CORE_SEL2_SPMC */
 	/*
 	 * Shift MPIDR value if it's not already shifted.
 	 * Using logical shift ensures AFF0 to be filled with zeroes.
@@ -47,6 +51,7 @@ WEAK_FUNC get_core_pos_mpidr , :
 	ubfx	x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
 	add	x1, x1, x2, LSL #(CFG_CORE_CLUSTER_SHIFT)
 	add	x0, x0, x1, LSL #(CFG_CORE_THREAD_SHIFT)
+#endif
 #endif
 
 	ret
diff --git a/core/arch/arm/kernel/secure_partition.c b/core/arch/arm/kernel/secure_partition.c
index 8cdddbe0cebf144165d7541e2f8ddbd4d252f00a..f1b5bb249107dd07636a233c01fde00b2cffe313 100644
--- a/core/arch/arm/kernel/secure_partition.c
+++ b/core/arch/arm/kernel/secure_partition.c
@@ -1,8 +1,7 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2020-2023, Arm Limited.
+ * Copyright (c) 2020-2024, Arm Limited.
  */
-#include <bench.h>
 #include <crypto/crypto.h>
 #include <initcall.h>
 #include <kernel/boot.h>
@@ -20,12 +19,13 @@
 #include <mm/core_mmu.h>
 #include <mm/fobj.h>
 #include <mm/mobj.h>
+#include <mm/phys_mem.h>
 #include <mm/vm.h>
 #include <optee_ffa.h>
 #include <stdio.h>
 #include <string.h>
-#include <tee_api_types.h>
 #include <tee/uuid.h>
+#include <tee_api_types.h>
 #include <trace.h>
 #include <types_ext.h>
 #include <utee_defines.h>
@@ -38,6 +38,7 @@
 #define SP_MANIFEST_ATTR_WRITE		BIT(1)
 #define SP_MANIFEST_ATTR_EXEC		BIT(2)
 #define SP_MANIFEST_ATTR_NSEC		BIT(3)
+#define SP_MANIFEST_ATTR_GP		BIT(4)
 
 #define SP_MANIFEST_ATTR_RO		(SP_MANIFEST_ATTR_READ)
 #define SP_MANIFEST_ATTR_RW		(SP_MANIFEST_ATTR_READ | \
@@ -54,6 +55,16 @@
 #define SP_MANIFEST_NS_INT_MANAGED_EXIT	(0x1)
 #define SP_MANIFEST_NS_INT_SIGNALED	(0x2)
 
+#define SP_MANIFEST_EXEC_STATE_AARCH64	(0x0)
+#define SP_MANIFEST_EXEC_STATE_AARCH32	(0x1)
+
+#define SP_MANIFEST_DIRECT_REQ_RECEIVE	BIT(0)
+#define SP_MANIFEST_DIRECT_REQ_SEND	BIT(1)
+#define SP_MANIFEST_INDIRECT_REQ	BIT(2)
+
+#define SP_MANIFEST_VM_CREATED_MSG	BIT(0)
+#define SP_MANIFEST_VM_DESTROYED_MSG	BIT(1)
+
 #define SP_PKG_HEADER_MAGIC (0x474b5053)
 #define SP_PKG_HEADER_VERSION_V1 (0x1)
 #define SP_PKG_HEADER_VERSION_V2 (0x2)
@@ -120,8 +131,6 @@ TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size,
 				 bool count_only)
 {
 	TEE_Result res = TEE_SUCCESS;
-	uint32_t part_props = FFA_PART_PROP_DIRECT_REQ_RECV |
-			      FFA_PART_PROP_DIRECT_REQ_SEND;
 	struct sp_session *s = NULL;
 
 	TAILQ_FOREACH(s, &open_sp_sessions, link) {
@@ -138,7 +147,7 @@ TEE_Result sp_partition_info_get(uint32_t ffa_vers, void *buf, size_t buf_size,
 			res = spmc_fill_partition_entry(ffa_vers, buf, buf_size,
 							*elem_count,
 							s->endpoint_id, 1,
-							part_props, uuid_words);
+							s->props, uuid_words);
 		}
 		*elem_count += 1;
 	}
@@ -170,23 +179,29 @@ bool sp_has_exclusive_access(struct sp_mem_map_region *mem,
 	return !sp_mem_is_shared(mem);
 }
 
-static TEE_Result new_session_id(uint16_t *endpoint_id)
+static bool endpoint_id_is_valid(uint32_t id)
 {
-	struct sp_session *session = NULL;
+	/*
+	 * These IDs are assigned at the SPMC init so already have valid values
+	 * by the time this function gets first called
+	 */
+	return id != spmd_id && id != spmc_id && id != optee_endpoint_id &&
+	       id >= FFA_SWD_ID_MIN && id <= FFA_SWD_ID_MAX;
+}
 
-	*endpoint_id = SPMC_ENDPOINT_ID;
+static TEE_Result new_session_id(uint16_t *endpoint_id)
+{
+	uint32_t id = 0;
 
 	/* Find the first available endpoint id */
-	do {
-		if (*endpoint_id == UINT16_MAX)
-			return TEE_ERROR_BAD_FORMAT;
-
-		(*endpoint_id)++;
-
-		session = sp_get_session(*endpoint_id);
-	} while (session);
+	for (id = FFA_SWD_ID_MIN; id <= FFA_SWD_ID_MAX; id++) {
+		if (endpoint_id_is_valid(id) && !sp_get_session(id)) {
+			*endpoint_id = id;
+			return TEE_SUCCESS;
+		}
+	}
 
-	return TEE_SUCCESS;
+	return TEE_ERROR_BAD_FORMAT;
 }
 
 static TEE_Result sp_create_ctx(const TEE_UUID *bin_uuid, struct sp_session *s)
@@ -209,6 +224,10 @@ static TEE_Result sp_create_ctx(const TEE_UUID *bin_uuid, struct sp_session *s)
 
 	set_sp_ctx_ops(&spc->ts_ctx);
 
+#ifdef CFG_TA_PAUTH
+	crypto_rng_read(&spc->uctx.keys, sizeof(spc->uctx.keys));
+#endif
+
 	return TEE_SUCCESS;
 
 err:
@@ -252,6 +271,9 @@ static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions,
 
 	s->boot_order = boot_order;
 
+	/* Other properties are filled later, based on the SP's manifest */
+	s->props = FFA_PART_PROP_IS_PE_ID;
+
 	res = new_session_id(&s->endpoint_id);
 	if (res)
 		goto err;
@@ -513,7 +535,7 @@ static TEE_Result load_binary_sp(struct ts_session *s,
 	bin_page_count = bin_size_rounded / SMALL_PAGE_SIZE;
 
 	/* Allocate memory */
-	mm = tee_mm_alloc(&tee_mm_sec_ddr, bin_size_rounded);
+	mm = phys_mem_ta_alloc(bin_size_rounded);
 	if (!mm) {
 		res = TEE_ERROR_OUT_OF_MEMORY;
 		goto err;
@@ -734,21 +756,17 @@ static void fill_boot_info_1_1(vaddr_t buf, const void *fdt)
 
 static TEE_Result create_and_map_boot_info(struct sp_ctx *ctx, const void *fdt,
 					   struct thread_smc_args *args,
-					   vaddr_t *va, size_t *mapped_size)
+					   vaddr_t *va, size_t *mapped_size,
+					   uint32_t sp_ffa_version)
 {
 	size_t total_size = ROUNDUP(CFG_SP_INIT_INFO_MAX_SIZE, SMALL_PAGE_SIZE);
 	size_t num_pages = total_size / SMALL_PAGE_SIZE;
 	uint32_t perm = TEE_MATTR_UR | TEE_MATTR_PRW;
 	TEE_Result res = TEE_SUCCESS;
-	uint32_t sp_ffa_version = 0;
 	struct fobj *f = NULL;
 	struct mobj *m = NULL;
 	uint32_t info_reg = 0;
 
-	res = sp_dt_get_u32(fdt, 0, "ffa-version", &sp_ffa_version);
-	if (res)
-		return res;
-
 	f = fobj_sec_mem_alloc(num_pages);
 	m = mobj_with_fobj_alloc(f, NULL, TEE_MATTR_MEM_TYPE_TAGGED);
 	fobj_put(f);
@@ -879,6 +897,15 @@ static TEE_Result handle_fdt_load_relative_mem_regions(struct sp_ctx *ctx,
 			return TEE_ERROR_BAD_FORMAT;
 		}
 
+		if (IS_ENABLED(CFG_TA_BTI) &&
+		    attributes & SP_MANIFEST_ATTR_GP) {
+			if (!(attributes & SP_MANIFEST_ATTR_RX)) {
+				EMSG("Guard only executable region");
+				return TEE_ERROR_BAD_FORMAT;
+			}
+			perm |= TEE_MATTR_GUARDED;
+		}
+
 		res = sp_dt_get_u32(fdt, subnode, "load-flags", &flags);
 		if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND) {
 			EMSG("Optional field with invalid value: flags");
@@ -900,7 +927,7 @@ static TEE_Result handle_fdt_load_relative_mem_regions(struct sp_ctx *ctx,
 			struct mobj *m = NULL;
 			unsigned int idx = 0;
 
-			mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
+			mm = phys_mem_ta_alloc(size);
 			if (!mm)
 				return TEE_ERROR_OUT_OF_MEMORY;
 
@@ -1093,8 +1120,10 @@ static TEE_Result read_manifest_endpoint_id(struct sp_session *s)
 	if (!sp_dt_get_u32(s->fdt, 0, "id", &endpoint_id)) {
 		TEE_Result res = TEE_ERROR_GENERIC;
 
-		if (endpoint_id <= SPMC_ENDPOINT_ID)
+		if (!endpoint_id_is_valid(endpoint_id)) {
+			EMSG("Invalid endpoint ID 0x%"PRIx32, endpoint_id);
 			return TEE_ERROR_BAD_FORMAT;
+		}
 
 		res = swap_sp_endpoints(endpoint_id, s->endpoint_id);
 		if (res)
@@ -1206,6 +1235,15 @@ static TEE_Result handle_fdt_mem_regions(struct sp_ctx *ctx, void *fdt)
 			return TEE_ERROR_BAD_FORMAT;
 		}
 
+		if (IS_ENABLED(CFG_TA_BTI) &&
+		    attributes & SP_MANIFEST_ATTR_GP) {
+			if (!(attributes & SP_MANIFEST_ATTR_RX)) {
+				EMSG("Guard only executable region");
+				return TEE_ERROR_BAD_FORMAT;
+			}
+			perm |= TEE_MATTR_GUARDED;
+		}
+
 		/*
 		 * The SP is a secure endpoint, security attribute can be
 		 * secure or non-secure.
@@ -1222,7 +1260,7 @@ static TEE_Result handle_fdt_mem_regions(struct sp_ctx *ctx, void *fdt)
 
 		if (alloc_needed) {
 			/* Base address is missing, we have to allocate */
-			mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
+			mm = phys_mem_ta_alloc(size);
 			if (!mm)
 				return TEE_ERROR_OUT_OF_MEMORY;
 
@@ -1374,6 +1412,22 @@ static TEE_Result handle_hw_features(void *fdt)
 			return res;
 	}
 
+	/* Modify the property only if it's already present */
+	if (!sp_dt_get_u32(fdt, node, "bti", &val)) {
+		res = fdt_setprop_u32(fdt, node, "bti",
+				      feat_bti_is_implemented());
+		if (res)
+			return res;
+	}
+
+	/* Modify the property only if it's already present */
+	if (!sp_dt_get_u32(fdt, node, "pauth", &val)) {
+		res = fdt_setprop_u32(fdt, node, "pauth",
+				      feat_pauth_is_implemented());
+		if (res)
+			return res;
+	}
+
 	return TEE_SUCCESS;
 }
 
@@ -1408,6 +1462,101 @@ static TEE_Result read_ns_interrupts_action(const void *fdt,
 	return TEE_SUCCESS;
 }
 
+static TEE_Result read_ffa_version(const void *fdt, struct sp_session *s)
+{
+	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
+	uint32_t ffa_version = 0;
+
+	res = sp_dt_get_u32(fdt, 0, "ffa-version", &ffa_version);
+	if (res) {
+		EMSG("Mandatory property is missing: ffa-version");
+		return res;
+	}
+
+	if (ffa_version != FFA_VERSION_1_0 && ffa_version != FFA_VERSION_1_1) {
+		EMSG("Invalid FF-A version value: 0x%08"PRIx32, ffa_version);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	s->rxtx.ffa_vers = ffa_version;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result read_sp_exec_state(const void *fdt, struct sp_session *s)
+{
+	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
+	uint32_t exec_state = 0;
+
+	res = sp_dt_get_u32(fdt, 0, "execution-state", &exec_state);
+	if (res) {
+		EMSG("Mandatory property is missing: execution-state");
+		return res;
+	}
+
+	/* Currently only AArch64 SPs are supported */
+	if (exec_state == SP_MANIFEST_EXEC_STATE_AARCH64) {
+		s->props |= FFA_PART_PROP_AARCH64_STATE;
+	} else {
+		EMSG("Invalid execution-state value: %"PRIu32, exec_state);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result read_sp_msg_types(const void *fdt, struct sp_session *s)
+{
+	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
+	uint32_t msg_method = 0;
+
+	res = sp_dt_get_u32(fdt, 0, "messaging-method", &msg_method);
+	if (res) {
+		EMSG("Mandatory property is missing: messaging-method");
+		return res;
+	}
+
+	if (msg_method & SP_MANIFEST_DIRECT_REQ_RECEIVE)
+		s->props |= FFA_PART_PROP_DIRECT_REQ_RECV;
+
+	if (msg_method & SP_MANIFEST_DIRECT_REQ_SEND)
+		s->props |= FFA_PART_PROP_DIRECT_REQ_SEND;
+
+	if (msg_method & SP_MANIFEST_INDIRECT_REQ)
+		IMSG("Indirect messaging is not supported");
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result read_vm_availability_msg(const void *fdt,
+					   struct sp_session *s)
+{
+	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
+	uint32_t v = 0;
+
+	res = sp_dt_get_u32(fdt, 0, "vm-availability-messages", &v);
+
+	/* This field in the manifest is optional */
+	if (res == TEE_ERROR_ITEM_NOT_FOUND)
+		return TEE_SUCCESS;
+
+	if (res)
+		return res;
+
+	if (v & ~(SP_MANIFEST_VM_CREATED_MSG | SP_MANIFEST_VM_DESTROYED_MSG)) {
+		EMSG("Invalid vm-availability-messages value: %"PRIu32, v);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (v & SP_MANIFEST_VM_CREATED_MSG)
+		s->props |= FFA_PART_PROP_NOTIF_CREATED;
+
+	if (v & SP_MANIFEST_VM_DESTROYED_MSG)
+		s->props |= FFA_PART_PROP_NOTIF_DESTROYED;
+
+	return TEE_SUCCESS;
+}
+
 static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt)
 {
 	TEE_Result res = TEE_SUCCESS;
@@ -1447,6 +1596,22 @@ static TEE_Result sp_init_uuid(const TEE_UUID *bin_uuid, const void * const fdt)
 	if (res)
 		return res;
 
+	res = read_ffa_version(fdt, sess);
+	if (res)
+		return res;
+
+	res = read_sp_exec_state(fdt, sess);
+	if (res)
+		return res;
+
+	res = read_sp_msg_types(fdt, sess);
+	if (res)
+		return res;
+
+	res = read_vm_availability_msg(fdt, sess);
+	if (res)
+		return res;
+
 	return TEE_SUCCESS;
 }
 
@@ -1497,7 +1662,7 @@ static TEE_Result sp_first_run(struct sp_session *sess)
 		goto out;
 
 	res = create_and_map_boot_info(ctx, fdt_copy, &args, &boot_info_va,
-				       &boot_info_size);
+				       &boot_info_size, sess->rxtx.ffa_vers);
 	if (res)
 		goto out;
 
@@ -1536,6 +1701,10 @@ TEE_Result sp_enter(struct thread_smc_args *args, struct sp_session *sp)
 	ctx->sp_regs.x[5] = args->a5;
 	ctx->sp_regs.x[6] = args->a6;
 	ctx->sp_regs.x[7] = args->a7;
+#ifdef CFG_TA_PAUTH
+	ctx->sp_regs.apiakey_hi = ctx->uctx.keys.apia_hi;
+	ctx->sp_regs.apiakey_lo = ctx->uctx.keys.apia_lo;
+#endif
 
 	res = sp->ts_sess.ctx->ops->enter_invoke_cmd(&sp->ts_sess, 0);
 
@@ -1595,8 +1764,6 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
 	uint32_t panicked = false;
 	uint32_t panic_code = 0;
 
-	bm_timestamp();
-
 	sp_regs = &ctx->sp_regs;
 	ts_push_current_session(s);
 
@@ -1640,8 +1807,6 @@ static TEE_Result sp_enter_invoke_cmd(struct ts_session *s,
 	sess = ts_pop_current_session();
 	assert(sess == s);
 
-	bm_timestamp();
-
 	return res;
 }
 
@@ -1706,7 +1871,7 @@ static const struct ts_ops sp_ops = {
 
 static TEE_Result process_sp_pkg(uint64_t sp_pkg_pa, TEE_UUID *sp_uuid)
 {
-	enum teecore_memtypes mtype = MEM_AREA_TA_RAM;
+	enum teecore_memtypes mtype = MEM_AREA_SEC_RAM_OVERALL;
 	struct sp_pkg_header *sp_pkg_hdr = NULL;
 	struct fip_sp *sp = NULL;
 	uint64_t sp_fdt_end = 0;
diff --git a/core/arch/arm/kernel/semihosting_a64.S b/core/arch/arm/kernel/semihosting_a64.S
new file mode 100644
index 0000000000000000000000000000000000000000..1271cc8bd4d5ed032cc734e8c48af04b3aa17863
--- /dev/null
+++ b/core/arch/arm/kernel/semihosting_a64.S
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 Linaro, Ltd.
+ */
+
+#include <asm.S>
+
+/*
+ * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg)
+ *
+ * Refer to "Semihosting for Aarch32 and Aarch64":
+ * https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst
+ */
+FUNC __do_semihosting , :
+	hlt	#0xf000
+	ret
+END_FUNC __do_semihosting
diff --git a/core/arch/arm/kernel/spmc_sp_handler.c b/core/arch/arm/kernel/spmc_sp_handler.c
index 65e0a82cbd36354c130c446c6ed661dad93355fb..782e4bdef86c5cdf6694760230b74381270152ce 100644
--- a/core/arch/arm/kernel/spmc_sp_handler.c
+++ b/core/arch/arm/kernel/spmc_sp_handler.c
@@ -3,7 +3,6 @@
  * Copyright (c) 2021-2024, Arm Limited
  */
 #include <assert.h>
-#include <bench.h>
 #include <io.h>
 #include <kernel/panic.h>
 #include <kernel/secure_partition.h>
@@ -47,9 +46,6 @@ static TEE_Result ffa_get_dst(struct thread_smc_args *args,
 {
 	struct sp_session *s = NULL;
 
-	if (args->a2 != FFA_PARAM_MBZ)
-		return FFA_INVALID_PARAMETERS;
-
 	s = sp_get_session(FFA_DST(args->a1));
 
 	/* Message came from the NW */
@@ -143,8 +139,8 @@ static void spmc_sp_handle_mem_share(struct thread_smc_args *args,
 
 	cpu_spin_lock(&rxtx->spinlock);
 
-	/* Descriptor fragments aren't supported yet. */
-	if (frag_len != tot_len)
+	/* Descriptor fragments or custom buffers aren't supported yet. */
+	if (frag_len != tot_len || args->a3 || args->a4)
 		res = FFA_NOT_SUPPORTED;
 	else if (frag_len > rxtx->size)
 		res = FFA_INVALID_PARAMETERS;
@@ -152,7 +148,7 @@ static void spmc_sp_handle_mem_share(struct thread_smc_args *args,
 		res = spmc_read_mem_transaction(rxtx->ffa_vers, rxtx->rx,
 						frag_len, &mem_trans);
 	if (!res)
-		res = spmc_sp_add_share(&mem_trans, rxtx, tot_len,
+		res = spmc_sp_add_share(&mem_trans, rxtx, tot_len, frag_len,
 					&global_handle, owner_sp);
 	if (!res) {
 		args->a3 = high32_from_64(global_handle);
@@ -287,7 +283,7 @@ clean_up:
 }
 
 int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans,
-		      struct ffa_rxtx *rxtx, size_t blen,
+		      struct ffa_rxtx *rxtx, size_t blen, size_t flen,
 		      uint64_t *global_handle, struct sp_session *owner_sp)
 {
 	int res = FFA_INVALID_PARAMETERS;
@@ -298,9 +294,19 @@ int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans,
 	size_t addr_range_offs = 0;
 	struct ffa_mem_region *mem_reg = NULL;
 	uint8_t highest_permission = 0;
-	struct sp_mem *smem = sp_mem_new();
+	struct sp_mem *smem = NULL;
 	uint16_t sender_id = mem_trans->sender_id;
+	size_t addr_range_cnt = 0;
+	struct ffa_address_range *addr_range = NULL;
+	size_t total_page_count = 0;
+	size_t page_count_sum = 0;
+
+	if (blen != flen) {
+		DMSG("Fragmented memory share is not supported for SPs");
+		return FFA_NOT_SUPPORTED;
+	}
 
+	smem = sp_mem_new();
 	if (!smem)
 		return FFA_NO_MEMORY;
 
@@ -314,7 +320,7 @@ int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans,
 	mem_acc = (void *)((vaddr_t)rxtx->rx + mem_trans->mem_access_offs);
 
 	if (!num_mem_accs) {
-		res = FFA_DENIED;
+		res = FFA_INVALID_PARAMETERS;
 		goto cleanup;
 	}
 
@@ -327,32 +333,68 @@ int spmc_sp_add_share(struct ffa_mem_transaction_x *mem_trans,
 	if (MUL_OVERFLOW(num_mem_accs, sizeof(*mem_acc), &needed_size) ||
 	    ADD_OVERFLOW(needed_size, mem_trans->mem_access_offs,
 			 &needed_size) || needed_size > blen) {
-		res = FFA_NO_MEMORY;
+		res = FFA_INVALID_PARAMETERS;
 		goto cleanup;
 	}
 
 	for (i = 0; i < num_mem_accs; i++)
 		highest_permission |= READ_ONCE(mem_acc[i].access_perm.perm);
 
+	/* Check if the memory region array fits into the buffer */
 	addr_range_offs = READ_ONCE(mem_acc[0].region_offs);
+
+	if (ADD_OVERFLOW(addr_range_offs, sizeof(*mem_reg), &needed_size) ||
+	    needed_size > blen) {
+		res = FFA_INVALID_PARAMETERS;
+		goto cleanup;
+	}
+
 	mem_reg = (void *)((char *)rxtx->rx + addr_range_offs);
+	addr_range_cnt = READ_ONCE(mem_reg->address_range_count);
+	total_page_count = READ_ONCE(mem_reg->total_page_count);
 
-	/* Iterate over all the addresses */
-	if (owner_sp) {
-		size_t address_range = READ_ONCE(mem_reg->address_range_count);
+	/* Memory transaction without address ranges or pages is invalid */
+	if (!addr_range_cnt || !total_page_count) {
+		res = FFA_INVALID_PARAMETERS;
+		goto cleanup;
+	}
+
+	/* Check if the region descriptors fit into the buffer */
+	if (MUL_OVERFLOW(addr_range_cnt, sizeof(*addr_range), &needed_size) ||
+	    ADD_OVERFLOW(needed_size, addr_range_offs, &needed_size) ||
+	    needed_size > blen) {
+		res = FFA_INVALID_PARAMETERS;
+		goto cleanup;
+	}
 
-		for (i = 0; i < address_range; i++) {
-			struct ffa_address_range *addr_range = NULL;
+	page_count_sum = 0;
+	for (i = 0; i < addr_range_cnt; i++) {
+		addr_range = &mem_reg->address_range_array[i];
 
-			addr_range = &mem_reg->address_range_array[i];
+		/* Memory region without pages is invalid */
+		if (!addr_range->page_count) {
+			res = FFA_INVALID_PARAMETERS;
+			goto cleanup;
+		}
 
-			if (!core_is_buffer_inside((vaddr_t)addr_range,
-						   sizeof(*addr_range),
-						   (vaddr_t)rxtx->rx,
-						   rxtx->size)) {
-				res = FFA_NO_MEMORY;
-				goto cleanup;
-			}
+		/* Sum the page count of each region */
+		if (ADD_OVERFLOW(page_count_sum, addr_range->page_count,
+				 &page_count_sum)) {
+			res = FFA_INVALID_PARAMETERS;
+			goto cleanup;
+		}
+	}
+
+	/* Validate total page count */
+	if (total_page_count != page_count_sum) {
+		res = FFA_INVALID_PARAMETERS;
+		goto cleanup;
+	}
+
+	/* Iterate over all the addresses */
+	if (owner_sp) {
+		for (i = 0; i < addr_range_cnt; i++) {
+			addr_range = &mem_reg->address_range_array[i];
 			res = spmc_sp_add_sp_region(smem, addr_range,
 						    owner_sp,
 						    highest_permission);
@@ -508,7 +550,7 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer,
 		/* copy the mem_transaction_descr */
 		d_ds->sender_id = receiver->smem->sender_id;
 		d_ds->mem_reg_attr = receiver->smem->mem_reg_attr;
-		d_ds->flags = receiver->smem->flags;
+		d_ds->flags = FFA_MEMORY_TRANSACTION_TYPE_SHARE;
 		d_ds->tag = receiver->smem->tag;
 		d_ds->mem_access_count = 1;
 	} else {
@@ -521,7 +563,7 @@ static void create_retrieve_response(uint32_t ffa_vers, void *dst_buffer,
 
 		d_ds->sender_id = receiver->smem->sender_id;
 		d_ds->mem_reg_attr = receiver->smem->mem_reg_attr;
-		d_ds->flags = receiver->smem->flags;
+		d_ds->flags = FFA_MEMORY_TRANSACTION_TYPE_SHARE;
 		d_ds->tag = receiver->smem->tag;
 		d_ds->mem_access_size = sizeof(*mem_acc);
 		d_ds->mem_access_count = 1;
@@ -830,11 +872,6 @@ ffa_handle_sp_direct_req(struct thread_smc_args *args,
 	struct sp_session *dst = NULL;
 	TEE_Result res = FFA_OK;
 
-	if (args->a2 != FFA_PARAM_MBZ) {
-		ffa_set_error(args, FFA_INVALID_PARAMETERS);
-		return caller_sp;
-	}
-
 	res = ffa_get_dst(args, caller_sp, &dst);
 	if (res) {
 		/* Tried to send message to an incorrect endpoint */
@@ -853,6 +890,58 @@ ffa_handle_sp_direct_req(struct thread_smc_args *args,
 		return caller_sp;
 	}
 
+	if (caller_sp &&
+	    !(caller_sp->props & FFA_PART_PROP_DIRECT_REQ_SEND)) {
+		EMSG("SP 0x%"PRIx16" doesn't support sending direct requests",
+		     caller_sp->endpoint_id);
+		ffa_set_error(args, FFA_NOT_SUPPORTED);
+		return caller_sp;
+	}
+
+	if (!(dst->props & FFA_PART_PROP_DIRECT_REQ_RECV)) {
+		EMSG("SP 0x%"PRIx16" doesn't support receipt of direct requests",
+		     dst->endpoint_id);
+		ffa_set_error(args, FFA_NOT_SUPPORTED);
+		return caller_sp;
+	}
+
+	if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) {
+		switch (args->a2 & FFA_MSG_TYPE_MASK) {
+		case FFA_MSG_SEND_VM_CREATED:
+			/* The sender must be the NWd hypervisor (ID 0) */
+			if (FFA_SRC(args->a1) != 0 || caller_sp) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+
+			/* The SP must be subscribed for this message */
+			if (!(dst->props & FFA_PART_PROP_NOTIF_CREATED)) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+			break;
+		case FFA_MSG_SEND_VM_DESTROYED:
+			/* The sender must be the NWd hypervisor (ID 0) */
+			if (FFA_SRC(args->a1) != 0 || caller_sp) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+
+			/* The SP must be subscribed for this message */
+			if (!(dst->props & FFA_PART_PROP_NOTIF_DESTROYED)) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+			break;
+		default:
+			ffa_set_error(args, FFA_NOT_SUPPORTED);
+			return caller_sp;
+		}
+	} else if (args->a2 != FFA_PARAM_MBZ) {
+		ffa_set_error(args, FFA_INVALID_PARAMETERS);
+		return caller_sp;
+	}
+
 	cpu_spin_lock(&dst->spinlock);
 	if (dst->state != sp_idle) {
 		DMSG("SP is busy");
@@ -902,6 +991,43 @@ ffa_handle_sp_direct_resp(struct thread_smc_args *args,
 		return caller_sp;
 	}
 
+	if (args->a2 & FFA_MSG_FLAG_FRAMEWORK) {
+		switch (args->a2 & FFA_MSG_TYPE_MASK) {
+		case FFA_MSG_RESP_VM_CREATED:
+			/* The destination must be the NWd hypervisor (ID 0) */
+			if (FFA_DST(args->a1) != 0 || dst) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+
+			/* The SP must be subscribed for this message */
+			if (!(dst->props & FFA_PART_PROP_NOTIF_CREATED)) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+			break;
+		case FFA_MSG_RESP_VM_DESTROYED:
+			/* The destination must be the NWd hypervisor (ID 0) */
+			if (FFA_DST(args->a1) != 0 || dst) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+
+			/* The SP must be subscribed for this message */
+			if (!(dst->props & FFA_PART_PROP_NOTIF_DESTROYED)) {
+				ffa_set_error(args, FFA_INVALID_PARAMETERS);
+				return caller_sp;
+			}
+			break;
+		default:
+			ffa_set_error(args, FFA_NOT_SUPPORTED);
+			return caller_sp;
+		}
+	} else if (args->a2 != FFA_PARAM_MBZ) {
+		ffa_set_error(args, FFA_INVALID_PARAMETERS);
+		return caller_sp;
+	}
+
 	if (dst && dst->state != sp_busy) {
 		EMSG("SP is not waiting for a request");
 		ffa_set_error(args, FFA_INVALID_PARAMETERS);
@@ -984,12 +1110,6 @@ static void handle_features(struct thread_smc_args *args)
 		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
 }
 
-static void handle_spm_id_get(struct thread_smc_args *args)
-{
-	spmc_set_args(args, FFA_SUCCESS_32, FFA_PARAM_MBZ, SPMC_ENDPOINT_ID,
-		      FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
-}
-
 static void handle_mem_perm_get(struct thread_smc_args *args,
 				struct sp_session *sp_s)
 {
@@ -1220,7 +1340,7 @@ void spmc_sp_msg_handler(struct thread_smc_args *args,
 			sp_enter(args, caller_sp);
 			break;
 		case FFA_SPM_ID_GET:
-			handle_spm_id_get(args);
+			spmc_handle_spm_id_get(args);
 			sp_enter(args, caller_sp);
 			break;
 		case FFA_PARTITION_INFO_GET:
diff --git a/core/arch/arm/kernel/stmm_sp.c b/core/arch/arm/kernel/stmm_sp.c
index 6d991a3068abafe299c79478c4e75b620af2af67..b0d648725f3beca8f8fd237449d8d5c7dbf87ae5 100644
--- a/core/arch/arm/kernel/stmm_sp.c
+++ b/core/arch/arm/kernel/stmm_sp.c
@@ -9,6 +9,7 @@
 #include <keep.h>
 #include <kernel/abort.h>
 #include <kernel/stmm_sp.h>
+#include <kernel/tee_ta_manager.h>
 #include <kernel/thread_private.h>
 #include <kernel/user_mode_ctx.h>
 #include <mempool.h>
@@ -180,7 +181,7 @@ static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0,
 static TEE_Result alloc_and_map_sp_fobj(struct stmm_ctx *spc, size_t sz,
 					uint32_t prot, vaddr_t *va)
 {
-	size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
+	size_t num_pgs = ROUNDUP_DIV(sz, SMALL_PAGE_SIZE);
 	struct fobj *fobj = fobj_ta_mem_alloc(num_pgs);
 	TEE_Result res = TEE_SUCCESS;
 	struct mobj *mobj = NULL;
@@ -334,7 +335,9 @@ static TEE_Result load_stmm(struct stmm_ctx *spc)
 TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess)
 {
 	struct stmm_ctx *spc = NULL;
-	TEE_Result res = TEE_SUCCESS;
+
+	/* Caller is expected to hold tee_ta_mutex for safe changes in @sess */
+	assert(mutex_is_locked(&tee_ta_mutex));
 
 	if (memcmp(uuid, &stmm_uuid, sizeof(*uuid)))
 		return TEE_ERROR_ITEM_NOT_FOUND;
@@ -343,12 +346,18 @@ TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess)
 	if (!spc)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
-	spc->is_initializing = true;
+	spc->ta_ctx.is_initializing = true;
 
-	mutex_lock(&tee_ta_mutex);
 	sess->ts_sess.ctx = &spc->ta_ctx.ts_ctx;
 	sess->ts_sess.handle_scall = sess->ts_sess.ctx->ops->handle_scall;
-	mutex_unlock(&tee_ta_mutex);
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result stmm_complete_session(struct tee_ta_session *sess)
+{
+	struct stmm_ctx *spc = to_stmm_ctx(sess->ts_sess.ctx);
+	TEE_Result res = TEE_SUCCESS;
 
 	ts_push_current_session(&sess->ts_sess);
 	res = load_stmm(spc);
@@ -362,7 +371,7 @@ TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess)
 	}
 
 	mutex_lock(&tee_ta_mutex);
-	spc->is_initializing = false;
+	spc->ta_ctx.is_initializing = false;
 	TAILQ_INSERT_TAIL(&tee_ctxes, &spc->ta_ctx, link);
 	mutex_unlock(&tee_ta_mutex);
 
@@ -381,7 +390,7 @@ static TEE_Result stmm_enter_open_session(struct ts_session *s)
 	if (ta_sess->param->types != exp_pt)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (spc->is_initializing) {
+	if (spc->ta_ctx.is_initializing) {
 		/* StMM is initialized in stmm_init_session() */
 		ta_sess->err_origin = TEE_ORIGIN_TEE;
 		return TEE_ERROR_BAD_STATE;
diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk
index c95c0bda34ccfece19d9bc1dbf07dbc6b5743992..40b7a3f9262ee192b0ad4a2b08372590c032f184 100644
--- a/core/arch/arm/kernel/sub.mk
+++ b/core/arch/arm/kernel/sub.mk
@@ -2,6 +2,9 @@ srcs-y += rpc_io_i2c.c
 srcs-y += idle.c
 
 srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c
+ifeq ($(CFG_CALLOUT),y)
+srcs-$(CFG_ARM64_core) += generic_timer.c
+endif
 srcs-$(CFG_ARM64_core) += timer_a64.c
 
 srcs-$(CFG_ARM32_core) += spin_lock_a32.S
@@ -52,6 +55,9 @@ srcs-$(CFG_ARM64_core) += unwind_arm64.c
 endif
 
 srcs-$(CFG_NS_VIRTUALIZATION) += virtualization.c
+ifeq ($(CFG_SEMIHOSTING),y)
+srcs-$(CFG_ARM64_core) += semihosting_a64.S
+endif
 
 srcs-y += link_dummies_paged.c
 srcs-y += link_dummies_init.c
diff --git a/core/arch/arm/kernel/tee_time_arm_cntpct.c b/core/arch/arm/kernel/tee_time_arm_cntpct.c
index 112dfc3d3b5d599085acb3038bdaff1d44fdda51..51542715b6208820cf25c658b1032dc6474696a3 100644
--- a/core/arch/arm/kernel/tee_time_arm_cntpct.c
+++ b/core/arch/arm/kernel/tee_time_arm_cntpct.c
@@ -7,14 +7,13 @@
 #include <crypto/crypto.h>
 #include <kernel/misc.h>
 #include <kernel/tee_time.h>
-#include <kernel/time_source.h>
 #include <mm/core_mmu.h>
 #include <stdint.h>
 #include <tee/tee_cryp_utl.h>
 #include <trace.h>
 #include <utee_defines.h>
 
-static TEE_Result arm_cntpct_get_sys_time(TEE_Time *time)
+TEE_Result tee_time_get_sys_time(TEE_Time *time)
 {
 	uint64_t cntpct = barrier_read_counter_timer();
 	uint32_t cntfrq = read_cntfrq();
@@ -25,13 +24,10 @@ static TEE_Result arm_cntpct_get_sys_time(TEE_Time *time)
 	return TEE_SUCCESS;
 }
 
-static const struct time_source arm_cntpct_time_source = {
-	.name = "arm cntpct",
-	.protection_level = 1000,
-	.get_sys_time = arm_cntpct_get_sys_time,
-};
-
-REGISTER_TIME_SOURCE(arm_cntpct_time_source)
+uint32_t tee_time_get_sys_time_protection_level(void)
+{
+	return 1000;
+}
 
 /*
  * We collect jitter using cntpct in 32- or 64-bit mode that is typically
diff --git a/core/arch/arm/kernel/thread.c b/core/arch/arm/kernel/thread.c
index 0dd9007ba63864289750f62dd2315a630c62084b..b983a40a233bf4dd37d79c42598dd731f33c57f4 100644
--- a/core/arch/arm/kernel/thread.c
+++ b/core/arch/arm/kernel/thread.c
@@ -31,7 +31,6 @@
 #include <mm/mobj.h>
 #include <mm/tee_mm.h>
 #include <mm/tee_pager.h>
-#include <mm/vm.h>
 #include <smccc.h>
 #include <sm/sm.h>
 #include <trace.h>
@@ -551,14 +550,6 @@ int thread_state_suspend(uint32_t flags, uint32_t cpsr, vaddr_t pc)
 	return ct;
 }
 
-bool thread_init_stack(uint32_t thread_id, vaddr_t sp)
-{
-	if (thread_id >= CFG_NUM_THREADS)
-		return false;
-	threads[thread_id].stack_va_end = sp;
-	return true;
-}
-
 static void __maybe_unused
 set_core_local_kcode_offset(struct thread_core_local *cls, long offset)
 {
@@ -990,7 +981,6 @@ static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0,
 	regs->x[1] = a1;
 	regs->x[2] = a2;
 	regs->x[3] = a3;
-	regs->sp = user_sp;
 	regs->pc = entry_func;
 	regs->cpsr = spsr;
 	regs->x[13] = user_sp;	/* Used when running TA in Aarch32 */
@@ -1009,10 +999,18 @@ static struct thread_pauth_keys *thread_get_pauth_keys(void)
 {
 #if defined(CFG_TA_PAUTH)
 	struct ts_session *s = ts_get_current_session();
-	/* Only user TA's support the PAUTH keys */
-	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
 
-	return &utc->uctx.keys;
+	if  (is_user_ta_ctx(s->ctx)) {
+		struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
+
+		return &utc->uctx.keys;
+	} else if (is_sp_ctx(s->ctx)) {
+		struct sp_ctx *spc = to_sp_ctx(s->ctx);
+
+		return &spc->uctx.keys;
+	}
+
+	panic("[abort] Only user TAs and SPs support PAUTH keys");
 #else
 	return NULL;
 #endif
diff --git a/core/arch/arm/kernel/thread_a32.S b/core/arch/arm/kernel/thread_a32.S
index 5a204212494e6aa883fb2c0e03ce59d3def146b2..fb30941790bc3f254471fb4bee9d66f31432b84c 100644
--- a/core/arch/arm/kernel/thread_a32.S
+++ b/core/arch/arm/kernel/thread_a32.S
@@ -467,9 +467,43 @@ END_FUNC thread_unwind_user_mode
 	push	{r0-r3, r12, lr}
 	.endif
 
+	/*
+	 * Use SP_abt to update core local flags.
+	 * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_TMP |
+	 *         THREAD_CLF_{FIQ|IRQ};
+	 */
+	cps     #CPSR_MODE_ABT
+	ldr     r1, [sp, #THREAD_CORE_LOCAL_FLAGS]
+	lsl     r1, r1, #THREAD_CLF_SAVED_SHIFT
+	.ifc    \mode\(),fiq
+	orr     r1, r1, #(THREAD_CLF_TMP | THREAD_CLF_FIQ)
+	.else
+	orr     r1, r1, #(THREAD_CLF_TMP | THREAD_CLF_IRQ)
+	.endif
+	str     r1, [sp, #THREAD_CORE_LOCAL_FLAGS]
+	.ifc    \mode\(),fiq
+	cps     #CPSR_MODE_FIQ
+	.else
+	cps     #CPSR_MODE_IRQ
+	.endif
+
 	bl	thread_check_canaries
 	bl	interrupt_main_handler
 
+	/*
+	 * Use SP_abt to update core local flags.
+	 * flags >>= THREAD_CLF_SAVED_SHIFT;
+	 */
+	cps     #CPSR_MODE_ABT
+	ldr     r1, [sp, #THREAD_CORE_LOCAL_FLAGS]
+	lsr     r1, r1, #THREAD_CLF_SAVED_SHIFT
+	str     r1, [sp, #THREAD_CORE_LOCAL_FLAGS]
+	.ifc    \mode\(),fiq
+	cps     #CPSR_MODE_FIQ
+	.else
+	cps     #CPSR_MODE_IRQ
+	.endif
+
 	mrs	r0, spsr
 	cmp_spsr_user_mode r0
 
diff --git a/core/arch/arm/kernel/thread_optee_smc.c b/core/arch/arm/kernel/thread_optee_smc.c
index c1fcc23b36cdb7f5f41f84fd63dceab9ef8fe438..95ae9ff1e8e16fb794bead0db6544d0d8ff4b47a 100644
--- a/core/arch/arm/kernel/thread_optee_smc.c
+++ b/core/arch/arm/kernel/thread_optee_smc.c
@@ -22,7 +22,6 @@
 #include <tee/entry_fast.h>
 #include <tee/entry_std.h>
 #include <tee/tee_cryp_utl.h>
-#include <tee/tee_fs_rpc.h>
 
 static bool thread_prealloc_rpc_cache;
 static unsigned int thread_rpc_pnum;
@@ -35,7 +34,7 @@ void thread_handle_fast_smc(struct thread_smc_args *args)
 	thread_check_canaries();
 
 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
-	    virt_set_guest(args->a7)) {
+	    virt_set_guest(args->a7) && args->a7 != HYP_CLNT_ID) {
 		args->a0 = OPTEE_SMC_RETURN_ENOTAVAIL;
 		goto out;
 	}
diff --git a/core/arch/arm/kernel/thread_spmc.c b/core/arch/arm/kernel/thread_spmc.c
index dd63f82575ff91131e3f86cd96c0361458c96dca..dafecc6a1e98df23ea31c50afa926863e54d360c 100644
--- a/core/arch/arm/kernel/thread_spmc.c
+++ b/core/arch/arm/kernel/thread_spmc.c
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
  * Copyright (c) 2020-2023, Linaro Limited.
- * Copyright (c) 2019-2021, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2024, Arm Limited. All rights reserved.
  */
 
 #include <assert.h>
@@ -47,14 +47,27 @@ struct mem_frag_state {
 };
 #endif
 
-static unsigned int spmc_notif_lock = SPINLOCK_UNLOCK;
-static int do_bottom_half_value = -1;
-static uint16_t notif_vm_id;
-static bool spmc_notif_is_ready;
+struct notif_vm_bitmap {
+	bool initialized;
+	int do_bottom_half_value;
+	uint64_t pending;
+	uint64_t bound;
+};
+
+static unsigned int spmc_notif_lock __nex_data = SPINLOCK_UNLOCK;
+static bool spmc_notif_is_ready __nex_bss;
+static int notif_intid __nex_data __maybe_unused = -1;
+
+/* Id used to look up the guest specific struct notif_vm_bitmap */
+static unsigned int notif_vm_bitmap_id __nex_bss;
+/* Notification state when ns-virtualization isn't enabled */
+static struct notif_vm_bitmap default_notif_vm_bitmap;
 
 /* Initialized in spmc_init() below */
-static uint16_t my_endpoint_id __nex_bss;
+uint16_t optee_endpoint_id __nex_bss;
+uint16_t spmc_id __nex_bss;
 #ifdef CFG_CORE_SEL1_SPMC
+uint16_t spmd_id __nex_bss;
 static const uint32_t my_part_props = FFA_PART_PROP_DIRECT_REQ_RECV |
 				      FFA_PART_PROP_DIRECT_REQ_SEND |
 #ifdef CFG_NS_VIRTUALIZATION
@@ -103,10 +116,6 @@ static bool is_nw_buf(struct ffa_rxtx *rxtx)
 static SLIST_HEAD(mem_frag_state_head, mem_frag_state) frag_state_head =
 	SLIST_HEAD_INITIALIZER(&frag_state_head);
 
-static uint64_t notif_pending_bitmap;
-static uint64_t notif_bound_bitmap;
-static bool notif_vm_id_valid;
-static int notif_intid = -1;
 #else
 static uint8_t __rx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
 static uint8_t __tx_buf[SMALL_PAGE_SIZE] __aligned(SMALL_PAGE_SIZE);
@@ -138,6 +147,14 @@ void spmc_set_args(struct thread_smc_args *args, uint32_t fid, uint32_t src_dst,
 					  .a5 = w5, };
 }
 
+static void set_simple_ret_val(struct thread_smc_args *args, int ffa_ret)
+{
+	if (ffa_ret)
+		spmc_set_args(args, FFA_ERROR, 0, ffa_ret, 0, 0, 0);
+	else
+		spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0);
+}
+
 uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx)
 {
 	/*
@@ -154,6 +171,53 @@ uint32_t spmc_exchange_version(uint32_t vers, struct ffa_rxtx *rxtx)
 	return rxtx->ffa_vers;
 }
 
+static bool is_ffa_success(uint32_t fid)
+{
+#ifdef ARM64
+	if (fid == FFA_SUCCESS_64)
+		return true;
+#endif
+	return fid == FFA_SUCCESS_32;
+}
+
+static int32_t get_ffa_ret_code(const struct thread_smc_args *args)
+{
+	if (is_ffa_success(args->a0))
+		return FFA_OK;
+	if (args->a0 == FFA_ERROR && args->a2)
+		return args->a2;
+	return FFA_NOT_SUPPORTED;
+}
+
+static int ffa_simple_call(uint32_t fid, unsigned long a1, unsigned long a2,
+			   unsigned long a3, unsigned long a4)
+{
+	struct thread_smc_args args = {
+		.a0 = fid,
+		.a1 = a1,
+		.a2 = a2,
+		.a3 = a3,
+		.a4 = a4,
+	};
+
+	thread_smccc(&args);
+
+	return get_ffa_ret_code(&args);
+}
+
+static int __maybe_unused ffa_features(uint32_t id)
+{
+	return ffa_simple_call(FFA_FEATURES, id, 0, 0, 0);
+}
+
+static int __maybe_unused ffa_set_notification(uint16_t dst, uint16_t src,
+					       uint32_t flags, uint64_t bitmap)
+{
+	return ffa_simple_call(FFA_NOTIFICATION_SET,
+			       SHIFT_U32(src, 16) | dst, flags,
+			       low32_from_64(bitmap), high32_from_64(bitmap));
+}
+
 #if defined(CFG_CORE_SEL1_SPMC)
 static void handle_features(struct thread_smc_args *args)
 {
@@ -233,7 +297,7 @@ static int map_buf(paddr_t pa, unsigned int sz, void **va_ret)
 	if (!core_pbuf_is(CORE_MEM_NON_SEC, pa, sz))
 		return FFA_INVALID_PARAMETERS;
 
-	mm = tee_mm_alloc(&tee_mm_shm, sz);
+	mm = tee_mm_alloc(&core_virt_shm_pool, sz);
 	if (!mm)
 		return FFA_NO_MEMORY;
 
@@ -248,15 +312,15 @@ static int map_buf(paddr_t pa, unsigned int sz, void **va_ret)
 	return 0;
 }
 
-static void handle_spm_id_get(struct thread_smc_args *args)
+void spmc_handle_spm_id_get(struct thread_smc_args *args)
 {
-	spmc_set_args(args, FFA_SUCCESS_32, FFA_PARAM_MBZ, my_endpoint_id,
+	spmc_set_args(args, FFA_SUCCESS_32, FFA_PARAM_MBZ, spmc_id,
 		      FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
 }
 
 static void unmap_buf(void *va, size_t sz)
 {
-	tee_mm_entry_t *mm = tee_mm_find(&tee_mm_shm, (vaddr_t)va);
+	tee_mm_entry_t *mm = tee_mm_find(&core_virt_shm_pool, (vaddr_t)va);
 
 	assert(mm);
 	core_mmu_unmap_pages(tee_mm_get_smem(mm), sz / SMALL_PAGE_SIZE);
@@ -266,7 +330,6 @@ static void unmap_buf(void *va, size_t sz)
 void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *rxtx)
 {
 	int rc = 0;
-	uint32_t ret_fid = FFA_ERROR;
 	unsigned int sz = 0;
 	paddr_t rx_pa = 0;
 	paddr_t tx_pa = 0;
@@ -368,18 +431,15 @@ void spmc_handle_rxtx_map(struct thread_smc_args *args, struct ffa_rxtx *rxtx)
 
 	rxtx->size = sz;
 	rxtx->tx_is_mine = true;
-	ret_fid = FFA_SUCCESS_32;
 	DMSG("Mapped tx %#"PRIxPA" size %#x @ %p", tx_pa, sz, tx);
 	DMSG("Mapped rx %#"PRIxPA" size %#x @ %p", rx_pa, sz, rx);
 out:
 	cpu_spin_unlock(&rxtx->spinlock);
-	spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
-		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+	set_simple_ret_val(args, rc);
 }
 
 void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *rxtx)
 {
-	uint32_t ret_fid = FFA_ERROR;
 	int rc = FFA_INVALID_PARAMETERS;
 
 	cpu_spin_lock(&rxtx->spinlock);
@@ -387,41 +447,40 @@ void spmc_handle_rxtx_unmap(struct thread_smc_args *args, struct ffa_rxtx *rxtx)
 	if (!rxtx->size)
 		goto out;
 
-	/* We don't unmap the SP memory as the SP might still use it */
-	if (is_nw_buf(rxtx)) {
+	/*
+	 * We don't unmap the SP memory as the SP might still use it.
+	 * We avoid to make changes to nexus mappings at this stage since
+	 * there currently isn't a way to replicate those changes to all
+	 * partitions.
+	 */
+	if (is_nw_buf(rxtx) && !IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
 		unmap_buf(rxtx->rx, rxtx->size);
 		unmap_buf(rxtx->tx, rxtx->size);
 	}
 	rxtx->size = 0;
 	rxtx->rx = NULL;
 	rxtx->tx = NULL;
-	ret_fid = FFA_SUCCESS_32;
 	rc = 0;
 out:
 	cpu_spin_unlock(&rxtx->spinlock);
-	spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
-		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+	set_simple_ret_val(args, rc);
 }
 
 void spmc_handle_rx_release(struct thread_smc_args *args, struct ffa_rxtx *rxtx)
 {
-	uint32_t ret_fid = 0;
 	int rc = 0;
 
 	cpu_spin_lock(&rxtx->spinlock);
 	/* The senders RX is our TX */
 	if (!rxtx->size || rxtx->tx_is_mine) {
-		ret_fid = FFA_ERROR;
 		rc = FFA_DENIED;
 	} else {
-		ret_fid = FFA_SUCCESS_32;
 		rc = 0;
 		rxtx->tx_is_mine = true;
 	}
 	cpu_spin_unlock(&rxtx->spinlock);
 
-	spmc_set_args(args, ret_fid, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
-		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+	set_simple_ret_val(args, rc);
 }
 
 static bool is_nil_uuid(uint32_t w0, uint32_t w1, uint32_t w2, uint32_t w3)
@@ -464,6 +523,12 @@ TEE_Result spmc_fill_partition_entry(uint32_t ffa_vers, void *buf, size_t blen,
 
 	fpi->partition_properties = part_props;
 
+	/* In FF-A 1.0 only bits [2:0] are defined, let's mask others */
+	if (ffa_vers < FFA_VERSION_1_1)
+		fpi->partition_properties &= FFA_PART_PROP_DIRECT_REQ_RECV |
+					     FFA_PART_PROP_DIRECT_REQ_SEND |
+					     FFA_PART_PROP_INDIRECT_MSGS;
+
 	if (ffa_vers >= FFA_VERSION_1_1) {
 		if (uuid_words)
 			memcpy(fpi->uuid, uuid_words, FFA_UUID_SIZE);
@@ -480,7 +545,7 @@ static int handle_partition_info_get_all(size_t *elem_count,
 	if (!count_only) {
 		/* Add OP-TEE SP */
 		if (spmc_fill_partition_entry(rxtx->ffa_vers, rxtx->tx,
-					      rxtx->size, 0, my_endpoint_id,
+					      rxtx->size, 0, optee_endpoint_id,
 					      CFG_TEE_CORE_NB_CORE,
 					      my_part_props, my_uuid_words))
 			return FFA_NO_MEMORY;
@@ -535,7 +600,7 @@ void spmc_handle_partition_info_get(struct thread_smc_args *args,
 		if (!count_only) {
 			res = spmc_fill_partition_entry(rxtx->ffa_vers,
 							rxtx->tx, rxtx->size, 0,
-							my_endpoint_id,
+							optee_endpoint_id,
 							CFG_TEE_CORE_NB_CORE,
 							my_part_props,
 							my_uuid_words);
@@ -593,7 +658,7 @@ static void spmc_handle_run(struct thread_smc_args *args)
 	uint16_t thread_id = FFA_TARGET_INFO_GET_VCPU_ID(args->a1);
 	uint32_t rc = FFA_OK;
 
-	if (endpoint != my_endpoint_id) {
+	if (endpoint != optee_endpoint_id) {
 		/*
 		 * The endpoint should be an SP, try to resume the SP from
 		 * preempted into busy state.
@@ -609,15 +674,31 @@ static void spmc_handle_run(struct thread_smc_args *args)
 	rc = FFA_INVALID_PARAMETERS;
 
 out:
-	spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, rc, FFA_PARAM_MBZ,
-		      FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+	set_simple_ret_val(args, rc);
 }
 #endif /*CFG_CORE_SEL1_SPMC*/
 
+static struct notif_vm_bitmap *get_notif_vm_bitmap(struct guest_partition *prtn,
+						   uint16_t vm_id)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		if (!prtn)
+			return NULL;
+		assert(vm_id == virt_get_guest_id(prtn));
+		return virt_get_guest_spec_data(prtn, notif_vm_bitmap_id);
+	}
+	if (vm_id)
+		return NULL;
+	return &default_notif_vm_bitmap;
+}
+
 static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value,
 					uint16_t vm_id)
 {
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t old_itr_status = 0;
+	uint32_t res = 0;
 
 	if (!spmc_notif_is_ready) {
 		/*
@@ -628,14 +709,27 @@ static uint32_t spmc_enable_async_notif(uint32_t bottom_half_value,
 		return TEE_ERROR_NOT_IMPLEMENTED;
 	}
 
+	if (bottom_half_value >= OPTEE_FFA_MAX_ASYNC_NOTIF_VALUE) {
+		EMSG("Invalid bottom half value %"PRIu32, bottom_half_value);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	prtn = virt_get_guest(vm_id);
+	nvb = get_notif_vm_bitmap(prtn, vm_id);
+	if (!nvb) {
+		res = TEE_ERROR_BAD_PARAMETERS;
+		goto out;
+	}
+
 	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
-	do_bottom_half_value = bottom_half_value;
-	if (!IS_ENABLED(CFG_CORE_SEL1_SPMC))
-		notif_vm_id = vm_id;
+	nvb->do_bottom_half_value = bottom_half_value;
 	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
 
-	notif_deliver_atomic_event(NOTIF_EVENT_STARTED);
-	return TEE_SUCCESS;
+	notif_deliver_atomic_event(NOTIF_EVENT_STARTED, vm_id);
+	res = TEE_SUCCESS;
+out:
+	virt_put_guest(prtn);
+	return res;
 }
 
 static void handle_yielding_call(struct thread_smc_args *args,
@@ -697,12 +791,15 @@ static void handle_blocking_call(struct thread_smc_args *args,
 	case OPTEE_FFA_GET_OS_VERSION:
 		spmc_set_args(args, direct_resp_fid, swap_src_dst(args->a1), 0,
 			      CFG_OPTEE_REVISION_MAJOR,
-			      CFG_OPTEE_REVISION_MINOR, TEE_IMPL_GIT_SHA1);
+			      CFG_OPTEE_REVISION_MINOR,
+			      TEE_IMPL_GIT_SHA1 >> 32);
 		break;
 	case OPTEE_FFA_EXCHANGE_CAPABILITIES:
 		sec_caps = OPTEE_FFA_SEC_CAP_ARG_OFFSET;
 		if (spmc_notif_is_ready)
 			sec_caps |= OPTEE_FFA_SEC_CAP_ASYNC_NOTIF;
+		if (IS_ENABLED(CFG_RPMB_ANNOUNCE_PROBE_CAP))
+			sec_caps |= OPTEE_FFA_SEC_CAP_RPMB_PROBE;
 		spmc_set_args(args, direct_resp_fid,
 			      swap_src_dst(args->a1), 0, 0,
 			      THREAD_RPC_MAX_NUM_PARAMS, sec_caps);
@@ -784,7 +881,8 @@ static void handle_direct_request(struct thread_smc_args *args,
 	uint32_t direct_resp_fid = 0;
 
 	if (IS_ENABLED(CFG_SECURE_PARTITION) &&
-	    FFA_DST(args->a1) != my_endpoint_id) {
+	    FFA_DST(args->a1) != spmc_id &&
+	    FFA_DST(args->a1) != optee_endpoint_id) {
 		spmc_sp_start_thread(args);
 		return;
 	}
@@ -816,7 +914,8 @@ static void handle_direct_request(struct thread_smc_args *args,
 	 * thread cannot be allocated or found. virt_unset_guest() is also
 	 * called from thread_state_suspend() and thread_state_free().
 	 */
-	virt_unset_guest();
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		virt_unset_guest();
 }
 
 int spmc_read_mem_transaction(uint32_t ffa_vers, void *buf, size_t blen,
@@ -896,7 +995,7 @@ static int get_acc_perms(vaddr_t mem_acc_base, unsigned int mem_access_size,
 	for (n = 0; n < mem_access_count; n++) {
 		mem_acc = (void *)(mem_acc_base + mem_access_size * n);
 		descr = &mem_acc->access_perm;
-		if (READ_ONCE(descr->endpoint_id) == my_endpoint_id) {
+		if (READ_ONCE(descr->endpoint_id) == optee_endpoint_id) {
 			*acc_perms = READ_ONCE(descr->perm);
 			*region_offs = READ_ONCE(mem_acc[n].region_offs);
 			return 0;
@@ -1026,7 +1125,7 @@ static bool is_sp_share(struct ffa_mem_transaction_x *mem_trans,
 	 * OP-TEE. We do read it later on again, but there are some additional
 	 * checks there to make sure that the data is correct.
 	 */
-	return READ_ONCE(perm->endpoint_id) != my_endpoint_id;
+	return READ_ONCE(perm->endpoint_id) != optee_endpoint_id;
 }
 
 static int add_mem_share(struct ffa_mem_transaction_x *mem_trans,
@@ -1044,6 +1143,9 @@ static int add_mem_share(struct ffa_mem_transaction_x *mem_trans,
 	if (rc)
 		return rc;
 
+	if (!share.page_count || !share.region_count)
+		return FFA_INVALID_PARAMETERS;
+
 	if (MUL_OVERFLOW(share.region_count,
 			 sizeof(struct ffa_address_range), &n) ||
 	    ADD_OVERFLOW(n, addr_range_offs, &n) || n > blen)
@@ -1056,7 +1158,7 @@ static int add_mem_share(struct ffa_mem_transaction_x *mem_trans,
 		return FFA_NO_MEMORY;
 
 	if (flen != blen) {
-		struct mem_frag_state *s = calloc(sizeof(*s), 1);
+		struct mem_frag_state *s = calloc(1, sizeof(*s));
 
 		if (!s) {
 			rc = FFA_NO_MEMORY;
@@ -1118,7 +1220,7 @@ static int handle_mem_share_tmem(paddr_t pbuf, size_t blen, size_t flen,
 	if (len < flen || len - offs < flen)
 		return FFA_INVALID_PARAMETERS;
 
-	mm = tee_mm_alloc(&tee_mm_shm, len);
+	mm = tee_mm_alloc(&core_virt_shm_pool, len);
 	if (!mm)
 		return FFA_NO_MEMORY;
 
@@ -1131,13 +1233,27 @@ static int handle_mem_share_tmem(paddr_t pbuf, size_t blen, size_t flen,
 
 	cpu_spin_lock(&rxtx->spinlock);
 	rc = spmc_read_mem_transaction(rxtx->ffa_vers, buf, flen, &mem_trans);
-	if (!rc && IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
-	    virt_set_guest(mem_trans.sender_id))
+	if (rc)
+		goto unlock;
+
+	if (is_sp_share(&mem_trans, buf)) {
+		rc = spmc_sp_add_share(&mem_trans, buf, blen, flen,
+				       global_handle, NULL);
+		goto unlock;
+	}
+
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
+	    virt_set_guest(mem_trans.sender_id)) {
 		rc = FFA_DENIED;
-	if (!rc)
-		rc = add_mem_share(&mem_trans, mm, buf, blen, flen,
-				   global_handle);
-	virt_unset_guest();
+		goto unlock;
+	}
+
+	rc = add_mem_share(&mem_trans, mm, buf, blen, flen, global_handle);
+
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		virt_unset_guest();
+
+unlock:
 	cpu_spin_unlock(&rxtx->spinlock);
 	if (rc > 0)
 		return rc;
@@ -1165,7 +1281,7 @@ static int handle_mem_share_rxbuf(size_t blen, size_t flen,
 	if (rc)
 		goto out;
 	if (is_sp_share(&mem_trans, rxtx->rx)) {
-		rc = spmc_sp_add_share(&mem_trans, rxtx, blen,
+		rc = spmc_sp_add_share(&mem_trans, rxtx, blen, flen,
 				       global_handle, NULL);
 		goto out;
 	}
@@ -1177,7 +1293,8 @@ static int handle_mem_share_rxbuf(size_t blen, size_t flen,
 	rc = add_mem_share(&mem_trans, NULL, rxtx->rx, blen, flen,
 			   global_handle);
 
-	virt_unset_guest();
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		virt_unset_guest();
 
 out:
 	cpu_spin_unlock(&rxtx->spinlock);
@@ -1305,7 +1422,9 @@ static void handle_mem_frag_tx(struct thread_smc_args *args,
 
 	rc = add_mem_share_frag(s, buf, flen);
 out:
-	virt_unset_guest();
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		virt_unset_guest();
+
 	cpu_spin_unlock(&rxtx->spinlock);
 
 	if (rc <= 0 && mm) {
@@ -1331,8 +1450,7 @@ out_set_rc:
 
 static void handle_mem_reclaim(struct thread_smc_args *args)
 {
-	uint32_t ret_val = FFA_INVALID_PARAMETERS;
-	uint32_t ret_fid = FFA_ERROR;
+	int rc = FFA_INVALID_PARAMETERS;
 	uint64_t cookie = 0;
 
 	if (args->a3 || args->a4 || args->a5 || args->a6 || args->a7)
@@ -1348,29 +1466,35 @@ static void handle_mem_reclaim(struct thread_smc_args *args)
 			guest_id = (cookie >> FFA_MEMORY_HANDLE_PRTN_SHIFT) &
 				   FFA_MEMORY_HANDLE_PRTN_MASK;
 		}
-		if (!guest_id || virt_set_guest(guest_id))
+		if (!guest_id)
 			goto out;
+		if (virt_set_guest(guest_id)) {
+			if (!virt_reclaim_cookie_from_destroyed_guest(guest_id,
+								      cookie))
+				rc = FFA_OK;
+			goto out;
+		}
 	}
 
 	switch (mobj_ffa_sel1_spmc_reclaim(cookie)) {
 	case TEE_SUCCESS:
-		ret_fid = FFA_SUCCESS_32;
-		ret_val = 0;
+		rc = FFA_OK;
 		break;
 	case TEE_ERROR_ITEM_NOT_FOUND:
 		DMSG("cookie %#"PRIx64" not found", cookie);
-		ret_val = FFA_INVALID_PARAMETERS;
+		rc = FFA_INVALID_PARAMETERS;
 		break;
 	default:
 		DMSG("cookie %#"PRIx64" busy", cookie);
-		ret_val = FFA_DENIED;
+		rc = FFA_DENIED;
 		break;
 	}
 
-	virt_unset_guest();
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		virt_unset_guest();
 
 out:
-	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
+	set_simple_ret_val(args, rc);
 }
 
 static void handle_notification_bitmap_create(struct thread_smc_args *args)
@@ -1381,23 +1505,32 @@ static void handle_notification_bitmap_create(struct thread_smc_args *args)
 
 	if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 &&
 	    !args->a5 && !args->a6 && !args->a7) {
+		struct guest_partition *prtn = NULL;
+		struct notif_vm_bitmap *nvb = NULL;
 		uint16_t vm_id = args->a1;
 
+		prtn = virt_get_guest(vm_id);
+		nvb = get_notif_vm_bitmap(prtn, vm_id);
+		if (!nvb) {
+			ret_val = FFA_INVALID_PARAMETERS;
+			goto out_virt_put;
+		}
+
 		old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
 
-		if (notif_vm_id_valid) {
-			if (vm_id == notif_vm_id)
-				ret_val = FFA_DENIED;
-			else
-				ret_val = FFA_NO_MEMORY;
-		} else {
-			notif_vm_id = vm_id;
-			notif_vm_id_valid = true;
-			ret_val = FFA_OK;
-			ret_fid = FFA_SUCCESS_32;
+		if (nvb->initialized) {
+			ret_val = FFA_DENIED;
+			goto out_unlock;
 		}
 
+		nvb->initialized = true;
+		nvb->do_bottom_half_value = -1;
+		ret_val = FFA_OK;
+		ret_fid = FFA_SUCCESS_32;
+out_unlock:
 		cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out_virt_put:
+		virt_put_guest(prtn);
 	}
 
 	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
@@ -1411,21 +1544,31 @@ static void handle_notification_bitmap_destroy(struct thread_smc_args *args)
 
 	if (!FFA_TARGET_INFO_GET_SP_ID(args->a1) && !args->a3 && !args->a4 &&
 	    !args->a5 && !args->a6 && !args->a7) {
+		struct guest_partition *prtn = NULL;
+		struct notif_vm_bitmap *nvb = NULL;
 		uint16_t vm_id = args->a1;
 
+		prtn = virt_get_guest(vm_id);
+		nvb = get_notif_vm_bitmap(prtn, vm_id);
+		if (!nvb) {
+			ret_val = FFA_INVALID_PARAMETERS;
+			goto out_virt_put;
+		}
+
 		old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
 
-		if (notif_vm_id_valid && vm_id == notif_vm_id) {
-			if (notif_pending_bitmap || notif_bound_bitmap) {
-				ret_val = FFA_DENIED;
-			} else {
-				notif_vm_id_valid = false;
-				ret_val = FFA_OK;
-				ret_fid = FFA_SUCCESS_32;
-			}
+		if (nvb->pending || nvb->bound) {
+			ret_val = FFA_DENIED;
+			goto out_unlock;
 		}
 
+		memset(nvb, 0, sizeof(*nvb));
+		ret_val = FFA_OK;
+		ret_fid = FFA_SUCCESS_32;
+out_unlock:
 		cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out_virt_put:
+		virt_put_guest(prtn);
 	}
 
 	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
@@ -1434,6 +1577,8 @@ static void handle_notification_bitmap_destroy(struct thread_smc_args *args)
 static void handle_notification_bind(struct thread_smc_args *args)
 {
 	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t ret_fid = FFA_ERROR;
 	uint32_t old_itr_status = 0;
 	uint64_t bitmap = 0;
@@ -1442,8 +1587,8 @@ static void handle_notification_bind(struct thread_smc_args *args)
 	if (args->a5 || args->a6 || args->a7)
 		goto out;
 	if (args->a2) {
-		/* We only deal with global notifications for now */
-		ret_val = FFA_NOT_SUPPORTED;
+		/* We only deal with global notifications */
+		ret_val = FFA_DENIED;
 		goto out;
 	}
 
@@ -1451,19 +1596,26 @@ static void handle_notification_bind(struct thread_smc_args *args)
 	vm_id = FFA_DST(args->a1);
 	bitmap = reg_pair_to_64(args->a4, args->a3);
 
+	prtn = virt_get_guest(vm_id);
+	nvb = get_notif_vm_bitmap(prtn, vm_id);
+	if (!nvb) {
+		ret_val = FFA_INVALID_PARAMETERS;
+		goto out_virt_put;
+	}
+
 	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
 
-	if (notif_vm_id_valid && vm_id == notif_vm_id) {
-		if (bitmap & notif_bound_bitmap) {
-			ret_val = FFA_DENIED;
-		} else {
-			notif_bound_bitmap |= bitmap;
-			ret_val = FFA_OK;
-			ret_fid = FFA_SUCCESS_32;
-		}
+	if ((bitmap & nvb->bound)) {
+		ret_val = FFA_DENIED;
+	} else {
+		nvb->bound |= bitmap;
+		ret_val = FFA_OK;
+		ret_fid = FFA_SUCCESS_32;
 	}
 
 	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out_virt_put:
+	virt_put_guest(prtn);
 out:
 	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
 }
@@ -1471,6 +1623,8 @@ out:
 static void handle_notification_unbind(struct thread_smc_args *args)
 {
 	uint32_t ret_val = FFA_INVALID_PARAMETERS;
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t ret_fid = FFA_ERROR;
 	uint32_t old_itr_status = 0;
 	uint64_t bitmap = 0;
@@ -1483,26 +1637,26 @@ static void handle_notification_unbind(struct thread_smc_args *args)
 	vm_id = FFA_DST(args->a1);
 	bitmap = reg_pair_to_64(args->a4, args->a3);
 
+	prtn = virt_get_guest(vm_id);
+	nvb = get_notif_vm_bitmap(prtn, vm_id);
+	if (!nvb) {
+		ret_val = FFA_INVALID_PARAMETERS;
+		goto out_virt_put;
+	}
+
 	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
 
-	if (notif_vm_id_valid && vm_id == notif_vm_id) {
-		/*
-		 * Spec says:
-		 * At least one notification is bound to another Sender or
-		 * is currently pending.
-		 *
-		 * Not sure what the intention is.
-		 */
-		if (bitmap & notif_pending_bitmap) {
-			ret_val = FFA_DENIED;
-		} else {
-			notif_bound_bitmap &= ~bitmap;
-			ret_val = FFA_OK;
-			ret_fid = FFA_SUCCESS_32;
-		}
+	if (bitmap & nvb->pending) {
+		ret_val = FFA_DENIED;
+	} else {
+		nvb->bound &= ~bitmap;
+		ret_val = FFA_OK;
+		ret_fid = FFA_SUCCESS_32;
 	}
 
 	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out_virt_put:
+	virt_put_guest(prtn);
 out:
 	spmc_set_args(args, ret_fid, 0, ret_val, 0, 0, 0);
 }
@@ -1510,6 +1664,8 @@ out:
 static void handle_notification_get(struct thread_smc_args *args)
 {
 	uint32_t w2 = FFA_INVALID_PARAMETERS;
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t ret_fid = FFA_ERROR;
 	uint32_t old_itr_status = 0;
 	uint16_t vm_id = 0;
@@ -1524,43 +1680,197 @@ static void handle_notification_get(struct thread_smc_args *args)
 	}
 	vm_id = FFA_DST(args->a1);
 
+	prtn = virt_get_guest(vm_id);
+	nvb = get_notif_vm_bitmap(prtn, vm_id);
+	if (!nvb)
+		goto out_virt_put;
+
 	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
 
-	if (notif_vm_id_valid && vm_id == notif_vm_id) {
-		reg_pair_from_64(notif_pending_bitmap, &w3, &w2);
-		notif_pending_bitmap = 0;
-		ret_fid = FFA_SUCCESS_32;
-	}
+	reg_pair_from_64(nvb->pending, &w3, &w2);
+	nvb->pending = 0;
+	ret_fid = FFA_SUCCESS_32;
 
 	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+out_virt_put:
+	virt_put_guest(prtn);
 out:
 	spmc_set_args(args, ret_fid, 0, w2, w3, 0, 0);
 }
 
+struct notif_info_get_state {
+	struct thread_smc_args *args;
+	unsigned int ids_per_reg;
+	unsigned int ids_count;
+	unsigned int id_pos;
+	unsigned int count;
+	unsigned int max_list_count;
+	unsigned int list_count;
+};
+
+static unsigned long get_smc_arg(struct thread_smc_args *args, unsigned int idx)
+{
+	switch (idx) {
+	case 0:
+		return args->a0;
+	case 1:
+		return args->a1;
+	case 2:
+		return args->a2;
+	case 3:
+		return args->a3;
+	case 4:
+		return args->a4;
+	case 5:
+		return args->a5;
+	case 6:
+		return args->a6;
+	case 7:
+		return args->a7;
+	default:
+		assert(0);
+		return 0;
+	}
+}
+
+static void set_smc_arg(struct thread_smc_args *args, unsigned int idx,
+			unsigned long val)
+{
+	switch (idx) {
+	case 0:
+		args->a0 = val;
+		break;
+	case 1:
+		args->a1 = val;
+		break;
+	case 2:
+		args->a2 = val;
+		break;
+	case 3:
+		args->a3 = val;
+		break;
+	case 4:
+		args->a4 = val;
+		break;
+	case 5:
+		args->a5 = val;
+		break;
+	case 6:
+		args->a6 = val;
+		break;
+	case 7:
+		args->a7 = val;
+		break;
+	default:
+		assert(0);
+	}
+}
+
+static bool add_id_in_regs(struct notif_info_get_state *state,
+			   uint16_t id)
+{
+	unsigned int reg_idx = state->id_pos / state->ids_per_reg + 3;
+	unsigned int reg_shift = (state->id_pos % state->ids_per_reg) * 16;
+	unsigned long v;
+
+	if (reg_idx > 7)
+		return false;
+
+	v = get_smc_arg(state->args, reg_idx);
+	v &= ~(0xffffUL << reg_shift);
+	v |= (unsigned long)id << reg_shift;
+	set_smc_arg(state->args, reg_idx, v);
+
+	state->id_pos++;
+	state->count++;
+	return true;
+}
+
+static bool add_id_count(struct notif_info_get_state *state)
+{
+	assert(state->list_count < state->max_list_count &&
+	       state->count >= 1 && state->count <= 4);
+
+	state->ids_count |= (state->count - 1) << (state->list_count * 2 + 12);
+	state->list_count++;
+	state->count = 0;
+
+	return state->list_count < state->max_list_count;
+}
+
+static bool add_nvb_to_state(struct notif_info_get_state *state,
+			     uint16_t guest_id, struct notif_vm_bitmap *nvb)
+{
+	if (!nvb->pending)
+		return true;
+	/*
+	 * Add only the guest_id, meaning a global notification for this
+	 * guest.
+	 *
+	 * If notifications for one or more specific vCPUs we'd add those
+	 * before calling add_id_count(), but that's not supported.
+	 */
+	return add_id_in_regs(state, guest_id) && add_id_count(state);
+}
+
 static void handle_notification_info_get(struct thread_smc_args *args)
 {
-	uint32_t w2 = FFA_INVALID_PARAMETERS;
-	uint32_t ret_fid = FFA_ERROR;
+	struct notif_info_get_state state = { .args = args };
+	uint32_t ffa_res = FFA_INVALID_PARAMETERS;
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
+	uint32_t more_pending_flag = 0;
+	uint32_t itr_state = 0;
+	uint16_t guest_id = 0;
 
 	if (args->a1 || args->a2 || args->a3 || args->a4 || args->a5 ||
 	    args->a6 || args->a7)
-		goto out;
+		goto err;
 
-	if (OPTEE_SMC_IS_64(args->a0))
-		ret_fid = FFA_SUCCESS_64;
-	else
-		ret_fid = FFA_SUCCESS_32;
+	if (OPTEE_SMC_IS_64(args->a0)) {
+		spmc_set_args(args, FFA_SUCCESS_64, 0, 0, 0, 0, 0);
+		state.ids_per_reg = 4;
+		state.max_list_count = 31;
+	} else {
+		spmc_set_args(args, FFA_SUCCESS_32, 0, 0, 0, 0, 0);
+		state.ids_per_reg = 2;
+		state.max_list_count = 15;
+	}
 
-	/*
-	 * Note, we're only supporting physical OS kernel in normal world
-	 * with Global Notifications.
-	 * So one list of ID list registers (BIT[11:7])
-	 * and one count of IDs (BIT[13:12] + 1)
-	 * and the VM is always 0.
-	 */
-	w2 = SHIFT_U32(1, 7);
-out:
-	spmc_set_args(args, ret_fid, 0, w2, 0, 0, 0);
+	while (true) {
+		/*
+		 * With NS-Virtualization we need to go through all
+		 * partitions to collect the notification bitmaps, without
+		 * we just check the only notification bitmap we have.
+		 */
+		if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+			prtn = virt_next_guest(prtn);
+			if (!prtn)
+				break;
+			guest_id = virt_get_guest_id(prtn);
+		}
+		nvb = get_notif_vm_bitmap(prtn, guest_id);
+
+		itr_state = cpu_spin_lock_xsave(&spmc_notif_lock);
+		if (!add_nvb_to_state(&state, guest_id, nvb))
+			more_pending_flag = BIT(0);
+		cpu_spin_unlock_xrestore(&spmc_notif_lock, itr_state);
+
+		if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || more_pending_flag)
+			break;
+	}
+	virt_put_guest(prtn);
+
+	if (!state.id_pos) {
+		ffa_res = FFA_NO_DATA;
+		goto err;
+	}
+	args->a2 = (state.list_count << FFA_NOTIF_INFO_GET_ID_COUNT_SHIFT) |
+		   (state.ids_count << FFA_NOTIF_INFO_GET_ID_LIST_SHIFT) |
+		   more_pending_flag;
+	return;
+err:
+	spmc_set_args(args, FFA_ERROR, 0, ffa_res, 0, 0, 0);
 }
 
 void thread_spmc_set_async_notif_intid(int intid)
@@ -1571,22 +1881,52 @@ void thread_spmc_set_async_notif_intid(int intid)
 	DMSG("Asynchronous notifications are ready");
 }
 
-void notif_send_async(uint32_t value)
+void notif_send_async(uint32_t value, uint16_t guest_id)
 {
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t old_itr_status = 0;
 
-	old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
-	assert(value == NOTIF_VALUE_DO_BOTTOM_HALF && spmc_notif_is_ready &&
-	       do_bottom_half_value >= 0 && notif_intid >= 0);
-	notif_pending_bitmap |= BIT64(do_bottom_half_value);
-	interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid,
-			    ITR_CPU_MASK_TO_THIS_CPU);
-	cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+	prtn = virt_get_guest(guest_id);
+	nvb = get_notif_vm_bitmap(prtn, guest_id);
+
+	if (nvb) {
+		old_itr_status = cpu_spin_lock_xsave(&spmc_notif_lock);
+		assert(value == NOTIF_VALUE_DO_BOTTOM_HALF &&
+		       spmc_notif_is_ready && nvb->do_bottom_half_value >= 0 &&
+		       notif_intid >= 0);
+		nvb->pending |= BIT64(nvb->do_bottom_half_value);
+		interrupt_raise_sgi(interrupt_get_main_chip(), notif_intid,
+				    ITR_CPU_MASK_TO_THIS_CPU);
+		cpu_spin_unlock_xrestore(&spmc_notif_lock, old_itr_status);
+	}
+
+	virt_put_guest(prtn);
 }
 #else
-void __noreturn notif_send_async(uint32_t value __unused)
-{
-	panic();
+void notif_send_async(uint32_t value, uint16_t guest_id)
+{
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
+	/* global notification, delay notification interrupt */
+	uint32_t flags = BIT32(1);
+	int res = 0;
+
+	prtn = virt_get_guest(guest_id);
+	nvb = get_notif_vm_bitmap(prtn, guest_id);
+
+	if (nvb) {
+		assert(value == NOTIF_VALUE_DO_BOTTOM_HALF &&
+		       spmc_notif_is_ready && nvb->do_bottom_half_value >= 0);
+		res = ffa_set_notification(guest_id, optee_endpoint_id, flags,
+					   BIT64(nvb->do_bottom_half_value));
+		if (res) {
+			EMSG("notification set failed with error %d", res);
+			panic();
+		}
+	}
+
+	virt_put_guest(prtn);
 }
 #endif
 
@@ -1601,7 +1941,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
 		handle_features(args);
 		break;
 	case FFA_SPM_ID_GET:
-		handle_spm_id_get(args);
+		spmc_handle_spm_id_get(args);
 		break;
 #ifdef ARM64
 	case FFA_RXTX_MAP_64:
@@ -1623,7 +1963,6 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
 		break;
 #endif /*CFG_CORE_SEL1_SPMC*/
 	case FFA_INTERRUPT:
-		interrupt_main_handler();
 		if (IS_ENABLED(CFG_CORE_SEL1_SPMC))
 			spmc_set_args(args, FFA_NORMAL_WORLD_RESUME, 0, 0, 0,
 				      0, 0);
@@ -1687,8 +2026,7 @@ void thread_spmc_msg_recv(struct thread_smc_args *args)
 		break;
 	default:
 		EMSG("Unhandled FFA function ID %#"PRIx32, (uint32_t)args->a0);
-		spmc_set_args(args, FFA_ERROR, FFA_PARAM_MBZ, FFA_NOT_SUPPORTED,
-			      FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
+		set_simple_ret_val(args, FFA_NOT_SUPPORTED);
 	}
 }
 
@@ -2006,11 +2344,70 @@ void thread_spmc_register_secondary_ep(vaddr_t ep)
 		EMSG("FFA_SECONDARY_EP_REGISTER_64 ret %#lx", ret);
 }
 
+static uint16_t ffa_id_get(void)
+{
+	/*
+	 * Ask the SPM component running at a higher EL to return our FF-A ID.
+	 * This can either be the SPMC ID (if the SPMC is enabled in OP-TEE) or
+	 * the partition ID (if not).
+	 */
+	struct thread_smc_args args = {
+		.a0 = FFA_ID_GET,
+	};
+
+	thread_smccc(&args);
+	if (!is_ffa_success(args.a0)) {
+		if (args.a0 == FFA_ERROR)
+			EMSG("Get id failed with error %ld", args.a2);
+		else
+			EMSG("Get id failed");
+		panic();
+	}
+
+	return args.a2;
+}
+
+static uint16_t ffa_spm_id_get(void)
+{
+	/*
+	 * Ask the SPM component running at a higher EL to return its ID.
+	 * If OP-TEE implements the S-EL1 SPMC, this will get the SPMD ID.
+	 * If not, the ID of the SPMC will be returned.
+	 */
+	struct thread_smc_args args = {
+		.a0 = FFA_SPM_ID_GET,
+	};
+
+	thread_smccc(&args);
+	if (!is_ffa_success(args.a0)) {
+		if (args.a0 == FFA_ERROR)
+			EMSG("Get spm id failed with error %ld", args.a2);
+		else
+			EMSG("Get spm id failed");
+		panic();
+	}
+
+	return args.a2;
+}
+
 #if defined(CFG_CORE_SEL1_SPMC)
 static TEE_Result spmc_init(void)
 {
-	my_endpoint_id = SPMC_ENDPOINT_ID;
-	DMSG("My endpoint ID %#x", my_endpoint_id);
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
+	    virt_add_guest_spec_data(&notif_vm_bitmap_id,
+				     sizeof(struct notif_vm_bitmap), NULL))
+		panic("virt_add_guest_spec_data");
+	spmd_id = ffa_spm_id_get();
+	DMSG("SPMD ID %#"PRIx16, spmd_id);
+
+	spmc_id = ffa_id_get();
+	DMSG("SPMC ID %#"PRIx16, spmc_id);
+
+	optee_endpoint_id = FFA_SWD_ID_MIN;
+	while (optee_endpoint_id == spmd_id || optee_endpoint_id == spmc_id)
+		optee_endpoint_id++;
+
+	DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id);
 
 	/*
 	 * If SPMD think we are version 1.0 it will report version 1.0 to
@@ -2027,15 +2424,6 @@ static TEE_Result spmc_init(void)
 	return TEE_SUCCESS;
 }
 #else /* !defined(CFG_CORE_SEL1_SPMC) */
-static bool is_ffa_success(uint32_t fid)
-{
-#ifdef ARM64
-	if (fid == FFA_SUCCESS_64)
-		return true;
-#endif
-	return fid == FFA_SUCCESS_32;
-}
-
 static void spmc_rxtx_map(struct ffa_rxtx *rxtx)
 {
 	struct thread_smc_args args = {
@@ -2059,24 +2447,6 @@ static void spmc_rxtx_map(struct ffa_rxtx *rxtx)
 	}
 }
 
-static uint16_t get_my_id(void)
-{
-	struct thread_smc_args args = {
-		.a0 = FFA_ID_GET,
-	};
-
-	thread_smccc(&args);
-	if (!is_ffa_success(args.a0)) {
-		if (args.a0 == FFA_ERROR)
-			EMSG("Get id failed with error %ld", args.a2);
-		else
-			EMSG("Get id failed");
-		panic();
-	}
-
-	return args.a2;
-}
-
 static uint32_t get_ffa_version(uint32_t my_version)
 {
 	struct thread_smc_args args = {
@@ -2137,7 +2507,7 @@ static void *spmc_retrieve_req(uint64_t cookie,
 	acc_descr_array->region_offs = 0;
 	acc_descr_array->reserved = 0;
 	perm_descr = &acc_descr_array->access_perm;
-	perm_descr->endpoint_id = my_endpoint_id;
+	perm_descr->endpoint_id = optee_endpoint_id;
 	perm_descr->perm = FFA_MEM_ACC_RW;
 	perm_descr->flags = 0;
 
@@ -2175,7 +2545,7 @@ void thread_spmc_relinquish(uint64_t cookie)
 	relinquish_desc->handle = cookie;
 	relinquish_desc->flags = 0;
 	relinquish_desc->endpoint_count = 1;
-	relinquish_desc->endpoint_id_array[0] = my_endpoint_id;
+	relinquish_desc->endpoint_id_array[0] = optee_endpoint_id;
 	thread_smccc(&args);
 	if (!is_ffa_success(args.a0))
 		EMSG("Failed to relinquish cookie %#"PRIx64, cookie);
@@ -2276,22 +2646,20 @@ static TEE_Result spmc_init(void)
 	my_rxtx.ffa_vers = my_vers;
 
 	spmc_rxtx_map(&my_rxtx);
-	my_endpoint_id = get_my_id();
-	DMSG("My endpoint ID %#x", my_endpoint_id);
+
+	spmc_id = ffa_spm_id_get();
+	DMSG("SPMC ID %#"PRIx16, spmc_id);
+
+	optee_endpoint_id = ffa_id_get();
+	DMSG("OP-TEE endpoint ID %#"PRIx16, optee_endpoint_id);
+
+	if (!ffa_features(FFA_NOTIFICATION_SET)) {
+		spmc_notif_is_ready = true;
+		DMSG("Asynchronous notifications are ready");
+	}
 
 	return TEE_SUCCESS;
 }
 #endif /* !defined(CFG_CORE_SEL1_SPMC) */
 
-/*
- * boot_final() is always done before exiting at end of boot
- * initialization.  In case of virtualization the init-calls are done only
- * once a OP-TEE partition has been created. So with virtualization we have
- * to initialize via boot_final() to make sure we have a value assigned
- * before it's used the first time.
- */
-#ifdef CFG_NS_VIRTUALIZATION
-boot_final(spmc_init);
-#else
-service_init(spmc_init);
-#endif
+nex_service_init(spmc_init);
diff --git a/core/arch/arm/kernel/thread_spmc_a64.S b/core/arch/arm/kernel/thread_spmc_a64.S
index 46f241c9f0571e67474b6d58338aa20de94d7136..f451263550a1e33a84f13923c75d622330992ae1 100644
--- a/core/arch/arm/kernel/thread_spmc_a64.S
+++ b/core/arch/arm/kernel/thread_spmc_a64.S
@@ -48,8 +48,13 @@ LOCAL_FUNC ffa_msg_send_direct_resp , :
 	mov	x2, #FFA_PARAM_MBZ			/* RES MBZ */
 
 .ffa_msg_loop:
-	/* Invoke SMC with caller provided parameters */
+	/*
+	 * Native interrupts unmasked while invoking SMC with caller
+	 * provided parameters.
+	 */
+	msr	daifclr, #DAIFBIT_NATIVE_INTR
 	smc	#0
+	msr	daifset, #DAIFBIT_NATIVE_INTR
 
 	/* Store the parameters as struct thread_smc_args on stack */
 	sub	sp, sp, #THREAD_SMC_ARGS_SIZE
diff --git a/core/arch/arm/kernel/timer_a64.c b/core/arch/arm/kernel/timer_a64.c
index d64a997093cb64b96d344c8ab035361249c8b1b5..16f4ac0fae6e7b3a43612e3a803b97b8b9d78dbc 100644
--- a/core/arch/arm/kernel/timer_a64.c
+++ b/core/arch/arm/kernel/timer_a64.c
@@ -12,16 +12,14 @@ static bool timer_running;
 
 void generic_timer_start(uint32_t time_ms)
 {
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
-	uint32_t timer_ticks;
-
-	cpu_spin_lock(&timer_lock);
+	uint32_t exceptions = cpu_spin_lock_xsave(&timer_lock);
+	uint32_t timer_ticks = 0;
 
 	if (timer_running == true)
 		goto exit;
 
 	/* The timer will fire time_ms from now */
-	timer_ticks = (read_cntfrq() * time_ms) / 1000;
+	timer_ticks = ((uint64_t)read_cntfrq() * time_ms) / 1000;
 	write_cntps_tval(timer_ticks);
 
 	/* Enable the secure physical timer */
@@ -30,28 +28,24 @@ void generic_timer_start(uint32_t time_ms)
 	timer_running = true;
 
 exit:
-	cpu_spin_unlock(&timer_lock);
-	thread_set_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&timer_lock, exceptions);
 }
 
 void generic_timer_stop(void)
 {
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
-
-	cpu_spin_lock(&timer_lock);
+	uint32_t exceptions = cpu_spin_lock_xsave(&timer_lock);
 
 	/* Disable the timer */
 	write_cntps_ctl(0);
 
 	timer_running = false;
 
-	cpu_spin_unlock(&timer_lock);
-	thread_set_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&timer_lock, exceptions);
 }
 
 void generic_timer_handler(uint32_t time_ms)
 {
-	uint32_t timer_ticks;
+	uint32_t timer_ticks = 0;
 
 	/* Ensure that the timer did assert the interrupt */
 	assert((read_cntps_ctl() >> 2));
@@ -60,7 +54,7 @@ void generic_timer_handler(uint32_t time_ms)
 	write_cntps_ctl(0);
 
 	/* Reconfigure timer to fire time_ms from now */
-	timer_ticks = (read_cntfrq() * time_ms) / 1000;
+	timer_ticks = ((uint64_t)read_cntfrq() * time_ms) / 1000;
 	write_cntps_tval(timer_ticks);
 
 	/* Enable the secure physical timer */
diff --git a/core/arch/arm/kernel/virtualization.c b/core/arch/arm/kernel/virtualization.c
index 54b73c7f6d4630d11f27b03415cc697dbd271d55..68b65767efbd08f6495d3a508763399a9f879262 100644
--- a/core/arch/arm/kernel/virtualization.c
+++ b/core/arch/arm/kernel/virtualization.c
@@ -1,51 +1,72 @@
 // SPDX-License-Identifier: BSD-2-Clause
-/* Copyright (c) 2018, EPAM Systems. All rights reserved. */
+/*
+ * Copyright (c) 2018, EPAM Systems. All rights reserved.
+ * Copyright (c) 2023-2024, Linaro Limited
+ */
 
+#include <bitstring.h>
 #include <compiler.h>
-#include <platform_config.h>
 #include <kernel/boot.h>
 #include <kernel/linker.h>
-#include <kernel/mutex.h>
 #include <kernel/misc.h>
+#include <kernel/mutex.h>
+#include <kernel/notif.h>
 #include <kernel/panic.h>
 #include <kernel/refcount.h>
 #include <kernel/spinlock.h>
+#include <kernel/thread_spmc.h>
 #include <kernel/virtualization.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_mm.h>
 #include <platform_config.h>
 #include <sm/optee_smc.h>
 #include <string.h>
+#include <string_ext.h>
 #include <util.h>
 
-static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK;
+LIST_HEAD(prtn_list_head, guest_partition);
 
-static LIST_HEAD(prtn_list_head, guest_partition) prtn_list __nex_data =
-	LIST_HEAD_INITIALIZER(prtn_list_head);
+static unsigned int prtn_list_lock __nex_data = SPINLOCK_UNLOCK;
 
-/* Free pages used for guest partitions */
-tee_mm_pool_t virt_mapper_pool __nex_bss;
+static struct prtn_list_head prtn_list __nex_data =
+	LIST_HEAD_INITIALIZER(prtn_list);
+static struct prtn_list_head prtn_destroy_list __nex_data =
+	LIST_HEAD_INITIALIZER(prtn_destroy_list);
 
 /* Memory used by OP-TEE core */
-struct tee_mmap_region *kmemory_map __nex_bss;
+struct memory_map *kmem_map __nex_bss;
+
+struct guest_spec_data {
+	size_t size;
+	void (*destroy)(void *data);
+};
+
+static bool add_disabled __nex_bss;
+static unsigned gsd_count __nex_bss;
+static struct guest_spec_data *gsd_array __nex_bss;
 
 struct guest_partition {
 	LIST_ENTRY(guest_partition) link;
 	struct mmu_partition *mmu_prtn;
-	struct tee_mmap_region *memory_map;
+	struct memory_map mem_map;
 	struct mutex mutex;
 	void *tables_va;
 	tee_mm_entry_t *tee_ram;
 	tee_mm_entry_t *ta_ram;
 	tee_mm_entry_t *tables;
 	bool runtime_initialized;
+	bool got_guest_destroyed;
+	bool shutting_down;
 	uint16_t id;
 	struct refcount refc;
 #ifdef CFG_CORE_SEL1_SPMC
-	uint64_t cookies[64];
+	uint64_t cookies[SPMC_CORE_SEL1_MAX_SHM_COUNT];
 	uint8_t cookie_count;
+	bitstr_t bit_decl(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT);
 #endif
+	void **data_array;
 };
 
 struct guest_partition *current_partition[CFG_TEE_CORE_NB_CORE] __nex_bss;
@@ -82,19 +103,18 @@ static void set_current_prtn(struct guest_partition *prtn)
 
 static size_t get_ta_ram_size(void)
 {
-	size_t ta_size = 0;
+	size_t ta_size = nex_phys_mem_get_ta_size();
 
-	core_mmu_get_ta_range(NULL, &ta_size);
 	return ROUNDDOWN(ta_size / CFG_VIRT_GUEST_COUNT - VCORE_UNPG_RW_SZ -
 			 core_mmu_get_total_pages_size(), SMALL_PAGE_SIZE);
 }
 
-static struct tee_mmap_region *prepare_memory_map(paddr_t tee_data,
-						  paddr_t ta_ram)
+static TEE_Result prepare_memory_map(struct memory_map *mem_map,
+				     paddr_t tee_data)
 {
-	int i, entries;
+	struct tee_mmap_region *map = NULL;
 	vaddr_t max_va = 0;
-	struct tee_mmap_region *map;
+	size_t n = 0;
 	/*
 	 * This function assumes that at time of operation,
 	 * kmemory_map (aka static_memory_map from core_mmu.c)
@@ -104,86 +124,53 @@ static struct tee_mmap_region *prepare_memory_map(paddr_t tee_data,
 	 * called when hypervisor creates a guest.
 	 */
 
-	/* Count number of entries in nexus memory map */
-	for (map = kmemory_map, entries = 1; map->type != MEM_AREA_END;
-	     map++, entries++)
-		;
-
 	/* Allocate entries for virtual guest map */
-	map = nex_calloc(entries + 1, sizeof(struct tee_mmap_region));
-	if (!map)
-		return NULL;
+	mem_map->map = nex_calloc(kmem_map->count + 1, sizeof(*mem_map->map));
+	if (!mem_map->map)
+		return TEE_ERROR_OUT_OF_MEMORY;
+	mem_map->count = kmem_map->count;
+	mem_map->alloc_count = kmem_map->count + 1;
 
-	memcpy(map, kmemory_map, sizeof(*map) * entries);
+	memcpy(mem_map->map, kmem_map->map,
+	       sizeof(*mem_map->map) * mem_map->count);
 
 	/* Map TEE .data and .bss sections */
-	for (i = 0; i < entries; i++) {
-		if (map[i].va == (vaddr_t)(VCORE_UNPG_RW_PA)) {
-			map[i].type = MEM_AREA_TEE_RAM_RW;
-			map[i].attr = core_mmu_type_to_attr(map[i].type);
-			map[i].pa = tee_data;
+	for (n = 0; n < mem_map->count; n++) {
+		map = mem_map->map + n;
+		if (map->va == (vaddr_t)(VCORE_UNPG_RW_PA)) {
+			map->type = MEM_AREA_TEE_RAM_RW;
+			map->attr = core_mmu_type_to_attr(map->type);
+			map->pa = tee_data;
 		}
-		if (map[i].va + map[i].size > max_va)
-			max_va = map[i].va + map[i].size;
+		if (map->va + map->size > max_va)
+			max_va = map->va + map->size;
 	}
 
-	/* Map TA_RAM */
-	assert(map[entries - 1].type == MEM_AREA_END);
-	map[entries] = map[entries - 1];
-	map[entries - 1].region_size = SMALL_PAGE_SIZE;
-	map[entries - 1].va = ROUNDUP(max_va, map[entries - 1].region_size);
-	map[entries - 1].va +=
-		(ta_ram - map[entries - 1].va) & CORE_MMU_PGDIR_MASK;
-	map[entries - 1].pa = ta_ram;
-	map[entries - 1].size = get_ta_ram_size();
-	map[entries - 1].type = MEM_AREA_TA_RAM;
-	map[entries - 1].attr = core_mmu_type_to_attr(map[entries - 1].type);
-
 	DMSG("New map (%08lx):",  (vaddr_t)(VCORE_UNPG_RW_PA));
 
-	for (i = 0; i < entries; i++)
+	for (n = 0; n < mem_map->count; n++)
 		DMSG("T: %-16s rsz: %08x, pa: %08lx, va: %08lx, sz: %08lx attr: %x",
-		     teecore_memtype_name(map[i].type),
-		     map[i].region_size, map[i].pa, map[i].va,
-		     map[i].size, map[i].attr);
-	return map;
+		     teecore_memtype_name(mem_map->map[n].type),
+		     mem_map->map[n].region_size, mem_map->map[n].pa,
+		     mem_map->map[n].va, mem_map->map[n].size,
+		     mem_map->map[n].attr);
+	return TEE_SUCCESS;
 }
 
-void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base,
+void virt_init_memory(struct memory_map *mem_map, paddr_t secmem0_base,
 		      paddr_size_t secmem0_size, paddr_t secmem1_base,
 		      paddr_size_t secmem1_size)
 {
-	struct tee_mmap_region *map = NULL;
-	paddr_size_t size = secmem0_size;
-	paddr_t base = secmem0_base;
-
-	if (secmem1_size) {
-		assert(secmem0_base + secmem0_size <= secmem1_base);
-		size = secmem1_base + secmem1_size - base;
-	}
+	size_t n = 0;
 
 	/* Init page pool that covers all secure RAM */
-	if (!tee_mm_init(&virt_mapper_pool, base, size,
-			 SMALL_PAGE_SHIFT, TEE_MM_POOL_NEX_MALLOC))
-		panic("Can't create pool with free pages");
-	DMSG("Created virtual mapper pool from %"PRIxPA" to %"PRIxPA,
-	     base, base + size);
-
-	if (secmem1_size) {
-		/* Carve out an eventual gap between secmem0 and secmem1 */
-		base = secmem0_base + secmem0_size;
-		size = secmem1_base - base;
-		if (size) {
-			DMSG("Carving out gap between secmem0 and secmem1 (0x%"PRIxPA":0x%"PRIxPASZ")",
-			     base, size);
-			if (!tee_mm_alloc2(&virt_mapper_pool, base, size))
-				panic("Can't carve out secmem gap");
-		}
-	}
-
+	nex_phys_mem_init(secmem0_base, secmem0_size, secmem1_base,
+			  secmem1_size);
 
 	/* Carve out areas that are used by OP-TEE core */
-	for (map = memory_map; map->type != MEM_AREA_END; map++) {
+	for (n = 0; n < mem_map->count; n++) {
+		struct tee_mmap_region *map = mem_map->map + n;
+
 		switch (map->type) {
 		case MEM_AREA_TEE_RAM_RX:
 		case MEM_AREA_TEE_RAM_RO:
@@ -191,8 +178,7 @@ void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base,
 		case MEM_AREA_NEX_RAM_RW:
 			DMSG("Carving out area of type %d (0x%08lx-0x%08lx)",
 			     map->type, map->pa, map->pa + map->size);
-			if (!tee_mm_alloc2(&virt_mapper_pool, map->pa,
-					   map->size))
+			if (!nex_phys_mem_alloc2(map->pa, map->size))
 				panic("Can't carve out used area");
 			break;
 		default:
@@ -200,7 +186,7 @@ void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base,
 		}
 	}
 
-	kmemory_map = memory_map;
+	kmem_map = mem_map;
 }
 
 
@@ -209,7 +195,7 @@ static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn)
 	TEE_Result res = TEE_SUCCESS;
 	paddr_t original_data_pa = 0;
 
-	prtn->tee_ram = tee_mm_alloc(&virt_mapper_pool, VCORE_UNPG_RW_SZ);
+	prtn->tee_ram = nex_phys_mem_core_alloc(VCORE_UNPG_RW_SZ);
 	if (!prtn->tee_ram) {
 		EMSG("Can't allocate memory for TEE runtime context");
 		res = TEE_ERROR_OUT_OF_MEMORY;
@@ -217,7 +203,7 @@ static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn)
 	}
 	DMSG("TEE RAM: %08" PRIxPA, tee_mm_get_smem(prtn->tee_ram));
 
-	prtn->ta_ram = tee_mm_alloc(&virt_mapper_pool, get_ta_ram_size());
+	prtn->ta_ram = nex_phys_mem_ta_alloc(get_ta_ram_size());
 	if (!prtn->ta_ram) {
 		EMSG("Can't allocate memory for TA data");
 		res = TEE_ERROR_OUT_OF_MEMORY;
@@ -225,8 +211,7 @@ static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn)
 	}
 	DMSG("TA RAM: %08" PRIxPA, tee_mm_get_smem(prtn->ta_ram));
 
-	prtn->tables = tee_mm_alloc(&virt_mapper_pool,
-				   core_mmu_get_total_pages_size());
+	prtn->tables = nex_phys_mem_core_alloc(core_mmu_get_total_pages_size());
 	if (!prtn->tables) {
 		EMSG("Can't allocate memory for page tables");
 		res = TEE_ERROR_OUT_OF_MEMORY;
@@ -244,14 +229,12 @@ static TEE_Result configure_guest_prtn_mem(struct guest_partition *prtn)
 		goto err;
 	}
 
-	prtn->memory_map = prepare_memory_map(tee_mm_get_smem(prtn->tee_ram),
-					     tee_mm_get_smem(prtn->ta_ram));
-	if (!prtn->memory_map) {
-		res = TEE_ERROR_OUT_OF_MEMORY;
+	res = prepare_memory_map(&prtn->mem_map,
+				 tee_mm_get_smem(prtn->tee_ram));
+	if (res)
 		goto err;
-	}
 
-	core_init_mmu_prtn(prtn->mmu_prtn, prtn->memory_map);
+	core_init_mmu_prtn(prtn->mmu_prtn, &prtn->mem_map);
 
 	original_data_pa = virt_to_phys(__data_start);
 	/* Switch to guest's mappings */
@@ -276,32 +259,74 @@ err:
 	if (prtn->tables)
 		tee_mm_free(prtn->tables);
 	nex_free(prtn->mmu_prtn);
-	nex_free(prtn->memory_map);
+	nex_free(prtn->mem_map.map);
 
 	return res;
 }
 
+static void destroy_gsd(struct guest_partition *prtn, bool free_only)
+{
+	size_t n = 0;
+
+	for (n = 0; n < gsd_count; n++) {
+		if (!free_only && prtn->data_array[n] && gsd_array[n].destroy)
+			gsd_array[n].destroy(prtn->data_array[n]);
+		nex_free(prtn->data_array[n]);
+	}
+	nex_free(prtn->data_array);
+	prtn->data_array = NULL;
+}
+
+static TEE_Result alloc_gsd(struct guest_partition *prtn)
+{
+	unsigned int n = 0;
+
+	if (!gsd_count)
+		return TEE_SUCCESS;
+
+	prtn->data_array = nex_calloc(gsd_count, sizeof(void *));
+	if (!prtn->data_array)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	for (n = 0; n < gsd_count; n++) {
+		prtn->data_array[n] = nex_calloc(1, gsd_array[n].size);
+		if (!prtn->data_array[n]) {
+			destroy_gsd(prtn, true /*free_only*/);
+			return TEE_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
 TEE_Result virt_guest_created(uint16_t guest_id)
 {
 	struct guest_partition *prtn = NULL;
 	TEE_Result res = TEE_SUCCESS;
 	uint32_t exceptions = 0;
 
+	if (guest_id == HYP_CLNT_ID)
+		return TEE_ERROR_BAD_PARAMETERS;
+
 	prtn = nex_calloc(1, sizeof(*prtn));
 	if (!prtn)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
+	res = alloc_gsd(prtn);
+	if (res)
+		goto err_free_prtn;
+
 	prtn->id = guest_id;
 	mutex_init(&prtn->mutex);
 	refcount_set(&prtn->refc, 1);
 	res = configure_guest_prtn_mem(prtn);
-	if (res) {
-		nex_free(prtn);
-		return res;
-	}
+	if (res)
+		goto err_free_gsd;
 
 	set_current_prtn(prtn);
 
+	malloc_add_pool(__heap1_start, __heap1_end - __heap1_start);
+	phys_mem_init(0, 0, tee_mm_get_smem(prtn->ta_ram),
+		      tee_mm_get_bytes(prtn->ta_ram));
 	/* Initialize threads */
 	thread_init_threads();
 	/* Do the preinitcalls */
@@ -317,50 +342,170 @@ TEE_Result virt_guest_created(uint16_t guest_id)
 	core_mmu_set_default_prtn();
 
 	return TEE_SUCCESS;
+
+err_free_gsd:
+	destroy_gsd(prtn, true /*free_only*/);
+err_free_prtn:
+	nex_free(prtn);
+	return res;
 }
 
-TEE_Result virt_guest_destroyed(uint16_t guest_id)
+static bool
+prtn_have_remaining_resources(struct guest_partition *prtn __maybe_unused)
 {
-	struct guest_partition *prtn;
-	uint32_t exceptions;
+#ifdef CFG_CORE_SEL1_SPMC
+	int i = 0;
+
+	if (prtn->cookie_count)
+		return true;
+	bit_ffs(prtn->shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i);
+	return i >= 0;
+#else
+	return false;
+#endif
+}
+
+static void get_prtn(struct guest_partition *prtn)
+{
+	if (!refcount_inc(&prtn->refc))
+		panic();
+}
+
+uint16_t virt_get_guest_id(struct guest_partition *prtn)
+{
+	if (!prtn)
+		return 0;
+	return prtn->id;
+}
+
+static struct guest_partition *find_guest_by_id_unlocked(uint16_t guest_id)
+{
+	struct guest_partition *prtn = NULL;
 
-	IMSG("Removing guest %d", guest_id);
+	LIST_FOREACH(prtn, &prtn_list, link)
+		if (!prtn->shutting_down && prtn->id == guest_id)
+			return prtn;
+
+	return NULL;
+}
+
+struct guest_partition *virt_next_guest(struct guest_partition *prtn)
+{
+	struct guest_partition *ret = NULL;
+	uint32_t exceptions = 0;
 
 	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+	if (prtn)
+		ret = LIST_NEXT(prtn, link);
+	else
+		ret = LIST_FIRST(&prtn_list);
+
+	while (ret && ret->shutting_down)
+		ret = LIST_NEXT(prtn, link);
+	if (ret)
+		get_prtn(ret);
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 
-	LIST_FOREACH(prtn, &prtn_list, link) {
-		if (prtn->id == guest_id) {
-			LIST_REMOVE(prtn, link);
-			break;
-		}
-	}
+	virt_put_guest(prtn);
+
+	return ret;
+}
+
+struct guest_partition *virt_get_current_guest(void)
+{
+	struct guest_partition *prtn = get_current_prtn();
+
+	if (prtn)
+		get_prtn(prtn);
+	return prtn;
+}
+
+struct guest_partition *virt_get_guest(uint16_t guest_id)
+{
+	struct guest_partition *prtn = NULL;
+	uint32_t exceptions = 0;
+
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+	prtn = find_guest_by_id_unlocked(guest_id);
+	if (prtn)
+		get_prtn(prtn);
 	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 
-	if (prtn) {
-		if (!refcount_dec(&prtn->refc)) {
-			EMSG("Guest thread(s) is still running. refc = %d",
-			     refcount_val(&prtn->refc));
-			panic();
+	return prtn;
+}
+
+void virt_put_guest(struct guest_partition *prtn)
+{
+	if (prtn && refcount_dec(&prtn->refc)) {
+		uint32_t exceptions = 0;
+		bool do_free = true;
+
+		assert(prtn->shutting_down);
+
+		exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+		LIST_REMOVE(prtn, link);
+		if (prtn_have_remaining_resources(prtn)) {
+			LIST_INSERT_HEAD(&prtn_destroy_list, prtn, link);
+			/*
+			 * Delay the nex_free() until
+			 * virt_reclaim_cookie_from_destroyed_guest()
+			 * is done with this partition.
+			 */
+			do_free = false;
 		}
+		cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 
+		destroy_gsd(prtn, false /*!free_only*/);
 		tee_mm_free(prtn->tee_ram);
+		prtn->tee_ram = NULL;
 		tee_mm_free(prtn->ta_ram);
+		prtn->ta_ram = NULL;
 		tee_mm_free(prtn->tables);
+		prtn->tables = NULL;
 		core_free_mmu_prtn(prtn->mmu_prtn);
-		nex_free(prtn->memory_map);
-		nex_free(prtn);
-	} else
+		prtn->mmu_prtn = NULL;
+		nex_free(prtn->mem_map.map);
+		prtn->mem_map.map = NULL;
+		if (do_free)
+			nex_free(prtn);
+	}
+}
+
+TEE_Result virt_guest_destroyed(uint16_t guest_id)
+{
+	struct guest_partition *prtn = NULL;
+	uint32_t exceptions = 0;
+
+	IMSG("Removing guest %"PRId16, guest_id);
+
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+
+	prtn = find_guest_by_id_unlocked(guest_id);
+	if (prtn && !prtn->got_guest_destroyed)
+		prtn->got_guest_destroyed = true;
+	else
+		prtn = NULL;
+
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
+
+	if (prtn) {
+		notif_deliver_atomic_event(NOTIF_EVENT_SHUTDOWN, prtn->id);
+
+		exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+		prtn->shutting_down = true;
+		cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
+
+		virt_put_guest(prtn);
+	} else {
 		EMSG("Client with id %d is not found", guest_id);
+	}
 
 	return TEE_SUCCESS;
 }
 
 TEE_Result virt_set_guest(uint16_t guest_id)
 {
-	struct guest_partition *prtn;
-	uint32_t exceptions;
-
-	prtn = get_current_prtn();
+	struct guest_partition *prtn = get_current_prtn();
 
 	/* This can be true only if we return from IRQ RPC */
 	if (prtn && prtn->id == guest_id)
@@ -369,22 +514,14 @@ TEE_Result virt_set_guest(uint16_t guest_id)
 	if (prtn)
 		panic("Virtual guest partition is already set");
 
-	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
-	LIST_FOREACH(prtn, &prtn_list, link) {
-		if (prtn->id == guest_id) {
-			set_current_prtn(prtn);
-			core_mmu_set_prtn(prtn->mmu_prtn);
-			refcount_inc(&prtn->refc);
-			cpu_spin_unlock_xrestore(&prtn_list_lock,
-						 exceptions);
-			return TEE_SUCCESS;
-		}
-	}
-	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
+	prtn = virt_get_guest(guest_id);
+	if (!prtn)
+		return TEE_ERROR_ITEM_NOT_FOUND;
 
-	if (guest_id == HYP_CLNT_ID)
-		return TEE_SUCCESS;
-	return TEE_ERROR_ITEM_NOT_FOUND;
+	set_current_prtn(prtn);
+	core_mmu_set_prtn(prtn->mmu_prtn);
+
+	return TEE_SUCCESS;
 }
 
 void virt_unset_guest(void)
@@ -396,8 +533,7 @@ void virt_unset_guest(void)
 
 	set_current_prtn(NULL);
 	core_mmu_set_default_prtn();
-	if (refcount_dec(&prtn->refc))
-		panic();
+	virt_put_guest(prtn);
 }
 
 void virt_on_stdcall(void)
@@ -409,13 +545,14 @@ void virt_on_stdcall(void)
 		mutex_lock(&prtn->mutex);
 		if (!prtn->runtime_initialized) {
 			init_tee_runtime();
+			call_driver_initcalls();
 			prtn->runtime_initialized = true;
 		}
 		mutex_unlock(&prtn->mutex);
 	}
 }
 
-struct tee_mmap_region *virt_get_memory_map(void)
+struct memory_map *virt_get_memory_map(void)
 {
 	struct guest_partition *prtn;
 
@@ -424,17 +561,7 @@ struct tee_mmap_region *virt_get_memory_map(void)
 	if (!prtn)
 		return NULL;
 
-	return prtn->memory_map;
-}
-
-void virt_get_ta_ram(vaddr_t *start, vaddr_t *end)
-{
-	struct guest_partition *prtn = get_current_prtn();
-
-	*start = (vaddr_t)phys_to_virt(tee_mm_get_smem(prtn->ta_ram),
-				       MEM_AREA_TA_RAM,
-				       tee_mm_get_bytes(prtn->ta_ram));
-	*end = *start + tee_mm_get_bytes(prtn->ta_ram);
+	return &prtn->mem_map;
 }
 
 #ifdef CFG_CORE_SEL1_SPMC
@@ -469,8 +596,9 @@ TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie)
 {
 	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
 	struct guest_partition *prtn = NULL;
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
+	uint32_t exceptions = 0;
 
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
 	if (find_prtn_cookie(cookie, NULL))
 		goto out;
 
@@ -481,38 +609,148 @@ TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie)
 		res = TEE_SUCCESS;
 	}
 out:
-	thread_unmask_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 
 	return res;
 }
 
 void virt_remove_cookie(uint64_t cookie)
 {
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
 	struct guest_partition *prtn = NULL;
+	uint32_t exceptions = 0;
 	int i = 0;
 
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
 	prtn = find_prtn_cookie(cookie, &i);
 	if (prtn) {
 		memmove(prtn->cookies + i, prtn->cookies + i + 1,
 			sizeof(uint64_t) * (prtn->cookie_count - i - 1));
 		prtn->cookie_count--;
 	}
-	thread_unmask_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 }
 
 uint16_t virt_find_guest_by_cookie(uint64_t cookie)
 {
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_FOREIGN_INTR);
 	struct guest_partition *prtn = NULL;
+	uint32_t exceptions = 0;
 	uint16_t ret = 0;
 
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
 	prtn = find_prtn_cookie(cookie, NULL);
 	if (prtn)
 		ret = prtn->id;
 
-	thread_unmask_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
 
 	return ret;
 }
+
+bitstr_t *virt_get_shm_bits(void)
+{
+	return get_current_prtn()->shm_bits;
+}
+
+static TEE_Result reclaim_cookie(struct guest_partition *prtn, uint64_t cookie)
+{
+	if (cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT) {
+		size_t n = 0;
+
+		for (n = 0; n < prtn->cookie_count; n++) {
+			if (prtn->cookies[n] == cookie) {
+				memmove(prtn->cookies + n,
+					prtn->cookies + n + 1,
+					sizeof(uint64_t) *
+						(prtn->cookie_count - n - 1));
+				prtn->cookie_count--;
+				return TEE_SUCCESS;
+			}
+		}
+	} else {
+		uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT |
+				SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK,
+					  FFA_MEMORY_HANDLE_PRTN_SHIFT);
+		int64_t i = cookie & ~mask;
+
+		if (i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT &&
+		    bit_test(prtn->shm_bits, i)) {
+			bit_clear(prtn->shm_bits, i);
+			return TEE_SUCCESS;
+		}
+	}
+
+	return TEE_ERROR_ITEM_NOT_FOUND;
+}
+
+TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id,
+						    uint64_t cookie)
+
+{
+	struct guest_partition *prtn = NULL;
+	TEE_Result res = TEE_ERROR_ITEM_NOT_FOUND;
+	uint32_t exceptions = 0;
+
+	exceptions = cpu_spin_lock_xsave(&prtn_list_lock);
+	LIST_FOREACH(prtn, &prtn_destroy_list, link) {
+		if (prtn->id == guest_id) {
+			res = reclaim_cookie(prtn, cookie);
+			if (prtn_have_remaining_resources(prtn))
+				prtn = NULL;
+			else
+				LIST_REMOVE(prtn, link);
+			break;
+		}
+	}
+	cpu_spin_unlock_xrestore(&prtn_list_lock, exceptions);
+
+	nex_free(prtn);
+
+	return res;
+}
 #endif /*CFG_CORE_SEL1_SPMC*/
+
+TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size,
+				    void (*data_destroy)(void *data))
+{
+	void *p = NULL;
+
+	/*
+	 * This function only executes successfully in a single threaded
+	 * environment before exiting to the normal world the first time.
+	 * If add_disabled is true, it means we're not in this environment
+	 * any longer.
+	 */
+
+	if (add_disabled)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	p = nex_realloc(gsd_array, sizeof(*gsd_array) * (gsd_count + 1));
+	if (!p)
+		return TEE_ERROR_OUT_OF_MEMORY;
+	gsd_array = p;
+
+	gsd_array[gsd_count] = (struct guest_spec_data){
+		.size = data_size,
+		.destroy = data_destroy,
+	};
+	*data_id = gsd_count + 1;
+	gsd_count++;
+	return TEE_SUCCESS;
+}
+
+void *virt_get_guest_spec_data(struct guest_partition *prtn,
+			       unsigned int data_id)
+{
+	assert(data_id);
+	if (!data_id || !prtn || data_id > gsd_count)
+		return NULL;
+	return prtn->data_array[data_id - 1];
+}
+
+static TEE_Result virt_disable_add(void)
+{
+	add_disabled = true;
+
+	return TEE_SUCCESS;
+}
+nex_release_init_resource(virt_disable_add);
diff --git a/core/arch/arm/mm/core_mmu.c b/core/arch/arm/mm/core_mmu.c
index 0b6af6ad06388ed12da7ec4a25754e6aceb8777a..334cdc6ac711282f7f902409c747822b7884df3d 100644
--- a/core/arch/arm/mm/core_mmu.c
+++ b/core/arch/arm/mm/core_mmu.c
@@ -11,7 +11,6 @@
 #include <kernel/cache_helpers.h>
 #include <kernel/spinlock.h>
 #include <kernel/tee_l2cc_mutex.h>
-#include <kernel/tee_misc.h>
 #include <kernel/tlb_helpers.h>
 #include <kernel/tz_ssvce_pl310.h>
 #include <mm/core_memprot.h>
@@ -150,7 +149,7 @@ TEE_Result cache_op_outer(enum cache_op op, paddr_t pa, size_t len)
 	}
 
 	tee_l2cc_mutex_unlock();
-	thread_set_exceptions(exceptions);
+	thread_unmask_exceptions(exceptions);
 	return ret;
 }
 #endif /*CFG_PL310*/
diff --git a/core/arch/arm/mm/core_mmu_lpae.c b/core/arch/arm/mm/core_mmu_lpae.c
index dffbda8d094f615d27882ee306468d8cf174b647..e83a5e092eb38fa417870e84622a3bc277965ef8 100644
--- a/core/arch/arm/mm/core_mmu_lpae.c
+++ b/core/arch/arm/mm/core_mmu_lpae.c
@@ -609,26 +609,27 @@ static bool core_mmu_entry_copy(struct core_mmu_table_info *tbl_info,
 }
 
 static void core_init_mmu_prtn_tee(struct mmu_partition *prtn,
-				   struct tee_mmap_region *mm)
+				   struct memory_map *mem_map)
 {
-	size_t n;
+	size_t n = 0;
 
-	assert(prtn && mm);
+	assert(prtn && mem_map);
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) {
+	for (n = 0; n < mem_map->count; n++) {
+		struct tee_mmap_region *mm = mem_map->map + n;
 		debug_print(" %010" PRIxVA " %010" PRIxPA " %10zx %x",
-			    mm[n].va, mm[n].pa, mm[n].size, mm[n].attr);
+			    mm->va, mm->pa, mm->size, mm->attr);
 
-		if (!IS_PAGE_ALIGNED(mm[n].pa) || !IS_PAGE_ALIGNED(mm[n].size))
+		if (!IS_PAGE_ALIGNED(mm->pa) || !IS_PAGE_ALIGNED(mm->size))
 			panic("unaligned region");
 	}
 
 	/* Clear table before use */
 	memset(prtn->base_tables, 0, sizeof(base_xlation_table));
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++)
-		if (!core_mmu_is_dynamic_vaspace(mm + n))
-			core_mmu_map_region(prtn, mm + n);
+	for (n = 0; n < mem_map->count; n++)
+		if (!core_mmu_is_dynamic_vaspace(mem_map->map + n))
+			core_mmu_map_region(prtn, mem_map->map + n);
 
 	/*
 	 * Primary mapping table is ready at index `get_core_pos()`
@@ -787,13 +788,13 @@ static void core_init_mmu_prtn_ta(struct mmu_partition *prtn)
 			core_init_mmu_prtn_ta_core(prtn, base_idx, core);
 }
 
-void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm)
+void core_init_mmu_prtn(struct mmu_partition *prtn, struct memory_map *mem_map)
 {
-	core_init_mmu_prtn_tee(prtn, mm);
+	core_init_mmu_prtn_tee(prtn, mem_map);
 	core_init_mmu_prtn_ta(prtn);
 }
 
-void core_init_mmu(struct tee_mmap_region *mm)
+void core_init_mmu(struct memory_map *mem_map)
 {
 	uint64_t max_va = 0;
 	size_t n;
@@ -807,10 +808,10 @@ void core_init_mmu(struct tee_mmap_region *mm)
 	COMPILE_TIME_ASSERT(XLAT_TABLES_SIZE == sizeof(xlat_tables));
 
 	/* Initialize default pagetables */
-	core_init_mmu_prtn_tee(&default_partition, mm);
+	core_init_mmu_prtn_tee(&default_partition, mem_map);
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) {
-		vaddr_t va_end = mm[n].va + mm[n].size - 1;
+	for (n = 0; n < mem_map->count; n++) {
+		vaddr_t va_end = mem_map->map[n].va + mem_map->map[n].size - 1;
 
 		if (va_end > max_va)
 			max_va = va_end;
diff --git a/core/arch/arm/mm/core_mmu_v7.c b/core/arch/arm/mm/core_mmu_v7.c
index 61e703da89c841d783d208a122e2b9705eca3fc6..c9c235b93f7c1134158d2c7010684eb8b4220629 100644
--- a/core/arch/arm/mm/core_mmu_v7.c
+++ b/core/arch/arm/mm/core_mmu_v7.c
@@ -188,7 +188,7 @@
 #else
 #	define XLAT_TABLE_ASLR_EXTRA 0
 #endif
-#define MAX_XLAT_TABLES		(4 + XLAT_TABLE_ASLR_EXTRA)
+#define MAX_XLAT_TABLES		(6 + XLAT_TABLE_ASLR_EXTRA)
 #endif /*!MAX_XLAT_TABLES*/
 
 enum desc_type {
@@ -229,25 +229,9 @@ static struct mmu_partition default_partition = {
 	.tables_used = 0,
 };
 
-#ifdef CFG_NS_VIRTUALIZATION
-static struct mmu_partition *current_prtn[CFG_TEE_CORE_NB_CORE];
-
-void core_mmu_set_default_prtn_tbl(void)
-{
-	size_t n = 0;
-
-	for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++)
-		current_prtn[n] = &default_partition;
-}
-#endif
-
 static struct mmu_partition *get_prtn(void)
 {
-#ifdef CFG_NS_VIRTUALIZATION
-	return current_prtn[get_core_pos()];
-#else
 	return &default_partition;
-#endif
 }
 
 static vaddr_t core_mmu_get_main_ttb_va(struct mmu_partition *prtn)
@@ -280,8 +264,7 @@ static paddr_t core_mmu_get_ul1_ttb_pa(struct mmu_partition *prtn)
 
 static void *core_mmu_alloc_l2(struct mmu_partition *prtn, size_t size)
 {
-	uint32_t to_alloc = ROUNDUP(size, NUM_L2_ENTRIES * SMALL_PAGE_SIZE) /
-		(NUM_L2_ENTRIES * SMALL_PAGE_SIZE);
+	uint32_t to_alloc = ROUNDUP_DIV(size, NUM_L2_ENTRIES * SMALL_PAGE_SIZE);
 
 	DMSG("L2 table used: %d/%d", prtn->tables_used + to_alloc,
 	     MAX_XLAT_TABLES);
@@ -709,64 +692,28 @@ bool core_mmu_user_mapping_is_active(void)
 	return ret;
 }
 
-static void print_mmap_area(const struct tee_mmap_region *mm __maybe_unused,
-				const char *str __maybe_unused)
+bool __noprof core_mmu_user_va_range_is_defined(void)
 {
-	if (!(mm->attr & TEE_MATTR_VALID_BLOCK))
-		debug_print("%s [%08" PRIxVA " %08" PRIxVA "] not mapped",
-				str, mm->va, mm->va + mm->size);
-	else
-		debug_print("%s [%08" PRIxVA " %08" PRIxVA "] %s-%s-%s-%s",
-				str, mm->va, mm->va + mm->size,
-				mattr_is_cached(mm->attr) ? "MEM" : "DEV",
-				mm->attr & TEE_MATTR_PW ? "RW" : "RO",
-				mm->attr & TEE_MATTR_PX ? "X" : "XN",
-				mm->attr & TEE_MATTR_SECURE ? "S" : "NS");
-}
-
-void map_memarea_sections(const struct tee_mmap_region *mm, uint32_t *ttb)
-{
-	uint32_t attr = mattr_to_desc(1, mm->attr);
-	size_t idx = mm->va >> SECTION_SHIFT;
-	paddr_t pa = 0;
-	size_t n;
-
-	if (core_mmap_is_end_of_table(mm))
-		return;
-
-	print_mmap_area(mm, "section map");
-
-	attr = mattr_to_desc(1, mm->attr);
-	if (attr != INVALID_DESC)
-		pa = mm->pa;
-
-	n = ROUNDUP(mm->size, SECTION_SIZE) >> SECTION_SHIFT;
-	while (n--) {
-		assert(!attr || !ttb[idx] || ttb[idx] == (pa | attr));
-
-		ttb[idx] = pa | attr;
-		idx++;
-		pa += SECTION_SIZE;
-	}
+	return true;
 }
 
-void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm)
+void core_init_mmu_prtn(struct mmu_partition *prtn, struct memory_map *mem_map)
 {
 	void *ttb1 = (void *)core_mmu_get_main_ttb_va(prtn);
-	size_t n;
+	size_t n = 0;
 
 	/* reset L1 table */
 	memset(ttb1, 0, L1_TBL_SIZE);
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++)
-		if (!core_mmu_is_dynamic_vaspace(mm + n))
-			core_mmu_map_region(prtn, mm + n);
+	for (n = 0; n < mem_map->count; n++)
+		if (!core_mmu_is_dynamic_vaspace(mem_map->map + n))
+			core_mmu_map_region(prtn, mem_map->map + n);
 }
 
-void core_init_mmu(struct tee_mmap_region *mm)
+void core_init_mmu(struct memory_map *mem_map)
 {
 	/* Initialize default pagetables */
-	core_init_mmu_prtn(&default_partition, mm);
+	core_init_mmu_prtn(&default_partition, mem_map);
 }
 
 void core_init_mmu_regs(struct core_mmu_config *cfg)
diff --git a/core/arch/arm/mm/mobj_ffa.c b/core/arch/arm/mm/mobj_ffa.c
index 8d3d71447fe2399176e09551fa7718920e26a7d2..a00f98e39eb2ced6ef74adb3d9c3c99f4147998f 100644
--- a/core/arch/arm/mm/mobj_ffa.c
+++ b/core/arch/arm/mm/mobj_ffa.c
@@ -91,8 +91,19 @@ struct mobj_ffa {
 SLIST_HEAD(mobj_ffa_head, mobj_ffa);
 
 #ifdef CFG_CORE_SEL1_SPMC
-#define NUM_SHMS	64
-static bitstr_t bit_decl(shm_bits, NUM_SHMS);
+#ifdef CFG_NS_VIRTUALIZATION
+static bitstr_t *get_shm_bits(void)
+{
+	return virt_get_shm_bits();
+}
+#else
+static bitstr_t bit_decl(__shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT);
+
+static bitstr_t *get_shm_bits(void)
+{
+	return __shm_bits;
+}
+#endif
 #endif
 
 static struct mobj_ffa_head shm_head = SLIST_HEAD_INITIALIZER(shm_head);
@@ -149,6 +160,7 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie,
 					unsigned int num_pages)
 {
 	struct mobj_ffa *mf = NULL;
+	bitstr_t *shm_bits = NULL;
 	uint32_t exceptions = 0;
 	int i = 0;
 
@@ -171,8 +183,9 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie,
 		return mf;
 	}
 
+	shm_bits = get_shm_bits();
 	exceptions = cpu_spin_lock_xsave(&shm_lock);
-	bit_ffc(shm_bits, NUM_SHMS, &i);
+	bit_ffc(shm_bits, SPMC_CORE_SEL1_MAX_SHM_COUNT, &i);
 	if (i != -1) {
 		bit_set(shm_bits, i);
 		mf->cookie = i;
@@ -197,7 +210,7 @@ struct mobj_ffa *mobj_ffa_sel1_spmc_new(uint64_t cookie,
 
 static size_t get_page_count(struct mobj_ffa *mf)
 {
-	return ROUNDUP(mf->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
+	return ROUNDUP_DIV(mf->mobj.size, SMALL_PAGE_SIZE);
 }
 
 static bool cmp_cookie(struct mobj_ffa *mf, uint64_t cookie)
@@ -259,6 +272,7 @@ void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf)
 	if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) ||
 	    !(mf->cookie & FFA_MEMORY_HANDLE_HYPERVISOR_BIT)) {
 		uint64_t mask = FFA_MEMORY_HANDLE_NON_SECURE_BIT;
+		bitstr_t *shm_bits = get_shm_bits();
 		uint32_t exceptions = 0;
 		int64_t i = 0;
 
@@ -266,7 +280,7 @@ void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mf)
 			mask |= SHIFT_U64(FFA_MEMORY_HANDLE_PRTN_MASK,
 					  FFA_MEMORY_HANDLE_PRTN_SHIFT);
 		i = mf->cookie & ~mask;
-		assert(i >= 0 && i < NUM_SHMS);
+		assert(i >= 0 && i < SPMC_CORE_SEL1_MAX_SHM_COUNT);
 
 		exceptions = cpu_spin_lock_xsave(&shm_lock);
 		assert(bit_test(shm_bits, i));
@@ -680,7 +694,7 @@ static TEE_Result ffa_inc_map(struct mobj *mobj)
 	 */
 	if (!mf->mm) {
 		sz = ROUNDUP(mobj->size + mf->page_offset, SMALL_PAGE_SIZE);
-		mf->mm = tee_mm_alloc(&tee_mm_shm, sz);
+		mf->mm = tee_mm_alloc(&core_virt_shm_pool, sz);
 		if (!mf->mm) {
 			res = TEE_ERROR_OUT_OF_MEMORY;
 			goto out;
@@ -728,7 +742,7 @@ static TEE_Result mapped_shm_init(void)
 	if (!pool_start || !pool_end)
 		panic("Can't find region for shmem pool");
 
-	if (!tee_mm_init(&tee_mm_shm, pool_start, pool_end - pool_start,
+	if (!tee_mm_init(&core_virt_shm_pool, pool_start, pool_end - pool_start,
 			 SMALL_PAGE_SHIFT,
 			 TEE_MM_POOL_NO_FLAGS))
 		panic("Could not create shmem pool");
diff --git a/core/arch/arm/mm/sp_mem.c b/core/arch/arm/mm/sp_mem.c
index bdba7309b6c637d833a85eb7232fd534e9193365..59e415c62a713fb37379622563eb29f998f33741 100644
--- a/core/arch/arm/mm/sp_mem.c
+++ b/core/arch/arm/mm/sp_mem.c
@@ -69,7 +69,7 @@ struct mobj *sp_mem_new_mobj(uint64_t pages, uint32_t mem_type, bool is_secure)
 
 static size_t get_page_count(struct mobj_sp *ms)
 {
-	return ROUNDUP(ms->mobj.size, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
+	return ROUNDUP_DIV(ms->mobj.size, SMALL_PAGE_SIZE);
 }
 
 /* Add some physical pages to the mobj object. */
@@ -224,7 +224,7 @@ struct sp_mem *sp_mem_new(void)
 	uint32_t exceptions = 0;
 	int i = 0;
 
-	smem = calloc(sizeof(*smem), 1);
+	smem = calloc(1, sizeof(*smem));
 	if (!smem)
 		return NULL;
 
diff --git a/core/arch/arm/mm/sub.mk b/core/arch/arm/mm/sub.mk
index 1fff63560b25faaa973741b547c6a82e15e50bc9..ed92c12a4cc1cbd90f9dbd5a257f633ae1585432 100644
--- a/core/arch/arm/mm/sub.mk
+++ b/core/arch/arm/mm/sub.mk
@@ -7,9 +7,6 @@ srcs-y += core_mmu_v7.c
 endif
 srcs-$(CFG_CORE_FFA) += mobj_ffa.c
 srcs-$(CFG_SECURE_PARTITION) += sp_mem.c
-ifneq ($(CFG_CORE_FFA),y)
-srcs-$(CFG_CORE_DYN_SHM) += mobj_dyn_shm.c
-endif
 
 ifeq ($(CFG_SYSCALL_FTRACE),y)
 # We would not like to profile MMU APIs as these are used to switch TA
diff --git a/core/arch/arm/mm/tee_pager.c b/core/arch/arm/mm/tee_pager.c
index a9d3f39d2c5cf9b39d74ac584ee60247ba15a562..3897cd28ab9237aab50634d8c723d201791e20d4 100644
--- a/core/arch/arm/mm/tee_pager.c
+++ b/core/arch/arm/mm/tee_pager.c
@@ -931,7 +931,7 @@ static struct pgt **alloc_merged_pgt_array(struct vm_paged_region *a,
 	    a->pgt_array[a_pgt_count - 1] != a_next->pgt_array[0])
 		return NULL;
 
-	pgt_array = calloc(sizeof(struct pgt *), pgt_count);
+	pgt_array = calloc(pgt_count, sizeof(struct pgt *));
 	if (!pgt_array)
 		return NULL;
 
@@ -2004,7 +2004,7 @@ void *tee_pager_alloc(size_t size)
 	if (!size)
 		return NULL;
 
-	mm = tee_mm_alloc(&tee_mm_vcore, ROUNDUP(size, SMALL_PAGE_SIZE));
+	mm = tee_mm_alloc(&core_virt_mem_pool, ROUNDUP(size, SMALL_PAGE_SIZE));
 	if (!mm)
 		return NULL;
 
@@ -2031,7 +2031,8 @@ vaddr_t tee_pager_init_iv_region(struct fobj *fobj)
 
 	assert(!pager_iv_region);
 
-	mm = tee_mm_alloc(&tee_mm_vcore, fobj->num_pages * SMALL_PAGE_SIZE);
+	mm = tee_mm_alloc(&core_virt_mem_pool,
+			  fobj->num_pages * SMALL_PAGE_SIZE);
 	if (!mm)
 		panic();
 
diff --git a/core/arch/arm/plat-amlogic/main.c b/core/arch/arm/plat-amlogic/main.c
index fd5ede4ae5d9b8d736a5fd496f940e1d2faa065b..42a32c2977109d2a7c76b76e33f5ca1fb960ffa0 100644
--- a/core/arch/arm/plat-amlogic/main.c
+++ b/core/arch/arm/plat-amlogic/main.c
@@ -13,7 +13,7 @@ static struct amlogic_uart_data console_data;
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE,
 			CORE_MMU_PGDIR_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	amlogic_uart_init(&console_data, CONSOLE_UART_BASE);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-aspeed/platform_ast2600.c b/core/arch/arm/plat-aspeed/platform_ast2600.c
index b6132c0229b3ef28ed12e7377fe04fe0ec95cdf6..8cc3eb394cbb374cec90be98f5553401fcccfdb0 100644
--- a/core/arch/arm/plat-aspeed/platform_ast2600.c
+++ b/core/arch/arm/plat-aspeed/platform_ast2600.c
@@ -70,7 +70,7 @@ void boot_secondary_init_intc(void)
 	gic_init_per_cpu();
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-aspeed/platform_ast2700.c b/core/arch/arm/plat-aspeed/platform_ast2700.c
index 106c88df173c4bd7fdc582a34df2b26ae7cbcb73..d88ec72bbe2e84869ea130c2df4d021a7d499d7c 100644
--- a/core/arch/arm/plat-aspeed/platform_ast2700.c
+++ b/core/arch/arm/plat-aspeed/platform_ast2700.c
@@ -29,7 +29,7 @@ void boot_secondary_init_intc(void)
 	gic_init_per_cpu();
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-bcm/main.c b/core/arch/arm/plat-bcm/main.c
index d6f37fa1f14dce16460dc9d489fa692ba8bb5361..387d9d063b41a52b06caf8aed0e11a59c481156a 100644
--- a/core/arch/arm/plat-bcm/main.c
+++ b/core/arch/arm/plat-bcm/main.c
@@ -62,7 +62,7 @@ void plat_trace_ext_puts(const char *str)
 		bcm_elog_putchar(*p);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-corstone1000/conf.mk b/core/arch/arm/plat-corstone1000/conf.mk
index 98347b143f2d1e5b075f184d61f2418797d57097..9fa0729d5e99bd5dfedd537d8aca14864cd745c2 100644
--- a/core/arch/arm/plat-corstone1000/conf.mk
+++ b/core/arch/arm/plat-corstone1000/conf.mk
@@ -33,8 +33,8 @@ CFG_WITH_ARM_TRUSTED_FW ?= y
 CFG_TEE_CORE_NB_CORE ?= 1
 CFG_TZDRAM_START ?= 0x02002000
 
-# TEE_RAM (OPTEE kernel + DATA) + TA_RAM = 3MB
-CFG_TZDRAM_SIZE  ?= 0x300000
+# TEE_RAM (OP-TEE kernel + DATA) + TA_RAM
+CFG_TZDRAM_SIZE  ?= 0x340000
 CFG_SHMEM_START  ?= 0x86000000
 CFG_SHMEM_SIZE   ?= 0x00200000
 
diff --git a/core/arch/arm/plat-corstone1000/main.c b/core/arch/arm/plat-corstone1000/main.c
index b3861c4c88f7049cb537ace23446251a64c9832d..9e1482a7bb7c8e82012ec44ab46cff5d4717fa24 100644
--- a/core/arch/arm/plat-corstone1000/main.c
+++ b/core/arch/arm/plat-corstone1000/main.c
@@ -15,7 +15,6 @@
 static struct pl011_data console_data __nex_bss;
 
 register_ddr(DRAM0_BASE, DRAM0_SIZE);
-register_ddr(MM_COMM_BUF_BASE, MM_COMM_BUF_SIZE);
 
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
@@ -31,7 +30,7 @@ void boot_secondary_init_intc(void)
 	gic_init_per_cpu();
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
 		   CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-corstone1000/platform_config.h b/core/arch/arm/plat-corstone1000/platform_config.h
index 6653d38bc6ffe0b3bb6b49f7a9c35739347a8281..f59c93a146742af17d87e1f413268488c697ac15 100644
--- a/core/arch/arm/plat-corstone1000/platform_config.h
+++ b/core/arch/arm/plat-corstone1000/platform_config.h
@@ -26,9 +26,6 @@
 #define GICD_BASE		(GIC_BASE + GICD_OFFSET)
 #define GICC_BASE		(GIC_BASE + GICC_OFFSET)
 
-#define MM_COMM_BUF_BASE	0x02000000
-#define MM_COMM_BUF_SIZE	0x1000
-
 #define UART_BAUDRATE		115200
 #define CONSOLE_BAUDRATE	UART_BAUDRATE
 
diff --git a/core/arch/arm/plat-d02/main.c b/core/arch/arm/plat-d02/main.c
index 759ca3b9ad1afee03c647d2fe213f9d6dd0d9b57..0e5b9ec3c688fe2bf08e616eaa63b7cdb1cf199a 100644
--- a/core/arch/arm/plat-d02/main.c
+++ b/core/arch/arm/plat-d02/main.c
@@ -16,7 +16,7 @@ static struct hi16xx_uart_data console_data;
 register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE,
 			HI16XX_UART_REG_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	hi16xx_uart_init(&console_data, CONSOLE_UART_BASE,
 			 CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-d06/conf.mk b/core/arch/arm/plat-d06/conf.mk
index 7c250a7c30465687c271a5881f752fcc720e7530..55f1c3970f99f109d81e314e67d73b807fd8d27b 100644
--- a/core/arch/arm/plat-d06/conf.mk
+++ b/core/arch/arm/plat-d06/conf.mk
@@ -17,6 +17,8 @@ $(call force,CFG_WITH_LPAE,y)
 $(call force,CFG_ARM_GICV3,y)
 $(call force,CFG_LPAE_ADDR_SPACE_BITS,48)
 $(call force,CFG_LPC_UART,y)
+$(call force,CFG_CRYPTO_PBKDF2,y)
+$(call force,CFG_CRYPTO_HW_PBKDF2,y)
 
 CFG_TEE_CORE_LOG_LEVEL ?= 4
 
diff --git a/core/arch/arm/plat-d06/main.c b/core/arch/arm/plat-d06/main.c
index 77369440117e842a2a4b3f3bac9d36beeda8e50b..9b83e75d38a9dfd48eefca3431296bb5a923c431 100644
--- a/core/arch/arm/plat-d06/main.c
+++ b/core/arch/arm/plat-d06/main.c
@@ -11,7 +11,7 @@ static struct lpc_uart_data console_data __nex_bss;
 
 register_phys_mem_pgdir(MEM_AREA_IO_NSEC, LPC_BASE, LPC_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	lpc_uart_init(&console_data, LPC_BASE, CONSOLE_UART_CLK_IN_HZ,
 		      CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-hikey/conf.mk b/core/arch/arm/plat-hikey/conf.mk
index 1fe28b99eaa6a3e01ef8db396ca377f5ae329de8..ac245b17f5b2d22cb26c2eb413411751aeb52b57 100644
--- a/core/arch/arm/plat-hikey/conf.mk
+++ b/core/arch/arm/plat-hikey/conf.mk
@@ -58,6 +58,7 @@ CFG_TZDRAM_SIZE ?= 0x01000000
 CFG_SHMEM_START ?= 0x3EE00000
 CFG_SHMEM_SIZE ?= 0x00200000
 CFG_TEE_RAM_VA_SIZE ?= 0x00200000
+CFG_DRAM1_BASE ?= 0x40000000
 
 CFG_IN_TREE_EARLY_TAS += avb/023f8f1a-292a-432b-8fc4-de8471358067
 
diff --git a/core/arch/arm/plat-hikey/main.c b/core/arch/arm/plat-hikey/main.c
index 239072db5bc86c8c4593a3de3e6b2050994b729d..44707bd6a73394790110d0417a5d7fd3270ad2b8 100644
--- a/core/arch/arm/plat-hikey/main.c
+++ b/core/arch/arm/plat-hikey/main.c
@@ -33,15 +33,15 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC, PMX1_BASE, PMX1_REG_SIZE);
 register_phys_mem_pgdir(MEM_AREA_IO_NSEC, GPIO6_BASE, PL061_REG_SIZE);
 register_phys_mem_pgdir(MEM_AREA_IO_NSEC, SPI_BASE, PL022_REG_SIZE);
 #endif
-register_dynamic_shm(DRAM0_BASE, DRAM0_SIZE_NSEC);
+register_ddr(DRAM0_BASE, DRAM0_SIZE_NSEC);
 #ifdef DRAM1_SIZE_NSEC
-register_dynamic_shm(DRAM1_BASE, DRAM1_SIZE_NSEC);
+register_ddr(DRAM1_BASE, DRAM1_SIZE_NSEC);
 #endif
 #ifdef DRAM2_SIZE_NSEC
-register_dynamic_shm(DRAM2_BASE, DRAM2_SIZE_NSEC);
+register_ddr(DRAM2_BASE, DRAM2_SIZE_NSEC);
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
 		   CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-hikey/platform_config.h b/core/arch/arm/plat-hikey/platform_config.h
index 35e6f3d1a7fa1cc7d01a87cfc11dfe8d9a2e8a39..ff7949fff4b620c3dd85a41bb6550d82e86c7d77 100644
--- a/core/arch/arm/plat-hikey/platform_config.h
+++ b/core/arch/arm/plat-hikey/platform_config.h
@@ -105,9 +105,10 @@
  */
 
 #define DRAM0_BASE		0x00000000
-#define DRAM0_SIZE		0x3F000000
+/* DRAM0 exists below TZDRAM */
+#define DRAM0_SIZE		(CFG_TZDRAM_START - DRAM0_BASE)
 #define DRAM0_SIZE_NSEC		0x3E000000
-#define DRAM1_BASE		0x40000000
+#define DRAM1_BASE		CFG_DRAM1_BASE
 
 #if defined(PLATFORM_FLAVOR_hikey)
 
@@ -130,7 +131,7 @@
 #if (CFG_DRAM_SIZE_GB == 3)
 #define DRAM1_SIZE_NSEC		0x80000000
 #elif (CFG_DRAM_SIZE_GB == 4)
-#define DRAM1_SIZE_NSEC		0xA0000000
+#define DRAM1_SIZE_NSEC		(0xE0000000 - DRAM1_BASE)
 #define DRAM2_BASE		0x200000000
 #define DRAM2_SIZE_NSEC		0x20000000
 #elif (CFG_DRAM_SIZE_GB == 6)
diff --git a/core/arch/arm/plat-hisilicon/main.c b/core/arch/arm/plat-hisilicon/main.c
index 4840b98f2448f7b5b958a447a9d6e071884ec4e6..77b8385cc121c117f573b8275dfeeb71fdfb88b7 100644
--- a/core/arch/arm/plat-hisilicon/main.c
+++ b/core/arch/arm/plat-hisilicon/main.c
@@ -24,7 +24,7 @@ register_phys_mem(MEM_AREA_IO_SEC, CPU_CRG_BASE, CPU_CRG_SIZE);
 register_phys_mem(MEM_AREA_IO_SEC, SYS_CTRL_BASE, SYS_CTRL_SIZE);
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE,
 		CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-imx/conf.mk b/core/arch/arm/plat-imx/conf.mk
index 85bbfe5032a95f8aae2020921a97d2944ca58b27..05a2243fab3cbeeb132232dbb2608aa9fcb4fcb5 100644
--- a/core/arch/arm/plat-imx/conf.mk
+++ b/core/arch/arm/plat-imx/conf.mk
@@ -71,7 +71,8 @@ mx8mn-flavorlist = \
 
 mx8mp-flavorlist = \
 	mx8mpevk \
-	mx8mp_rsb3720_6g
+	mx8mp_rsb3720_6g \
+	mx8mp_phyboard_pollux
 
 mx8qm-flavorlist = \
 	mx8qmmek \
@@ -89,6 +90,12 @@ mx8ulp-flavorlist = \
 mx93-flavorlist = \
 	mx93evk \
 
+mx95-flavorlist = \
+	mx95evk \
+
+mx91-flavorlist = \
+	mx91evk \
+
 ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist)))
 $(call force,CFG_MX6,y)
 $(call force,CFG_MX6UL,y)
@@ -164,24 +171,28 @@ else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mq-flavorlist)))
 $(call force,CFG_MX8MQ,y)
 $(call force,CFG_MX8M,y)
 $(call force,CFG_ARM64_core,y)
+$(call force,CFG_TZC380,y)
 CFG_DRAM_BASE ?= 0x40000000
 CFG_TEE_CORE_NB_CORE ?= 4
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist)))
 $(call force,CFG_MX8MM,y)
 $(call force,CFG_MX8M,y)
 $(call force,CFG_ARM64_core,y)
+$(call force,CFG_TZC380,y)
 CFG_DRAM_BASE ?= 0x40000000
 CFG_TEE_CORE_NB_CORE ?= 4
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mn-flavorlist)))
 $(call force,CFG_MX8MN,y)
 $(call force,CFG_MX8M,y)
 $(call force,CFG_ARM64_core,y)
+$(call force,CFG_TZC380,y)
 CFG_DRAM_BASE ?= 0x40000000
 CFG_TEE_CORE_NB_CORE ?= 4
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mp-flavorlist)))
 $(call force,CFG_MX8MP,y)
 $(call force,CFG_MX8M,y)
 $(call force,CFG_ARM64_core,y)
+$(call force,CFG_TZC380,y)
 CFG_DRAM_BASE ?= 0x40000000
 CFG_TEE_CORE_NB_CORE ?= 4
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist)))
@@ -231,6 +242,28 @@ $(call force,CFG_CRYPTO_DRIVER,n)
 $(call force,CFG_NXP_CAAM,n)
 CFG_IMX_MU ?= y
 CFG_IMX_ELE ?= n
+else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx95-flavorlist)))
+$(call force,CFG_MX95,y)
+$(call force,CFG_ARM64_core,y)
+CFG_IMX_LPUART ?= y
+CFG_DRAM_BASE ?= 0x80000000
+CFG_TEE_CORE_NB_CORE ?= 6
+$(call force,CFG_NXP_SNVS,n)
+$(call force,CFG_IMX_OCOTP,n)
+$(call force,CFG_TZC380,n)
+$(call force,CFG_NXP_CAAM,n)
+else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx91-flavorlist)))
+$(call force,CFG_MX91,y)
+$(call force,CFG_ARM64_core,y)
+CFG_IMX_LPUART ?= y
+CFG_DRAM_BASE ?= 0x80000000
+CFG_TEE_CORE_NB_CORE ?= 1
+$(call force,CFG_NXP_SNVS,n)
+$(call force,CFG_IMX_OCOTP,n)
+$(call force,CFG_TZC380,n)
+$(call force,CFG_NXP_CAAM,n)
+CFG_IMX_MU ?= y
+CFG_IMX_ELE ?= n
 else
 $(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)")
 endif
@@ -383,6 +416,13 @@ $(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
 $(call force,CFG_CORE_ARM64_PA_BITS,36)
 endif
 
+ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mp_phyboard_pollux))
+CFG_DDR_SIZE ?= 0x80000000
+CFG_UART_BASE ?= UART1_BASE
+$(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
+$(call force,CFG_CORE_ARM64_PA_BITS,36)
+endif
+
 ifneq (,$(filter $(PLATFORM_FLAVOR),mx8mp_rsb3720_6g))
 CFG_DDR_SIZE ?= UL(0x180000000)
 CFG_UART_BASE ?= UART3_BASE
@@ -418,9 +458,17 @@ CFG_DDR_SIZE ?= 0x80000000
 CFG_UART_BASE ?= UART5_BASE
 endif
 
-ifneq (,$(filter $(PLATFORM_FLAVOR),mx93evk))
+ifneq (,$(filter $(PLATFORM_FLAVOR),mx93evk mx91evk))
+CFG_DDR_SIZE ?= 0x80000000
+CFG_UART_BASE ?= UART1_BASE
+endif
+
+ifneq (,$(filter $(PLATFORM_FLAVOR),mx95evk))
 CFG_DDR_SIZE ?= 0x80000000
 CFG_UART_BASE ?= UART1_BASE
+CFG_NSEC_DDR_1_BASE ?= 0x100000000UL
+CFG_NSEC_DDR_1_SIZE ?= 0x380000000UL
+CFG_CORE_ARM64_PA_BITS ?= 40
 endif
 
 # i.MX6 Solo/SL/SoloX/DualLite/Dual/Quad specific config
@@ -502,6 +550,7 @@ CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE))
 
 # Enable embedded tests by default
 CFG_ENABLE_EMBEDDED_TESTS ?= y
+CFG_ATTESTATION_PTA ?= y
 
 # Set default heap size for imx platforms to 128k
 CFG_CORE_HEAP_SIZE ?= 131072
@@ -516,6 +565,7 @@ endif
 CFG_IMX_OCOTP ?= y
 CFG_IMX_DIGPROG ?= y
 CFG_PKCS11_TA ?= y
+CFG_CORE_HUK_SUBKEY_COMPAT_USE_OTP_DIE_ID ?= y
 
 # Almost all platforms include CAAM HW Modules, except the
 # ones forced to be disabled
@@ -534,4 +584,3 @@ CFG_IMX_CAAM ?= y
 endif
 
 endif
-
diff --git a/core/arch/arm/plat-imx/imx-common.c b/core/arch/arm/plat-imx/imx-common.c
index 7339137b3e668f32f68638accfb0e475de2271cd..42a6d76043b4bed594225a81a1ef87f25a1f942c 100644
--- a/core/arch/arm/plat-imx/imx-common.c
+++ b/core/arch/arm/plat-imx/imx-common.c
@@ -68,6 +68,10 @@ uint32_t imx_get_digprog(void)
 		imx_digprog = SOC_MX8ULP << 16;
 	else if (IS_ENABLED(CFG_MX93))
 		imx_digprog = SOC_MX93 << 16;
+	else if (IS_ENABLED(CFG_MX91))
+		imx_digprog = SOC_MX91 << 16;
+	else if (IS_ENABLED(CFG_MX95))
+		imx_digprog = SOC_MX95 << 16;
 
 	return imx_digprog;
 }
diff --git a/core/arch/arm/plat-imx/imx-regs.h b/core/arch/arm/plat-imx/imx-regs.h
index f8462867c5fa0b971aa4abb0b8541c1a07dbbbf1..7751b770544c6a4d3c528721097706fc360aa7e1 100644
--- a/core/arch/arm/plat-imx/imx-regs.h
+++ b/core/arch/arm/plat-imx/imx-regs.h
@@ -43,8 +43,10 @@
 #include <registers/imx8q.h>
 #elif defined(CFG_MX8ULP)
 #include <registers/imx8ulp.h>
-#elif defined(CFG_MX93)
+#elif defined(CFG_MX93) || defined(CFG_MX91)
 #include <registers/imx93.h>
+#elif defined(CFG_MX95)
+#include <registers/imx95.h>
 #else
 #error "CFG_MX* not defined"
 #endif
diff --git a/core/arch/arm/plat-imx/imx.h b/core/arch/arm/plat-imx/imx.h
index dfdee0b3cf98df4103fa7f76b277a410d4b72006..4a66422fb5c0a0aedcc5492d0089322255dc67d0 100644
--- a/core/arch/arm/plat-imx/imx.h
+++ b/core/arch/arm/plat-imx/imx.h
@@ -26,6 +26,8 @@
 #define SOC_MX8M	0x82
 #define SOC_MX8ULP	0x83
 #define SOC_MX93	0xC1
+#define SOC_MX95        0x1C1
+#define SOC_MX91        0xCB
 
 #ifndef __ASSEMBLER__
 bool soc_is_imx6(void);
diff --git a/core/arch/arm/plat-imx/main.c b/core/arch/arm/plat-imx/main.c
index 9ae1c7ce53181f7f2e0ed2ebecba079f95b04ea4..07b01f76519ac90ec88ff0f4c4031fc7b127f8c1 100644
--- a/core/arch/arm/plat-imx/main.c
+++ b/core/arch/arm/plat-imx/main.c
@@ -97,7 +97,7 @@ register_ddr(CFG_DRAM_BASE, CFG_DDR_SIZE);
 register_ddr(CFG_NSEC_DDR_1_BASE, CFG_NSEC_DDR_1_SIZE);
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 #ifdef CONSOLE_UART_BASE
 	imx_uart_init(&console_data, CONSOLE_UART_BASE);
diff --git a/core/arch/arm/plat-imx/registers/imx95.h b/core/arch/arm/plat-imx/registers/imx95.h
new file mode 100644
index 0000000000000000000000000000000000000000..30072e7fe4eec23d1dea1753f64bdea068169bb8
--- /dev/null
+++ b/core/arch/arm/plat-imx/registers/imx95.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2024 NXP
+ */
+#ifndef __IMX95_H__
+#define __IMX95_H__
+
+#define GICD_BASE 0x48000000
+#define GICR_BASE 0x48060000
+
+#define UART1_BASE 0x44380000
+
+#endif /* __IMX95_H__ */
diff --git a/core/arch/arm/plat-k3/conf.mk b/core/arch/arm/plat-k3/conf.mk
index 2fd235e22fb63c866dfcf6d394cf6ef3df6da1d2..170bd40370ab13462a491ae278a176f0da962ab0 100644
--- a/core/arch/arm/plat-k3/conf.mk
+++ b/core/arch/arm/plat-k3/conf.mk
@@ -1,6 +1,7 @@
 CFG_WITH_STATS ?= y
 CFG_CRYPTO_WITH_CE ?= y
 CFG_CONSOLE_UART ?= 0
+CFG_WITH_SOFTWARE_PRNG ?= n
 
 CFG_TZDRAM_START ?= 0x9e800000
 CFG_TZDRAM_SIZE ?= 0x01400000 # 20MB
@@ -22,12 +23,6 @@ ifneq (,$(filter ${PLATFORM_FLAVOR},am65x))
 $(call force,CFG_CORE_CLUSTER_SHIFT,1)
 endif
 
-ifneq (,$(filter ${PLATFORM_FLAVOR},am65x j721e j784s4 am64x am62x))
-CFG_WITH_SOFTWARE_PRNG ?= n
-else
-$(call force,CFG_WITH_SOFTWARE_PRNG,y)
-endif
-
 ifneq ($(CFG_WITH_SOFTWARE_PRNG),y)
 $(call force,CFG_SA2UL,y)
 CFG_HWRNG_QUALITY ?= 1024
diff --git a/core/arch/arm/plat-k3/drivers/sa2ul.c b/core/arch/arm/plat-k3/drivers/sa2ul.c
index e11423ef33c03a3a8b6f48befd0fc9acbb5cbc3d..df868ab69c7ffa5a4aadce058a000530ba0f4c39 100644
--- a/core/arch/arm/plat-k3/drivers/sa2ul.c
+++ b/core/arch/arm/plat-k3/drivers/sa2ul.c
@@ -150,4 +150,4 @@ static TEE_Result sa2ul_init(void)
 
 	return TEE_SUCCESS;
 }
-driver_init(sa2ul_init);
+service_init_crypto(sa2ul_init);
diff --git a/core/arch/arm/plat-k3/drivers/sec_proxy.c b/core/arch/arm/plat-k3/drivers/sec_proxy.c
index 3961d7264718415952b44663a789f45883cea0ac..152fb5e19a2ab2e8eb1e99011158c2aaa16180b3 100644
--- a/core/arch/arm/plat-k3/drivers/sec_proxy.c
+++ b/core/arch/arm/plat-k3/drivers/sec_proxy.c
@@ -213,7 +213,7 @@ TEE_Result k3_sec_proxy_recv(struct k3_sec_proxy_msg *msg)
 
 		i = msg->len - trail_bytes;
 		while (trail_bytes--) {
-			msg->buf[i] = data_trail & 0xff;
+			msg->buf[i++] = data_trail & 0xff;
 			data_trail >>= 8;
 		}
 	}
diff --git a/core/arch/arm/plat-k3/drivers/ti_sci.c b/core/arch/arm/plat-k3/drivers/ti_sci.c
index 9d7c7dcb40a9b3298a2ae6e8545e939c79e50839..2d98f177e8a45176d3fa59166d57b691fc8ac651 100644
--- a/core/arch/arm/plat-k3/drivers/ti_sci.c
+++ b/core/arch/arm/plat-k3/drivers/ti_sci.c
@@ -8,6 +8,7 @@
  */
 
 #include <assert.h>
+#include <kernel/mutex.h>
 #include <malloc.h>
 #include <platform_config.h>
 #include <string.h>
@@ -19,7 +20,6 @@
 #include "ti_sci.h"
 #include "ti_sci_protocol.h"
 
-static uint8_t message_sequence;
 
 /**
  * struct ti_sci_xfer - Structure representing a message flow
@@ -66,7 +66,6 @@ static int ti_sci_setup_xfer(uint16_t msg_type, uint32_t msg_flags,
 	}
 
 	hdr = (struct ti_sci_msg_hdr *)tx_buf;
-	hdr->seq = ++message_sequence;
 	hdr->type = msg_type;
 	hdr->host = OPTEE_HOST_ID;
 	hdr->flags = msg_flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED;
@@ -81,77 +80,72 @@ static int ti_sci_setup_xfer(uint16_t msg_type, uint32_t msg_flags,
 }
 
 /**
- * ti_sci_get_response() - Receive response from mailbox channel
+ * ti_sci_do_xfer() - Do one transfer
  *
- * @xfer:	Transfer to initiate and wait for response
+ * @xfer: Transfer to initiate and wait for response
  *
  * Return: 0 if all goes well, else appropriate error message
  */
-static inline int ti_sci_get_response(struct ti_sci_xfer *xfer)
+static int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
 {
-	struct k3_sec_proxy_msg *msg = &xfer->rx_message;
-	struct ti_sci_msg_hdr *hdr = NULL;
+	struct k3_sec_proxy_msg *txmsg = &xfer->tx_message;
+	struct k3_sec_proxy_msg *rxmsg = &xfer->rx_message;
+	struct ti_sci_msg_hdr *txhdr = (struct ti_sci_msg_hdr *)txmsg->buf;
+	struct ti_sci_msg_hdr *rxhdr = (struct ti_sci_msg_hdr *)rxmsg->buf;
+	static uint8_t message_sequence;
+	static struct mutex ti_sci_mutex_lock = MUTEX_INITIALIZER;
 	unsigned int retry = 5;
 	int ret = 0;
 
+	mutex_lock(&ti_sci_mutex_lock);
+
+	message_sequence++;
+	txhdr->seq = message_sequence;
+
+	/* Send the message */
+	ret = k3_sec_proxy_send(txmsg);
+	if (ret) {
+		EMSG("Message sending failed (%d)", ret);
+		goto unlock;
+	}
+
+	FMSG("Sending %"PRIx16" with seq %"PRIu8" host %"PRIu8,
+	     txhdr->type, txhdr->seq, txhdr->host);
+
+	/* Get the response */
 	for (; retry > 0; retry--) {
 		/* Receive the response */
-		ret = k3_sec_proxy_recv(msg);
+		ret = k3_sec_proxy_recv(rxmsg);
 		if (ret) {
 			EMSG("Message receive failed (%d)", ret);
-			return ret;
+			goto unlock;
 		}
 
-		/* msg is updated by Secure Proxy driver */
-		hdr = (struct ti_sci_msg_hdr *)msg->buf;
-
 		/* Sanity check for message response */
-		if (hdr->seq == message_sequence)
+		if (rxhdr->seq == message_sequence)
 			break;
 
-		IMSG("Message with sequence ID %u is not expected", hdr->seq);
+		IMSG("Message with sequence ID %"PRIu8" is not expected",
+		     rxhdr->seq);
 	}
 	if (!retry) {
 		EMSG("Timed out waiting for message");
-		return TEE_ERROR_BUSY;
+		ret = TEE_ERROR_BUSY;
+		goto unlock;
 	}
 
-	if (!(hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) {
+	if (!(rxhdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK)) {
 		DMSG("Message not acknowledged");
-		return TEE_ERROR_ACCESS_DENIED;
-	}
-
-	return 0;
-}
-
-/**
- * ti_sci_do_xfer() - Do one transfer
- *
- * @xfer: Transfer to initiate and wait for response
- *
- * Return: 0 if all goes well, else appropriate error message
- */
-static inline int ti_sci_do_xfer(struct ti_sci_xfer *xfer)
-{
-	struct k3_sec_proxy_msg *msg = &xfer->tx_message;
-	int ret = 0;
-
-	/* Send the message */
-	ret = k3_sec_proxy_send(msg);
-	if (ret) {
-		EMSG("Message sending failed (%d)", ret);
-		return ret;
+		ret = TEE_ERROR_ACCESS_DENIED;
+		goto unlock;
 	}
 
-	/* Get the response */
-	ret = ti_sci_get_response(xfer);
-	if (ret) {
-		if ((TEE_Result)ret != TEE_ERROR_ACCESS_DENIED)
-			EMSG("Failed to get response (%d)", ret);
-		return ret;
-	}
+	FMSG("Receive %"PRIx16" with seq %"PRIu8" host %"PRIu8,
+	     rxhdr->type, rxhdr->seq, rxhdr->host);
 
-	return 0;
+unlock:
+	mutex_unlock(&ti_sci_mutex_lock);
+	return ret;
 }
 
 int ti_sci_get_revision(struct ti_sci_msg_resp_version *rev_info)
diff --git a/core/arch/arm/plat-k3/main.c b/core/arch/arm/plat-k3/main.c
index e029554412f422a166c809b9f725a8c03b51e487..50c1fba0d58526a68ccb48b35b995d7e871d1eab 100644
--- a/core/arch/arm/plat-k3/main.c
+++ b/core/arch/arm/plat-k3/main.c
@@ -42,7 +42,7 @@ void boot_secondary_init_intc(void)
 	gic_init_per_cpu();
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
@@ -64,7 +64,13 @@ static TEE_Result init_ti_sci(void)
 	return TEE_SUCCESS;
 }
 
-service_init(init_ti_sci);
+/*
+ * TISCI services are required for initialization of TRNG service that gets
+ * initialized during service_init_crypto.
+ *
+ * Initialize TISCI service just before service_init_crypto.
+ */
+early_init_late(init_ti_sci);
 
 static TEE_Result secure_boot_information(void)
 {
diff --git a/core/arch/arm/plat-ls/conf.mk b/core/arch/arm/plat-ls/conf.mk
index 8402e6249638b446a83dc3c29c887b8521acf05d..ae77a277cf04804c44c2e81d8f4c9ce1fc15c4d0 100644
--- a/core/arch/arm/plat-ls/conf.mk
+++ b/core/arch/arm/plat-ls/conf.mk
@@ -65,7 +65,7 @@ $(call force,CFG_DRAM1_SIZE,0x1F80000000)
 $(call force,CFG_CORE_CLUSTER_SHIFT,1)
 $(call force,CFG_ARM_GICV3,y)
 $(call force,CFG_PL011,y)
-$(call force,CFG_CORE_ARM64_PA_BITS,48)
+$(call force,CFG_CORE_ARM64_PA_BITS,40)
 $(call force,CFG_EMBED_DTB,y)
 $(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-qds.dts)
 CFG_LS_I2C ?= y
@@ -83,7 +83,7 @@ $(call force,CFG_DRAM1_SIZE,0x1F80000000)
 $(call force,CFG_CORE_CLUSTER_SHIFT,1)
 $(call force,CFG_ARM_GICV3,y)
 $(call force,CFG_PL011,y)
-$(call force,CFG_CORE_ARM64_PA_BITS,48)
+$(call force,CFG_CORE_ARM64_PA_BITS,40)
 $(call force,CFG_EMBED_DTB,y)
 $(call force,CFG_EMBED_DTB_SOURCE_FILE,fsl-lx2160a-rdb.dts)
 CFG_LS_I2C ?= y
diff --git a/core/arch/arm/plat-ls/main.c b/core/arch/arm/plat-ls/main.c
index 8358bc133649722efc0503d4ed2103617a7b2dc1..7e013f9c2382654cc2c5fb9ed52bbdf78f3b6a1a 100644
--- a/core/arch/arm/plat-ls/main.c
+++ b/core/arch/arm/plat-ls/main.c
@@ -112,7 +112,7 @@ void plat_primary_init_early(void)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 #ifdef CFG_PL011
 	/*
@@ -141,23 +141,16 @@ static TEE_Result get_gic_base_addr_from_dt(paddr_t *gic_addr)
 		gic_offset = fdt_path_offset(fdt,
 					     "/interrupt-controller@6000000");
 
-	if (gic_offset > 0) {
-		paddr = fdt_reg_base_address(fdt, gic_offset);
-		if (paddr == DT_INFO_INVALID_REG) {
-			EMSG("GIC: Unable to get base addr from DT");
-			return TEE_ERROR_ITEM_NOT_FOUND;
-		}
-
-		size = fdt_reg_size(fdt, gic_offset);
-		if (size == DT_INFO_INVALID_REG_SIZE) {
-			EMSG("GIC: Unable to get size of base addr from DT");
-			return TEE_ERROR_ITEM_NOT_FOUND;
-		}
-	} else {
+	if (gic_offset < 0) {
 		EMSG("Unable to get gic offset node");
 		return TEE_ERROR_ITEM_NOT_FOUND;
 	}
 
+	if (fdt_reg_info(fdt, gic_offset, &paddr, &size)) {
+		EMSG("GIC: Unable to get base addr or size from DT");
+		return TEE_ERROR_ITEM_NOT_FOUND;
+	}
+
 	/* make entry in page table */
 	if (!core_mmu_add_mapping(MEM_AREA_IO_SEC, paddr, size)) {
 		EMSG("GIC controller base MMU PA mapping failure");
diff --git a/core/arch/arm/plat-marvell/main.c b/core/arch/arm/plat-marvell/main.c
index a299b21cb3e4f22894963ae60835d292abf2c982..1075c0260418d86368a18332f40ddfea59c589e0 100644
--- a/core/arch/arm/plat-marvell/main.c
+++ b/core/arch/arm/plat-marvell/main.c
@@ -85,7 +85,7 @@ void boot_primary_init_intc(void)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 #if defined(PLATFORM_FLAVOR_armada7k8k)
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
diff --git a/core/arch/arm/plat-mediatek/conf.mk b/core/arch/arm/plat-mediatek/conf.mk
index ed15acb8c88d4e6d16d5003c82140dbc91dc29ae..bd83bdc9be70d87e9e8c06513f8ff3d36c75d979 100644
--- a/core/arch/arm/plat-mediatek/conf.mk
+++ b/core/arch/arm/plat-mediatek/conf.mk
@@ -14,6 +14,10 @@ CFG_DRAM_BASE ?= 0x40000000
 # default DRAM size 1 GiB
 CFG_DRAM_SIZE ?= 0x40000000
 
+# When need to create a virtual memory pool for mapping other
+# physical address, enable the config to increase MAX_XLAT_TABLES.
+CFG_MTK_RESERVED_VA ?= n
+
 ifeq ($(PLATFORM_FLAVOR),mt8173)
 # 2**1 = 2 cores per cluster
 $(call force,CFG_TEE_CORE_NB_CORE,4)
@@ -78,3 +82,15 @@ CFG_TZDRAM_SIZE ?=  0x00a00000
 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE))
 CFG_SHMEM_SIZE ?= 0x00200000
 endif
+
+ifeq ($(PLATFORM_FLAVOR),mt7988)
+$(call force,CFG_TEE_CORE_NB_CORE,4)
+$(call force,CFG_CORE_CLUSTER_SHIFT,1)
+$(call force,CFG_ARM_GICV3,y)
+$(call force,CFG_GIC,y)
+$(call force,CFG_WITH_SOFTWARE_PRNG,y)
+CFG_TZDRAM_START ?= 0x43041000
+CFG_TZDRAM_SIZE ?=  0x04ff000
+CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE))
+CFG_SHMEM_SIZE ?= 0x00200000
+endif
diff --git a/core/arch/arm/plat-mediatek/main.c b/core/arch/arm/plat-mediatek/main.c
index de7e06344fbef635e0659c5952f5f64d8b83dbb1..4d84e3242bcbbfba85ccc527fbf8f264ac296158 100644
--- a/core/arch/arm/plat-mediatek/main.c
+++ b/core/arch/arm/plat-mediatek/main.c
@@ -33,7 +33,7 @@ void boot_primary_init_intc(void)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	if (CFG_TEE_CORE_LOG_LEVEL != 0) {
 		serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
diff --git a/core/arch/arm/plat-mediatek/platform_config.h b/core/arch/arm/plat-mediatek/platform_config.h
index 17e070568f04b5b3c020ec411d0f1f2f5cc31d81..c85b0d0b7223509d6b6a0f86f7f5a37013748f4b 100644
--- a/core/arch/arm/plat-mediatek/platform_config.h
+++ b/core/arch/arm/plat-mediatek/platform_config.h
@@ -105,12 +105,27 @@
 #define CONSOLE_BAUDRATE	115200
 #define CONSOLE_UART_CLK_IN_HZ	26000000
 
+#elif defined(PLATFORM_FLAVOR_mt7988)
+
+#define GIC_BASE		0x0C000000
+#define GICC_OFFSET		0x400000
+#define GICD_OFFSET		0x000000
+
+#define UART0_BASE		0x11000000
+#define UART1_BASE		0x11000100
+#define UART2_BASE		0x11000200
+
+#define CONSOLE_UART_BASE	UART0_BASE
+#define CONSOLE_BAUDRATE	115200
+#define CONSOLE_UART_CLK_IN_HZ	40000000
+
 #else
 #error "Unknown platform flavor"
 #endif
 
-#ifdef CFG_WITH_LPAE
-#define MAX_XLAT_TABLES		5
+#ifdef CFG_MTK_RESERVED_VA
+#define MAX_XLAT_TABLES		(30 + (CFG_RESERVED_VASPACE_SIZE) / \
+				 (CORE_MMU_PGDIR_SIZE) + 1)
 #endif
 
 #endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-nuvoton/main.c b/core/arch/arm/plat-nuvoton/main.c
index 88db73db1d49f314cf5602e4eca92fed1535c2d6..c5ca4075e7d7f812a4f599af0be2149917f2b986 100644
--- a/core/arch/arm/plat-nuvoton/main.c
+++ b/core/arch/arm/plat-nuvoton/main.c
@@ -60,7 +60,7 @@ void boot_primary_init_intc(void)
 	gic_init(GICC_BASE, GICD_BASE);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-poplar/main.c b/core/arch/arm/plat-poplar/main.c
index ec244ceb53fd08105c8f47076ce12a4067e08764..a97b6c8b32654a7921f002f2fadbafafdae5dd9b 100644
--- a/core/arch/arm/plat-poplar/main.c
+++ b/core/arch/arm/plat-poplar/main.c
@@ -20,7 +20,7 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
 /* for dynamic shared memory */
 register_dynamic_shm(DRAM0_BASE_NSEC, DRAM0_SIZE_NSEC);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE,
 		CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-rcar/conf.mk b/core/arch/arm/plat-rcar/conf.mk
index c810dfeb8385025a0f24eea44370bd1282d3e81f..451df5c0ecfc03c236990fb380a91fdacf7658f8 100644
--- a/core/arch/arm/plat-rcar/conf.mk
+++ b/core/arch/arm/plat-rcar/conf.mk
@@ -37,6 +37,7 @@ endif
 ifeq ($(CFG_RCAR_GEN4), y)
 # 1xx - for SCIFxx
 # 2xx - for HSCIFxx
+CFG_TZDRAM_SIZE	= 0x2200000
 CFG_RCAR_UART ?= 200
 $(call force,CFG_RCAR_ROMAPI, n)
 $(call force,CFG_CORE_CLUSTER_SHIFT, 1)
diff --git a/core/arch/arm/plat-rcar/main.c b/core/arch/arm/plat-rcar/main.c
index 452e05e97091217977934ea1afb660a7706f0257..122ad9b9707efcc34f67ebfacfa93682cb3f24b1 100644
--- a/core/arch/arm/plat-rcar/main.c
+++ b/core/arch/arm/plat-rcar/main.c
@@ -65,7 +65,7 @@ static struct scif_uart_data console_data __nex_bss;
 uint32_t rcar_prr_value __nex_bss;
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	scif_uart_init(&console_data, CONSOLE_UART_BASE);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-rd1ae/conf.mk b/core/arch/arm/plat-rd1ae/conf.mk
new file mode 100644
index 0000000000000000000000000000000000000000..d9fb7c2d10d118d0dcf7d698357c46456f7275b7
--- /dev/null
+++ b/core/arch/arm/plat-rd1ae/conf.mk
@@ -0,0 +1,27 @@
+# RD-1 AE is based on Neoverse V3AE CPU, but there is
+# no compiler support for it yet. Use Neoverse V2 until
+# it becomes available.
+include core/arch/arm/cpu/neoverse-v2.mk
+
+# ARM debugger needs this
+platform-cflags-debug-info = -gdwarf-4
+platform-aflags-debug-info = -gdwarf-4
+
+$(call force,CFG_ARM64_core,y)
+
+$(call force,CFG_ARM_GICV3,y)
+
+CFG_CORE_SEL1_SPMC      ?= y
+CFG_WITH_ARM_TRUSTED_FW	?= y
+CFG_CORE_RESERVED_SHM   ?= n
+
+$(call force,CFG_GIC,y)
+$(call force,CFG_PL011,y)
+$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
+$(call force,CFG_CORE_ARM64_PA_BITS,42)
+$(call force,CFG_TEE_CORE_NB_CORE,16)
+
+CFG_CORE_HEAP_SIZE ?= 0x32000
+
+CFG_TZDRAM_START ?= 0xFFC00000
+CFG_TZDRAM_SIZE  ?= 0x00400000
diff --git a/core/arch/arm/plat-rd1ae/main.c b/core/arch/arm/plat-rd1ae/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..71b123d9d45511f9a40bad8af322a3b177c91d96
--- /dev/null
+++ b/core/arch/arm/plat-rd1ae/main.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Arm Limited
+ */
+
+#include <console.h>
+#include <drivers/gic.h>
+#include <drivers/pl011.h>
+#include <kernel/boot.h>
+#include <mm/core_mmu.h>
+#include <platform_config.h>
+#include <stdint.h>
+#include <trace.h>
+
+static struct pl011_data console_data __nex_bss;
+
+register_ddr(DRAM0_BASE, DRAM0_SIZE);
+register_ddr(DRAM1_BASE, DRAM1_SIZE);
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICC_BASE, GIC_CPU_REG_SIZE);
+
+void boot_primary_init_intc(void)
+{
+	gic_init(GICC_BASE, GICD_BASE);
+}
+
+void boot_secondary_init_intc(void)
+{
+	gic_init_per_cpu();
+}
+
+void plat_console_init(void)
+{
+	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
+		   CONSOLE_BAUDRATE);
+	register_serial_console(&console_data.chip);
+}
diff --git a/core/arch/arm/plat-rd1ae/platform_config.h b/core/arch/arm/plat-rd1ae/platform_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b074bdb77771f81e43578127dfad4cadfc3d7f6
--- /dev/null
+++ b/core/arch/arm/plat-rd1ae/platform_config.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Arm Limited
+ */
+
+#ifndef PLATFORM_CONFIG_H
+#define PLATFORM_CONFIG_H
+
+#include <mm/generic_ram_layout.h>
+
+/* Make stacks aligned to data cache line length */
+#define STACK_ALIGNMENT			64
+
+#define DRAM0_BASE			UL(0x80000000)
+#define DRAM0_SIZE			UL(0x80000000)
+
+#define DRAM1_BASE			ULL(0x8080000000)
+#define DRAM1_SIZE			ULL(0x80000000)
+
+#define SYS_COUNTER_FREQ_IN_TICKS	UL(7372800)
+
+#define UART0_BASE			UL(0x2A400000)
+#define UART1_BASE			UL(0x2A410000)
+#define CONSOLE_UART_BASE		UART1_BASE
+#define UART_BAUDRATE			115200
+#define CONSOLE_BAUDRATE		UART_BAUDRATE
+#define CONSOLE_UART_CLK_IN_HZ		UL(7372800)
+
+/* GIC related constants */
+#define GICD_BASE			UL(0x30000000)
+#define GICC_BASE			UL(0x2C000000)
+
+ /* RD-1 AE topology related constants */
+#define RD1AE_MAX_CPUS_PER_CLUSTER	U(1)
+#define PLAT_ARM_CLUSTER_COUNT		U(1)
+#define PLAT_RD1AE_CHIP_COUNT		U(1)
+#define RD1AE_MAX_CLUSTERS_PER_CHIP	U(16)
+#define RD1AE_MAX_PE_PER_CPU		U(1)
+
+#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-rd1ae/rd1ae_core_pos.S b/core/arch/arm/plat-rd1ae/rd1ae_core_pos.S
new file mode 100644
index 0000000000000000000000000000000000000000..ecb73feabfca33f9494af68910502cbfb8e9f1ab
--- /dev/null
+++ b/core/arch/arm/plat-rd1ae/rd1ae_core_pos.S
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Arm Limited
+ */
+
+#include <asm.S>
+#include <arm.h>
+#include "platform_config.h"
+
+FUNC get_core_pos_mpidr , :
+        mov     x4, x0
+
+        /*
+         * The MT bit in MPIDR is always set for n1sdp and the
+         * affinity level 0 corresponds to thread affinity level.
+         */
+
+        /* Extract individual affinity fields from MPIDR */
+        ubfx    x0, x4, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+        ubfx    x1, x4, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+        ubfx    x2, x4, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+        ubfx    x3, x4, #MPIDR_AFF3_SHIFT, #MPIDR_AFFINITY_BITS
+
+        /* Compute linear position */
+        mov     x4, #RD1AE_MAX_CLUSTERS_PER_CHIP
+        madd    x2, x3, x4, x2
+        mov     x4, #RD1AE_MAX_CPUS_PER_CLUSTER
+        madd    x1, x2, x4, x1
+        mov     x4, #RD1AE_MAX_PE_PER_CPU
+        madd    x0, x1, x4, x0
+        ret
+END_FUNC get_core_pos_mpidr
diff --git a/core/arch/arm/plat-rd1ae/sub.mk b/core/arch/arm/plat-rd1ae/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..02fff3592caa111e605ce8519e9b6472af27c155
--- /dev/null
+++ b/core/arch/arm/plat-rd1ae/sub.mk
@@ -0,0 +1,3 @@
+global-incdirs-y += .
+srcs-y += main.c
+srcs-y	+= rd1ae_core_pos.S
diff --git a/core/arch/arm/plat-rockchip/conf.mk b/core/arch/arm/plat-rockchip/conf.mk
index e8e9f4c66f0d58a88bb54d5493c3cb6fdc970f1c..3ab8448595441974a74742f3324d196afcaffc93 100644
--- a/core/arch/arm/plat-rockchip/conf.mk
+++ b/core/arch/arm/plat-rockchip/conf.mk
@@ -56,6 +56,24 @@ CFG_SHMEM_SIZE   ?= 0x00400000
 CFG_EARLY_CONSOLE ?= n
 endif
 
+ifeq ($(PLATFORM_FLAVOR),rk3588)
+include core/arch/arm/cpu/cortex-armv8-0.mk
+$(call force,CFG_TEE_CORE_NB_CORE,8)
+$(call force,CFG_ARM_GICV3,y)
+$(call force,CFG_CRYPTO_WITH_CE,y)
+
+CFG_TZDRAM_START ?= 0x08400000
+CFG_TZDRAM_SIZE ?= 0x02000000
+CFG_SHMEM_START ?= 0x0a4000000
+CFG_SHMEM_SIZE ?= 0x00400000
+
+CFG_EARLY_CONSOLE ?= y
+CFG_EARLY_CONSOLE_BASE ?= UART2_BASE
+CFG_EARLY_CONSOLE_SIZE ?= UART2_SIZE
+CFG_EARLY_CONSOLE_BAUDRATE ?= 1500000
+CFG_EARLY_CONSOLE_CLK_IN_HZ ?= 24000000
+endif
+
 ifeq ($(platform-flavor-armv8),1)
 $(call force,CFG_ARM64_core,y)
 $(call force,CFG_WITH_ARM_TRUSTED_FW,y)
diff --git a/core/arch/arm/plat-rockchip/main.c b/core/arch/arm/plat-rockchip/main.c
index a85900fa31434c7a39f93878b62e7aee9d6e5c93..03112f6bad3f5379f3316570c0176727d1471fd0 100644
--- a/core/arch/arm/plat-rockchip/main.c
+++ b/core/arch/arm/plat-rockchip/main.c
@@ -20,6 +20,13 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC,
 			CFG_EARLY_CONSOLE_BASE, CFG_EARLY_CONSOLE_SIZE);
 #endif
 
+#ifdef CFG_DRAM_BASE
+register_ddr(CFG_DRAM_BASE, CFG_DRAM_SIZE);
+#endif
+#ifdef CFG_NSEC_DDR_1_BASE
+register_ddr(CFG_NSEC_DDR_1_BASE, CFG_NSEC_DDR_1_SIZE);
+#endif
+
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, GIC_SIZE);
 
 void boot_primary_init_intc(void)
@@ -32,7 +39,7 @@ void boot_secondary_init_intc(void)
 	gic_init_per_cpu();
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 #if defined(CFG_EARLY_CONSOLE)
 	/*
diff --git a/core/arch/arm/plat-rockchip/platform_config.h b/core/arch/arm/plat-rockchip/platform_config.h
index 31439e29b068af6445e94ecae6692e74e3f44814..990c8875e50f6db4c37482d8d3674047a274874f 100644
--- a/core/arch/arm/plat-rockchip/platform_config.h
+++ b/core/arch/arm/plat-rockchip/platform_config.h
@@ -1,7 +1,8 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
  * Copyright (C) 2017, Fuzhou Rockchip Electronics Co., Ltd.
  * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
  */
 
 #ifndef PLATFORM_CONFIG_H
@@ -85,6 +86,35 @@
 #define FIREWALL_DDR_BASE	0xff534000
 #define FIREWALL_DDR_SIZE	SIZE_K(16)
 
+#elif defined(PLATFORM_FLAVOR_rk3588)
+
+#define GIC_BASE		0xfe600000
+#define GIC_SIZE		SIZE_K(64)
+#define GICC_BASE		0
+#define GICD_BASE		GIC_BASE
+#define GICR_BASE		(GIC_BASE + 0x80000)
+
+#define UART0_BASE		0xfd890000
+#define UART0_SIZE		SIZE_K(64)
+
+#define UART1_BASE		0xfeb40000
+#define UART1_SIZE		SIZE_K(64)
+
+#define UART2_BASE		0xfeb50000
+#define UART2_SIZE		SIZE_K(64)
+
+#define UART3_BASE		0xfeb60000
+#define UART3_SIZE		SIZE_K(64)
+
+#define FIREWALL_DDR_BASE	0xfe030000
+#define FIREWALL_DDR_SIZE	SIZE_K(32)
+
+#define FIREWALL_DSU_BASE	0xfe010000
+#define FIREWALL_DSU_SIZE	SIZE_K(32)
+
+#define TRNG_S_BASE		0xfe398000
+#define TRNG_S_SIZE		SIZE_K(32)
+
 #else
 #error "Unknown platform flavor"
 #endif
diff --git a/core/arch/arm/plat-rockchip/platform_rk3588.c b/core/arch/arm/plat-rockchip/platform_rk3588.c
new file mode 100644
index 0000000000000000000000000000000000000000..f876f4754040d1f7562b21fb9bf02e749ea6c8f2
--- /dev/null
+++ b/core/arch/arm/plat-rockchip/platform_rk3588.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (C) 2019, Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2024, Rockchip, Inc. All rights reserved.
+ */
+
+#include <common.h>
+#include <io.h>
+#include <kernel/panic.h>
+#include <kernel/mutex.h>
+#include <mm/core_memprot.h>
+#include <platform.h>
+#include <platform_config.h>
+#include <rng_support.h>
+#include <string.h>
+
+#define FIREWALL_DDR_RGN(i)		((i) * 0x4)
+#define FIREWALL_DDR_CON		0xf0
+#define FIREWALL_DSU_RGN(i)		((i) * 0x4)
+#define FIREWALL_DSU_CON(i)		(0xf0 + ((i) * 0x4))
+
+#define RG_MAP_SECURE(top, base)	\
+	(((((top) - 1) & 0x7fff) << 16) | ((base) & 0x7fff))
+
+#define DDR_CHN_CNT			4
+
+#define TRNG_S_CTRL		0x0000
+#define TRNG_S_STAT		0x0004
+#define TRNG_S_MODE		0x0008
+#define TRNG_S_IE		0x0010
+#define TRNG_S_ISTAT		0x0014
+#define TRNG_S_RAND		0x0020
+#define TRNG_S_AUTO_RQSTS	0x0060
+
+#define CMD_NOP			0
+#define CMD_RAND		1
+#define CMD_SEED		2
+
+#define LEN_128BIT		0
+#define LEN_256BIT		3
+
+#define TRNG_S_SEEDED_BIT	BIT32(9)
+#define TRNG_S_SEED_DONE_BIT	BIT32(1)
+#define TRNG_S_RAND_RDY_BIT	BIT32(0)
+
+#define TRNG_POLL_PERIOD_US	0
+#define TRNG_POLL_TIMEOUT_US	1000
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DDR_BASE, FIREWALL_DDR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, FIREWALL_DSU_BASE, FIREWALL_DSU_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, TRNG_S_BASE, TRNG_S_SIZE);
+
+static struct mutex trng_mutex = MUTEX_INITIALIZER;
+
+int platform_secure_ddr_region(int rgn, paddr_t st, size_t sz)
+{
+	vaddr_t fw_ddr_base = (vaddr_t)phys_to_virt_io(FIREWALL_DDR_BASE,
+						       FIREWALL_DDR_SIZE);
+	vaddr_t fw_dsu_base = (vaddr_t)phys_to_virt_io(FIREWALL_DSU_BASE,
+						       FIREWALL_DSU_SIZE);
+	paddr_t ed = st + sz;
+	uint32_t st_mb = st / SIZE_M(1);
+	uint32_t ed_mb = ed / SIZE_M(1);
+	uint32_t i = 0;
+
+	if (!fw_ddr_base || !fw_dsu_base)
+		panic();
+
+	assert(rgn <= 16);
+	assert(st < ed);
+
+	/* Check aligned 1MB */
+	assert(st % SIZE_M(1) == 0);
+	assert(ed % SIZE_M(1) == 0);
+
+	DMSG("protecting region %d: 0x%"PRIxPA"-0x%"PRIxPA"", rgn, st, ed);
+
+	/* Map secure region in DDR */
+	io_write32(fw_ddr_base + FIREWALL_DDR_RGN(rgn),
+		   RG_MAP_SECURE(ed_mb, st_mb));
+
+	/* Map secure region in each DSU channel and enable */
+	for (i = 0; i < DDR_CHN_CNT; i++) {
+		io_write32(fw_dsu_base + FIREWALL_DSU_RGN(i),
+			   RG_MAP_SECURE(ed_mb, st_mb));
+		io_setbits32(fw_dsu_base + FIREWALL_DSU_CON(i), BIT(rgn));
+	}
+
+	/* Enable secure region for DDR */
+	io_setbits32(fw_ddr_base + FIREWALL_DDR_CON, BIT(rgn));
+
+	return 0;
+}
+
+TEE_Result hw_get_random_bytes(void *buf, size_t blen)
+{
+	vaddr_t trng_s_base = (vaddr_t)phys_to_virt_io(TRNG_S_BASE,
+						       TRNG_S_SIZE);
+	size_t remaining = blen;
+	size_t copy_len = 0;
+	uint32_t val = 0;
+	uint32_t rnd = 0;
+
+	mutex_lock(&trng_mutex);
+
+	if (!trng_s_base)
+		panic("TRNG_S base not mapped");
+
+	/* Ensure TRNG is seeded and ready */
+	val = io_read32(trng_s_base + TRNG_S_STAT);
+	if (!(val & TRNG_S_SEEDED_BIT)) {
+		/* TRNG not seeded, issue SEED command */
+		io_write32(trng_s_base + TRNG_S_CTRL, CMD_SEED);
+
+		/* Wait for SEED_DONE flag with timeout */
+		if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val,
+					   val & TRNG_S_SEED_DONE_BIT,
+					   TRNG_POLL_PERIOD_US,
+					   TRNG_POLL_TIMEOUT_US)) {
+			mutex_unlock(&trng_mutex);
+			return TEE_ERROR_BUSY;
+		}
+
+		/* SEED_DONE flag set, clear SEED_DONE */
+		io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_SEED_DONE_BIT);
+	}
+
+	/* Set RNG length to 256 bits */
+	io_write32(trng_s_base + TRNG_S_MODE, LEN_256BIT);
+
+	while (remaining > 0) {
+		/* Set RAND command to generate random numbers */
+		io_write32(trng_s_base + TRNG_S_CTRL, CMD_RAND);
+
+		/* Wait for RAND_RDY flag with timeout */
+		if (IO_READ32_POLL_TIMEOUT(trng_s_base + TRNG_S_ISTAT, val,
+					   val & TRNG_S_RAND_RDY_BIT,
+					   TRNG_POLL_PERIOD_US,
+					   TRNG_POLL_TIMEOUT_US)) {
+			mutex_unlock(&trng_mutex);
+			return TEE_ERROR_BUSY;
+		}
+
+		/* Read random data from RAND register */
+		rnd = io_read32(trng_s_base + TRNG_S_RAND);
+
+		/* Copy as many bytes as required */
+		copy_len = MIN(remaining, sizeof(uint32_t));
+		memcpy((uint8_t *)buf + (blen - remaining), &rnd, copy_len);
+		remaining -= copy_len;
+
+		/* Clear RAND_RDY flag */
+		io_write32(trng_s_base + TRNG_S_ISTAT, TRNG_S_RAND_RDY_BIT);
+	}
+
+	/* Reset RNG mode to NOP */
+	io_write32(trng_s_base + TRNG_S_CTRL, CMD_NOP);
+
+	mutex_unlock(&trng_mutex);
+
+	return TEE_SUCCESS;
+}
diff --git a/core/arch/arm/plat-rockchip/sub.mk b/core/arch/arm/plat-rockchip/sub.mk
index 74f8cf5a920c0d7cd425234b9330fae2ef0420c2..693d90ed5d9784b9b683e855f450bb80b0d18354 100644
--- a/core/arch/arm/plat-rockchip/sub.mk
+++ b/core/arch/arm/plat-rockchip/sub.mk
@@ -4,6 +4,7 @@ srcs-y += platform.c
 srcs-$(PLATFORM_FLAVOR_px30) += platform_px30.c
 srcs-$(PLATFORM_FLAVOR_rk322x) += platform_rk322x.c
 srcs-$(PLATFORM_FLAVOR_rk3399) += platform_rk3399.c
+srcs-$(PLATFORM_FLAVOR_rk3588) += platform_rk3588.c
 
 ifeq ($(PLATFORM_FLAVOR),rk322x)
 srcs-y += plat_init.S
diff --git a/core/arch/arm/plat-rpi3/main.c b/core/arch/arm/plat-rpi3/main.c
index 3e9021dfaacf73ca029251c6165d25c4e3838fe7..5008c1b10d78bff96d24b2066e7e6adcbf059262 100644
--- a/core/arch/arm/plat-rpi3/main.c
+++ b/core/arch/arm/plat-rpi3/main.c
@@ -39,7 +39,7 @@ register_phys_mem_pgdir(MEM_AREA_IO_NSEC,
 
 static struct serial8250_uart_data console_data;
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-rzg/main.c b/core/arch/arm/plat-rzg/main.c
index 31dfd084e46b1bc40eeb8c9bdbb71945189d419a..c58ca47b25c9ec0774f9d020dcf03ecee5b16e5e 100644
--- a/core/arch/arm/plat-rzg/main.c
+++ b/core/arch/arm/plat-rzg/main.c
@@ -28,7 +28,7 @@ register_dynamic_shm(NSEC_DDR_3_BASE, NSEC_DDR_3_SIZE);
 
 static struct scif_uart_data console_data __nex_bss;
 
-void console_init(void)
+void plat_console_init(void)
 {
 	scif_uart_init(&console_data, CONSOLE_UART_BASE);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-rzn1/main.c b/core/arch/arm/plat-rzn1/main.c
index bed02b80f74bad1714683622cf01482922439b50..025645fedab1ac545c7f8bca63c7ed0bb40ddb3d 100644
--- a/core/arch/arm/plat-rzn1/main.c
+++ b/core/arch/arm/plat-rzn1/main.c
@@ -34,7 +34,7 @@ register_phys_mem(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE);
 register_phys_mem(MEM_AREA_IO_SEC, PERIPH_REG_BASE, CORE_MMU_PGDIR_SIZE);
 register_ddr(DRAM_BASE, DRAM_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	ns16550_init(&console_data, CONSOLE_UART_BASE, IO_WIDTH_U32, 2);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-sam/conf.mk b/core/arch/arm/plat-sam/conf.mk
index feef98c0ee5da03a4b976e8f90b6523ab3200493..2cd1fed0676e389a7f8a0381dee89cea66b5f800 100644
--- a/core/arch/arm/plat-sam/conf.mk
+++ b/core/arch/arm/plat-sam/conf.mk
@@ -4,6 +4,7 @@ flavor_dts_file-sama5d2xult = at91-sama5d2_xplained.dts
 flavor_dts_file-sama5d2_xplained = at91-sama5d2_xplained.dts
 flavor_dts_file-sama5d27_som1_ek = at91-sama5d27_som1_ek.dts
 flavor_dts_file-sama5d27_wlsom1_ek = at91-sama5d27_wlsom1_ek.dts
+flavor_dts_file-sama7g54_ek = at91-sama7g54_ek.dts
 
 ifeq ($(PLATFORM_FLAVOR),sama5d2xult)
 $(warning "sama5d2xult is deprecated, please use sama5d2_xplained")
@@ -14,21 +15,31 @@ $(error Invalid platform flavor $(PLATFORM_FLAVOR))
 endif
 CFG_EMBED_DTB_SOURCE_FILE ?= $(flavor_dts_file-$(PLATFORM_FLAVOR))
 
+ifeq ($(PLATFORM_FLAVOR),sama7g54_ek)
+include core/arch/arm/cpu/cortex-a7.mk
+$(call force,CFG_SAMA7G5,y)
+$(call force,CFG_GIC,y)
+$(call force,CFG_TZC400,y)
+$(call force,CFG_MICROCHIP_PIT,y)
+$(call force,CFG_SCMI_MSG_RESET_DOMAIN,y)
+else
 include core/arch/arm/cpu/cortex-a5.mk
+$(call force,CFG_SAMA5D2,y)
+$(call force,CFG_ATMEL_SAIC,y)
+$(call force,CFG_PL310,y)
+$(call force,CFG_PL310_SIP_PROTOCOL,y)
+endif
 
 $(call force,CFG_TEE_CORE_NB_CORE,1)
 $(call force,CFG_ATMEL_UART,y)
-$(call force,CFG_ATMEL_SAIC,y)
 $(call force,CFG_ATMEL_TCB,y)
 $(call force,CFG_NO_SMP,y)
-$(call force,CFG_PL310,y)
-$(call force,CFG_PL310_LOCKED,y)
 $(call force,CFG_AT91_MATRIX,y)
 $(call force,CFG_DRIVERS_CLK,y)
 $(call force,CFG_DRIVERS_CLK_DT,y)
 $(call force,CFG_DRIVERS_CLK_FIXED,y)
+$(call force,CFG_DRIVERS_RSTCTRL,y)
 $(call force,CFG_DRIVERS_SAM_CLK,y)
-$(call force,CFG_DRIVERS_SAMA5D2_CLK,y)
 $(call force,CFG_PSCI_ARM32,y)
 $(call force,CFG_SM_PLATFORM_HANDLER,y)
 $(call force,CFG_CORE_HAS_GENERIC_TIMER,n)
@@ -36,24 +47,30 @@ $(call force,CFG_CORE_HAS_GENERIC_TIMER,n)
 # These values are forced because of matrix configuration for secure area.
 # When modifying these, always update matrix settings in
 # matrix_configure_slave_h64mx().
+ifeq ($(CFG_SAMA7G5),y)
+$(call force,CFG_TZDRAM_START,0x60000000)
+endif
+ifeq ($(CFG_SAMA5D2),y)
 $(call force,CFG_TZDRAM_START,0x20000000)
+endif
 $(call force,CFG_TZDRAM_SIZE,0x800000)
 
-# This value is forced because this feature isn't used by SAM platforms.
+# This value is forced because these feature aren't used by SAM platforms.
 $(call force,CFG_EXTERNAL_DT,n)
+$(call force,CFG_CORE_DYN_SHM,n)
 
 CFG_MMAP_REGIONS ?= 24
 
-CFG_SHMEM_START  ?= 0x21000000
+CFG_SHMEM_START  ?= ($(CFG_TZDRAM_START) + 0x1000000)
 CFG_SHMEM_SIZE   ?= 0x400000
 
-CFG_SCMI_SHMEM_START  ?= 0x21400000
+CFG_SCMI_SHMEM_START  ?= ($(CFG_TZDRAM_START) + 0x1400000)
 CFG_SCMI_SHMEM_SIZE   ?= 0x1000
 
 CFG_TEE_RAM_VA_SIZE ?= 0x100000
 
 # Device tree related configuration
-CFG_DT_ADDR ?= 0x21500000
+CFG_DT_ADDR ?= ($(CFG_TZDRAM_START) + 0x1500000)
 CFG_GENERATE_DTB_OVERLAY ?= y
 
 CFG_WITH_SOFTWARE_PRNG ?= n
@@ -113,4 +130,12 @@ $(call force,CFG_SCMI_MSG_SMT_FASTCALL_ENTRY,y)
 endif
 
 CFG_DRIVERS_NVMEM ?= y
+ifeq ($(CFG_SAMA7G5),y)
+CFG_ATMEL_SFC ?= n
+CFG_NVMEM_DIE_ID ?= n
+CFG_NVMEM_HUK ?= n
+else
 CFG_ATMEL_SFC ?= y
+CFG_NVMEM_DIE_ID ?= y
+CFG_NVMEM_HUK ?= y
+endif
diff --git a/core/arch/arm/plat-sam/freq.c b/core/arch/arm/plat-sam/freq.c
index b6fd72f2c6d62f96a325f6b13969cc06d2d9acb0..6a6a1ba330499c1c51056a1669e38a49ad7b3fdd 100644
--- a/core/arch/arm/plat-sam/freq.c
+++ b/core/arch/arm/plat-sam/freq.c
@@ -4,6 +4,8 @@
  */
 
 #include <assert.h>
+#include <at91_clk.h>
+#include <config.h>
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
 #include <kernel/boot.h>
@@ -22,7 +24,11 @@ static TEE_Result get_freq_from_dt(void)
 	if (!fdt)
 		panic();
 
-	node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a5");
+	if (IS_ENABLED(CFG_SAMA7G5))
+		node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a7");
+	else
+		node = fdt_node_offset_by_compatible(fdt, -1, "arm,cortex-a5");
+
 	if (!node)
 		panic();
 
@@ -31,7 +37,7 @@ static TEE_Result get_freq_from_dt(void)
 
 	freq = clk_get_rate(clk);
 
-	return TEE_SUCCESS;
+	return at91_clk_register_cpu_opp(fdt, node, clk);
 }
 early_init_late(get_freq_from_dt);
 
diff --git a/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c b/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c
index ff837c11e38271e1d62e3566c0ff5bb173135c93..35aded4b75da44c4a8839a3fdf6f0f68b8c01a6b 100644
--- a/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c
+++ b/core/arch/arm/plat-sam/nsec-service/sm_platform_handler.c
@@ -10,13 +10,34 @@
 #include <kernel/tee_misc.h>
 #include <mm/core_memprot.h>
 #include <sam_sfr.h>
+#include <sam_pl310.h>
 #include <sm/optee_smc.h>
 #include <sm/sm.h>
 #include <smc_ids.h>
 
 static enum sm_handler_ret sam_sip_handler(struct thread_smc_args *args)
 {
+	/*
+	 * As all sama5 SoCs are single-core ones, check the code compiled for a
+	 * single core. No serializations done to protect against concurrency.
+	 */
+	static_assert(CFG_TEE_CORE_NB_CORE == 1);
+
 	switch (OPTEE_SMC_FUNC_NUM(args->a0)) {
+#ifdef CFG_PL310_SIP_PROTOCOL
+	case SAM_SMC_SIP_PL310_ENABLE:
+		args->a0 = pl310_enable();
+		break;
+	case SAM_SMC_SIP_PL310_DISABLE:
+		args->a0 = pl310_disable();
+		break;
+	case SAM_SMC_SIP_PL310_EN_WRITEBACK:
+		args->a0 = pl310_enable_writeback();
+		break;
+	case SAM_SMC_SIP_PL310_DIS_WRITEBACK:
+		args->a0 = pl310_disable_writeback();
+		break;
+#endif
 	case SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND:
 		atmel_sfr_set_usb_suspend(args->a1);
 		args->a0 = SAMA5_SMC_SIP_RETURN_SUCCESS;
diff --git a/core/arch/arm/plat-sam/nsec-service/smc_ids.h b/core/arch/arm/plat-sam/nsec-service/smc_ids.h
index 17180a05d461893847b3956dac4a8a41fa087a97..529d37a836b728ea73018a2c5b8b51b0f6ba3fe2 100644
--- a/core/arch/arm/plat-sam/nsec-service/smc_ids.h
+++ b/core/arch/arm/plat-sam/nsec-service/smc_ids.h
@@ -8,6 +8,11 @@
 #include <optee_msg.h>
 #include <sm/optee_smc.h>
 
+#define SAM_SMC_SIP_PL310_ENABLE	1
+#define SAM_SMC_SIP_PL310_DISABLE	2
+#define SAM_SMC_SIP_PL310_EN_WRITEBACK	3
+#define SAM_SMC_SIP_PL310_DIS_WRITEBACK	4
+
 #define SAMA5_SMC_SIP_SCMI_CALL_ID	0x200
 
 #define SAMA5_SMC_SIP_SFR_SET_USB_SUSPEND	0x300
diff --git a/core/arch/arm/plat-sam/main.c b/core/arch/arm/plat-sam/platform_sama5d2.c
similarity index 99%
rename from core/arch/arm/plat-sam/main.c
rename to core/arch/arm/plat-sam/platform_sama5d2.c
index 1fffce5884fbbb2d826ca99dcf49224650131faf..c52d8a8f1d6e6225c115e935d30801f962a3f7be 100644
--- a/core/arch/arm/plat-sam/main.c
+++ b/core/arch/arm/plat-sam/platform_sama5d2.c
@@ -499,7 +499,7 @@ static struct atmel_uart_data console_data;
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE,
 			CORE_MMU_PGDIR_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	atmel_uart_init(&console_data, CONSOLE_UART_BASE);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-sam/platform_sama7g5.c b/core/arch/arm/plat-sam/platform_sama7g5.c
new file mode 100644
index 0000000000000000000000000000000000000000..9c0653a059762e3681c06951d941805897339984
--- /dev/null
+++ b/core/arch/arm/plat-sam/platform_sama7g5.c
@@ -0,0 +1,937 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024 Microchip Technology Inc.
+ */
+
+#include <assert.h>
+#include <console.h>
+#include <drivers/atmel_uart.h>
+#include <drivers/gic.h>
+#include <drivers/tzc400.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <matrix.h>
+#include <mm/core_mmu.h>
+#include <platform_config.h>
+#include <tz_matrix.h>
+#include <util.h>
+
+#define MATRIX_SAMA7G54 0
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE,
+			CORE_MMU_PGDIR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, MATRIX_BASE_ADDRESS,
+			CORE_MMU_PGDIR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZC_BASE_ADDRESS, CORE_MMU_PGDIR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, TZPM_BASE_ADDRESS,
+			CORE_MMU_PGDIR_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_INTERFACE_BASE, GICC_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_DISTRIBUTOR_BASE, GICD_SIZE);
+
+static struct matrix matrixes[] = {
+	{
+		.matrix = MATRIX_SAMA7G54,
+		.p = { .pa = MATRIX_BASE_ADDRESS, },
+	},
+};
+
+static struct peri_security peri_security_array[] = {
+	{
+		.peri_id = ID_DWDT_SW,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = DWDT_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_DWDT_NSW,
+		.security_type = SECURITY_TYPE_NS,
+		.addr = DWDT_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_DWDT_NSW_ALARM,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = DWDT_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SCKC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = SCKC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SHDWC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = SHDWC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_RSTC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = RSTC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_RTC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = RTC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_RTT,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = RTT_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_CHIPID,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = CHIPID_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PMC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = PMC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIOA,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIOB,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x40,
+	},
+	{
+		.peri_id = ID_PIOC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x80,
+	},
+	{
+		.peri_id = ID_PIOD,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0xC0,
+	},
+	{
+		.peri_id = ID_PIOE,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x100,
+	},
+	{
+		.peri_id = ID_SECUMOD,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = SECUMOD_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SECURAM,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = 0xE0000000,
+	},
+	{
+		.peri_id = ID_SFR,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SFR_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SFRBU,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = SFRBU_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_HSMC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = HSMC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_XDMAC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_XDMAC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_XDMAC2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_ACC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = ACC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_ADC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = ADC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_AES,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AES_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZAESBASC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = TZAESBASC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_ASRC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = ASRC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_CPKCC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = CPKCC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_CSI,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = CSI_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_CSI2DC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = CSI2DC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_DDRPUBL,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = DDRPUBL_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_DDRUMCTL,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = DDRUMCTL_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_EIC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = EIC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM3,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM3_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM4,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM4_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM5,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM5_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM6,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM6_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM7,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM7_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM8,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM8_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM9,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM9_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM10,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM10_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_FLEXCOM11,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = FLEXCOM11_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_GMAC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = GMAC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_GMAC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = GMAC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_GMAC0_TSU,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC1_TSU,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_ICM,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = ICM_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_ISC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = ISC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_I2SMCC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = I2SMCC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_I2SMCC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = I2SMCC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MATRIX,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = MATRIX_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN3,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN3_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN4,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN4_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN5,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN5_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_OTPC,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = OTPC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PDMC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PDMC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PDMC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PDMC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B3,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B3_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B4,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B4_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B5,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B5_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PWM,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PWM_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_QSPI0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = QSPI0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_QSPI1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = QSPI1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SDMMC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SDMMC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SDMMC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SDMMC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SDMMC2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SDMMC2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SHA,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SHA_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SPDIFRX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SPDIFRX_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SPDIFTX,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SPDIFTX_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SSC0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SSC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SSC1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SSC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC0_CHANNEL0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC0_CHANNEL1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS + 0x40,
+	},
+	{
+		.peri_id = ID_TC0_CHANNEL2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS + 0x80,
+	},
+	{
+		.peri_id = ID_TC1_CHANNEL0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC1_CHANNEL1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS + 0x40,
+	},
+	{
+		.peri_id = ID_TC1_CHANNEL2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS + 0x80,
+	},
+	{
+		.peri_id = ID_TCPCA,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TCPCA_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TCPCB,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TCPCB_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TDES,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TDES_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TRNG,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TRNG_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZAESB_NS,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TZAESBNS_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZAESB_NS_SINT,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = TZAESBNS_BASE_ADDRESS,},
+	{
+		.peri_id = ID_TZAESB_S,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TZAESBS_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZAESB_S_SINT,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = TZAESBS_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZC,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = TZC_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TZPM,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TZPM_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_UDPHSA,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = UDPHSA_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_UDPHSB,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = UDPHSB_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_UHPHS,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_XDMAC0_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_XDMAC1_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_XDMAC2_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = XDMAC2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_AES_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = AES_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_GMAC0_Q1,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC0_Q2,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC0_Q3,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC0_Q4,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC0_Q5,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_GMAC1_Q1,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_ICM_SINT,
+		.security_type = SECURITY_TYPE_AS,
+		.addr = ICM_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN0_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN1_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN2_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN3_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN3_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN4_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN4_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_MCAN5_INT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = MCAN5_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIOA_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIOB_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x40,
+	},
+	{
+		.peri_id = ID_PIOC_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x80,
+	},
+	{
+		.peri_id = ID_PIOD_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0xC0,
+	},
+	{
+		.peri_id = ID_PIOE_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIO_BASE_ADDRESS + 0x100,
+	},
+	{
+		.peri_id = ID_PIT64B0_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B1_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B2_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B2_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B3_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B3_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B4_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B4_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_PIT64B5_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = PIT64B5_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_SDMMC0_TIMER,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_SDMMC1_TIMER,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_SDMMC2_TIMER,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_SHA_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = SHA_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC0_SINT0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC0_SINT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC0_SINT2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC0_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC1_SINT0,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC1_SINT1,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TC1_SINT2,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TC1_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TDES_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TDES_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_TRNG_SINT,
+		.security_type = SECURITY_TYPE_PS,
+		.addr = TRNG_BASE_ADDRESS,
+	},
+	{
+		.peri_id = ID_EXT_IRQ0,
+		.security_type = SECURITY_TYPE_PS,
+	},
+	{
+		.peri_id = ID_EXT_IRQ1,
+		.security_type = SECURITY_TYPE_PS,
+	},
+};
+
+static struct atmel_uart_data console_data;
+
+void plat_console_init(void)
+{
+	atmel_uart_init(&console_data, CONSOLE_UART_BASE);
+	register_serial_console(&console_data.chip);
+}
+
+struct peri_security *peri_security_get(unsigned int idx)
+{
+	struct peri_security *p = NULL;
+
+	if (idx < ARRAY_SIZE(peri_security_array))
+		p = &peri_security_array[idx];
+
+	return p;
+}
+
+struct matrix *matrix_get(unsigned int idx)
+{
+	struct matrix *p = NULL;
+
+	if (idx < ARRAY_SIZE(matrixes))
+		p = &matrixes[idx];
+
+	return p;
+}
+
+static void matrix_configure_slave(void)
+{
+	unsigned int sasplit_setting = 0;
+	unsigned int srtop_setting = 0;
+	unsigned int ssr_setting = 0;
+	unsigned int base = 0;
+
+	static_assert(CFG_TZDRAM_START == DDR_CS_ADDR);
+	static_assert(CFG_TZDRAM_SIZE == 0x800000);
+
+	base = matrix_base(MATRIX_SAMA7G54);
+
+	/* 0: QSPI0: Normal world */
+	/* 1: QSPI1: Normal world */
+	srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M) |
+			MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_128M);
+	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_128M) |
+			  MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_128M);
+	ssr_setting = MATRIX_LANSECH_NS(0) |
+		      MATRIX_LANSECH_NS(1) |
+		      MATRIX_RDNSECH_NS(0) |
+		      MATRIX_RDNSECH_NS(1) |
+		      MATRIX_WRNSECH_NS(0) |
+		      MATRIX_WRNSECH_NS(1);
+	matrix_configure_slave_security(base, 0, srtop_setting,
+					sasplit_setting, ssr_setting);
+	matrix_configure_slave_security(base, 1, srtop_setting,
+					sasplit_setting, ssr_setting);
+
+	/* 2: TZAESB: Default */
+
+	/* 3: UDDRC_P1: Non-Secure, except op-tee tee/ta memory */
+	/*
+	 * Matrix DDR configuration is hardcoded here and is difficult to
+	 * generate at runtime. Since this configuration expect the secure
+	 * DRAM to be at start of RAM and 8M of size, enforce it here.
+	 */
+	srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128M);
+	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8M);
+	ssr_setting = MATRIX_LANSECH_S(0) |
+		      MATRIX_RDNSECH_S(0) |
+		      MATRIX_WRNSECH_S(0);
+	matrix_configure_slave_security(base, 3, srtop_setting,
+					sasplit_setting, ssr_setting);
+
+	/* 4: APB6: Default */
+
+	/*
+	 * 5: SRAM_P0
+	 * 6: SRAM_P1
+	 */
+	srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_128K);
+	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_64K);
+	ssr_setting = MATRIX_LANSECH_NS(0) |
+		      MATRIX_RDNSECH_S(0) |
+		      MATRIX_WRNSECH_S(0);
+	matrix_configure_slave_security(base, 5, srtop_setting,
+					sasplit_setting, ssr_setting);
+	matrix_configure_slave_security(base, 6, srtop_setting,
+					sasplit_setting, ssr_setting);
+
+	/*
+	 * 7: SMC
+	 * EBI_CS0 ----> Slave Region 0
+	 * EBI_CS1 ----> Slave Region 1
+	 * EBI_CS2 ----> Slave Region 2
+	 * EBI_CS3 ----> Slave Region 3
+	 * NFC_CMD ----> Slave Region 4 : Non-Secure
+	 */
+	srtop_setting =	MATRIX_SRTOP(4, MATRIX_SRTOP_VALUE_128M);
+	sasplit_setting = MATRIX_SASPLIT(4, MATRIX_SASPLIT_VALUE_128M);
+	ssr_setting = MATRIX_LANSECH_NS(4) |
+		      MATRIX_RDNSECH_NS(4) |
+		      MATRIX_WRNSECH_NS(4);
+	matrix_configure_slave_security(base, 7, srtop_setting,
+					sasplit_setting, ssr_setting);
+
+	/*
+	 * 8: NFC_RAM
+	 * Slave area below SASSPLIT boundary is configured as Not Secured
+	 */
+	srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_8K);
+	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_8K);
+	ssr_setting = MATRIX_LANSECH_NS(0);
+	matrix_configure_slave_security(base, 8, srtop_setting,
+					sasplit_setting, ssr_setting);
+
+	/*
+	 * 9: USB_RAM
+	 * Slave area below SASSPLIT boundary is configured as Not Secured
+	 */
+	srtop_setting = MATRIX_SRTOP(0, MATRIX_SRTOP_VALUE_1M) |
+			MATRIX_SRTOP(1, MATRIX_SRTOP_VALUE_1M) |
+			MATRIX_SRTOP(2, MATRIX_SRTOP_VALUE_4K) |
+			MATRIX_SRTOP(3, MATRIX_SRTOP_VALUE_4K);
+	sasplit_setting = MATRIX_SASPLIT(0, MATRIX_SASPLIT_VALUE_1M) |
+			  MATRIX_SASPLIT(1, MATRIX_SASPLIT_VALUE_1M) |
+			  MATRIX_SASPLIT(2, MATRIX_SASPLIT_VALUE_4K) |
+			  MATRIX_SASPLIT(3, MATRIX_SASPLIT_VALUE_4K);
+	ssr_setting = MATRIX_LANSECH_NS(0) |
+		      MATRIX_LANSECH_NS(1) |
+		      MATRIX_LANSECH_NS(2) |
+		      MATRIX_LANSECH_NS(3);
+	matrix_configure_slave_security(base, 9, srtop_setting,
+					sasplit_setting, ssr_setting);
+}
+
+static void matrix_init(void)
+{
+	matrix_write_protect_disable(matrix_base(MATRIX_SAMA7G54));
+	matrix_configure_slave();
+}
+
+static void tzc400_init(void)
+{
+	struct tzc_region_config cfg = { };
+	unsigned int tzc_idx = 0;
+	vaddr_t addr = 0;
+
+	for (tzc_idx = 0; tzc_idx <= 1; tzc_idx++) {
+		addr = TZC_BASE_ADDRESS + 0x1000 * tzc_idx;
+		tzc_init(addr);
+
+		if (tzc_idx)
+			cfg.filters = BIT(0);
+		else
+			cfg.filters = GENMASK_32(3, 0);
+		cfg.sec_attr = TZC_REGION_S_RDWR;
+
+		cfg.base = 0x00000000;
+		cfg.top = 0xffffffff;
+		cfg.ns_device_access = BIT(16) | BIT(0);
+		tzc_configure_region(0, &cfg);
+
+		cfg.base = CFG_TZDRAM_START;
+		cfg.top = cfg.base + CFG_TZDRAM_SIZE - 1;
+		cfg.ns_device_access = 0;
+		tzc_configure_region(1, &cfg);
+
+		cfg.base += CFG_TZDRAM_SIZE;
+		cfg.top = cfg.base - CFG_TZDRAM_SIZE + DDR_CS_SIZE - 1;
+		cfg.ns_device_access = BIT(16) | BIT(0);
+		tzc_configure_region(2, &cfg);
+	}
+}
+
+static void tzpm_init(void)
+{
+	struct peri_security *p = peri_security_array;
+	unsigned int i = 0;
+	vaddr_t addr = TZPM_BASE_ADDRESS;
+
+	/* TZPM_PIDx register write is possible. */
+	io_write32(addr + 0x04, 0x12AC4B5D);
+
+	for (i = 0; i < ARRAY_SIZE(peri_security_array); i++, p++)
+		if (p->peri_id < 128 &&
+		    p->security_type == SECURITY_TYPE_PS)
+			io_setbits32(addr + 8 + 4 * (p->peri_id / 32),
+				     BIT(p->peri_id % 32));
+}
+
+void plat_primary_init_early(void)
+{
+	assert(!cpu_mmu_enabled());
+	matrix_init();
+	tzc400_init();
+	tzpm_init();
+}
+
+void boot_primary_init_intc(void)
+{
+	gic_init(GIC_INTERFACE_BASE, GIC_DISTRIBUTOR_BASE);
+}
diff --git a/core/arch/arm/plat-sam/sam_pl310.c b/core/arch/arm/plat-sam/sam_pl310.c
index d2cc227937a9163ec2dea936062fe503f723c093..fd357d8bf02c7660362133ef0e507768c2b02399 100644
--- a/core/arch/arm/plat-sam/sam_pl310.c
+++ b/core/arch/arm/plat-sam/sam_pl310.c
@@ -33,8 +33,14 @@
 #include <mm/core_mmu.h>
 #include <sama5d2.h>
 #include <sam_sfr.h>
+#include <sam_pl310.h>
+#include <sm/optee_smc.h>
 #include <types_ext.h>
 
+/* L2 Cache Controller (L2CC) */
+#define L2CC_DCR_DWB	BIT(1) /* Disable Write-back, Force Write-through */
+#define L2CC_DCR_DCL	BIT(0) /* Disable Cache Linefill */
+
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, PL310_BASE, CORE_MMU_PGDIR_SIZE);
 
 vaddr_t pl310_base(void)
@@ -66,3 +72,41 @@ void arm_cl2_enable(vaddr_t pl310_base)
 	/* Enable PL310 ctrl -> only set lsb bit */
 	io_write32(pl310_base + PL310_CTRL, 1);
 }
+
+#ifdef CFG_PL310_SIP_PROTOCOL
+TEE_Result pl310_enable(void)
+{
+	vaddr_t base = pl310_base();
+
+	arm_cl2_config(base);
+	arm_cl2_enable(base);
+
+	return OPTEE_SMC_RETURN_OK;
+}
+
+TEE_Result pl310_disable(void)
+{
+	EMSG("not implemented");
+
+	return OPTEE_SMC_RETURN_ENOTAVAIL;
+}
+
+TEE_Result pl310_enable_writeback(void)
+{
+	vaddr_t base = pl310_base();
+
+	io_write32(base + PL310_DEBUG_CTRL, 0);
+
+	return OPTEE_SMC_RETURN_OK;
+}
+
+TEE_Result pl310_disable_writeback(void)
+{
+	uint32_t val = L2CC_DCR_DWB | L2CC_DCR_DCL;
+	vaddr_t base = pl310_base();
+
+	io_write32(base + PL310_DEBUG_CTRL, val);
+
+	return OPTEE_SMC_RETURN_OK;
+}
+#endif
diff --git a/core/arch/arm/plat-sam/sam_pl310.h b/core/arch/arm/plat-sam/sam_pl310.h
new file mode 100644
index 0000000000000000000000000000000000000000..2b414ab5070283b9d34d7d4d0d4c62ade4ad1614
--- /dev/null
+++ b/core/arch/arm/plat-sam/sam_pl310.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Microchip Technology Inc. and its subsidiaries.
+ */
+
+#ifndef __SAM_PL310_H__
+#define __SAM_PL310_H__
+
+TEE_Result pl310_enable(void);
+TEE_Result pl310_disable(void);
+TEE_Result pl310_enable_writeback(void);
+TEE_Result pl310_disable_writeback(void);
+
+#endif /* __SAM_PL310_H__ */
diff --git a/core/arch/arm/plat-sam/sam_sfr.c b/core/arch/arm/plat-sam/sam_sfr.c
index 3e3523a3ce021c67b89e16dad3e8f3ed258d4513..184f72b037e23446a58dda8337acab1d457892ec 100644
--- a/core/arch/arm/plat-sam/sam_sfr.c
+++ b/core/arch/arm/plat-sam/sam_sfr.c
@@ -12,7 +12,7 @@
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <sam_sfr.h>
-#include <sama5d2.h>
+#include <platform_config.h>
 #include <types_ext.h>
 
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, SFR_BASE, CORE_MMU_PGDIR_SIZE);
diff --git a/core/arch/arm/plat-sam/scmi_server.c b/core/arch/arm/plat-sam/scmi_server.c
index 06e2ee61bbf035e9ee18e913b66aae8932fcd6cf..c7ce06f64aad6bef83c609f4f418a7fc60c92362 100644
--- a/core/arch/arm/plat-sam/scmi_server.c
+++ b/core/arch/arm/plat-sam/scmi_server.c
@@ -6,6 +6,8 @@
 
 #include <at91_clk.h>
 #include <confine_array_index.h>
+#include <drivers/atmel_rstc.h>
+#include <drivers/rstctrl.h>
 #include <drivers/scmi-msg.h>
 #include <drivers/scmi.h>
 #include <dt-bindings/clock/at91.h>
@@ -16,8 +18,34 @@ static_assert(SMT_BUF_SLOT_SIZE <= CFG_SCMI_SHMEM_SIZE);
 
 register_phys_mem(MEM_AREA_IO_NSEC, CFG_SCMI_SHMEM_START, CFG_SCMI_SHMEM_SIZE);
 
+#define RESET_CELL(_scmi_id, _id, _name) \
+	[(_scmi_id)] = { \
+		.reset_id = (_id), \
+		.name = (_name), \
+	}
+
+#define RST_SCMI_USB1 0
+#define RST_SCMI_USB2 1
+#define RST_SCMI_USB3 2
+
+struct sam_scmi_rd {
+	unsigned int reset_id;
+	const char *name;
+	struct rstctrl *rstctrl;
+};
+
+static struct sam_scmi_rd sam_scmi_reset_domain[] = {
+#ifdef CFG_SAMA7G5
+	RESET_CELL(RST_SCMI_USB1, SHIFT_U32(0xE4, RESET_ID_SHIFT) | 4, "USB1"),
+	RESET_CELL(RST_SCMI_USB2, SHIFT_U32(0xE4, RESET_ID_SHIFT) | 5, "USB2"),
+	RESET_CELL(RST_SCMI_USB3, SHIFT_U32(0xE4, RESET_ID_SHIFT) | 6, "USB3"),
+#endif
+};
+
 struct channel_resources {
 	struct scmi_msg_channel *channel;
+	struct sam_scmi_rd *rd;
+	size_t rd_count;
 };
 
 static const struct channel_resources scmi_channel[] = {
@@ -26,6 +54,8 @@ static const struct channel_resources scmi_channel[] = {
 			.shm_addr = { .pa = CFG_SCMI_SHMEM_START },
 			.shm_size = SMT_BUF_SLOT_SIZE,
 		},
+		.rd = sam_scmi_reset_domain,
+		.rd_count = ARRAY_SIZE(sam_scmi_reset_domain),
 	},
 };
 
@@ -63,6 +93,7 @@ const char *plat_scmi_sub_vendor_name(void)
 /* Currently supporting only SCMI Base protocol */
 static const uint8_t plat_protocol_list[] = {
 	SCMI_PROTOCOL_ID_CLOCK,
+	SCMI_PROTOCOL_ID_RESET_DOMAIN,
 	0 /* Null termination */
 };
 
@@ -76,13 +107,514 @@ const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused)
 	return plat_protocol_list;
 }
 
-struct sama5d2_pmc_clk {
+struct sam_pmc_clk {
 	unsigned int scmi_id;
 	unsigned int pmc_type;
 	unsigned int pmc_id;
 };
 
-static const struct sama5d2_pmc_clk pmc_clks[] = {
+#ifdef CFG_SAMA7G5
+static const struct sam_pmc_clk pmc_clks[] = {
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_MCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_MCK
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_UTMI,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_UTMI
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_CPUPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_CPUPLL
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_MAIN,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_MAIN
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_SYSPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_SYSPLL
+	},
+
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_AUDIOPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_AUDIOPMCPLL
+	},
+
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_MCK_PRES,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_MCK_PRES
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_DDRPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_DDRPLL
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_IMGPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_IMGPLL
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_CORE_ETHPLLCK,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_ETHPLL
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_UTMI1,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_UTMI1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_UTMI2,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_UTMI2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_UTMI3,
+		.pmc_type = PMC_TYPE_CORE,
+		.pmc_id = PMC_UTMI3
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK0,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 8
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK1,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 9
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK2,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 10
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK3,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 11
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK4,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 12
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK5,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 13
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK6,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 14
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_SYSTEM_PCK7,
+		.pmc_type = PMC_TYPE_SYSTEM,
+		.pmc_id = 15
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_ASRC_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_ASRC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_ASRC_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_ASRC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CSI_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_CSI
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CSI_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_CSI
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CSI2DC_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_CSI2DC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_MACB0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_GMAC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_MACB0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_GMAC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_MACB0_TSU,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_GMAC0_TSU
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_MACB1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_GMAC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_MACB1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_GMAC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_MACB1_TSU,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_GMAC1_TSU
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_TDES_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_TDES
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_HSMC_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_HSMC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_PIOA_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_PIOA
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX2_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX3_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM3
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX4_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM4
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX5_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM5
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX6_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM6
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX7_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM7
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX8_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM8
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX9_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM9
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX10_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM10
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_FLX11_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_FLEXCOM11
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_TCB0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_TC0_CHANNEL0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_TCB1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_TC1_CHANNEL0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_PWM_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_PWM
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_ADC_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_ADC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_UHPHS_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_UHPHS
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSA_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_UDPHSA
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_UDPHSB_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_UDPHSB
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SSC0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SSC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SSC1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SSC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_TRNG_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_TRNG
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_PDMC0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_PDMC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_PDMC1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_PDMC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SECURAM_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SECURAM
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_I2S0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_I2SMCC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_I2S1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_I2SMCC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN2_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN3_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN3
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN4_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN4
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_CAN5_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_MCAN5
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_DMA0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_XDMAC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_DMA1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_XDMAC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_DMA2_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_XDMAC2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SPDIFRX
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SPDIFTX
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_SPDIFRX_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_SPDIFRX
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_SPDIFTX_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_SPDIFTX
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_AES_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_AES
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_AESB_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_TZAESBASC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SHA_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SHA
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC0_HCLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SDMMC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC1_HCLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SDMMC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_SDMMC2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_ISC_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_ISC
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_QSPI0_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_QSPI0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_PERIPH_QSPI1_CLK,
+		.pmc_type = PMC_TYPE_PERIPHERAL,
+		.pmc_id = ID_QSPI1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_QSPI0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_QSPI0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_QSPI1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_QSPI1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_SDMMC0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_SDMMC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_SDMMC1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_SDMMC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_SDMMC2_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_SDMMC2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_TCB0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_TC0_CHANNEL0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_TCB1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_TC1_CHANNEL0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_I2S0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_I2SMCC0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_I2S1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_I2SMCC1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN0_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN0
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN1_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN1
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN2_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN2
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN3_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN3
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN4_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN4
+	},
+	{
+		.scmi_id = AT91_SCMI_CLK_GCK_CAN5_GCLK,
+		.pmc_type = PMC_TYPE_GCK,
+		.pmc_id = ID_MCAN5
+	},
+};
+#else
+static const struct sam_pmc_clk pmc_clks[] = {
 	{
 		.scmi_id = AT91_SCMI_CLK_CORE_MCK,
 		.pmc_type = PMC_TYPE_CORE,
@@ -489,13 +1021,14 @@ static const struct sama5d2_pmc_clk pmc_clks[] = {
 		.pmc_id = 2
 	},
 };
+#endif
 
 static TEE_Result sam_init_scmi_clk(void)
 {
 	unsigned int i = 0;
 	struct clk *clk = NULL;
 	TEE_Result res = TEE_ERROR_GENERIC;
-	const struct sama5d2_pmc_clk *pmc_clk = NULL;
+	const struct sam_pmc_clk *pmc_clk = NULL;
 
 	for (i = 0; i < ARRAY_SIZE(pmc_clks); i++) {
 		pmc_clk = &pmc_clks[i];
@@ -524,15 +1057,72 @@ static TEE_Result sam_init_scmi_clk(void)
 		return res;
 	}
 
+	clk = at91_cpu_opp_clk_get();
+	if (clk) {
+		res = scmi_clk_add(clk, 0, AT91_SCMI_CLK_CPU_OPP);
+		if (res) {
+			EMSG("Failed to add CPU OPP clock to SCMI clocks");
+			return res;
+		}
+	}
+
 	return TEE_SUCCESS;
 }
 
+static struct sam_scmi_rd *find_rd(unsigned int channel_id,
+				   unsigned int scmi_id)
+{
+	const struct channel_resources *resource = find_resource(channel_id);
+
+	if (resource && scmi_id < resource->rd_count)
+		return &resource->rd[scmi_id];
+
+	return NULL;
+}
+
+int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id,
+			       bool assert_not_deassert)
+{
+	const struct sam_scmi_rd *rd = find_rd(channel_id, scmi_id);
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!rd)
+		return SCMI_NOT_FOUND;
+
+	if (!rd->rstctrl)
+		return SCMI_DENIED;
+
+	if (assert_not_deassert) {
+		FMSG("SCMI reset %u set", scmi_id);
+		res = rstctrl_assert(rd->rstctrl);
+	} else {
+		FMSG("SCMI reset %u release", scmi_id);
+		res = rstctrl_deassert(rd->rstctrl);
+	}
+
+	if (res)
+		return SCMI_HARDWARE_ERROR;
+
+	return SCMI_SUCCESS;
+}
+
+size_t plat_scmi_rd_count(unsigned int channel_id)
+{
+	const struct channel_resources *resource = find_resource(channel_id);
+
+	if (!resource)
+		return 0;
+
+	return resource->rd_count;
+}
+
 /*
  * Initialize platform SCMI resources
  */
 static TEE_Result sam_init_scmi_server(void)
 {
 	size_t i = 0;
+	size_t j = 0;
 
 	for (i = 0; i < ARRAY_SIZE(scmi_channel); i++) {
 		const struct channel_resources *res = scmi_channel + i;
@@ -544,6 +1134,18 @@ static TEE_Result sam_init_scmi_server(void)
 		assert(chan->shm_addr.va);
 
 		scmi_smt_init_agent_channel(chan);
+
+		for (j = 0; j < res->rd_count; j++) {
+			struct sam_scmi_rd *rd = &res->rd[j];
+			struct rstctrl *rstctrl = NULL;
+
+			rstctrl = sam_get_rstctrl(rd->reset_id);
+			assert(rstctrl);
+			if (rstctrl_get_exclusive(rstctrl))
+				continue;
+
+			rd->rstctrl = rstctrl;
+		}
 	}
 
 	return sam_init_scmi_clk();
diff --git a/core/arch/arm/plat-sam/sub.mk b/core/arch/arm/plat-sam/sub.mk
index a067d685a5bef97c3daf627b2e8409d66ab34b83..2ec74d3eb7382c7456aa532acb221ea48bdc5948 100644
--- a/core/arch/arm/plat-sam/sub.mk
+++ b/core/arch/arm/plat-sam/sub.mk
@@ -1,5 +1,7 @@
 global-incdirs-y += .
-srcs-y += main.c freq.c sam_sfr.c
+srcs-y += freq.c sam_sfr.c
+srcs-$(CFG_SAMA5D2) += platform_sama5d2.c
+srcs-$(CFG_SAMA7G5) += platform_sama7g5.c
 srcs-$(CFG_AT91_MATRIX) += matrix.c
 srcs-$(CFG_PL310) += sam_pl310.c
 srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.c
diff --git a/core/arch/arm/plat-sprd/console.c b/core/arch/arm/plat-sprd/console.c
index 15a4b3b9479438feef5172e630fb7d4088e7e4dd..eb765ff5ab881886128f0831e3dfa1effec99078 100644
--- a/core/arch/arm/plat-sprd/console.c
+++ b/core/arch/arm/plat-sprd/console.c
@@ -32,7 +32,7 @@
 
 static struct sprd_uart_data console_data;
 
-void console_init(void)
+void plat_console_init(void)
 {
 	sprd_uart_init(&console_data, CONSOLE_UART_BASE);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-stm/main.c b/core/arch/arm/plat-stm/main.c
index f0657cb83080ead1cb4dc294b54ab5776a7f615b..45e25dcd2426f2e24571a8545c2eab7fcd33a07e 100644
--- a/core/arch/arm/plat-stm/main.c
+++ b/core/arch/arm/plat-stm/main.c
@@ -56,7 +56,7 @@ TEE_Result tee_entry_std(struct optee_msg_arg *arg, uint32_t num_params)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	stih_asc_init(&console_data, UART_CONSOLE_BASE);
 }
diff --git a/core/arch/arm/plat-stm32mp1/conf.mk b/core/arch/arm/plat-stm32mp1/conf.mk
index a629c0803b298e79b099b6fd523f45c39bf47b5f..50b79fc31196a3b5408cd30fd079a9f87b04b296 100644
--- a/core/arch/arm/plat-stm32mp1/conf.mk
+++ b/core/arch/arm/plat-stm32mp1/conf.mk
@@ -58,6 +58,9 @@ flavorlist-MP15 = $(flavor_dts_file-157A_DHCOR_AVENGER96) \
 
 flavorlist-MP13 = $(flavor_dts_file-135F_DK)
 
+flavorlist-dh-platforms = $(flavor_dts_file-157A_DHCOR_AVENGER96) \
+			  $(flavor_dts_file-157C_DHCOM_PDK2)
+
 ifneq ($(PLATFORM_FLAVOR),)
 ifeq ($(flavor_dts_file-$(PLATFORM_FLAVOR)),)
 $(error Invalid platform flavor $(PLATFORM_FLAVOR))
@@ -89,6 +92,10 @@ ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-MP15)),)
 $(call force,CFG_STM32MP15,y)
 endif
 
+ifneq ($(filter $(CFG_EMBED_DTB_SOURCE_FILE),$(flavorlist-dh-platforms)),)
+CFG_STM32_ALLOW_UNSAFE_PROBE ?= y
+endif
+
 # CFG_STM32MP1x switches are exclusive.
 # - CFG_STM32MP15 is enabled for STM32MP15x-* targets (default)
 # - CFG_STM32MP13 is enabled for STM32MP13x-* targets
@@ -130,7 +137,7 @@ $(call force,CFG_SECONDARY_INIT_CNTFRQ,n)
 $(call force,CFG_STM32_GPIO,y)
 $(call force,CFG_STM32_VREFBUF,y)
 $(call force,CFG_STM32MP_CLK_CORE,y)
-$(call force,CFG_STM32MP1_SHARED_RESOURCES,n)
+$(call force,CFG_STM32MP1_RSTCTRL,y)
 $(call force,CFG_STM32MP13_CLK,y)
 $(call force,CFG_STM32MP13_REGULATOR_IOD,y)
 $(call force,CFG_TEE_CORE_NB_CORE,1)
@@ -145,8 +152,8 @@ $(call force,CFG_BOOT_SECONDARY_REQUEST,y)
 $(call force,CFG_DRIVERS_CLK_FIXED,n)
 $(call force,CFG_HALT_CORES_ON_PANIC_SGI,15)
 $(call force,CFG_SECONDARY_INIT_CNTFRQ,y)
-$(call force,CFG_STM32MP1_SHARED_RESOURCES,y)
 $(call force,CFG_STM32_SAES,n)
+$(call force,CFG_STM32MP1_RSTCTRL,y)
 $(call force,CFG_STM32MP15_CLK,y)
 CFG_CORE_RESERVED_SHM ?= n
 CFG_HALT_CORES_ON_PANIC ?= y
@@ -199,6 +206,7 @@ CFG_DRAM_SIZE    ?= 0x40000000
 CFG_STM32MP1_SCMI_SHM_SYSRAM ?= n
 ifeq ($(CFG_STM32MP1_SCMI_SHM_SYSRAM),y)
 $(call force,CFG_STM32MP1_SCMI_SHM_BASE,0x2ffff000)
+CFG_TZSRAM_SIZE  ?= 0x0003f000
 else
 CFG_STM32MP1_SCMI_SHM_BASE ?= 0
 endif
@@ -212,7 +220,7 @@ else
 CFG_TZDRAM_SIZE  ?= 0x02000000
 endif
 CFG_TZSRAM_START ?= 0x2ffc0000
-CFG_TZSRAM_SIZE  ?= 0x0003f000
+CFG_TZSRAM_SIZE  ?= 0x00040000
 ifeq ($(CFG_CORE_RESERVED_SHM),y)
 CFG_SHMEM_START  ?= ($(CFG_TZDRAM_START) + $(CFG_TZDRAM_SIZE))
 CFG_SHMEM_SIZE   ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_SHMEM_START))
@@ -260,6 +268,7 @@ $(eval $(call cfg-depends-all,CFG_STM32_RSTCTRL,CFG_DRIVERS_RSTCTRL))
 CFG_WDT ?= $(CFG_STM32_IWDG)
 CFG_WDT_SM_HANDLER ?= $(CFG_WDT)
 CFG_WDT_SM_HANDLER_ID ?= 0xbc000000
+$(eval $(call cfg-depends-all,CFG_STM32_IWDG,CFG_WDT_SM_HANDLER CFG_WDT))
 
 # Platform specific configuration
 CFG_STM32MP_PANIC_ON_TZC_PERM_VIOLATION ?= y
@@ -297,7 +306,7 @@ endif # CFG_SCMI_PTA
 
 CFG_SCMI_SCPFW ?= n
 ifeq ($(CFG_SCMI_SCPFW),y)
-$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-stm32mp1)
+$(call force,CFG_SCMI_SCPFW_PRODUCT,stm32mp1)
 endif
 
 CFG_SCMI_MSG_DRIVERS ?= n
@@ -332,6 +341,9 @@ endif
 CFG_ENABLE_EMBEDDED_TESTS ?= y
 CFG_WITH_STATS ?= y
 
+# Default enable software fallback on crypto drivers
+CFG_STM32_SAES_SW_FALLBACK ?= y
+
 # Enable OTP update with BSEC driver
 CFG_STM32_BSEC_WRITE ?= y
 
@@ -341,9 +353,6 @@ CFG_TEE_CORE_DEBUG ?= n
 CFG_UNWIND ?= n
 CFG_LOCKDEP ?= n
 CFG_TA_BGET_TEST ?= n
-# Default disable early TA compression to support a smaller HEAP size
-CFG_EARLY_TA_COMPRESS ?= n
-CFG_CORE_HEAP_SIZE ?= 49152
 endif
 
 # Non-secure UART and GPIO/pinctrl for the output console
@@ -408,3 +417,11 @@ CFG_STM32_DEBUG_ACCESS ?= $(CFG_TEE_CORE_DEBUG)
 ifeq ($(call cfg-all-enabled,CFG_STM32MP15 CFG_STM32MP13),y)
 $(error CFG_STM32MP13_CLK and CFG_STM32MP15_CLK are exclusive)
 endif
+
+CFG_DRIVERS_FIREWALL ?= y
+ifeq ($(CFG_STM32_ETZPC),y)
+$(call force,CFG_DRIVERS_FIREWALL,y)
+endif
+
+# Allow probing of unsafe peripherals. Firewall config will not be checked
+CFG_STM32_ALLOW_UNSAFE_PROBE ?= n
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
index 42735b8985e54c341f10af00f8c9ae3076d63b3d..effb14d448abfc1af6c7bb7c93bfadc9e90801b7 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
+++ b/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_pmic.c
@@ -288,40 +288,6 @@ const char *stm32mp_pmic_get_cpu_supply_name(void)
 	return cpu_supply_name;
 }
 
-/* Preallocate not that much regu references */
-static char *nsec_access_regu_name[PMIC_REGU_COUNT];
-
-bool stm32mp_nsec_can_access_pmic_regu(const char *name)
-{
-	size_t n = 0;
-
-	for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++)
-		if (nsec_access_regu_name[n] &&
-		    !strcmp(nsec_access_regu_name[n], name))
-			return true;
-
-	return false;
-}
-
-static void register_nsec_regu(const char *name_ref)
-{
-	size_t n = 0;
-
-	assert(!stm32mp_nsec_can_access_pmic_regu(name_ref));
-
-	for (n = 0; n < ARRAY_SIZE(nsec_access_regu_name); n++) {
-		if (!nsec_access_regu_name[n]) {
-			nsec_access_regu_name[n] = strdup(name_ref);
-
-			if (!nsec_access_regu_name[n])
-				panic();
-			break;
-		}
-	}
-
-	assert(stm32mp_nsec_can_access_pmic_regu(name_ref));
-}
-
 static TEE_Result pmic_set_state(struct regulator *regulator, bool enable)
 {
 	struct pmic_regulator_data *priv = regulator->priv;
@@ -389,14 +355,6 @@ static TEE_Result pmic_set_voltage(struct regulator *regulator, int level_uv)
 	return TEE_SUCCESS;
 }
 
-static int cmp_int_value(const void *a, const void *b)
-{
-	const int *ia = a;
-	const int *ib = b;
-
-	return CMP_TRILEAN(*ia, *ib);
-}
-
 static size_t refine_levels_array(size_t count, int *levels_uv,
 				  int min_uv, int max_uv)
 {
@@ -404,7 +362,7 @@ static size_t refine_levels_array(size_t count, int *levels_uv,
 	size_t m = 0;
 
 	/* We need to sort the array has STPMIC1 driver does not */
-	qsort(levels_uv, count, sizeof(*levels_uv), cmp_int_value);
+	qsort_int(levels_uv, count);
 
 	/* Remove duplicates and return optimized count */
 	for (n = 1; n < count; n++) {
@@ -550,8 +508,10 @@ static TEE_Result release_voltage_lists(void)
 	for (n = 0; n < ARRAY_SIZE(pmic_regulators); n++) {
 		struct pmic_regulator_data *priv = pmic_regulators[n].priv;
 
-		if (priv && priv->voltages_level)
+		if (priv && priv->voltages_level) {
 			free(priv->voltages_level);
+			priv->voltages_level = NULL;
+		}
 	}
 
 	return TEE_SUCCESS;
@@ -637,9 +597,6 @@ static void parse_regulator_fdt_nodes(const void *fdt, int pmic_node)
 
 		assert(stpmic1_regulator_is_valid(regu_name));
 
-		if (status & DT_STATUS_OK_NSEC)
-			register_nsec_regu(regu_name);
-
 		for (n = 0; n < ARRAY_SIZE(regu_lp_state); n++)
 			dt_get_regu_low_power_config(fdt, regu_name, regu_node,
 						     regu_lp_state[n].name);
@@ -713,29 +670,6 @@ void stm32mp_put_pmic(void)
 	stm32_i2c_suspend(i2c_handle);
 }
 
-static void register_non_secure_pmic(void)
-{
-	/* Allow this function to be called when STPMIC1 not used */
-	if (!i2c_handle->base.pa)
-		return;
-
-	stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl);
-	if (i2c_handle->pinctrl_sleep)
-		stm32mp_register_non_secure_pinctrl(i2c_handle->pinctrl_sleep);
-
-	stm32mp_register_non_secure_periph_iomem(i2c_handle->base.pa);
-}
-
-static void register_secure_pmic(void)
-{
-	stm32mp_register_secure_pinctrl(i2c_handle->pinctrl);
-	if (i2c_handle->pinctrl_sleep)
-		stm32mp_register_secure_pinctrl(i2c_handle->pinctrl_sleep);
-
-	stm32mp_register_secure_periph_iomem(i2c_handle->base.pa);
-	register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic");
-}
-
 static TEE_Result initialize_pmic(const void *fdt, int pmic_node)
 {
 	unsigned long pmic_version = 0;
@@ -753,9 +687,7 @@ static TEE_Result initialize_pmic(const void *fdt, int pmic_node)
 	stm32mp_put_pmic();
 
 	if (dt_pmic_is_secure())
-		register_secure_pmic();
-	else
-		register_non_secure_pmic();
+		register_pm_driver_cb(pmic_pm, NULL, "stm32mp1-pmic");
 
 	parse_regulator_fdt_nodes(fdt, pmic_node);
 
diff --git a/core/arch/arm/plat-stm32mp1/main.c b/core/arch/arm/plat-stm32mp1/main.c
index eed6b77c238350f917253f9af9f4fda63cdc2dcd..b9075920aaa8f5a035624ca6961377043908db99 100644
--- a/core/arch/arm/plat-stm32mp1/main.c
+++ b/core/arch/arm/plat-stm32mp1/main.c
@@ -1,28 +1,33 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2017-2022, STMicroelectronics
+ * Copyright (c) 2017-2024, STMicroelectronics
  * Copyright (c) 2016-2018, Linaro Limited
  */
 
 #include <boot_api.h>
 #include <config.h>
 #include <console.h>
+#include <drivers/firewall_device.h>
 #include <drivers/gic.h>
 #include <drivers/pinctrl.h>
+#include <drivers/stm32_bsec.h>
 #include <drivers/stm32_etzpc.h>
 #include <drivers/stm32_gpio.h>
 #include <drivers/stm32_iwdg.h>
-#include <drivers/stm32_tamp.h>
 #include <drivers/stm32_uart.h>
-#include <drivers/stm32mp1_etzpc.h>
 #include <drivers/stm32mp_dt_bindings.h>
+#ifdef CFG_STM32MP15
+#include <drivers/stm32mp1_rcc.h>
+#endif
 #include <io.h>
 #include <kernel/boot.h>
 #include <kernel/dt.h>
+#include <kernel/dt_driver.h>
 #include <kernel/misc.h>
 #include <kernel/panic.h>
 #include <kernel/spinlock.h>
 #include <kernel/tee_misc.h>
+#include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <platform_config.h>
 #include <sm/psci.h>
@@ -76,22 +81,21 @@ service_init(platform_banner);
  */
 static struct stm32_uart_pdata console_data;
 
-void console_init(void)
+void plat_console_init(void)
 {
 	/* Early console initialization before MMU setup */
 	struct uart {
 		paddr_t pa;
-		bool secure;
 	} uarts[] = {
 		[0] = { .pa = 0 },
-		[1] = { .pa = USART1_BASE, .secure = true, },
-		[2] = { .pa = USART2_BASE, .secure = false, },
-		[3] = { .pa = USART3_BASE, .secure = false, },
-		[4] = { .pa = UART4_BASE, .secure = false, },
-		[5] = { .pa = UART5_BASE, .secure = false, },
-		[6] = { .pa = USART6_BASE, .secure = false, },
-		[7] = { .pa = UART7_BASE, .secure = false, },
-		[8] = { .pa = UART8_BASE, .secure = false, },
+		[1] = { .pa = USART1_BASE },
+		[2] = { .pa = USART2_BASE },
+		[3] = { .pa = USART3_BASE },
+		[4] = { .pa = UART4_BASE },
+		[5] = { .pa = UART5_BASE },
+		[6] = { .pa = USART6_BASE },
+		[7] = { .pa = UART7_BASE },
+		[8] = { .pa = UART8_BASE },
 	};
 
 	COMPILE_TIME_ASSERT(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART);
@@ -102,7 +106,6 @@ void console_init(void)
 	/* No clock yet bound to the UART console */
 	console_data.clock = NULL;
 
-	console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure;
 	stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa);
 
 	register_serial_console(&console_data.chip);
@@ -139,7 +142,7 @@ static TEE_Result init_console_from_dt(void)
 	console_flush();
 	console_data = *pd;
 	register_serial_console(&console_data.chip);
-	IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-");
+	IMSG("DTB enables console");
 	free(pd);
 
 	return TEE_SUCCESS;
@@ -165,84 +168,6 @@ void boot_secondary_init_intc(void)
 	stm32mp_register_online_cpu();
 }
 
-#ifdef CFG_STM32MP13
-#ifdef CFG_STM32_ETZPC
-/* Configure ETZPC cell and lock it when resource is secure */
-static void config_lock_decprot(uint32_t decprot_id,
-				enum etzpc_decprot_attributes decprot_attr)
-{
-	etzpc_configure_decprot(decprot_id, decprot_attr);
-
-	if (decprot_attr == ETZPC_DECPROT_S_RW)
-		etzpc_lock_decprot(decprot_id);
-}
-
-static TEE_Result set_etzpc_secure_configuration(void)
-{
-	config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_DDRCTRLPHY_ID,
-			    ETZPC_DECPROT_NS_R_S_W);
-
-	/* Configure ETZPC with peripheral registering */
-	config_lock_decprot(STM32MP1_ETZPC_ADC1_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_ADC2_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_CRYP_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_DCMIPP_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_ETH1_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_ETH2_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_FMC_ID, ETZPC_DECPROT_NS_RW);
-	/* HASH is secure */
-	config_lock_decprot(STM32MP1_ETZPC_HASH_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_I2C3_ID, ETZPC_DECPROT_NS_RW);
-	/* I2C4 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_I2C4_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_I2C5_ID, ETZPC_DECPROT_NS_RW);
-	/* IWDG1 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_LPTIM2_ID, ETZPC_DECPROT_NS_RW);
-	/* LPTIM3 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_LPTIM3_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_LTDC_ID, ETZPC_DECPROT_NS_RW);
-	/* MCE is secure */
-	config_lock_decprot(STM32MP1_ETZPC_MCE_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_OTG_ID, ETZPC_DECPROT_NS_RW);
-	/* PKA is secure */
-	config_lock_decprot(STM32MP1_ETZPC_PKA_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_QSPI_ID, ETZPC_DECPROT_NS_RW);
-	/* RNG is secure */
-	config_lock_decprot(STM32MP1_ETZPC_RNG_ID, ETZPC_DECPROT_S_RW);
-	/* SAES is secure */
-	config_lock_decprot(STM32MP1_ETZPC_SAES_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SDMMC1_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SDMMC2_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SPI4_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SPI5_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID, ETZPC_DECPROT_NS_RW);
-	/* SRAM3 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID, ETZPC_DECPROT_S_RW);
-	/* STGENC is secure */
-	config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
-	/* TIM12 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_TIM12_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_TIM13_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_TIM14_ID, ETZPC_DECPROT_NS_RW);
-	/* TIM15 is secure */
-	config_lock_decprot(STM32MP1_ETZPC_TIM15_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_TIM16_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_TIM17_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_USART1_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_USART2_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_USBPHYCTRL_ID, ETZPC_DECPROT_NS_RW);
-	config_lock_decprot(STM32MP1_ETZPC_VREFBUF_ID, ETZPC_DECPROT_NS_RW);
-
-	return TEE_SUCCESS;
-}
-
-driver_init_late(set_etzpc_secure_configuration);
-#endif /* CFG_STM32_ETZPC */
-#endif /* CFG_STM32MP13 */
-
 #ifdef CFG_STM32MP15
 /*
  * This concerns OP-TEE pager for STM32MP1 to use secure internal
@@ -296,10 +221,6 @@ driver_init_late(set_etzpc_secure_configuration);
 #define SRAMS_START			SRAM1_BASE
 #define TZSRAM_END			(CFG_TZSRAM_START + CFG_TZSRAM_SIZE)
 
-#define SCMI_SHM_IS_IN_SRAMX	((CFG_STM32MP1_SCMI_SHM_BASE >= SRAM1_BASE) && \
-				 (CFG_STM32MP1_SCMI_SHM_BASE + \
-				  CFG_STM32MP1_SCMI_SHM_SIZE) <= SRAMS_END)
-
 #define TZSRAM_FITS_IN_SYSRAM_SEC	((CFG_TZSRAM_START >= SYSRAM_BASE) && \
 					 (TZSRAM_END <= SYSRAM_SEC_END))
 
@@ -325,68 +246,128 @@ driver_init_late(set_etzpc_secure_configuration);
  */
 static_assert(TZSRAM_FITS_IN_SYSRAM_SEC || TZSRAM_FITS_IN_SYSRAM_AND_SRAMS ||
 	      TZSRAM_FITS_IN_SRAMS || TZSRAM_IS_IN_DRAM);
+#endif /* CFG_WITH_PAGER */
+#endif /* CFG_STM32MP15 */
+
+static TEE_Result secure_pager_ram(struct dt_driver_provider *fw_provider,
+				   unsigned int decprot_id,
+				   paddr_t base, size_t secure_size)
+{
+	/* Lock firewall configuration for secure internal RAMs used by pager */
+	uint32_t query_arg = DECPROT(decprot_id, DECPROT_S_RW, DECPROT_LOCK);
+	struct firewall_query fw_query = {
+		.ctrl = dt_driver_provider_priv_data(fw_provider),
+		.args = &query_arg,
+		.arg_count = 1,
+	};
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool is_pager_ram = false;
+
+#if defined(CFG_WITH_PAGER)
+	is_pager_ram = core_is_buffer_intersect(CFG_TZSRAM_START,
+						CFG_TZSRAM_SIZE,
+						base, secure_size);
 #endif
+	if (!is_pager_ram)
+		return TEE_SUCCESS;
 
-#if TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS || \
-	SCMI_SHM_IS_IN_SRAMX
-/* At run time we enforce that SRAM1 to SRAM4 are properly assigned if used */
-static TEE_Result init_stm32mp15_secure_srams(void)
+	res = firewall_set_memory_configuration(&fw_query, base, secure_size);
+	if (res)
+		EMSG("Failed to configure secure SRAM %#"PRIxPA"..%#"PRIxPA,
+		     base, base + secure_size);
+
+	return res;
+}
+
+static TEE_Result non_secure_scmi_ram(struct dt_driver_provider *fw_provider,
+				      unsigned int decprot_id,
+				      paddr_t base, size_t size)
 {
-	if (IS_ENABLED(CFG_WITH_PAGER)) {
-		if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE,
-					     SRAM1_BASE, SRAM1_SIZE))
-			stm32mp_register_secure_periph_iomem(SRAM1_BASE);
+	/* Do not lock firewall configuration for non-secure internal RAMs */
+	uint32_t query_arg = DECPROT(decprot_id, DECPROT_NS_RW, DECPROT_UNLOCK);
+	struct firewall_query fw_query = {
+		.ctrl = dt_driver_provider_priv_data(fw_provider),
+		.args = &query_arg,
+		.arg_count = 1,
+	};
+	TEE_Result res = TEE_ERROR_GENERIC;
 
-		if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE,
-					     SRAM2_BASE, SRAM2_SIZE))
-			stm32mp_register_secure_periph_iomem(SRAM2_BASE);
+	if (!core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
+				      CFG_STM32MP1_SCMI_SHM_SIZE,
+				      base, size))
+		return TEE_SUCCESS;
 
-		if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE,
-					     SRAM3_BASE, SRAM3_SIZE))
-			stm32mp_register_secure_periph_iomem(SRAM3_BASE);
+	res = firewall_set_memory_configuration(&fw_query, base, size);
+	if (res)
+		EMSG("Failed to configure non-secure SRAM %#"PRIxPA"..%#"PRIxPA,
+		     base, base + size);
 
-		if (core_is_buffer_intersect(CFG_TZSRAM_START, CFG_TZSRAM_SIZE,
-					     SRAM4_BASE, SRAM4_SIZE))
-			stm32mp_register_secure_periph_iomem(SRAM4_BASE);
-	}
+	return res;
+}
 
-	if (SCMI_SHM_IS_IN_SRAMX) {
-		if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
-					     CFG_STM32MP1_SCMI_SHM_SIZE,
-					     SRAM1_BASE, SRAM1_SIZE))
-			stm32mp_register_non_secure_periph_iomem(SRAM1_BASE);
-
-		if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
-					     CFG_STM32MP1_SCMI_SHM_SIZE,
-					     SRAM2_BASE, SRAM2_SIZE))
-			stm32mp_register_non_secure_periph_iomem(SRAM2_BASE);
-
-		if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
-					     CFG_STM32MP1_SCMI_SHM_SIZE,
-					     SRAM3_BASE, SRAM3_SIZE))
-			stm32mp_register_non_secure_periph_iomem(SRAM3_BASE);
-
-		if (core_is_buffer_intersect(CFG_STM32MP1_SCMI_SHM_BASE,
-					     CFG_STM32MP1_SCMI_SHM_SIZE,
-					     SRAM4_BASE, SRAM4_SIZE))
-			stm32mp_register_non_secure_periph_iomem(SRAM4_BASE);
+/* At run time we enforce that SRAM1 to SRAM4 are properly assigned if used */
+static void configure_srams(struct dt_driver_provider *fw_provider)
+{
+	bool error = false;
+
+	if (IS_ENABLED(CFG_WITH_PAGER)) {
+		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM1_ID,
+				     SRAM1_BASE, SRAM1_SIZE))
+			error = true;
+
+		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM2_ID,
+				     SRAM2_BASE, SRAM2_SIZE))
+			error = true;
+
+		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM3_ID,
+				     SRAM3_BASE, SRAM3_SIZE))
+			error = true;
+
+#if defined(CFG_STM32MP15)
+		if (secure_pager_ram(fw_provider, STM32MP1_ETZPC_SRAM4_ID,
+				     SRAM4_BASE, SRAM4_SIZE))
+			error = true;
+#endif
+	}
+	if (CFG_STM32MP1_SCMI_SHM_BASE) {
+		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM1_ID,
+					SRAM1_BASE, SRAM1_SIZE))
+			error = true;
+
+		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM2_ID,
+					SRAM2_BASE, SRAM2_SIZE))
+			error = true;
+
+		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM3_ID,
+					SRAM3_BASE, SRAM3_SIZE))
+			error = true;
+
+#if defined(CFG_STM32MP15)
+		if (non_secure_scmi_ram(fw_provider, STM32MP1_ETZPC_SRAM4_ID,
+					SRAM4_BASE, SRAM4_SIZE))
+			error = true;
+#endif
 	}
 
-	return TEE_SUCCESS;
+	if (error)
+		panic();
 }
 
-service_init_late(init_stm32mp15_secure_srams);
-#endif /* TZSRAM_FITS_IN_SYSRAM_AND_SRAMS || TZSRAM_FITS_IN_SRAMS */
-#endif /* CFG_STM32MP15 && CFG_TZSRAM_START */
-
-static TEE_Result init_stm32mp1_drivers(void)
+static void configure_sysram(struct dt_driver_provider *fw_provider)
 {
-	/* Secure internal memories for the platform, once ETZPC is ready */
-	etzpc_configure_tzma(0, ETZPC_TZMA_ALL_SECURE);
-	etzpc_lock_tzma(0);
+	uint32_t query_arg = DECPROT(ETZPC_TZMA1_ID, DECPROT_S_RW,
+				     DECPROT_UNLOCK);
+	struct firewall_query firewall = {
+		.ctrl = dt_driver_provider_priv_data(fw_provider),
+		.args = &query_arg,
+		.arg_count = 1,
+	};
+	TEE_Result res = TEE_ERROR_GENERIC;
 
-	etzpc_configure_tzma(1, SYSRAM_SEC_SIZE >> SMALL_PAGE_SHIFT);
-	etzpc_lock_tzma(1);
+	res = firewall_set_memory_configuration(&firewall, SYSRAM_BASE,
+						SYSRAM_SEC_SIZE);
+	if (res)
+		panic("Unable to secure SYSRAM");
 
 	if (SYSRAM_SIZE > SYSRAM_SEC_SIZE) {
 		size_t nsec_size = SYSRAM_SIZE - SYSRAM_SEC_SIZE;
@@ -399,32 +380,37 @@ static TEE_Result init_stm32mp1_drivers(void)
 		/* Clear content from the non-secure part */
 		memset(va, 0, nsec_size);
 	}
-
-	return TEE_SUCCESS;
 }
 
-service_init_late(init_stm32mp1_drivers);
-
 static TEE_Result init_late_stm32mp1_drivers(void)
 {
-	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t __maybe_unused state = 0;
 
-	/* Set access permission to TAM backup registers */
-	if (IS_ENABLED(CFG_STM32_TAMP)) {
-		struct stm32_bkpregs_conf conf = {
-			.nb_zone1_regs = TAMP_BKP_REGISTER_ZONE1_COUNT,
-			.nb_zone2_regs = TAMP_BKP_REGISTER_ZONE2_COUNT,
-		};
-
-		res = stm32_tamp_set_secure_bkpregs(&conf);
-		if (res == TEE_ERROR_DEFER_DRIVER_INIT) {
-			/* TAMP driver was not probed if disabled in the DT */
-			res = TEE_SUCCESS;
-		}
-		if (res)
-			panic();
+	/* Configure SYSRAM and SRAMx secure hardening */
+	if (IS_ENABLED(CFG_STM32_ETZPC)) {
+		struct dt_driver_provider *prov = NULL;
+		int node = 0;
+
+		node = fdt_node_offset_by_compatible(get_embedded_dt(), -1,
+						     "st,stm32-etzpc");
+		if (node < 0)
+			panic("Could not get ETZPC node");
+
+		prov = dt_driver_get_provider_by_node(node, DT_DRIVER_FIREWALL);
+		assert(prov);
+
+		configure_sysram(prov);
+		configure_srams(prov);
 	}
 
+#ifdef CFG_STM32MP15
+	/* Device in Secure Closed state require RCC secure hardening */
+	if (stm32_bsec_get_state(&state))
+		panic();
+	if (state == BSEC_STATE_SEC_CLOSED && !stm32_rcc_is_secure())
+		panic("Closed device mandates secure RCC");
+#endif
+
 	return TEE_SUCCESS;
 }
 
@@ -574,3 +560,63 @@ early_init_late(init_debug);
 
 /* Some generic resources need to be unpaged */
 DECLARE_KEEP_PAGER(pinctrl_apply_state);
+
+bool stm32mp_allow_probe_shared_device(const void *fdt, int node)
+{
+	static int uart_console_node = -1;
+	const char *compat = NULL;
+	static bool once;
+
+	if (IS_ENABLED(CFG_STM32_ALLOW_UNSAFE_PROBE))
+		return true;
+
+	if (!once) {
+		get_console_node_from_dt((void *)fdt, &uart_console_node,
+					 NULL, NULL);
+		once = true;
+	}
+
+	compat = fdt_stringlist_get(fdt, node, "compatible", 0, NULL);
+
+	/*
+	 * Allow OP-TEE console and MP15 I2C and RNG to be shared
+	 * with non-secure world.
+	 */
+	if (node == uart_console_node ||
+	    !strcmp(compat, "st,stm32mp15-i2c-non-secure") ||
+	    (!strcmp(compat, "st,stm32-rng") &&
+	     IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)))
+		return true;
+
+	return false;
+}
+
+#if defined(CFG_STM32MP15) && defined(CFG_WITH_PAGER)
+paddr_t stm32mp1_pa_or_sram_alias_pa(paddr_t pa)
+{
+	/*
+	 * OP-TEE uses the alias physical addresses of SRAM1/2/3/4,
+	 * not the standard physical addresses. This choice was initially
+	 * driven by pager that needs physically contiguous memories
+	 * for internal secure memories.
+	 */
+	if (core_is_buffer_inside(pa, 1, SRAM1_ALT_BASE, SRAM1_SIZE))
+		pa += SRAM1_BASE - SRAM1_ALT_BASE;
+	else if (core_is_buffer_inside(pa, 1, SRAM2_ALT_BASE, SRAM2_SIZE))
+		pa += SRAM2_BASE - SRAM2_ALT_BASE;
+	else if (core_is_buffer_inside(pa, 1, SRAM3_ALT_BASE, SRAM3_SIZE))
+		pa += SRAM3_BASE - SRAM3_ALT_BASE;
+	else if (core_is_buffer_inside(pa, 1, SRAM4_ALT_BASE, SRAM4_SIZE))
+		pa += SRAM4_BASE - SRAM4_ALT_BASE;
+
+	return pa;
+}
+
+bool stm32mp1_ram_intersect_pager_ram(paddr_t base, size_t size)
+{
+	base = stm32mp1_pa_or_sram_alias_pa(base);
+
+	return core_is_buffer_intersect(base, size, CFG_TZSRAM_START,
+					CFG_TZSRAM_SIZE);
+}
+#endif
diff --git a/core/arch/arm/plat-stm32mp1/plat_tzc400.c b/core/arch/arm/plat-stm32mp1/plat_tzc400.c
index 25c75b93c0ef931114a4bc7a829746c9030c1f52..df8aff737404b91f5127b5ec4a67a52987fa4316 100644
--- a/core/arch/arm/plat-stm32mp1/plat_tzc400.c
+++ b/core/arch/arm/plat-stm32mp1/plat_tzc400.c
@@ -5,21 +5,102 @@
 
 #include <assert.h>
 #include <config.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32mp_dt_bindings.h>
 #include <drivers/tzc400.h>
 #include <initcall.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/dt.h>
 #include <kernel/interrupt.h>
 #include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <kernel/tee_misc.h>
+#include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <platform_config.h>
+#include <stm32_util.h>
 #include <trace.h>
 #include <util.h>
 
-#ifdef CFG_STM32MP15
-#define TZC_FILTERS_MASK	GENMASK_32(1, 0)
-#endif
-#ifdef CFG_STM32MP13
-#define TZC_FILTERS_MASK	GENMASK_32(0, 0)
-#endif
+#define IS_PAGE_ALIGNED(addr)		(((addr) & SMALL_PAGE_MASK) == 0)
+#define FILTER_MASK(_width)		GENMASK_32(((_width) - U(1)), U(0))
+
+/*
+ * struct stm32mp_tzc_region - Define a TZC400 region configuration
+ * @cfg: Region configuration bit mask
+ * @addr: Region physical base address
+ * @len: Region byte size
+ */
+struct stm32mp_tzc_region {
+	uint32_t cfg;
+	uint32_t addr;
+	uint32_t len;
+};
+
+/*
+ * struct stm32mp_tzc_platdata - Device platform data
+ * @name: Device name for debug purpose
+ * @base: TZC400 IOMEM base address
+ * @clk: TZC400 bus clocks (1 or 2 clocks, depending on the platform)
+ * @mem_base: Physical base address of the memory covered by the device
+ * @mem_size: Byte size of the physical memory covered by the device
+ * @itr_chip: Interrupt controller handle
+ * @itr_num: TZC400 interrupt number handled by @itr_chip
+ */
+struct stm32mp_tzc_platdata {
+	const char *name;
+	vaddr_t base;
+	struct clk *clk[2];
+	uint32_t mem_base;
+	uint32_t mem_size;
+	struct itr_chip *itr_chip;
+	size_t itr_num;
+};
+
+/*
+ * struct stm32mp_tzc_driver_data - Device configuration read from the hardware
+ * @nb_filters: Number of TZC400 filter cells
+ * @nb_regions: Number of regions supported by the TZC400
+ */
+struct stm32mp_tzc_driver_data {
+	uint32_t nb_filters;
+	uint32_t nb_regions;
+};
+
+/*
+ * struct tzc_device - Device data
+ * @pdata: Device configuration read from the platform DT
+ * @ddata: Device configuration data read from the hardware
+ * @reg: Array of regions configured in the controller
+ * @nb_reg_used: Number of cells in @reg
+ */
+struct tzc_device {
+	struct stm32mp_tzc_platdata pdata;
+	struct stm32mp_tzc_driver_data ddata;
+	struct tzc_region_config *reg;
+	uint32_t nb_reg_used;
+};
+
+/*
+ * struct tzc_region_non_sec - Registered non-secure memory region
+ * @region: Memory region description
+ * @link: Link in non-secure memory list
+ *
+ * At TZC driver initialization, there are memory regions defined in the DT
+ * with TZC configuration information. TZC is first configured for each of
+ * these regions and each is carved out from the overall memory address range
+ * controlled by TZC. This results in a series a memory regions that, by
+ * construction, are assigned to non-secure world.
+ */
+struct tzc_region_non_sec {
+	struct tzc_region_config region;
+	SLIST_ENTRY(tzc_region_non_sec) link;
+};
+
+static SLIST_HEAD(nsec_list_head, tzc_region_non_sec) nsec_region_list =
+	SLIST_HEAD_INITIALIZER(nsec_list_head);
 
 static enum itr_return tzc_it_handler(struct itr_handler *handler __unused)
 {
@@ -33,91 +114,439 @@ static enum itr_return tzc_it_handler(struct itr_handler *handler __unused)
 
 	return ITRR_HANDLED;
 }
+DECLARE_KEEP_PAGER(tzc_it_handler);
 
-static struct itr_handler tzc_itr_handler = {
-	.it = STM32MP1_IRQ_TZC,
-	.handler = tzc_it_handler,
-};
-DECLARE_KEEP_PAGER(tzc_itr_handler);
+static TEE_Result tzc_region_check_overlap(struct tzc_device *tzc_dev,
+					   const struct tzc_region_config *reg)
+{
+	unsigned int i = 0;
+
+	/* Check if base address already defined in another region */
+	for (i = 0; i < tzc_dev->nb_reg_used; i++)
+		if (reg->base <= tzc_dev->reg[i].top &&
+		    reg->top >= tzc_dev->reg[i].base)
+			return TEE_ERROR_ACCESS_CONFLICT;
+
+	return TEE_SUCCESS;
+}
 
-static bool tzc_region_is_non_secure(unsigned int i, uint64_t pa, size_t size)
+static void tzc_set_driverdata(struct tzc_device *tzc_dev)
 {
-	struct tzc_region_config region_cfg = { };
-	uint32_t ns_cpu_mask = TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID);
-	uint32_t filters_mask = TZC_FILTERS_MASK;
-	vaddr_t base = pa;
+	uintptr_t base = tzc_dev->pdata.base;
+	uint32_t regval = 0;
 
-	if (tzc_get_region_config(i, &region_cfg))
-		panic();
+	regval = io_read32(base + BUILD_CONFIG_OFF);
+	tzc_dev->ddata.nb_filters = ((regval >> BUILD_CONFIG_NF_SHIFT) &
+				     BUILD_CONFIG_NF_MASK) + 1;
+	tzc_dev->ddata.nb_regions = ((regval >>	BUILD_CONFIG_NR_SHIFT) &
+				     BUILD_CONFIG_NR_MASK);
 
-	return region_cfg.base == base && region_cfg.top == (base + size - 1) &&
-	       region_cfg.sec_attr == TZC_REGION_S_NONE &&
-	       (region_cfg.ns_device_access & ns_cpu_mask) == ns_cpu_mask &&
-	       region_cfg.filters == filters_mask;
+	DMSG("TZC400 Filters %"PRIu32" Regions %"PRIu32,
+	     tzc_dev->ddata.nb_filters, tzc_dev->ddata.nb_regions);
 }
 
-static bool tzc_region_is_secure(unsigned int i, vaddr_t base, size_t size)
+static void stm32mp_tzc_region0(bool enable)
 {
-	struct tzc_region_config region_cfg = { };
-	uint32_t filters_mask = TZC_FILTERS_MASK;
+	struct tzc_region_config region_cfg_0 = {
+		.base = 0,
+		.top = UINT_MAX,
+		.sec_attr = TZC_REGION_S_NONE,
+		.ns_device_access = 0,
+	};
 
-	if (tzc_get_region_config(i, &region_cfg))
-		panic();
+	if (enable)
+		region_cfg_0.sec_attr = TZC_REGION_S_RDWR;
+
+	tzc_configure_region(0, &region_cfg_0);
+}
+
+static void stm32mp_tzc_reset_region(struct tzc_device *tzc_dev)
+{
+	unsigned int i = 0;
+	const struct tzc_region_config cfg = { .top = 0x00000FFF };
+
+	/* Clean old configuration */
+	for (i = 0; i < tzc_dev->ddata.nb_regions; i++)
+		tzc_configure_region(i + 1, &cfg);
+}
+
+static TEE_Result append_region(struct tzc_device *tzc_dev,
+				const struct tzc_region_config *region_cfg)
+{
+	TEE_Result res = TEE_SUCCESS;
+	unsigned int index = tzc_dev->nb_reg_used;
+
+	if (index >= tzc_dev->ddata.nb_regions ||
+	    !core_is_buffer_inside(region_cfg->base,
+				   region_cfg->top + 1 - region_cfg->base,
+				   tzc_dev->pdata.mem_base,
+				   tzc_dev->pdata.mem_size))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = tzc_region_check_overlap(tzc_dev, region_cfg);
+	if (res)
+		return res;
+
+	tzc_dev->reg[tzc_dev->nb_reg_used] = *region_cfg;
+	tzc_dev->nb_reg_used++;
+
+	tzc_configure_region(tzc_dev->nb_reg_used, region_cfg);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+exclude_region_from_nsec(const struct tzc_region_config *reg_exclude)
+{
+	struct tzc_region_non_sec *reg = NULL;
+
+	SLIST_FOREACH(reg, &nsec_region_list, link) {
+		if (core_is_buffer_inside(reg_exclude->base,
+					  reg_exclude->top + 1 -
+					  reg_exclude->base,
+					  reg->region.base,
+					  reg->region.top + 1 -
+					  reg->region.base))
+			break;
+	}
+
+	if (!reg)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (reg_exclude->base == reg->region.base &&
+	    reg_exclude->top == reg->region.top) {
+		/* Remove this entry */
+		SLIST_REMOVE(&nsec_region_list, reg, tzc_region_non_sec, link);
+		free(reg);
+	} else if (reg_exclude->base == reg->region.base) {
+		reg->region.base = reg_exclude->top + 1;
+	} else if (reg_exclude->top == reg->region.top) {
+		reg->region.top = reg_exclude->base - 1;
+	} else {
+		struct tzc_region_non_sec *new_nsec =
+			calloc(1, sizeof(*new_nsec));
+
+		if (!new_nsec)
+			return TEE_ERROR_OUT_OF_MEMORY;
+
+		new_nsec->region = reg->region;
+		reg->region.top = reg_exclude->base - 1;
+		new_nsec->region.base = reg_exclude->top + 1;
+		SLIST_INSERT_AFTER(reg, new_nsec, link);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void stm32mp_tzc_cfg_boot_region(struct tzc_device *tzc_dev)
+{
+	unsigned int idx = 0;
+	static struct tzc_region_config boot_region[] = {
+		{
+			.base = CFG_TZDRAM_START,
+			.top = CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1,
+			.sec_attr = TZC_REGION_S_RDWR,
+			.ns_device_access = 0,
+		},
+#ifdef CFG_CORE_RESERVED_SHM
+		{
+			.base = CFG_SHMEM_START,
+			.top = CFG_SHMEM_START + CFG_SHMEM_SIZE - 1,
+			.sec_attr = TZC_REGION_S_NONE,
+			.ns_device_access =
+				TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID),
+		}
+#endif
+	};
+
+	static_assert(IS_PAGE_ALIGNED(CFG_TZDRAM_START));
+	static_assert(IS_PAGE_ALIGNED(CFG_TZDRAM_SIZE));
+#ifdef CFG_CORE_RESERVED_SHM
+	static_assert(IS_PAGE_ALIGNED(CFG_SHMEM_START));
+	static_assert(IS_PAGE_ALIGNED(CFG_SHMEM_SIZE));
+#endif
+
+	stm32mp_tzc_region0(true);
+
+	stm32mp_tzc_reset_region(tzc_dev);
+
+	for (idx = 0; idx < ARRAY_SIZE(boot_region); idx++) {
+		TEE_Result res = TEE_ERROR_GENERIC;
+
+		boot_region[idx].filters =
+			FILTER_MASK(tzc_dev->ddata.nb_filters);
+
+		res = append_region(tzc_dev, &boot_region[idx]);
+		if (res) {
+			EMSG("Failed to add region %u", idx);
+			panic();
+		}
+
+		res = exclude_region_from_nsec(&boot_region[idx]);
+		if (res) {
+			EMSG("Failed to configure region %u", idx);
+			panic();
+		}
+	}
+
+	/* Remove region0 access */
+	stm32mp_tzc_region0(false);
+}
+
+static TEE_Result add_node_memory_regions(struct tzc_device *tzc_dev,
+					  const void *fdt, int node)
+{
+	const fdt32_t *conf_list = NULL;
+	unsigned int nregions = 0;
+	unsigned int i = 0;
+	int len = 0;
+
+	conf_list = fdt_getprop(fdt, node, "memory-region", &len);
+	if (!conf_list)
+		return TEE_SUCCESS;
+
+	nregions = len / sizeof(uint32_t);
+	if (nregions > tzc_dev->ddata.nb_regions) {
+		EMSG("Too many regions defined in %s",
+		     fdt_get_name(fdt, node, NULL));
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	for (i = 0; i < nregions; i++) {
+		uint32_t phandle = fdt32_to_cpu(*(conf_list + i));
+		struct tzc_region_config region_cfg = { };
+		const fdt32_t *prop = NULL;
+		paddr_t region_base = 0;
+		size_t region_size = 0;
+		int pnode = 0;
+
+		pnode = fdt_node_offset_by_phandle(fdt, phandle);
+		if (pnode < 0)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		region_base = fdt_reg_base_address(fdt, pnode);
+		region_size = fdt_reg_size(fdt, pnode);
+		assert(region_base != (paddr_t)-1 && region_size != (size_t)-1);
+
+		if (!IS_PAGE_ALIGNED(region_base) ||
+		    !IS_PAGE_ALIGNED(region_size))
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		region_cfg.base = region_base;
+		region_cfg.top = region_base + region_size - 1;
+		region_cfg.filters = FILTER_MASK(tzc_dev->ddata.nb_filters);
+
+		prop = fdt_getprop(fdt, pnode, "st,protreg", &len);
+		if (!prop || (unsigned int)len != (2 * sizeof(uint32_t)))
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		switch (fdt32_to_cpu(prop[0])) {
+		case DT_TZC_REGION_S_NONE:
+			region_cfg.sec_attr = TZC_REGION_S_NONE;
+			break;
+		case DT_TZC_REGION_S_RD:
+			region_cfg.sec_attr = TZC_REGION_S_RD;
+			break;
+		case DT_TZC_REGION_S_WR:
+			region_cfg.sec_attr = TZC_REGION_S_WR;
+			break;
+		case DT_TZC_REGION_S_RDWR:
+			region_cfg.sec_attr = TZC_REGION_S_RDWR;
+			break;
+		default:
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		region_cfg.ns_device_access = fdt32_to_cpu(prop[1]);
+
+		DMSG("%#08"PRIxVA" - %#08"PRIxVA" : Sec access %i NS access %#"PRIx32,
+		     region_cfg.base, region_cfg.top, region_cfg.sec_attr,
+		     region_cfg.ns_device_access);
+
+		if (append_region(tzc_dev, &region_cfg))
+			panic("Error adding region");
+
+		if (exclude_region_from_nsec(&region_cfg))
+			panic("Not able to exclude region");
+	}
+
+	return TEE_SUCCESS;
+}
 
-	return region_cfg.base == base && region_cfg.top == (base + size - 1) &&
-	       region_cfg.sec_attr == TZC_REGION_S_RDWR &&
-	       region_cfg.ns_device_access == 0 &&
-	       region_cfg.filters == filters_mask;
+/*
+ * Adds a TZC region entry for each non-secure memory area defined by
+ * nsec_region_list. The function releases resources used to build this
+ * non-secure region list.
+ */
+static void add_carved_out_nsec(struct tzc_device *tzc_dev)
+{
+	struct tzc_region_non_sec *region = NULL;
+	struct tzc_region_non_sec *region_safe = NULL;
+
+	SLIST_FOREACH_SAFE(region, &nsec_region_list, link, region_safe) {
+		DMSG("%#08"PRIxVA" - %#08"PRIxVA" : Sec access %i NS access %#"PRIx32,
+		     region->region.base, region->region.top,
+		     region->region.sec_attr,
+		     region->region.ns_device_access);
+
+		if (append_region(tzc_dev, &region->region))
+			panic("Error adding region");
+
+		SLIST_REMOVE(&nsec_region_list, region,
+			     tzc_region_non_sec, link);
+		free(region);
+	};
 }
 
-static TEE_Result init_stm32mp1_tzc(void)
+static TEE_Result stm32mp_tzc_parse_fdt(struct tzc_device *tzc_dev,
+					const void *fdt, int node)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
-	void *base = phys_to_virt(TZC_BASE, MEM_AREA_IO_SEC, 1);
-	unsigned int region_index = 1;
-	const uint64_t dram_start = DDR_BASE;
-	const uint64_t dram_end = dram_start + CFG_DRAM_SIZE;
-	const uint64_t tzdram_start = CFG_TZDRAM_START;
-	const uint64_t tzdram_size = CFG_TZDRAM_SIZE;
-	const uint64_t tzdram_end = tzdram_start + tzdram_size;
+	struct io_pa_va base = { };
+	size_t reg_size = 0;
+	int offs = 0;
+
+	res = interrupt_dt_get(fdt, node, &tzc_dev->pdata.itr_chip,
+			       &tzc_dev->pdata.itr_num);
+	if (res)
+		return res;
 
-	assert(base);
+	res = clk_dt_get_by_index(fdt, node, 0, tzc_dev->pdata.clk);
+	if (res)
+		return res;
 
-	tzc_init((vaddr_t)base);
-	tzc_dump_state();
+	res = clk_dt_get_by_index(fdt, node, 1, tzc_dev->pdata.clk + 1);
+	if (res == TEE_ERROR_ITEM_NOT_FOUND)
+		DMSG("No secondary clock for %s",
+		     fdt_get_name(fdt, node, NULL));
+	else if (res)
+		return res;
+
+	base.pa = fdt_reg_base_address(fdt, node);
+	if (base.pa == DT_INFO_INVALID_REG)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	reg_size = fdt_reg_size(fdt, node);
+	if (reg_size == DT_INFO_INVALID_REG_SIZE)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	tzc_dev->pdata.name = strdup(fdt_get_name(fdt, node, NULL));
+	tzc_dev->pdata.base = io_pa_or_va_secure(&base, reg_size);
+
+	offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type",
+					     "memory", sizeof("memory"));
+	if (offs < 0)
+		panic("No memory reference for TZC DT node");
+
+	tzc_dev->pdata.mem_base = fdt_reg_base_address(fdt, offs);
+	tzc_dev->pdata.mem_size = fdt_reg_size(fdt, offs);
+
+	assert(tzc_dev->pdata.mem_base != DT_INFO_INVALID_REG &&
+	       tzc_dev->pdata.mem_size != DT_INFO_INVALID_REG_SIZE);
 
-	/*
-	 * Early boot stage is in charge of configuring memory regions
-	 * OP-TEE hence here only check this complies with static Core
-	 * expectations.
-	 */
-	if (dram_start < tzdram_start) {
-		if (!tzc_region_is_non_secure(region_index, dram_start,
-					      tzdram_start - dram_start))
-			panic("Unexpected TZC area on non-secure region");
-
-		region_index++;
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32mp1_tzc_pm(enum pm_op op,
+				  unsigned int pm_hint __unused,
+				  const struct pm_callback_handle *hdl)
+{
+	unsigned int i = 0;
+	struct tzc_device *tzc_dev =
+		(struct tzc_device *)PM_CALLBACK_GET_HANDLE(hdl);
+
+	if (op == PM_OP_RESUME) {
+		stm32mp_tzc_region0(true);
+
+		stm32mp_tzc_reset_region(tzc_dev);
+
+		for (i = 0; i < tzc_dev->nb_reg_used; i++)
+			tzc_configure_region(i + 1, &tzc_dev->reg[i]);
+
+		stm32mp_tzc_region0(false);
+	}
+
+	return TEE_SUCCESS;
+}
+DECLARE_KEEP_PAGER(stm32mp1_tzc_pm);
+
+static TEE_Result stm32mp1_tzc_probe(const void *fdt, int node,
+				     const void *compt_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct tzc_device *tzc_dev = NULL;
+	struct tzc_region_non_sec *nsec_region = NULL;
+
+	tzc_dev = calloc(1, sizeof(*tzc_dev));
+	if (!tzc_dev)
+		panic();
+
+	res = stm32mp_tzc_parse_fdt(tzc_dev, fdt, node);
+	if (res) {
+		free(tzc_dev);
+		return res;
 	}
 
-	if (!tzc_region_is_secure(region_index, tzdram_start, tzdram_size))
-		panic("Unexpected TZC configuration on secure region");
+	tzc_set_driverdata(tzc_dev);
+	tzc_dev->reg = calloc(tzc_dev->ddata.nb_regions,
+			      sizeof(*tzc_dev->reg));
+	if (!tzc_dev->reg)
+		panic();
+
+	if (clk_enable(tzc_dev->pdata.clk[0]))
+		panic();
+	if (tzc_dev->pdata.clk[1] && clk_enable(tzc_dev->pdata.clk[1]))
+		panic();
+
+	tzc_init(tzc_dev->pdata.base);
+
+	nsec_region = calloc(1, sizeof(*nsec_region));
+	if (!nsec_region)
+		panic();
+
+	nsec_region->region.base = tzc_dev->pdata.mem_base;
+	nsec_region->region.top = tzc_dev->pdata.mem_base +
+				  tzc_dev->pdata.mem_size - 1;
+	nsec_region->region.sec_attr = TZC_REGION_S_NONE;
+	nsec_region->region.ns_device_access = TZC_REGION_NSEC_ALL_ACCESS_RDWR;
+	nsec_region->region.filters = FILTER_MASK(tzc_dev->ddata.nb_filters);
+
+	SLIST_INSERT_HEAD(&nsec_region_list, nsec_region, link);
 
-	if (tzdram_end < dram_end) {
-		region_index++;
+	stm32mp_tzc_cfg_boot_region(tzc_dev);
 
-		if (!tzc_region_is_non_secure(region_index, tzdram_end,
-					      dram_end - tzdram_end))
-			panic("Unexpected TZC area on non-secure region");
+	res = add_node_memory_regions(tzc_dev, fdt, node);
+	if (res) {
+		EMSG("Can't add memory regions: %"PRIx32, res);
+		panic();
 	}
 
-	res = interrupt_add_handler_with_chip(interrupt_get_main_chip(),
-					      &tzc_itr_handler);
+	add_carved_out_nsec(tzc_dev);
+
+	tzc_dump_state();
+
+	res = interrupt_create_handler(tzc_dev->pdata.itr_chip,
+				       tzc_dev->pdata.itr_num, tzc_it_handler,
+				       NULL, 0, NULL);
 	if (res)
 		panic();
 
-	interrupt_enable(tzc_itr_handler.chip, tzc_itr_handler.it);
+	interrupt_enable(tzc_dev->pdata.itr_chip, tzc_dev->pdata.itr_num);
 	tzc_set_action(TZC_ACTION_INT);
 
+	register_pm_core_service_cb(stm32mp1_tzc_pm, tzc_dev,
+				    "stm32mp1-tzc400");
+
 	return TEE_SUCCESS;
 }
-driver_init(init_stm32mp1_tzc);
+
+static const struct dt_device_match tzc_secu_match_table[] = {
+	{ .compatible = "st,stm32mp1-tzc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(tzc_stm32mp1_dt_driver) = {
+	.name = "stm32mp1-tzc400",
+	.type = DT_DRIVER_NOTYPE,
+	.match_table = tzc_secu_match_table,
+	.probe = stm32mp1_tzc_probe,
+};
diff --git a/core/arch/arm/plat-stm32mp1/platform_config.h b/core/arch/arm/plat-stm32mp1/platform_config.h
index c3867fc8ed212cd6f5402c015a5d70cebe6d674e..c3f9b55386c5b533394b3facaf317c0ace3b95f9 100644
--- a/core/arch/arm/plat-stm32mp1/platform_config.h
+++ b/core/arch/arm/plat-stm32mp1/platform_config.h
@@ -79,12 +79,6 @@
 #endif
 #define RTC_BASE			0x5c004000
 #define SPI6_BASE			0x5c001000
-#ifdef CFG_STM32MP15
-#define SRAM1_BASE			0x30000000
-#define SRAM2_BASE			0x30020000
-#define SRAM3_BASE			0x30040000
-#define SRAM4_BASE			0x30050000
-#endif
 #define SYSCFG_BASE			0x50020000
 #ifdef CFG_STM32MP13
 #define SYSRAM_BASE			0x2ffe0000
@@ -109,6 +103,9 @@
 #define UART7_BASE			0x40018000
 #define UART8_BASE			0x40019000
 
+#define ROM_BASE			0
+#define ROM_SIZE			0x20000
+
 /* Console configuration */
 #define STM32MP1_DEBUG_USART_BASE	UART4_BASE
 #define GIC_SPI_UART4			84
@@ -181,15 +178,6 @@
 #define TAMP_BKP_REGISTER_OFF		0x100
 #define TAMP_BKP_REGISTER_COUNT		U(32)
 
-#define TAMP_BKP_REGISTER_ZONE1_COUNT	U(10)
-#define TAMP_BKP_REGISTER_ZONE2_COUNT	U(5)
-#define TAMP_BKP_REGISTER_ZONE3_COUNT	U(17)
-
-#if (TAMP_BKP_REGISTER_ZONE1_COUNT + TAMP_BKP_REGISTER_ZONE2_COUNT + \
-	TAMP_BKP_REGISTER_ZONE3_COUNT != TAMP_BKP_REGISTER_COUNT)
-#error Inconsistent TAMP backup register zone definition
-#endif
-
 /* TZC resources */
 #define STM32MP1_IRQ_TZC		36
 
@@ -232,10 +220,33 @@
 #endif
 
 #ifdef CFG_STM32MP15
+#define SRAM1_BASE			0x30000000
+#define SRAM2_BASE			0x30020000
+#define SRAM3_BASE			0x30040000
+#define SRAM4_BASE			0x30050000
+/* Alternate SRAM base address possibly used by remoteproc firmware */
+#define SRAM1_ALT_BASE			0x10000000
+#define SRAM2_ALT_BASE			0x10020000
+#define SRAM3_ALT_BASE			0x10040000
+#define SRAM4_ALT_BASE			0x10050000
+
 #define SRAM1_SIZE			0x20000
 #define SRAM2_SIZE			0x20000
 #define SRAM3_SIZE			0x10000
 #define SRAM4_SIZE			0x10000
+
+#define RETRAM_BASE			0x38000000
+#define RETRAM_SIZE			0x10000
+#endif
+
+#ifdef CFG_STM32MP13
+/* SRAM layout*/
+#define SRAM1_BASE			0x30000000
+#define SRAM1_SIZE			0x4000
+#define SRAM2_BASE			0x30004000
+#define SRAM2_SIZE			0x2000
+#define SRAM3_BASE			0x30006000
+#define SRAM3_SIZE			0x2000
 #endif
 
 #endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-stm32mp1/scmi_server.c b/core/arch/arm/plat-stm32mp1/scmi_server.c
index b0cc34b5d858f8ad23cdaa0b5794a1c399656314..7c93f7ca0bb179389eaaa2f65c6aa41b5a96e93c 100644
--- a/core/arch/arm/plat-stm32mp1/scmi_server.c
+++ b/core/arch/arm/plat-stm32mp1/scmi_server.c
@@ -7,10 +7,12 @@
 #include <confine_array_index.h>
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
+#include <drivers/firewall_device.h>
 #include <drivers/regulator.h>
 #include <drivers/rstctrl.h>
 #include <drivers/scmi-msg.h>
 #include <drivers/scmi.h>
+#include <drivers/stm32_remoteproc.h>
 #include <drivers/stm32_vrefbuf.h>
 #include <drivers/stm32mp1_pmic.h>
 #include <drivers/stm32mp1_pwr.h>
@@ -35,15 +37,20 @@
 #define SCMI_RD_NAME_SIZE	16
 #define SCMI_VOLTD_NAME_SIZE	16
 
+#define ETZPC_ID_ALWAYS_ACCESSIBLE	(STM32MP1_ETZPC_MAX_ID + 1)
+#define ETZPC_ID_NEVER_ACCESSIBLE	(STM32MP1_ETZPC_MAX_ID + 2)
+
 /*
  * struct stm32_scmi_clk - Data for the exposed clock
  * @clock_id: Clock identifier in RCC clock driver
+ * @etzpc_id: ETZPC ID of the peripheral related to the clock
  * @name: Clock string ID exposed to channel
  * @enabled: State of the SCMI clock
  */
 struct stm32_scmi_clk {
 	unsigned long clock_id;
 	struct clk *clk;
+	unsigned int etzpc_id;
 	const char *name;
 	bool enabled;
 };
@@ -51,11 +58,13 @@ struct stm32_scmi_clk {
 /*
  * struct stm32_scmi_rd - Data for the exposed reset controller
  * @reset_id: Reset identifier in RCC reset driver
+ * @etzpc_id: ETZPC ID of the peripheral related to the reset controller
  * @name: Reset string ID exposed to channel
  * @rstctrl: Reset controller device
  */
 struct stm32_scmi_rd {
 	unsigned long reset_id;
+	unsigned int etzpc_id;
 	const char *name;
 	struct rstctrl *rstctrl;
 };
@@ -98,16 +107,37 @@ register_phys_mem(MEM_AREA_IO_NSEC, CFG_STM32MP1_SCMI_SHM_BASE,
 #endif
 #endif /*CFG_STM32MP1_SCMI_SHM_BASE*/
 
+/* SCMI clock always accessible */
 #define CLOCK_CELL(_scmi_id, _id, _name, _init_enabled) \
 	[(_scmi_id)] = { \
 		.clock_id = (_id), \
+		.etzpc_id = ETZPC_ID_ALWAYS_ACCESSIBLE, \
+		.name = (_name), \
+		.enabled = (_init_enabled), \
+	}
+
+/* SCMI clock accessible upon DECPROT ID assigned to non-secure */
+#define CLOCK_CELL_DECPROT(_scmi_id, _id, _name, _init_enabled, _etzpc_id) \
+	[(_scmi_id)] = { \
+		.clock_id = (_id), \
+		.etzpc_id = (_etzpc_id), \
 		.name = (_name), \
 		.enabled = (_init_enabled), \
 	}
 
+/* SCMI reset domain always accessible */
 #define RESET_CELL(_scmi_id, _id, _name) \
 	[(_scmi_id)] = { \
 		.reset_id = (_id), \
+		.etzpc_id = ETZPC_ID_ALWAYS_ACCESSIBLE, \
+		.name = (_name), \
+	}
+
+/* SCMI reset domain accessible upon DECPROT ID assigned to non-secure */
+#define RESET_CELL_DECPROT(_scmi_id, _id, _name, _etzpc_id) \
+	[(_scmi_id)] = { \
+		.reset_id = (_id), \
+		.etzpc_id = (_etzpc_id), \
 		.name = (_name), \
 	}
 
@@ -178,38 +208,56 @@ static struct stm32_scmi_clk stm32_scmi_clock[] = {
 	CLOCK_CELL(CK_SCMI_MPU, CK_MPU, "ck_mpu", true),
 	CLOCK_CELL(CK_SCMI_AXI, CK_AXI, "ck_axi", true),
 	CLOCK_CELL(CK_SCMI_BSEC, BSEC, "bsec", true),
-	CLOCK_CELL(CK_SCMI_CRYP1, CRYP1, "cryp1", false),
+	CLOCK_CELL_DECPROT(CK_SCMI_CRYP1, CRYP1, "cryp1", false,
+			   STM32MP1_ETZPC_CRYP1_ID),
 	CLOCK_CELL(CK_SCMI_GPIOZ, GPIOZ, "gpioz", false),
-	CLOCK_CELL(CK_SCMI_HASH1, HASH1, "hash1", false),
-	CLOCK_CELL(CK_SCMI_I2C4, I2C4_K, "i2c4_k", false),
-	CLOCK_CELL(CK_SCMI_I2C6, I2C6_K, "i2c6_k", false),
-	CLOCK_CELL(CK_SCMI_IWDG1, IWDG1, "iwdg1", false),
-	CLOCK_CELL(CK_SCMI_RNG1, RNG1_K, "rng1_k", true),
+	CLOCK_CELL_DECPROT(CK_SCMI_HASH1, HASH1, "hash1", false,
+			   STM32MP1_ETZPC_HASH1_ID),
+	CLOCK_CELL_DECPROT(CK_SCMI_I2C4, I2C4_K, "i2c4_k", false,
+			   STM32MP1_ETZPC_I2C4_ID),
+	CLOCK_CELL_DECPROT(CK_SCMI_I2C6, I2C6_K, "i2c6_k", false,
+			   STM32MP1_ETZPC_I2C6_ID),
+	CLOCK_CELL_DECPROT(CK_SCMI_IWDG1, IWDG1, "iwdg1", false,
+			   STM32MP1_ETZPC_IWDG1_ID),
+	CLOCK_CELL_DECPROT(CK_SCMI_RNG1, RNG1_K, "rng1_k", true,
+			   STM32MP1_ETZPC_RNG1_ID),
 	CLOCK_CELL(CK_SCMI_RTC, RTC, "ck_rtc", true),
 	CLOCK_CELL(CK_SCMI_RTCAPB, RTCAPB, "rtcapb", true),
-	CLOCK_CELL(CK_SCMI_SPI6, SPI6_K, "spi6_k", false),
-	CLOCK_CELL(CK_SCMI_USART1, USART1_K, "usart1_k", false),
+	CLOCK_CELL_DECPROT(CK_SCMI_SPI6, SPI6_K, "spi6_k", false,
+			   STM32MP1_ETZPC_SPI6_ID),
+	CLOCK_CELL_DECPROT(CK_SCMI_USART1, USART1_K, "usart1_k", false,
+			   STM32MP1_ETZPC_USART1_ID),
 };
 #endif
 
 #ifdef CFG_STM32MP13
 static struct stm32_scmi_rd stm32_scmi_reset_domain[] = {
-	RESET_CELL(RST_SCMI_LTDC, LTDC_R, "ltdc"),
+	RESET_CELL_DECPROT(RST_SCMI_LTDC, LTDC_R, "ltdc",
+			   STM32MP1_ETZPC_LTDC_ID),
 	RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"),
 };
 #endif
 
 #ifdef CFG_STM32MP15
 static struct stm32_scmi_rd stm32_scmi_reset_domain[] = {
-	RESET_CELL(RST_SCMI_SPI6, SPI6_R, "spi6"),
-	RESET_CELL(RST_SCMI_I2C4, I2C4_R, "i2c4"),
-	RESET_CELL(RST_SCMI_I2C6, I2C6_R, "i2c6"),
-	RESET_CELL(RST_SCMI_USART1, USART1_R, "usart1"),
-	RESET_CELL(RST_SCMI_STGEN, STGEN_R, "stgen"),
-	RESET_CELL(RST_SCMI_GPIOZ, GPIOZ_R, "gpioz"),
-	RESET_CELL(RST_SCMI_CRYP1, CRYP1_R, "cryp1"),
-	RESET_CELL(RST_SCMI_HASH1, HASH1_R, "hash1"),
-	RESET_CELL(RST_SCMI_RNG1, RNG1_R, "rng1"),
+	RESET_CELL_DECPROT(RST_SCMI_SPI6, SPI6_R, "spi6",
+			   STM32MP1_ETZPC_SPI6_ID),
+	RESET_CELL_DECPROT(RST_SCMI_I2C4, I2C4_R, "i2c4",
+			   STM32MP1_ETZPC_I2C4_ID),
+	RESET_CELL_DECPROT(RST_SCMI_I2C6, I2C6_R, "i2c6",
+			   STM32MP1_ETZPC_I2C6_ID),
+	RESET_CELL_DECPROT(RST_SCMI_USART1, USART1_R, "usart1",
+			   STM32MP1_ETZPC_USART1_ID),
+	RESET_CELL_DECPROT(RST_SCMI_STGEN, STGEN_R, "stgen",
+			   STM32MP1_ETZPC_STGENC_ID),
+	RESET_CELL_DECPROT(RST_SCMI_GPIOZ, GPIOZ_R, "gpioz",
+			   ETZPC_ID_NEVER_ACCESSIBLE),
+	RESET_CELL_DECPROT(RST_SCMI_CRYP1, CRYP1_R, "cryp1",
+			   STM32MP1_ETZPC_CRYP1_ID),
+	RESET_CELL_DECPROT(RST_SCMI_HASH1, HASH1_R, "hash1",
+			   STM32MP1_ETZPC_HASH1_ID),
+	RESET_CELL_DECPROT(RST_SCMI_RNG1, RNG1_R, "rng1",
+			   STM32MP1_ETZPC_RNG1_ID),
 	RESET_CELL(RST_SCMI_MDMA, MDMA_R, "mdma"),
 	RESET_CELL(RST_SCMI_MCU, MCU_R, "mcu"),
 	RESET_CELL(RST_SCMI_MCU_HOLD_BOOT, MCU_HOLD_BOOT_R, "mcu_hold_boot"),
@@ -373,6 +421,41 @@ const uint8_t *plat_scmi_protocol_list(unsigned int channel_id __unused)
 	return plat_protocol_list;
 }
 
+static bool nsec_can_access_resource(unsigned int etzpc_id)
+{
+	static struct firewall_controller *etzpc_fw_ctrl;
+	uint32_t query_arg = DECPROT(etzpc_id, DECPROT_NS_RW, DECPROT_UNLOCK);
+	struct firewall_query query = {
+		.arg_count = 1,
+		.args = &query_arg,
+		.ctrl = etzpc_fw_ctrl,
+	};
+
+	if (etzpc_id == ETZPC_ID_NEVER_ACCESSIBLE)
+		return false;
+	if (etzpc_id == ETZPC_ID_ALWAYS_ACCESSIBLE)
+		return true;
+
+	if (!etzpc_fw_ctrl) {
+		struct dt_driver_provider *prov = NULL;
+		int node = 0;
+
+		node = fdt_node_offset_by_compatible(get_embedded_dt(), -1,
+						     "st,stm32-etzpc");
+		if (node < 0)
+			panic();
+
+		prov = dt_driver_get_provider_by_node(node, DT_DRIVER_FIREWALL);
+		if (!prov)
+			panic();
+
+		etzpc_fw_ctrl = dt_driver_provider_priv_data(prov);
+		query.ctrl = etzpc_fw_ctrl;
+	}
+
+	return firewall_check_access(&query) == TEE_SUCCESS;
+}
+
 /*
  * Platform SCMI clocks
  */
@@ -406,7 +489,7 @@ const char *plat_scmi_clock_get_name(unsigned int channel_id,
 {
 	struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id);
 
-	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
+	if (!clock || !nsec_can_access_resource(clock->etzpc_id))
 		return NULL;
 
 	return clock->name;
@@ -421,7 +504,7 @@ int32_t plat_scmi_clock_rates_array(unsigned int channel_id,
 	if (!clock)
 		return SCMI_NOT_FOUND;
 
-	if (!stm32mp_nsec_can_access_clock(clock->clock_id))
+	if (!nsec_can_access_resource(clock->etzpc_id))
 		return SCMI_DENIED;
 
 	/* Exposed clocks are currently fixed rate clocks */
@@ -443,7 +526,7 @@ unsigned long plat_scmi_clock_get_rate(unsigned int channel_id,
 {
 	struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id);
 
-	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
+	if (!clock || !nsec_can_access_resource(clock->etzpc_id))
 		return 0;
 
 	return clk_get_rate(clock->clk);
@@ -453,7 +536,7 @@ int32_t plat_scmi_clock_get_state(unsigned int channel_id, unsigned int scmi_id)
 {
 	struct stm32_scmi_clk *clock = find_clock(channel_id, scmi_id);
 
-	if (!clock || !stm32mp_nsec_can_access_clock(clock->clock_id))
+	if (!clock || !nsec_can_access_resource(clock->etzpc_id))
 		return 0;
 
 	return (int32_t)clock->enabled;
@@ -467,7 +550,7 @@ int32_t plat_scmi_clock_set_state(unsigned int channel_id, unsigned int scmi_id,
 	if (!clock)
 		return SCMI_NOT_FOUND;
 
-	if (!stm32mp_nsec_can_access_clock(clock->clock_id))
+	if (!nsec_can_access_resource(clock->etzpc_id))
 		return SCMI_DENIED;
 
 	if (enable_not_disable) {
@@ -533,13 +616,16 @@ int32_t plat_scmi_rd_autonomous(unsigned int channel_id, unsigned int scmi_id,
 	if (!rd)
 		return SCMI_NOT_FOUND;
 
-	if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id))
+	if (!rd->rstctrl || !nsec_can_access_resource(rd->etzpc_id))
 		return SCMI_DENIED;
-	assert(rd->rstctrl);
 
 #ifdef CFG_STM32MP15
+	/* Reset cycle on MCU hold boot is not supported */
 	if (rd->reset_id == MCU_HOLD_BOOT_R)
 		return SCMI_NOT_SUPPORTED;
+	/* Remoteproc driver may handle all MCU reset controllers */
+	if (rd->reset_id == MCU_R && stm32_rproc_is_secure(STM32_M4_RPROC_ID))
+		return SCMI_DENIED;
 #endif
 
 	/* Supports only reset with context loss */
@@ -566,9 +652,15 @@ int32_t plat_scmi_rd_set_state(unsigned int channel_id, unsigned int scmi_id,
 	if (!rd)
 		return SCMI_NOT_FOUND;
 
-	if (!rd->rstctrl || !stm32mp_nsec_can_access_reset(rd->reset_id))
+	if (!rd->rstctrl || !nsec_can_access_resource(rd->etzpc_id))
 		return SCMI_DENIED;
-	assert(rd->rstctrl);
+
+#ifdef CFG_STM32MP15
+	/* Remoteproc driver may handle all MCU reset controllers */
+	if ((rd->reset_id == MCU_R || rd->reset_id == MCU_HOLD_BOOT_R) &&
+	    stm32_rproc_is_secure(STM32_M4_RPROC_ID))
+		return SCMI_DENIED;
+#endif
 
 	if (assert_not_deassert) {
 		FMSG("SCMI reset %u set", scmi_id);
@@ -864,7 +956,7 @@ static TEE_Result stm32mp1_init_scmi_server(void)
 
 			/* Sync SCMI clocks with their targeted initial state */
 			if (clk->enabled &&
-			    stm32mp_nsec_can_access_clock(clk->clock_id))
+			    nsec_can_access_resource(clk->etzpc_id))
 				clk_enable(clk->clk);
 		}
 
@@ -876,9 +968,6 @@ static TEE_Result stm32mp1_init_scmi_server(void)
 			    strlen(rd->name) >= SCMI_RD_NAME_SIZE)
 				panic("SCMI reset domain name invalid");
 
-			if (stm32mp_nsec_can_access_clock(rd->reset_id))
-				continue;
-
 			rstctrl = stm32mp_rcc_reset_id_to_rstctrl(rd->reset_id);
 			assert(rstctrl);
 			if (rstctrl_get_exclusive(rstctrl))
diff --git a/core/arch/arm/plat-stm32mp1/shared_resources.c b/core/arch/arm/plat-stm32mp1/shared_resources.c
deleted file mode 100644
index 76ce6485918bff8f9257e8b06a1cf38b21a2a484..0000000000000000000000000000000000000000
--- a/core/arch/arm/plat-stm32mp1/shared_resources.c
+++ /dev/null
@@ -1,749 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * Copyright (c) 2017-2023, STMicroelectronics
- */
-
-#include <config.h>
-#include <drivers/pinctrl.h>
-#include <drivers/stm32_etzpc.h>
-#include <drivers/stm32_gpio.h>
-#include <drivers/stm32mp1_etzpc.h>
-#include <drivers/stm32mp1_rcc.h>
-#include <drivers/stm32mp_dt_bindings.h>
-#include <initcall.h>
-#include <io.h>
-#include <keep.h>
-#include <kernel/boot.h>
-#include <kernel/dt.h>
-#include <kernel/panic.h>
-#include <kernel/pm.h>
-#include <libfdt.h>
-#include <mm/core_memprot.h>
-#include <platform_config.h>
-#include <stdbool.h>
-#include <stm32_util.h>
-#include <string.h>
-
-/*
- * Once one starts to get the resource registering state, one cannot register
- * new resources. This ensures resource state cannot change.
- */
-static bool registering_locked;
-
-/*
- * Shared peripherals and resources registration
- *
- * Each resource assignation is stored in a table. The state defaults
- * to PERIPH_UNREGISTERED if the resource is not explicitly assigned.
- *
- * Resource driver that as not embedded (a.k.a their related CFG_xxx build
- * directive is disabled) are assigned to the non-secure world.
- *
- * Each IO of the GPIOZ IO can be secure or non-secure.
- *
- * It is the platform responsibility the ensure resource assignation
- * matches the access permission firewalls configuration.
- */
-enum shres_state {
-	SHRES_UNREGISTERED = 0,
-	SHRES_SECURE,
-	SHRES_NON_SECURE,
-};
-
-/* Use a byte array to store each resource state */
-static uint8_t shres_state[STM32MP1_SHRES_COUNT] = {
-#if !defined(CFG_STM32_IWDG)
-	[STM32MP1_SHRES_IWDG1] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_UART)
-	[STM32MP1_SHRES_USART1] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_SPI)
-	[STM32MP1_SHRES_SPI6] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_I2C)
-	[STM32MP1_SHRES_I2C4] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_I2C6] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_GPIO)
-	[STM32MP1_SHRES_GPIOZ(0)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(1)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(2)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(3)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(4)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(5)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(6)] = SHRES_NON_SECURE,
-	[STM32MP1_SHRES_GPIOZ(7)] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_RNG)
-	[STM32MP1_SHRES_RNG1] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_HASH)
-	[STM32MP1_SHRES_HASH1] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_CRYP)
-	[STM32MP1_SHRES_CRYP1] = SHRES_NON_SECURE,
-#endif
-#if !defined(CFG_STM32_RTC)
-	[STM32MP1_SHRES_RTC] = SHRES_NON_SECURE,
-#endif
-};
-
-static const char __maybe_unused *shres2str_id_tbl[STM32MP1_SHRES_COUNT] = {
-	[STM32MP1_SHRES_GPIOZ(0)] = "GPIOZ0",
-	[STM32MP1_SHRES_GPIOZ(1)] = "GPIOZ1",
-	[STM32MP1_SHRES_GPIOZ(2)] = "GPIOZ2",
-	[STM32MP1_SHRES_GPIOZ(3)] = "GPIOZ3",
-	[STM32MP1_SHRES_GPIOZ(4)] = "GPIOZ4",
-	[STM32MP1_SHRES_GPIOZ(5)] = "GPIOZ5",
-	[STM32MP1_SHRES_GPIOZ(6)] = "GPIOZ6",
-	[STM32MP1_SHRES_GPIOZ(7)] = "GPIOZ7",
-	[STM32MP1_SHRES_IWDG1] = "IWDG1",
-	[STM32MP1_SHRES_USART1] = "USART1",
-	[STM32MP1_SHRES_SPI6] = "SPI6",
-	[STM32MP1_SHRES_I2C4] = "I2C4",
-	[STM32MP1_SHRES_RNG1] = "RNG1",
-	[STM32MP1_SHRES_HASH1] = "HASH1",
-	[STM32MP1_SHRES_CRYP1] = "CRYP1",
-	[STM32MP1_SHRES_I2C6] = "I2C6",
-	[STM32MP1_SHRES_RTC] = "RTC",
-	[STM32MP1_SHRES_MCU] = "MCU",
-	[STM32MP1_SHRES_PLL3] = "PLL3",
-	[STM32MP1_SHRES_MDMA] = "MDMA",
-	[STM32MP1_SHRES_SRAM1] = "SRAM1",
-	[STM32MP1_SHRES_SRAM2] = "SRAM2",
-	[STM32MP1_SHRES_SRAM3] = "SRAM3",
-	[STM32MP1_SHRES_SRAM4] = "SRAM4",
-};
-
-static __maybe_unused const char *shres2str_id(enum stm32mp_shres id)
-{
-	return shres2str_id_tbl[id];
-}
-
-static const char *shres2str_state_tbl[4] __maybe_unused = {
-	[SHRES_UNREGISTERED] = "unregistered",
-	[SHRES_NON_SECURE] = "non-secure",
-	[SHRES_SECURE] = "secure",
-};
-
-static __maybe_unused const char *shres2str_state(enum shres_state id)
-{
-	return shres2str_state_tbl[id];
-}
-
-/* GPIOZ bank pin count depends on SoC variants */
-/* A light count routine for unpaged context to not depend on DTB support */
-static int gpioz_nbpin = -1;
-
-static unsigned int get_gpioz_nbpin(void)
-{
-	if (gpioz_nbpin < 0)
-		panic();
-
-	return gpioz_nbpin;
-}
-
-void stm32mp_register_gpioz_pin_count(size_t count)
-{
-	assert(gpioz_nbpin == -1);
-
-	gpioz_nbpin = count;
-}
-
-static void register_periph(enum stm32mp_shres id, enum shres_state state)
-{
-	assert(id < STM32MP1_SHRES_COUNT &&
-	       (state == SHRES_SECURE || state == SHRES_NON_SECURE));
-
-	if (registering_locked)
-		panic();
-
-	if (shres_state[id] != SHRES_UNREGISTERED &&
-	    shres_state[id] != state) {
-		DMSG("Cannot change %s from %s to %s",
-		     shres2str_id(id),
-		     shres2str_state(shres_state[id]),
-		     shres2str_state(state));
-		panic();
-	}
-
-	if (shres_state[id] == SHRES_UNREGISTERED)
-		DMSG("Register %s as %s",
-		     shres2str_id(id), shres2str_state(state));
-
-	switch (id) {
-	case STM32MP1_SHRES_GPIOZ(0):
-	case STM32MP1_SHRES_GPIOZ(1):
-	case STM32MP1_SHRES_GPIOZ(2):
-	case STM32MP1_SHRES_GPIOZ(3):
-	case STM32MP1_SHRES_GPIOZ(4):
-	case STM32MP1_SHRES_GPIOZ(5):
-	case STM32MP1_SHRES_GPIOZ(6):
-	case STM32MP1_SHRES_GPIOZ(7):
-		if ((id - STM32MP1_SHRES_GPIOZ(0)) >= get_gpioz_nbpin()) {
-			EMSG("Invalid GPIO %u >= %u",
-			     id - STM32MP1_SHRES_GPIOZ(0), get_gpioz_nbpin());
-			panic();
-		}
-		break;
-	default:
-		break;
-	}
-
-	shres_state[id] = state;
-
-	/* Explore clock tree to lock secure clock dependencies */
-	if (state == SHRES_SECURE) {
-		switch (id) {
-		case STM32MP1_SHRES_GPIOZ(0):
-		case STM32MP1_SHRES_GPIOZ(1):
-		case STM32MP1_SHRES_GPIOZ(2):
-		case STM32MP1_SHRES_GPIOZ(3):
-		case STM32MP1_SHRES_GPIOZ(4):
-		case STM32MP1_SHRES_GPIOZ(5):
-		case STM32MP1_SHRES_GPIOZ(6):
-		case STM32MP1_SHRES_GPIOZ(7):
-			stm32mp_register_clock_parents_secure(GPIOZ);
-			break;
-		case STM32MP1_SHRES_IWDG1:
-			stm32mp_register_clock_parents_secure(IWDG1);
-			break;
-		case STM32MP1_SHRES_USART1:
-			stm32mp_register_clock_parents_secure(USART1_K);
-			break;
-		case STM32MP1_SHRES_SPI6:
-			stm32mp_register_clock_parents_secure(SPI6_K);
-			break;
-		case STM32MP1_SHRES_I2C4:
-			stm32mp_register_clock_parents_secure(I2C4_K);
-			break;
-		case STM32MP1_SHRES_RNG1:
-			stm32mp_register_clock_parents_secure(RNG1_K);
-			break;
-		case STM32MP1_SHRES_HASH1:
-			stm32mp_register_clock_parents_secure(HASH1);
-			break;
-		case STM32MP1_SHRES_CRYP1:
-			stm32mp_register_clock_parents_secure(CRYP1);
-			break;
-		case STM32MP1_SHRES_I2C6:
-			stm32mp_register_clock_parents_secure(I2C6_K);
-			break;
-		case STM32MP1_SHRES_RTC:
-			stm32mp_register_clock_parents_secure(RTC);
-			break;
-		default:
-			/* No expected resource dependency */
-			break;
-		}
-	}
-}
-
-/* Register resource by ID */
-void stm32mp_register_secure_periph(enum stm32mp_shres id)
-{
-	register_periph(id, SHRES_SECURE);
-}
-
-void stm32mp_register_non_secure_periph(enum stm32mp_shres id)
-{
-	register_periph(id, SHRES_NON_SECURE);
-}
-
-/* Register resource by IO memory base address */
-static void register_periph_iomem(vaddr_t base, enum shres_state state)
-{
-	enum stm32mp_shres id = STM32MP1_SHRES_COUNT;
-
-	switch (base) {
-	case IWDG1_BASE:
-		id = STM32MP1_SHRES_IWDG1;
-		break;
-	case USART1_BASE:
-		id = STM32MP1_SHRES_USART1;
-		break;
-	case SPI6_BASE:
-		id = STM32MP1_SHRES_SPI6;
-		break;
-	case I2C4_BASE:
-		id = STM32MP1_SHRES_I2C4;
-		break;
-	case I2C6_BASE:
-		id = STM32MP1_SHRES_I2C6;
-		break;
-	case RTC_BASE:
-		id = STM32MP1_SHRES_RTC;
-		break;
-	case RNG1_BASE:
-		id = STM32MP1_SHRES_RNG1;
-		break;
-	case CRYP1_BASE:
-		id = STM32MP1_SHRES_CRYP1;
-		break;
-	case HASH1_BASE:
-		id = STM32MP1_SHRES_HASH1;
-		break;
-	case SRAM1_BASE:
-		id = STM32MP1_SHRES_SRAM1;
-		break;
-	case SRAM2_BASE:
-		id = STM32MP1_SHRES_SRAM2;
-		break;
-	case SRAM3_BASE:
-		id = STM32MP1_SHRES_SRAM3;
-		break;
-	case SRAM4_BASE:
-		id = STM32MP1_SHRES_SRAM4;
-		break;
-
-	/* Always non-secure resource cases */
-#ifdef CFG_WITH_NSEC_GPIOS
-	case GPIOA_BASE:
-	case GPIOB_BASE:
-	case GPIOC_BASE:
-	case GPIOD_BASE:
-	case GPIOE_BASE:
-	case GPIOF_BASE:
-	case GPIOG_BASE:
-	case GPIOH_BASE:
-	case GPIOI_BASE:
-	case GPIOJ_BASE:
-	case GPIOK_BASE:
-	fallthrough;
-#endif
-#ifdef CFG_WITH_NSEC_UARTS
-	case USART2_BASE:
-	case USART3_BASE:
-	case UART4_BASE:
-	case UART5_BASE:
-	case USART6_BASE:
-	case UART7_BASE:
-	case UART8_BASE:
-	fallthrough;
-#endif
-#ifdef CFG_WITH_NSEC_I2CS
-	case I2C5_BASE:
-	fallthrough;
-#endif
-	case IWDG2_BASE:
-		/* Allow drivers to register some non-secure resources */
-		DMSG("IO for non-secure resource 0x%lx", base);
-		if (state != SHRES_NON_SECURE)
-			panic();
-
-		return;
-
-	default:
-		panic();
-		break;
-	}
-
-	register_periph(id, state);
-}
-
-void stm32mp_register_secure_periph_iomem(vaddr_t base)
-{
-	register_periph_iomem(base, SHRES_SECURE);
-}
-
-void stm32mp_register_non_secure_periph_iomem(vaddr_t base)
-{
-	register_periph_iomem(base, SHRES_NON_SECURE);
-}
-
-/* Register GPIO resource */
-void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin)
-{
-	switch (bank) {
-	case GPIO_BANK_Z:
-		assert(pin < get_gpioz_nbpin());
-		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_SECURE);
-		break;
-	default:
-		EMSG("GPIO bank %u cannot be secured", bank);
-		panic();
-	}
-}
-
-void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin)
-{
-	switch (bank) {
-	case GPIO_BANK_Z:
-		assert(pin < get_gpioz_nbpin());
-		register_periph(STM32MP1_SHRES_GPIOZ(pin), SHRES_NON_SECURE);
-		break;
-	default:
-		break;
-	}
-}
-
-void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl)
-{
-	unsigned int *bank = NULL;
-	unsigned int *pin = NULL;
-	size_t count = 0;
-	size_t n = 0;
-
-	stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count);
-	if (!count)
-		return;
-
-	bank = calloc(count, sizeof(*bank));
-	pin = calloc(count, sizeof(*pin));
-	if (!bank || !pin)
-		panic();
-
-	stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count);
-	for (n = 0; n < count; n++)
-		stm32mp_register_secure_gpio(bank[n], pin[n]);
-
-	free(bank);
-	free(pin);
-}
-
-void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl)
-{
-	unsigned int *bank = NULL;
-	unsigned int *pin = NULL;
-	size_t count = 0;
-	size_t n = 0;
-
-	stm32_gpio_pinctrl_bank_pin(pinctrl, NULL, NULL, &count);
-	if (!count)
-		return;
-
-	bank = calloc(count, sizeof(*bank));
-	pin = calloc(count, sizeof(*pin));
-	if (!bank || !pin)
-		panic();
-
-	stm32_gpio_pinctrl_bank_pin(pinctrl, bank, pin, &count);
-	for (n = 0; n < count; n++)
-		stm32mp_register_non_secure_gpio(bank[n], pin[n]);
-
-	free(bank);
-	free(pin);
-}
-
-static void lock_registering(void)
-{
-	registering_locked = true;
-}
-
-bool stm32mp_periph_is_secure(enum stm32mp_shres id)
-{
-	lock_registering();
-
-	return shres_state[id] == SHRES_SECURE;
-}
-
-bool stm32mp_gpio_bank_is_non_secure(unsigned int bank)
-{
-	unsigned int not_secure = 0;
-	unsigned int pin = 0;
-
-	lock_registering();
-
-	if (bank != GPIO_BANK_Z)
-		return true;
-
-	for (pin = 0; pin < get_gpioz_nbpin(); pin++)
-		if (!stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin)))
-			not_secure++;
-
-	return not_secure > 0 && not_secure == get_gpioz_nbpin();
-}
-
-bool stm32mp_gpio_bank_is_secure(unsigned int bank)
-{
-	unsigned int secure = 0;
-	unsigned int pin = 0;
-
-	lock_registering();
-
-	if (bank != GPIO_BANK_Z)
-		return false;
-
-	for (pin = 0; pin < get_gpioz_nbpin(); pin++)
-		if (stm32mp_periph_is_secure(STM32MP1_SHRES_GPIOZ(pin)))
-			secure++;
-
-	return secure > 0 && secure == get_gpioz_nbpin();
-}
-
-bool stm32mp_nsec_can_access_clock(unsigned long clock_id)
-{
-	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
-
-	/* Oscillators and PLLs are visible from non-secure world */
-	COMPILE_TIME_ASSERT(CK_HSE == 0 &&
-			    (CK_HSE + 1) == CK_CSI &&
-			    (CK_HSE + 2) == CK_LSI &&
-			    (CK_HSE + 3) == CK_LSE &&
-			    (CK_HSE + 4) == CK_HSI &&
-			    (CK_HSE + 5) == CK_HSE_DIV2 &&
-			    (PLL1_P + 1) == PLL1_Q &&
-			    (PLL1_P + 2) == PLL1_R &&
-			    (PLL1_P + 3) == PLL2_P &&
-			    (PLL1_P + 4) == PLL2_Q &&
-			    (PLL1_P + 5) == PLL2_R &&
-			    (PLL1_P + 6) == PLL3_P &&
-			    (PLL1_P + 7) == PLL3_Q &&
-			    (PLL1_P + 8) == PLL3_R);
-
-	if (clock_id <= CK_HSE_DIV2 ||
-	    (clock_id >= PLL1_P && clock_id <= PLL3_R))
-		return true;
-
-	switch (clock_id) {
-	case RTCAPB:
-	case CK_MPU:
-	case CK_AXI:
-	case BSEC:
-		return true;
-	case GPIOZ:
-		return !stm32mp_gpio_bank_is_secure(GPIO_BANK_Z);
-	case SPI6_K:
-		shres_id = STM32MP1_SHRES_SPI6;
-		break;
-	case I2C4_K:
-		shres_id = STM32MP1_SHRES_I2C4;
-		break;
-	case I2C6_K:
-		shres_id = STM32MP1_SHRES_I2C6;
-		break;
-	case USART1_K:
-		shres_id = STM32MP1_SHRES_USART1;
-		break;
-	case IWDG1:
-		shres_id = STM32MP1_SHRES_IWDG1;
-		break;
-	case CRYP1:
-		shres_id = STM32MP1_SHRES_CRYP1;
-		break;
-	case HASH1:
-		shres_id = STM32MP1_SHRES_HASH1;
-		break;
-	case RNG1_K:
-		shres_id = STM32MP1_SHRES_RNG1;
-		break;
-	case RTC:
-		shres_id = STM32MP1_SHRES_RTC;
-		break;
-	case CK_MCU:
-		shres_id = STM32MP1_SHRES_MCU;
-		break;
-	default:
-		return false;
-	}
-
-	return !stm32mp_periph_is_secure(shres_id);
-}
-
-bool stm32mp_nsec_can_access_reset(unsigned int reset_id)
-{
-	enum stm32mp_shres shres_id = STM32MP1_SHRES_COUNT;
-
-	switch (reset_id) {
-	case GPIOZ_R:
-		return stm32mp_gpio_bank_is_non_secure(GPIO_BANK_Z);
-	case SPI6_R:
-		shres_id = STM32MP1_SHRES_SPI6;
-		break;
-	case I2C4_R:
-		shres_id = STM32MP1_SHRES_I2C4;
-		break;
-	case I2C6_R:
-		shres_id = STM32MP1_SHRES_I2C6;
-		break;
-	case USART1_R:
-		shres_id = STM32MP1_SHRES_USART1;
-		break;
-	case CRYP1_R:
-		shres_id = STM32MP1_SHRES_CRYP1;
-		break;
-	case HASH1_R:
-		shres_id = STM32MP1_SHRES_HASH1;
-		break;
-	case RNG1_R:
-		shres_id = STM32MP1_SHRES_RNG1;
-		break;
-	case MDMA_R:
-		shres_id = STM32MP1_SHRES_MDMA;
-		break;
-	case MCU_R:
-	case MCU_HOLD_BOOT_R:
-		shres_id = STM32MP1_SHRES_MCU;
-		break;
-	default:
-		return false;
-	}
-
-	return !stm32mp_periph_is_secure(shres_id);
-}
-
-static bool mckprot_resource(enum stm32mp_shres id)
-{
-	switch (id) {
-	case STM32MP1_SHRES_MCU:
-	case STM32MP1_SHRES_PLL3:
-		return true;
-	default:
-		return false;
-	}
-}
-
-#ifdef CFG_STM32_ETZPC
-static enum etzpc_decprot_attributes shres2decprot_attr(enum stm32mp_shres id)
-{
-	if (!stm32mp_periph_is_secure(id))
-		return ETZPC_DECPROT_NS_RW;
-
-	if (mckprot_resource(id))
-		return ETZPC_DECPROT_MCU_ISOLATION;
-
-	return ETZPC_DECPROT_S_RW;
-}
-
-/* Configure ETZPC cell and lock it when resource is secure */
-static void config_lock_decprot(uint32_t decprot_id,
-				enum etzpc_decprot_attributes decprot_attr)
-{
-	etzpc_configure_decprot(decprot_id, decprot_attr);
-
-	if (decprot_attr == ETZPC_DECPROT_S_RW)
-		etzpc_lock_decprot(decprot_id);
-}
-
-static void set_etzpc_secure_configuration(void)
-{
-	/* Some peripherals shall be secure */
-	config_lock_decprot(STM32MP1_ETZPC_STGENC_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_BKPSRAM_ID, ETZPC_DECPROT_S_RW);
-	config_lock_decprot(STM32MP1_ETZPC_DDRCTRL_ID, ETZPC_DECPROT_NS_R_S_W);
-	config_lock_decprot(STM32MP1_ETZPC_DDRPHYC_ID, ETZPC_DECPROT_NS_R_S_W);
-
-	/* Configure ETZPC with peripheral registering */
-	config_lock_decprot(STM32MP1_ETZPC_IWDG1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_IWDG1));
-	config_lock_decprot(STM32MP1_ETZPC_USART1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_USART1));
-	config_lock_decprot(STM32MP1_ETZPC_SPI6_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_SPI6));
-	config_lock_decprot(STM32MP1_ETZPC_I2C4_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_I2C4));
-	config_lock_decprot(STM32MP1_ETZPC_RNG1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_RNG1));
-	config_lock_decprot(STM32MP1_ETZPC_HASH1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_HASH1));
-	config_lock_decprot(STM32MP1_ETZPC_CRYP1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_CRYP1));
-	config_lock_decprot(STM32MP1_ETZPC_I2C6_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_I2C6));
-
-	config_lock_decprot(STM32MP1_ETZPC_SRAM1_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_SRAM1));
-	config_lock_decprot(STM32MP1_ETZPC_SRAM2_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_SRAM2));
-	config_lock_decprot(STM32MP1_ETZPC_SRAM3_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_SRAM3));
-	config_lock_decprot(STM32MP1_ETZPC_SRAM4_ID,
-			    shres2decprot_attr(STM32MP1_SHRES_SRAM4));
-}
-#else
-static void set_etzpc_secure_configuration(void)
-{
-	/* Nothing to do */
-}
-#endif
-
-static void check_rcc_secure_configuration(void)
-{
-	bool secure = stm32_rcc_is_secure();
-	bool mckprot = stm32_rcc_is_mckprot();
-	enum stm32mp_shres id = STM32MP1_SHRES_COUNT;
-	bool have_error = false;
-	uint32_t state = 0;
-
-	if (stm32_bsec_get_state(&state))
-		panic();
-
-	if (state == BSEC_STATE_SEC_CLOSED && !secure)
-		panic("Closed device mandates secure RCC");
-
-	for (id = 0; id < STM32MP1_SHRES_COUNT; id++) {
-		if  (shres_state[id] != SHRES_SECURE)
-			continue;
-
-		/* SRAMs have no constraints on RCC configuration */
-		if (id == STM32MP1_SHRES_SRAM1 ||
-		    id == STM32MP1_SHRES_SRAM2 ||
-		    id == STM32MP1_SHRES_SRAM3 ||
-		    id == STM32MP1_SHRES_SRAM4)
-			continue;
-
-		if ((mckprot_resource(id) && !mckprot) || !secure) {
-			EMSG("RCC %s MCKPROT %s and %s (%u) secure",
-			      secure ? "secure" : "non-secure",
-			      mckprot ? "set" : "not set",
-			      shres2str_id(id), id);
-			have_error = true;
-		}
-	}
-
-	if (have_error) {
-		if (IS_ENABLED(CFG_INSECURE))
-			EMSG("WARNING: CFG_INSECURE allows insecure RCC configuration");
-		else
-			panic();
-	}
-}
-
-static void set_gpio_secure_configuration(void)
-{
-	unsigned int pin = 0;
-
-	for (pin = 0; pin < get_gpioz_nbpin(); pin++) {
-		enum stm32mp_shres shres = STM32MP1_SHRES_GPIOZ(pin);
-		bool secure = stm32mp_periph_is_secure(shres);
-
-		stm32_gpio_set_secure_cfg(GPIO_BANK_Z, pin, secure);
-	}
-}
-
-static TEE_Result gpioz_pm(enum pm_op op, uint32_t pm_hint __unused,
-			   const struct pm_callback_handle *hdl __unused)
-{
-	if (op == PM_OP_RESUME)
-		set_gpio_secure_configuration();
-
-	return TEE_SUCCESS;
-}
-DECLARE_KEEP_PAGER(gpioz_pm);
-
-static TEE_Result stm32mp1_init_final_shres(void)
-{
-	enum stm32mp_shres id = STM32MP1_SHRES_COUNT;
-
-	lock_registering();
-
-	for (id = (enum stm32mp_shres)0; id < STM32MP1_SHRES_COUNT; id++) {
-		uint8_t __maybe_unused *state = &shres_state[id];
-
-		DMSG("stm32mp %-8s (%2u): %-14s",
-		     shres2str_id(id), id, shres2str_state(*state));
-	}
-
-	set_etzpc_secure_configuration();
-	if (IS_ENABLED(CFG_STM32_GPIO)) {
-		set_gpio_secure_configuration();
-		register_pm_driver_cb(gpioz_pm, NULL,
-				      "stm32mp1-shared-resources");
-	}
-	check_rcc_secure_configuration();
-
-	return TEE_SUCCESS;
-}
-/* Finalize shres after drivers initialization, hence driver_init_late() */
-driver_init_late(stm32mp1_init_final_shres);
diff --git a/core/arch/arm/plat-stm32mp1/stm32_util.h b/core/arch/arm/plat-stm32mp1/stm32_util.h
index 627933e4ad6a4155c01f4babc252077a6ff045bb..9be8da9391324a7a02059e077b9ea0f0e240729e 100644
--- a/core/arch/arm/plat-stm32mp1/stm32_util.h
+++ b/core/arch/arm/plat-stm32mp1/stm32_util.h
@@ -8,8 +8,6 @@
 
 #include <assert.h>
 #include <drivers/clk.h>
-#include <drivers/pinctrl.h>
-#include <drivers/stm32_bsec.h>
 #include <kernel/panic.h>
 #include <stdint.h>
 #include <tee_api_types.h>
@@ -46,39 +44,8 @@ void may_spin_unlock(unsigned int *lock, uint32_t exceptions);
 /* Helper from platform RCC clock driver */
 struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id);
 
-#ifdef CFG_STM32MP1_SHARED_RESOURCES
-/* Return true if @clock_id is shared by secure and non-secure worlds */
-bool stm32mp_nsec_can_access_clock(unsigned long clock_id);
-#else /* CFG_STM32MP1_SHARED_RESOURCES */
-static inline bool stm32mp_nsec_can_access_clock(unsigned long clock_id
-						 __unused)
-{
-	return true;
-}
-#endif /* CFG_STM32MP1_SHARED_RESOURCES */
-
 extern const struct clk_ops stm32mp1_clk_ops;
 
-#if defined(CFG_STPMIC1)
-/* Return true if non-secure world can manipulate regulator @pmic_regu_name */
-bool stm32mp_nsec_can_access_pmic_regu(const char *pmic_regu_name);
-#else
-static inline bool stm32mp_nsec_can_access_pmic_regu(const char *name __unused)
-{
-	return false;
-}
-#endif
-
-#ifdef CFG_STM32MP1_SHARED_RESOURCES
-/* Return true if and only if @reset_id relates to a non-secure peripheral */
-bool stm32mp_nsec_can_access_reset(unsigned int reset_id);
-#else /* CFG_STM32MP1_SHARED_RESOURCES */
-static inline bool stm32mp_nsec_can_access_reset(unsigned int reset_id __unused)
-{
-	return true;
-}
-#endif /* CFG_STM32MP1_SHARED_RESOURCES */
-
 /* Return rstctrl instance related to RCC reset controller DT binding ID */
 struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id);
 
@@ -97,236 +64,27 @@ struct stm32_bsec_static_cfg {
 
 void stm32mp_get_bsec_static_cfg(struct stm32_bsec_static_cfg *cfg);
 
-/*
- * Shared reference counter: increments by 2 on secure increment
- * request, decrements by 2 on secure decrement request. Bit #0
- * is set to 1 on non-secure increment request and reset to 0 on
- * non-secure decrement request. These counters initialize to
- * either 0, 1 or 2 upon their expect default state.
- * Counters saturate to UINT_MAX / 2.
- */
-#define SHREFCNT_NONSECURE_FLAG		0x1ul
-#define SHREFCNT_SECURE_STEP		0x2ul
-#define SHREFCNT_MAX			(UINT_MAX / 2)
-
-/* Return 1 if refcnt increments from 0, else return 0 */
-static inline int incr_shrefcnt(unsigned int *refcnt, bool secure)
-{
-	int rc = !*refcnt;
-
-	if (secure) {
-		if (*refcnt < SHREFCNT_MAX) {
-			*refcnt += SHREFCNT_SECURE_STEP;
-			assert(*refcnt < SHREFCNT_MAX);
-		}
-	} else {
-		*refcnt |= SHREFCNT_NONSECURE_FLAG;
-	}
-
-	return rc;
-}
-
-/* Return 1 if refcnt decrements to 0, else return 0 */
-static inline int decr_shrefcnt(unsigned int *refcnt, bool secure)
-{
-	int  rc = 0;
-
-	if (secure) {
-		if (*refcnt < SHREFCNT_MAX) {
-			if (*refcnt < SHREFCNT_SECURE_STEP)
-				panic();
-
-			*refcnt -= SHREFCNT_SECURE_STEP;
-			rc = !*refcnt;
-		}
-	} else {
-		rc = (*refcnt == SHREFCNT_NONSECURE_FLAG);
-		*refcnt &= ~SHREFCNT_NONSECURE_FLAG;
-	}
-
-	return rc;
-}
-
-static inline int incr_refcnt(unsigned int *refcnt)
-{
-	return incr_shrefcnt(refcnt, true);
-}
-
-static inline int decr_refcnt(unsigned int *refcnt)
-{
-	return decr_shrefcnt(refcnt, true);
-}
-
-/*
- * Shared peripherals and resources registration
- *
- * Resources listed in enum stm32mp_shres assigned at run-time to the
- * non-secure world, to the secure world or shared by both worlds.
- * In the later case, there must exist a secure service in OP-TEE
- * for the non-secure world to access the resource.
- *
- * Resources may be a peripheral, a bus, a clock or a memory.
- *
- * Shared resources driver API functions allows drivers to register the
- * resource as secure, non-secure or shared and to get the resource
- * assignation state.
- */
-#define STM32MP1_SHRES_GPIOZ(i)		(STM32MP1_SHRES_GPIOZ_0 + i)
-
-enum stm32mp_shres {
-	STM32MP1_SHRES_GPIOZ_0 = 0,
-	STM32MP1_SHRES_GPIOZ_1,
-	STM32MP1_SHRES_GPIOZ_2,
-	STM32MP1_SHRES_GPIOZ_3,
-	STM32MP1_SHRES_GPIOZ_4,
-	STM32MP1_SHRES_GPIOZ_5,
-	STM32MP1_SHRES_GPIOZ_6,
-	STM32MP1_SHRES_GPIOZ_7,
-	STM32MP1_SHRES_IWDG1,
-	STM32MP1_SHRES_USART1,
-	STM32MP1_SHRES_SPI6,
-	STM32MP1_SHRES_I2C4,
-	STM32MP1_SHRES_RNG1,
-	STM32MP1_SHRES_HASH1,
-	STM32MP1_SHRES_CRYP1,
-	STM32MP1_SHRES_I2C6,
-	STM32MP1_SHRES_RTC,
-	STM32MP1_SHRES_MCU,
-	STM32MP1_SHRES_PLL3,
-	STM32MP1_SHRES_MDMA,
-	STM32MP1_SHRES_SRAM1,
-	STM32MP1_SHRES_SRAM2,
-	STM32MP1_SHRES_SRAM3,
-	STM32MP1_SHRES_SRAM4,
-
-	STM32MP1_SHRES_COUNT
-};
-
-#ifdef CFG_STM32MP1_SHARED_RESOURCES
-/* Register resource @id as a secure peripheral */
-void stm32mp_register_secure_periph(enum stm32mp_shres id);
-
-/* Register resource @id as a non-secure peripheral */
-void stm32mp_register_non_secure_periph(enum stm32mp_shres id);
-
-/*
- * Register resource identified by @base as a secure peripheral
- * @base: IOMEM physical base address of the resource
- */
-void stm32mp_register_secure_periph_iomem(vaddr_t base);
-
-/*
- * Register resource identified by @base as a non-secure peripheral
- * @base: IOMEM physical base address of the resource
- */
-void stm32mp_register_non_secure_periph_iomem(vaddr_t base);
+bool stm32mp_allow_probe_shared_device(const void *fdt, int node);
 
+#if defined(CFG_STM32MP15) && defined(CFG_WITH_PAGER)
 /*
- * Register GPIO resource as a secure peripheral
- * @bank: Bank of the target GPIO
- * @pin: Bit position of the target GPIO in the bank
+ * Return the SRAM alias physical address related to @pa when applicable or
+ * @pa if it does not relate to an SRAMx non-aliased memory address.
  */
-void stm32mp_register_secure_gpio(unsigned int bank, unsigned int pin);
+paddr_t stm32mp1_pa_or_sram_alias_pa(paddr_t pa);
 
-/*
- * Register GPIO resource as a non-secure peripheral
- * @bank: Bank of the target GPIO
- * @pin: Bit position of the target GPIO in the bank
- */
-void stm32mp_register_non_secure_gpio(unsigned int bank, unsigned int pin);
-
-/*
- * Register pin resource of a pin control state as a secure peripheral
- * @bank: Bank of the target GPIO
- * @pin: Bit position of the target GPIO in the bank
- */
-void stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl);
-
-/*
- * Register pin resource of a pin control state as a non-secure peripheral
- * @bank: Bank of the target GPIO
- * @pin: Bit position of the target GPIO in the bank
- */
-void stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl);
-
-/* Return true if and only if resource @id is registered as secure */
-bool stm32mp_periph_is_secure(enum stm32mp_shres id);
-
-/* Return true if and only if GPIO bank @bank is registered as secure */
-bool stm32mp_gpio_bank_is_secure(unsigned int bank);
-
-/* Return true if and only if GPIO bank @bank is registered as non-secure */
-bool stm32mp_gpio_bank_is_non_secure(unsigned int bank);
-
-/* Register parent clocks of @clock (ID used in clock DT bindings) as secure */
-void stm32mp_register_clock_parents_secure(unsigned long clock_id);
-
-/* Register number of pins in the GPIOZ bank */
-void stm32mp_register_gpioz_pin_count(size_t count);
-
-#else /* CFG_STM32MP1_SHARED_RESOURCES */
-
-static inline void stm32mp_register_secure_periph(enum stm32mp_shres id
-						  __unused)
-{
-}
-
-static inline void stm32mp_register_non_secure_periph(enum stm32mp_shres id
-						      __unused)
-{
-}
-
-static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused)
-{
-}
-
-static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base
-							    __unused)
-{
-}
-
-static inline void stm32mp_register_secure_gpio(unsigned int bank __unused,
-						unsigned int pin __unused)
-{
-}
-
-static inline void stm32mp_register_non_secure_gpio(unsigned int bank __unused,
-						    unsigned int pin __unused)
-{
-}
-
-static inline void
-stm32mp_register_secure_pinctrl(struct pinctrl_state *pinctrl __unused)
-{
-}
-
-static inline void
-stm32mp_register_non_secure_pinctrl(struct pinctrl_state *pinctrl __unused)
-{
-}
-
-static inline bool stm32mp_periph_is_secure(enum stm32mp_shres id __unused)
-{
-	return true;
-}
-
-static inline bool stm32mp_gpio_bank_is_secure(unsigned int bank __unused)
+/* Return whether or not the physical address range intersec pager secure RAM */
+bool stm32mp1_ram_intersect_pager_ram(paddr_t base, size_t size);
+#else
+static inline paddr_t stm32mp1_pa_or_sram_alias_pa(paddr_t pa)
 {
-	return true;
+	return pa;
 }
 
-static inline bool stm32mp_gpio_bank_is_non_secure(unsigned int bank __unused)
+static inline bool stm32mp1_ram_intersect_pager_ram(paddr_t base __unused,
+						    size_t size __unused)
 {
 	return false;
 }
-
-static inline void stm32mp_register_clock_parents_secure(unsigned long clock_id
-							 __unused)
-{
-}
-
-static inline void stm32mp_register_gpioz_pin_count(size_t count __unused)
-{
-}
-#endif /* CFG_STM32MP1_SHARED_RESOURCES */
+#endif /*CFG_STM32MP15 && CFG_WITH_PAGER*/
 #endif /*__STM32_UTIL_H__*/
diff --git a/core/arch/arm/plat-stm32mp1/sub.mk b/core/arch/arm/plat-stm32mp1/sub.mk
index fa6e1486d781a5fdba99724fa1b41c19e548a1cb..25ad4cf05734cf70b2083cdc0d12ce602bcb81d7 100644
--- a/core/arch/arm/plat-stm32mp1/sub.mk
+++ b/core/arch/arm/plat-stm32mp1/sub.mk
@@ -3,7 +3,6 @@ global-incdirs-y += .
 srcs-y += main.c
 srcs-y += reset.S
 srcs-$(CFG_SCMI_MSG_DRIVERS) += scmi_server.c
-srcs-$(CFG_STM32MP1_SHARED_RESOURCES) += shared_resources.c
 srcs-$(CFG_TZC400) += plat_tzc400.c
 srcs-$(CFG_WITH_PAGER) += link_dummies_paged.c
 
diff --git a/core/arch/arm/plat-stm32mp2/conf.mk b/core/arch/arm/plat-stm32mp2/conf.mk
index 76dda579739873cdcad1851f08c613b2424a1303..fbc25be7e2a80f6d76cf02abf999873a032fb294 100644
--- a/core/arch/arm/plat-stm32mp2/conf.mk
+++ b/core/arch/arm/plat-stm32mp2/conf.mk
@@ -31,12 +31,20 @@ $(call force,CFG_GIC,y)
 $(call force,CFG_HALT_CORES_ON_PANIC_SGI,15)
 $(call force,CFG_INIT_CNTVOFF,y)
 $(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
+$(call force,CFG_STM32_SHARED_IO,y)
+$(call force,CFG_STM32MP_CLK_CORE,y)
+$(call force,CFG_STM32MP25_CLK,y)
+$(call force,CFG_STM32MP25_RSTCTRL,y)
 $(call force,CFG_WITH_ARM_TRUSTED_FW,y)
 $(call force,CFG_WITH_LPAE,y)
 
 CFG_TZDRAM_START ?= 0x82000000
 CFG_TZDRAM_SIZE  ?= 0x02000000
 
+# Support DDR ranges up to 8GBytes (address range: 0x80000000 + DDR size)
+CFG_CORE_LARGE_PHYS_ADDR ?= y
+CFG_CORE_ARM64_PA_BITS ?= 34
+
 CFG_CORE_HEAP_SIZE ?= 262144
 CFG_CORE_RESERVED_SHM ?= n
 CFG_DTB_MAX_SIZE ?= 262144
@@ -44,11 +52,25 @@ CFG_HALT_CORES_ON_PANIC ?= y
 CFG_MMAP_REGIONS ?= 30
 CFG_NUM_THREADS ?= 5
 CFG_TEE_CORE_NB_CORE ?= 2
+CFG_STM32MP_OPP_COUNT ?= 3
 
+CFG_STM32_FMC ?= y
 CFG_STM32_GPIO ?= y
+CFG_STM32_HPDMA ?= y
+CFG_STM32_HSEM ?= y
+CFG_STM32_IAC ?= y
+CFG_STM32_IPCC ?= y
+CFG_STM32_RIF ?= y
+CFG_STM32_RIFSC ?= y
+CFG_STM32_RISAB ?= y
+CFG_STM32_RISAF ?= y
+CFG_STM32_RNG ?= y
+CFG_STM32_SERC ?= y
+CFG_STM32_TAMP ?= y
 CFG_STM32_UART ?= y
 
 # Default enable some test facitilites
+CFG_ENABLE_EMBEDDED_TESTS ?= y
 CFG_WITH_STATS ?= y
 
 # Default disable ASLR
@@ -59,3 +81,31 @@ CFG_STM32_EARLY_CONSOLE_UART ?= 2
 
 # Default disable external DT support
 CFG_EXTERNAL_DT ?= n
+
+# Default enable HWRNG PTA support
+CFG_HWRNG_PTA ?= y
+ifeq ($(CFG_HWRNG_PTA),y)
+$(call force,CFG_STM32_RNG,y,Required by CFG_HWRNG_PTA)
+$(call force,CFG_WITH_SOFTWARE_PRNG,n,Required by CFG_HWRNG_PTA)
+CFG_HWRNG_QUALITY ?= 1024
+endif
+
+# Enable reset control
+ifeq ($(CFG_STM32MP25_RSTCTRL),y)
+$(call force,CFG_DRIVERS_RSTCTRL,y)
+$(call force,CFG_STM32_RSTCTRL,y)
+endif
+
+# Optional behavior upon receiving illegal access events
+CFG_STM32_PANIC_ON_IAC_EVENT ?= y
+ifeq ($(CFG_TEE_CORE_DEBUG),y)
+CFG_STM32_PANIC_ON_SERC_EVENT ?= n
+else
+CFG_STM32_PANIC_ON_SERC_EVENT ?= y
+endif
+
+# Default enable firewall support
+CFG_DRIVERS_FIREWALL ?= y
+ifeq ($(call cfg-one-enabled, CFG_STM32_RISAB CFG_STM32_RIFSC),y)
+$(call force,CFG_DRIVERS_FIREWALL,y)
+endif
diff --git a/core/arch/arm/plat-stm32mp2/drivers/stm32mp25_syscfg.c b/core/arch/arm/plat-stm32mp2/drivers/stm32mp25_syscfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..984940b77c5942b3020844641f33f12ce13f923a
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/drivers/stm32mp25_syscfg.c
@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <drivers/stm32_shared_io.h>
+#include <io.h>
+#include <mm/core_memprot.h>
+#include <stm32_sysconf.h>
+#include <trace.h>
+#include <types_ext.h>
+#include <util.h>
+
+#define SYSCON_OFFSET(id)	((id) & GENMASK_32(15, 0))
+#define SYSCON_BANK(id)		(((id) & GENMASK_32(31, 16)) >> 16)
+
+/* Safe Reset register definition */
+#define SYSCFG_SAFERSTCR		SYSCON_ID(SYSCON_SYSCFG, U(0x2018))
+#define SYSCFG_SAFERSTCR_EN		BIT(0)
+
+struct io_pa_va syscfg_base[SYSCON_NB_BANKS] = {
+	{ .pa = SYSCFG_BASE },
+	{ .pa = A35SSC_BASE }
+};
+
+static vaddr_t stm32mp_syscfg_base(uint32_t id)
+{
+	uint32_t bank = SYSCON_BANK(id);
+
+	assert(bank < SYSCON_NB_BANKS);
+
+	return io_pa_or_va_secure(&syscfg_base[bank], 1);
+}
+
+void stm32mp_syscfg_write(uint32_t id, uint32_t value, uint32_t bitmsk)
+{
+	vaddr_t syconf_base = stm32mp_syscfg_base(id);
+
+	io_mask32_stm32shregs(syconf_base + SYSCON_OFFSET(id), value, bitmsk);
+}
+
+uint32_t stm32mp_syscfg_read(uint32_t id)
+{
+	return io_read32(stm32mp_syscfg_base(id) + SYSCON_OFFSET(id));
+}
+
+void stm32mp25_syscfg_set_safe_reset(bool status)
+{
+	vaddr_t addr = stm32mp_syscfg_base(SYSCON_SYSCFG) + SYSCFG_SAFERSTCR;
+
+	FMSG("Set safe reset to  %d", status);
+
+	if (status)
+		io_setbits32(addr, SYSCFG_SAFERSTCR_EN);
+	else
+		io_clrbits32(addr, SYSCFG_SAFERSTCR_EN);
+}
diff --git a/core/arch/arm/plat-stm32mp2/drivers/sub.mk b/core/arch/arm/plat-stm32mp2/drivers/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..016dfe9a2fb7d73a38e75d732accd7acf66a66e8
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/drivers/sub.mk
@@ -0,0 +1 @@
+srcs-y += stm32mp25_syscfg.c
diff --git a/core/arch/arm/plat-stm32mp2/main.c b/core/arch/arm/plat-stm32mp2/main.c
index 81366e60d247c11049fe47505eb0d26fe8cc34e8..e64e74e049c503b82aa2e9c381bba5bd74c3e678 100644
--- a/core/arch/arm/plat-stm32mp2/main.c
+++ b/core/arch/arm/plat-stm32mp2/main.c
@@ -6,6 +6,7 @@
 #include <config.h>
 #include <console.h>
 #include <drivers/gic.h>
+#include <drivers/stm32_rif.h>
 #include <drivers/stm32_uart.h>
 #include <initcall.h>
 #include <kernel/boot.h>
@@ -58,24 +59,23 @@ service_init(platform_banner);
  */
 static struct stm32_uart_pdata console_data;
 
-void console_init(void)
+void plat_console_init(void)
 {
 #ifdef CFG_STM32_UART
 	/* Early console initialization before MMU setup */
 	struct uart {
 		paddr_t pa;
-		bool secure;
 	} uarts[] = {
 		[0] = { .pa = 0 },
-		[1] = { .pa = USART1_BASE, .secure = true, },
-		[2] = { .pa = USART2_BASE, .secure = false, },
-		[3] = { .pa = USART3_BASE, .secure = false, },
-		[4] = { .pa = UART4_BASE, .secure = false, },
-		[5] = { .pa = UART5_BASE, .secure = false, },
-		[6] = { .pa = USART6_BASE, .secure = false, },
-		[7] = { .pa = UART7_BASE, .secure = false, },
-		[8] = { .pa = UART8_BASE, .secure = false, },
-		[9] = { .pa = UART9_BASE, .secure = false, },
+		[1] = { .pa = USART1_BASE },
+		[2] = { .pa = USART2_BASE },
+		[3] = { .pa = USART3_BASE },
+		[4] = { .pa = UART4_BASE },
+		[5] = { .pa = UART5_BASE },
+		[6] = { .pa = USART6_BASE },
+		[7] = { .pa = UART7_BASE },
+		[8] = { .pa = UART8_BASE },
+		[9] = { .pa = UART9_BASE },
 	};
 
 	static_assert(ARRAY_SIZE(uarts) > CFG_STM32_EARLY_CONSOLE_UART);
@@ -85,7 +85,6 @@ void console_init(void)
 
 	/* No clock yet bound to the UART console */
 	console_data.clock = NULL;
-	console_data.secure = uarts[CFG_STM32_EARLY_CONSOLE_UART].secure;
 	stm32_uart_init(&console_data, uarts[CFG_STM32_EARLY_CONSOLE_UART].pa);
 	register_serial_console(&console_data.chip);
 
@@ -123,7 +122,7 @@ static TEE_Result init_console_from_dt(void)
 	console_flush();
 	console_data = *pd;
 	register_serial_console(&console_data.chip);
-	IMSG("DTB enables console (%ssecure)", pd->secure ? "" : "non-");
+	IMSG("DTB enables console");
 	free(pd);
 
 	return TEE_SUCCESS;
@@ -133,6 +132,13 @@ static TEE_Result init_console_from_dt(void)
 service_init_late(init_console_from_dt);
 #endif /*STM32_UART*/
 
+vaddr_t stm32_rcc_base(void)
+{
+	static struct io_pa_va base = { .pa = RCC_BASE };
+
+	return io_pa_or_va_secure(&base, 1);
+}
+
 void boot_primary_init_intc(void)
 {
 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
@@ -142,3 +148,27 @@ void boot_secondary_init_intc(void)
 {
 	gic_init_per_cpu();
 }
+
+#ifdef CFG_STM32_RIF
+void stm32_rif_access_violation_action(void)
+{
+}
+#endif /* CFG_STM32_RIF */
+
+bool stm32mp_allow_probe_shared_device(const void *fdt, int node)
+{
+	static int uart_console_node = -1;
+	static bool once;
+
+	if (!once) {
+		get_console_node_from_dt((void *)fdt, &uart_console_node,
+					 NULL, NULL);
+		once = true;
+	}
+
+	/* Allow OP-TEE console to be shared with non-secure world */
+	if (node == uart_console_node)
+		return true;
+
+	return false;
+}
diff --git a/core/arch/arm/plat-stm32mp2/platform_config.h b/core/arch/arm/plat-stm32mp2/platform_config.h
index 4d7af4a8c82b72f3a1dd6b6e5ae8c0bf8347cc1a..5145af6e2be8b1a911961ad3a7f6f4ec727903d8 100644
--- a/core/arch/arm/plat-stm32mp2/platform_config.h
+++ b/core/arch/arm/plat-stm32mp2/platform_config.h
@@ -54,7 +54,10 @@
 #define SAES_BASE			0x42050000
 #define PKA_BASE			0x42060000
 #define RIFSC_BASE			0x42080000
+#define RISAF4_BASE			0x420d0000
 #define RISAF5_BASE			0x420e0000
+#define RISAB1_BASE			0x420f0000
+#define RISAB2_BASE			0x42100000
 #define RISAB6_BASE			0x42140000
 #define BSEC3_BASE			0x44000000
 #define IWDG2_BASE			0x44002000
diff --git a/core/arch/arm/plat-stm32mp2/stm32_sysconf.h b/core/arch/arm/plat-stm32mp2/stm32_sysconf.h
new file mode 100644
index 0000000000000000000000000000000000000000..94d7205f527a6800f1b345185dd8508bd388f0f6
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/stm32_sysconf.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+
+#ifndef __STM32_SYSCONF_H__
+#define __STM32_SYSCONF_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <util.h>
+
+/* syscon banks */
+enum syscon_banks {
+	SYSCON_SYSCFG,
+	SYSCON_A35SSC,
+	SYSCON_NB_BANKS
+};
+
+#define SYSCON_ID(bank, offset) (((bank) << 16) | \
+				((offset) & GENMASK_32(15, 0)))
+
+/*
+ * SYSCFG register offsets (base relative)
+ */
+#define SYSCFG_VDERAMCR		SYSCON_ID(SYSCON_SYSCFG, 0x1800)
+
+/*
+ * SYSCFG_VDERAMCR register offsets
+ */
+#define VDERAMCR_VDERAM_EN		BIT(0)
+#define VDERAMCR_MASK			BIT(0)
+
+/*
+ * A35SSC register offsets (base relative)
+ */
+#define A35SS_SSC_CHGCLKREQ	SYSCON_ID(SYSCON_A35SSC, 0x0)
+#define A35SS_SSC_PLL_FREQ1	SYSCON_ID(SYSCON_A35SSC, 0x80)
+#define A35SS_SSC_PLL_FREQ2	SYSCON_ID(SYSCON_A35SSC, 0x90)
+#define A35SS_SSC_PLL_EN	SYSCON_ID(SYSCON_A35SSC, 0xA0)
+
+#define A35SSC_M33CFG_ACCESS_CR  SYSCON_ID(SYSCON_A35SSC, 0x2088)
+#define A35SSC_M33_TZEN_CR       SYSCON_ID(SYSCON_A35SSC, 0x20A0)
+#define A35SSC_M33_INITSVTOR_CR  SYSCON_ID(SYSCON_A35SSC, 0x20A4)
+#define A35SSC_M33_INITNSVTOR_CR SYSCON_ID(SYSCON_A35SSC, 0x20A8)
+
+/*
+ * A35SSC M33CFG_ACCESS_CR register
+ */
+#define A35SSC_M33_TZEN_CR_M33CFG_SEC		BIT(0)
+#define A35SSC_M33_TZEN_CR_M33CFG_PRIV		BIT(1)
+
+/*
+ * A35SSC M33_TZEN_CR register
+ */
+#define A35SSC_M33_TZEN_CR_CFG_SECEXT		BIT(0)
+
+/*
+ * A35SSC A35SS_SSC_CHGCLKREQ register
+ */
+#define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_EN	BIT(0)
+#define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK	BIT(0)
+
+#define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK	BIT(1)
+#define A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_SHIFT	U(1)
+
+/*
+ * A35SSC A35SS_SSC_PLL_FREQ1 register
+ */
+#define A35SS_SSC_PLL_FREQ1_FBDIV_MASK		GENMASK_32(11, 0)
+#define A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT		U(0)
+
+#define A35SS_SSC_PLL_FREQ1_REFDIV_MASK		GENMASK_32(21, 16)
+#define A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT	U(16)
+
+#define A35SS_SSC_PLL_FREQ1_MASK	(A35SS_SSC_PLL_FREQ1_REFDIV_MASK | \
+					 A35SS_SSC_PLL_FREQ1_FBDIV_MASK)
+
+/*
+ * A35SSC A35SS_SSC_PLL_FREQ2 register
+ */
+#define A35SS_SSC_PLL_FREQ2_POSTDIV1_MASK	GENMASK_32(2, 0)
+#define A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT	U(0)
+
+#define A35SS_SSC_PLL_FREQ2_POSTDIV2_MASK	GENMASK_32(5, 3)
+#define A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT	U(3)
+
+#define A35SS_SSC_PLL_FREQ2_MASK		GENMASK_32(5, 0)
+
+/*
+ * A35SSC A35SS_SSC_PLL_EN register
+ */
+#define A35SS_SSC_PLL_ENABLE_PD_EN			BIT(0)
+#define A35SS_SSC_PLL_ENABLE_PD_MASK			BIT(0)
+
+#define A35SS_SSC_PLL_ENABLE_LOCKP_MASK			BIT(1)
+
+#define A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_EN		BIT(2)
+#define A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK	BIT(2)
+
+/*
+ * Write masked value is SYSCONF register
+ * @id: SYSCONF register ID, processed with SYSCON_ID() macro
+ * @value: Value to be written
+ * @bitmsk: Bit mask applied to @value
+ */
+void stm32mp_syscfg_write(uint32_t id, uint32_t value, uint32_t bitmsk);
+
+/*
+ * Read SYSCONF reagister
+ * @id: SYSCONF register ID, processed with SYSCON_ID() macro
+ */
+uint32_t stm32mp_syscfg_read(uint32_t id);
+
+/*
+ * Set safe reset state
+ * @status: True to enable safe reset, false to disable safe reset
+ */
+void stm32mp25_syscfg_set_safe_reset(bool status);
+
+#endif /*__STM32_SYSCONF_H__*/
diff --git a/core/arch/arm/plat-stm32mp2/stm32_util.h b/core/arch/arm/plat-stm32mp2/stm32_util.h
index 2575f0a5c1cf8a35980fde4fa9a283a6069a013c..144f5ad619dd7acd18adc51a20fa12b63a3c61e3 100644
--- a/core/arch/arm/plat-stm32mp2/stm32_util.h
+++ b/core/arch/arm/plat-stm32mp2/stm32_util.h
@@ -6,20 +6,15 @@
 #ifndef __STM32_UTIL_H__
 #define __STM32_UTIL_H__
 
+#include <drivers/stm32mp2_rcc_util.h>
 #include <kernel/spinlock.h>
 #include <stdint.h>
 #include <types_ext.h>
 
-static inline void stm32mp_register_secure_periph_iomem(vaddr_t base __unused)
-{
-}
-
-static inline void stm32mp_register_non_secure_periph_iomem(vaddr_t base
-							    __unused) { }
-
-static inline void stm32mp_register_gpioz_pin_count(size_t count __unused) { }
-
 #define may_spin_lock(lock)		  cpu_spin_lock_xsave(lock)
 #define may_spin_unlock(lock, exceptions) cpu_spin_unlock_xrestore(lock, \
 								   exceptions)
+
+bool stm32mp_allow_probe_shared_device(const void *fdt, int node);
+
 #endif /*__STM32_UTIL_H__*/
diff --git a/core/arch/arm/plat-stm32mp2/stm32mp_pm.c b/core/arch/arm/plat-stm32mp2/stm32mp_pm.c
new file mode 100644
index 0000000000000000000000000000000000000000..7dfe0e36170efd6c5a3ffba793ee171bd4e59a66
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/stm32mp_pm.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023-2024, STMicroelectronics
+ */
+
+#include <kernel/misc.h>
+#include <kernel/pm.h>
+#include <kernel/thread.h>
+#include <sm/psci.h>
+#include <stm32mp_pm.h>
+
+/**
+ * @brief   Handler for system off
+ *
+ * @param[in] a0   Unused
+ * @param[in] a1   Unused
+ *
+ * @retval 0       if OK, other value else and TF-A will panic
+ */
+unsigned long thread_system_off_handler(unsigned long a0 __unused,
+					unsigned long a1 __unused)
+{
+	/*
+	 * configure targeted mode in PMIC for system OFF,
+	 * no need to save context
+	 */
+	uint32_t pm_hint = PM_HINT_CLOCK_STATE |
+		((PM_MAX_LEVEL << PM_HINT_PLATFORM_STATE_SHIFT) &
+		  PM_HINT_PLATFORM_STATE_MASK);
+
+	return pm_change_state(PM_OP_SUSPEND, pm_hint);
+}
+
+static uint32_t get_pm_hint(unsigned long a0)
+{
+	uint32_t pm_hint = 0U;
+
+	/* a0 is the highest power level which was powered down. */
+	if (a0 < PM_D2_LPLV_LEVEL)
+		pm_hint = PM_HINT_CLOCK_STATE;
+	else
+		pm_hint = PM_HINT_CONTEXT_STATE;
+
+	pm_hint |= ((a0 << PM_HINT_PLATFORM_STATE_SHIFT) &
+		    PM_HINT_PLATFORM_STATE_MASK);
+
+	return pm_hint;
+}
+
+/**
+ * @brief   Handler for cpu resume
+ *
+ * @param[in] a0   Max power level powered down
+ * @param[in] a1   Unused
+ *
+ * @retval 0       if OK, other value else and TF-A will panic
+ */
+unsigned long thread_cpu_resume_handler(unsigned long a0,
+					unsigned long a1 __unused)
+{
+	TEE_Result retstatus = TEE_SUCCESS;
+
+	retstatus = pm_change_state(PM_OP_RESUME, get_pm_hint(a0));
+
+	/*
+	 * Returned value to the TF-A.
+	 * If it is not 0, the system will panic
+	 */
+	if (retstatus == TEE_SUCCESS)
+		return 0;
+	else
+		return 1;
+}
+
+/**
+ * @brief   Handler for cpu suspend
+ *
+ * @param[in] a0   Max power level to power down
+ * @param[in] a1   Unused
+ *
+ * @retval 0       if OK, other value else and TF-A will panic
+ */
+unsigned long thread_cpu_suspend_handler(unsigned long a0,
+					 unsigned long a1 __unused)
+{
+	TEE_Result retstatus = TEE_SUCCESS;
+
+	retstatus = pm_change_state(PM_OP_SUSPEND, get_pm_hint(a0));
+
+	/*
+	 * Returned value to the TF-A.
+	 * If it is not 0, the system will panic
+	 */
+	if (retstatus == TEE_SUCCESS)
+		return 0;
+	else
+		return 1;
+}
diff --git a/core/arch/arm/plat-stm32mp2/stm32mp_pm.h b/core/arch/arm/plat-stm32mp2/stm32mp_pm.h
new file mode 100644
index 0000000000000000000000000000000000000000..d8ac02dc4e0d7b406747099fdfce30d5537e3199
--- /dev/null
+++ b/core/arch/arm/plat-stm32mp2/stm32mp_pm.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023-2024, STMicroelectronics
+ */
+
+#ifndef __STM32MP_PM_H__
+#define __STM32MP_PM_H__
+
+/*
+ * The PSCI topology is defined in TF-A, with 5 power levels supported in
+ * the first parameter a0="Max power level powered down" of TF-A SPD hooks
+ *
+ * power level                (associated low power mode for a0)
+ * 0: CPU1 core#0 or core#1   (Stop1 or LP-Stop1)
+ * 1: D1 domain               (LPLV-Stop1)
+ * 2: LPLV D1                 (Stop2 or LP-Stop2)
+ * 3: D2                      (LPLV-Stop1)
+ * 4: LPLV D2                 (Standby)
+ * 5: MAX                     (PowerOff)
+ *
+ * these power level are only managed in power driver (PMIC), for pm function
+ * use the 2 associated parameters:
+ * - PM_HINT_CONTEXT_STATE : advertise driver to save all their context in DDR
+ *                           (self refresh) for standby mode
+ * - PM_HINT_CLOCK_STATE : advertise driver to interrupt operation when clock
+ *                         are stalled for the other low power modes
+ */
+#define PM_CORE_LEVEL           0
+#define PM_D1_LEVEL             1
+#define PM_D1_LPLV_LEVEL        2
+#define PM_D2_LEVEL             3
+#define PM_D2_LPLV_LEVEL        4
+#define PM_MAX_LEVEL            5
+
+#endif /*__STM32MP_PM_H__*/
diff --git a/core/arch/arm/plat-stm32mp2/sub.mk b/core/arch/arm/plat-stm32mp2/sub.mk
index b5d5551e7f46aac78b063f67bd05d84f4980fcfd..3a097a47023f24f16cf00ca507ff095a67fa40d4 100644
--- a/core/arch/arm/plat-stm32mp2/sub.mk
+++ b/core/arch/arm/plat-stm32mp2/sub.mk
@@ -1,3 +1,5 @@
 global-incdirs-y += .
 
 srcs-y += main.c
+srcs-y += stm32mp_pm.c
+subdirs-y += drivers
diff --git a/core/arch/arm/plat-sunxi/main.c b/core/arch/arm/plat-sunxi/main.c
index b0f80484f218b43cab87818522d02b2cd0c8648a..5ed2f95c5a81c68346d40bdd012ebac201330f82 100644
--- a/core/arch/arm/plat-sunxi/main.c
+++ b/core/arch/arm/plat-sunxi/main.c
@@ -88,7 +88,7 @@ static void tzpc_init(void);
 
 static struct serial8250_uart_data console_data;
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data,
 			     CONSOLE_UART_BASE,
diff --git a/core/arch/arm/plat-synquacer/main.c b/core/arch/arm/plat-synquacer/main.c
index 2ba622f1edce3ef7c1483620609321e0f88c01c2..54d7bee6225eb34fea1836b698ab01f1f155b09a 100644
--- a/core/arch/arm/plat-synquacer/main.c
+++ b/core/arch/arm/plat-synquacer/main.c
@@ -28,7 +28,7 @@ register_phys_mem_pgdir(MEM_AREA_IO_SEC, GIC_BASE, CORE_MMU_PGDIR_SIZE);
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, THERMAL_SENSOR_BASE,
 			CORE_MMU_PGDIR_SIZE);
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
 		   CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-synquacer/rng_pta.c b/core/arch/arm/plat-synquacer/rng_pta.c
index 16a1e46b7cb28890114a9347f442479cd03550d9..2a34d33b53b71675523888dc18976f53c556d582 100644
--- a/core/arch/arm/plat-synquacer/rng_pta.c
+++ b/core/arch/arm/plat-synquacer/rng_pta.c
@@ -124,7 +124,7 @@ static unsigned int entropy_lock = SPINLOCK_UNLOCK;
 
 static void pool_add_entropy(uint8_t *entropy, uint32_t size)
 {
-	uint32_t copy_size;
+	uint32_t copy_size = 0;
 
 	if (entropy_size >= ENTROPY_POOL_SIZE)
 		return;
@@ -141,7 +141,7 @@ static void pool_add_entropy(uint8_t *entropy, uint32_t size)
 
 static void pool_get_entropy(uint8_t *buf, uint32_t size)
 {
-	uint32_t off;
+	uint32_t off = 0;
 
 	if (size > entropy_size)
 		return;
@@ -154,9 +154,11 @@ static void pool_get_entropy(uint8_t *buf, uint32_t size)
 
 static bool health_test(uint8_t sensor_id)
 {
-	uint32_t falling_edge_count = 0, rising_edge_count = 0;
-	uint32_t lo_edge_count, hi_edge_count;
-	uint32_t i;
+	uint32_t falling_edge_count = 0;
+	uint32_t rising_edge_count = 0;
+	uint32_t lo_edge_count = 0;
+	uint32_t hi_edge_count = 0;
+	uint32_t i = 0;
 
 	for (i = 0; i < (SENSOR_DATA_SIZE - 1); i++) {
 		if ((sensors_data[sensor_id][i] ^
@@ -179,10 +181,10 @@ static bool health_test(uint8_t sensor_id)
 
 static uint8_t pool_check_add_entropy(void)
 {
-	uint32_t i;
+	uint32_t i = 0;
 	uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE];
 	uint8_t pool_status = 0;
-	TEE_Result res;
+	TEE_Result res = TEE_ERROR_GENERIC;
 
 	for (i = 0; i < NUM_SENSORS; i++) {
 		/* Check if particular sensor data passes health test */
@@ -222,11 +224,12 @@ static uint8_t pool_check_add_entropy(void)
 
 void rng_collect_entropy(void)
 {
-	uint8_t i, pool_full = 0;
-	void *vaddr;
-	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
+	uint8_t i = 0;
+	void *vaddr = 0;
+	uint8_t pool_full = 0;
+	uint32_t exceptions = 0;
 
-	cpu_spin_lock(&entropy_lock);
+	exceptions = cpu_spin_lock_xsave(&entropy_lock);
 
 	for (i = 0; i < NUM_SENSORS; i++) {
 		vaddr = phys_to_virt_io(THERMAL_SENSOR_BASE0 +
@@ -247,16 +250,16 @@ void rng_collect_entropy(void)
 	if (pool_full)
 		generic_timer_stop();
 
-	cpu_spin_unlock(&entropy_lock);
-	thread_set_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&entropy_lock, exceptions);
 }
 
 static TEE_Result rng_get_entropy(uint32_t types,
 				  TEE_Param params[TEE_NUM_PARAMS])
 {
 	uint8_t *e = NULL;
-	uint32_t pool_size = 0, rq_size = 0;
-	uint32_t exceptions;
+	uint32_t rq_size = 0;
+	uint32_t pool_size = 0;
+	uint32_t exceptions = 0;
 	TEE_Result res = TEE_SUCCESS;
 
 	if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
@@ -276,8 +279,7 @@ static TEE_Result rng_get_entropy(uint32_t types,
 	if (!e)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
-	cpu_spin_lock(&entropy_lock);
+	exceptions = cpu_spin_lock_xsave(&entropy_lock);
 
 	/*
 	 * Report health test failure to normal world in case fail count
@@ -305,8 +307,7 @@ exit:
 	/* Enable timer FIQ to fetch entropy */
 	generic_timer_start(TIMER_PERIOD_MS);
 
-	cpu_spin_unlock(&entropy_lock);
-	thread_set_exceptions(exceptions);
+	cpu_spin_unlock_xrestore(&entropy_lock, exceptions);
 
 	return res;
 }
diff --git a/core/arch/arm/plat-telechips/conf.mk b/core/arch/arm/plat-telechips/conf.mk
new file mode 100644
index 0000000000000000000000000000000000000000..656dd9afdc419fc7e3c73e2782c3664dc41eb308
--- /dev/null
+++ b/core/arch/arm/plat-telechips/conf.mk
@@ -0,0 +1,38 @@
+ifeq ($(PLATFORM_FLAVOR),tcc805x)
+CFG_PL011 ?= y
+CFG_OPENEDGES_OMC ?= y
+CFG_ARM_SMCCC_TRNG ?= y
+
+$(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
+$(call force,CFG_CORE_ARM64_PA_BITS,35)
+$(call force,CFG_TEE_CORE_NB_CORE,4)
+
+CFG_TZDRAM_START ?= 0x2E000000
+CFG_TZDRAM_SIZE ?= 0x02000000
+
+include core/arch/arm/cpu/cortex-armv8-0.mk
+$(call force,CFG_ARM64_core,y)
+
+TCMKTOOL_IMGNAME ?= A72-OPTEE
+else
+$(error Unsupported PLATFORM_FLAVOR "$(PLATFORM_FLAVOR)")
+endif
+
+$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
+$(call force,CFG_GIC,y)
+$(call force,CFG_CACHE_API,y)
+$(call force,CFG_CORE_RESERVED_SHM,n)
+
+ifeq ($(platform-flavor-armv8),1)
+$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
+$(call force,CFG_CRYPTO_WITH_CE,y)
+endif
+
+CFG_NUM_THREADS ?= $(CFG_TEE_CORE_NB_CORE)
+CFG_SECSTOR_TA ?= n
+CFG_CORE_HEAP_SIZE ?= 1048576
+CFG_WITH_STATS ?= y
+
+ifeq ($(CFG_RPMB_FS),y)
+CFG_IN_TREE_EARLY_TAS += avb/023f8f1a-292a-432b-8fc4-de8471358067
+endif
diff --git a/core/arch/arm/plat-telechips/drivers/include/drivers/tcc_otp.h b/core/arch/arm/plat-telechips/drivers/include/drivers/tcc_otp.h
new file mode 100644
index 0000000000000000000000000000000000000000..da87c09c4facc1277503171d82cc99f6fda7fc24
--- /dev/null
+++ b/core/arch/arm/plat-telechips/drivers/include/drivers/tcc_otp.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#ifndef __DRIVERS_TCC_OTP_H
+#define __DRIVERS_TCC_OTP_H
+
+#include <tee_api_types.h>
+
+TEE_Result tcc_otp_read_128(uint32_t offset, uint32_t *buf);
+TEE_Result tcc_otp_write_128(uint32_t offset, const uint32_t *buf);
+
+#endif /* __DRIVERS_TCC_OTP_H */
diff --git a/core/arch/arm/plat-telechips/drivers/sub.mk b/core/arch/arm/plat-telechips/drivers/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..b394c7ffe9674dbdb276212e709f930d00627e64
--- /dev/null
+++ b/core/arch/arm/plat-telechips/drivers/sub.mk
@@ -0,0 +1 @@
+srcs-y += tcc_otp.c
diff --git a/core/arch/arm/plat-telechips/drivers/tcc_otp.c b/core/arch/arm/plat-telechips/drivers/tcc_otp.c
new file mode 100644
index 0000000000000000000000000000000000000000..91a94cd6ba4e12fd4fd435400aa4fcb57d24ceb8
--- /dev/null
+++ b/core/arch/arm/plat-telechips/drivers/tcc_otp.c
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#include <drivers/tcc_otp.h>
+#include <io.h>
+#include <kernel/delay.h>
+#include <mm/core_memprot.h>
+#include <otprom.h>
+#include <string.h>
+
+#define OTP_CTRL_SIZE		U(0x1000)
+#define OTP_CMD_SIZE		U(0x1000)
+
+#define GENERAL_STATUS		U(0x0)
+#define READ_STATUS		U(0x4)
+#define PROG_STATUS		U(0x8)
+#define OTP_ADDRESS		U(0x10)
+#define OTP_CONTROL		U(0x14)
+#define READ_DATA_PAYLOAD0	U(0x20)
+#define READ_DATA_PAYLOAD1	U(0x24)
+#define READ_DATA_PAYLOAD2	U(0x28)
+#define READ_DATA_PAYLOAD3	U(0x2C)
+#define READ_ADMIN_INFO0	U(0x30)
+#define READ_ADMIN_INFO1	U(0x34)
+#define READ_ADMIN_INFO2	U(0x38)
+#define READ_ADMIN_INFO3	U(0x3C)
+#define PROG_DATA_PAYLOAD0	U(0x40)
+#define PROG_DATA_PAYLOAD1	U(0x44)
+#define PROG_DATA_PAYLOAD2	U(0x48)
+#define PROG_DATA_PAYLOAD3	U(0x4C)
+#define PROG_ADMIN_INFO0	U(0x50)
+#define PROG_ADMIN_INFO1	U(0x54)
+#define PROG_ADMIN_INFO2	U(0x58)
+#define PROG_ADMIN_INFO3	U(0x5C)
+
+/* GENERAL_STATUS */
+#define STATUS_READY		BIT(0)
+
+/* READ_STATUS */
+#define DATA_ERR		BIT(3)
+#define PERMISSION_ERR          BIT(0)
+
+/* OTP_CONTROL Register */
+#define CTRL_DONE		BIT(16)
+#define CTRL_START		BIT(0)
+#define CTRL_CMD_PROG		SHIFT_U32(0xA, 4)
+#define CTRL_CMD_READ		SHIFT_U32(0xF, 4)
+
+/* Admin Info */
+#define ADMIN_VALID		BIT(0)
+
+/* Write Protection Control */
+#define EXT_WP			BIT(30)
+#define SOFT_WP			BIT(3)
+
+#define IS_16BYTE_ALIGNED(x)	IS_ALIGNED(x, 16)
+
+register_phys_mem(MEM_AREA_IO_SEC, OTP_CMD_BASE, OTP_CMD_SIZE);
+
+static void wait_for_ready(vaddr_t reg)
+{
+	while (!(io_read32(reg + GENERAL_STATUS) & STATUS_READY))
+		udelay(1);
+}
+
+static void wait_for_done(vaddr_t reg)
+{
+	while (!(io_read32(reg + OTP_CONTROL) & CTRL_DONE))
+		udelay(1);
+}
+
+TEE_Result tcc_otp_read_128(uint32_t offset, uint32_t *buf)
+{
+	vaddr_t reg = (vaddr_t)phys_to_virt_io(OTP_CMD_BASE, OTP_CMD_SIZE);
+	uint32_t status = 0;
+	uint32_t admin_info0 = 0;
+
+	if (!IS_16BYTE_ALIGNED(offset) || offset >= OTPROM_128_LIMIT ||
+	    offset < OTPROM_128_START || !buf || !reg) {
+		EMSG("Invalid parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	wait_for_ready(reg);
+	io_write32(reg + OTP_ADDRESS, offset);
+	io_write32(reg + OTP_CONTROL, CTRL_CMD_READ | CTRL_START);
+	wait_for_done(reg);
+
+	admin_info0 = io_read32(reg + READ_ADMIN_INFO0);
+	if (!(admin_info0 & ADMIN_VALID)) {
+		if (!admin_info0 && !io_read32(reg + READ_STATUS))
+			return TEE_ERROR_NO_DATA;
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	status = io_read32(reg + READ_STATUS);
+	if (status & (DATA_ERR | PERMISSION_ERR)) {
+		EMSG("Failed to read OTP (%#"PRIx32")", status);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	buf[0] = io_read32(reg + READ_DATA_PAYLOAD0);
+	buf[1] = io_read32(reg + READ_DATA_PAYLOAD1);
+	buf[2] = io_read32(reg + READ_DATA_PAYLOAD2);
+	buf[3] = io_read32(reg + READ_DATA_PAYLOAD3);
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result tcc_otp_write_128(uint32_t offset, const uint32_t *buf)
+{
+	vaddr_t reg = (vaddr_t)phys_to_virt_io(OTP_CMD_BASE, OTP_CMD_SIZE);
+	vaddr_t ctrl = (vaddr_t)phys_to_virt_io(OTP_CTRL_BASE, OTP_CTRL_SIZE);
+
+	if (!IS_16BYTE_ALIGNED(offset) || offset >= OTPROM_128_LIMIT ||
+	    offset < OTPROM_128_START || !buf || !reg) {
+		EMSG("Invalid parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (io_read32(ctrl) & EXT_WP) {
+		EMSG("EXT_WP is high");
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	wait_for_ready(reg);
+	io_clrbits32(ctrl, SOFT_WP);
+	io_write32(reg + OTP_ADDRESS, offset);
+	io_write32(reg + PROG_DATA_PAYLOAD0, buf[0]);
+	io_write32(reg + PROG_DATA_PAYLOAD1, buf[1]);
+	io_write32(reg + PROG_DATA_PAYLOAD2, buf[2]);
+	io_write32(reg + PROG_DATA_PAYLOAD3, buf[3]);
+	io_write32(reg + PROG_ADMIN_INFO0, 0);
+	io_write32(reg + PROG_ADMIN_INFO1, 0);
+	io_write32(reg + PROG_ADMIN_INFO2, 0);
+	io_write32(reg + PROG_ADMIN_INFO3, 0);
+	io_write32(reg + OTP_CONTROL, CTRL_CMD_PROG | CTRL_START);
+	wait_for_done(reg);
+	io_setbits32(ctrl, SOFT_WP);
+
+	return  TEE_SUCCESS;
+}
diff --git a/core/arch/arm/plat-telechips/link.mk b/core/arch/arm/plat-telechips/link.mk
new file mode 100644
index 0000000000000000000000000000000000000000..60386bbc49bb88721b934bd5f378ea2669a38b19
--- /dev/null
+++ b/core/arch/arm/plat-telechips/link.mk
@@ -0,0 +1,9 @@
+include core/arch/arm/kernel/link.mk
+
+all: $(link-out-dir)/optee.rom
+cleanfiles += $(link-out-dir)/optee.rom
+$(link-out-dir)/optee.rom: $(link-out-dir)/tee-pager_v2.bin
+	@$(cmd-echo-silent) '  GEN     $@'
+	$(q)$(PYTHON3) core/arch/arm/plat-telechips/scripts/tcmktool.py $< $@ $(TCMKTOOL_IMGNAME) \
+		$(CFG_OPTEE_REVISION_MAJOR).$(CFG_OPTEE_REVISION_MINOR)$(CFG_OPTEE_REVISION_EXTRA) \
+		$(CFG_TZDRAM_START) $(PLATFORM_FLAVOR)
diff --git a/core/arch/arm/plat-telechips/main.c b/core/arch/arm/plat-telechips/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..5d2e0667f47a477c559e36d2f7c7aff408b9b9db
--- /dev/null
+++ b/core/arch/arm/plat-telechips/main.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#include <console.h>
+#include <crypto/crypto.h>
+#include <drivers/gic.h>
+#include <drivers/pl011.h>
+#include <drivers/tcc_otp.h>
+#include <kernel/boot.h>
+#include <kernel/tee_common_otp.h>
+#include <otprom.h>
+#include <platform_config.h>
+
+register_phys_mem(MEM_AREA_IO_SEC, TCC_IO_BASE, TCC_IO_SIZE);
+#if defined(TZC_BASE)
+register_phys_mem(MEM_AREA_IO_SEC, TZC_BASE, TZC_SIZE);
+#endif
+
+register_ddr(DRAM0_BASE, DRAM0_SIZE);
+#if defined(DRAM1_BASE)
+register_ddr(DRAM1_BASE, DRAM1_SIZE);
+#endif
+
+static bool huk_is_ready;
+static uint32_t plat_huk[OTP_DATA_TEE_HUK_SIZE / sizeof(uint32_t)];
+
+void boot_primary_init_intc(void)
+{
+	gic_init(GICC_BASE, GICD_BASE);
+}
+
+void boot_secondary_init_intc(void)
+{
+	gic_init_per_cpu();
+}
+
+void plat_console_init(void)
+{
+#if defined(CFG_PL011)
+	static struct pl011_data console_data;
+
+	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
+		   CONSOLE_BAUDRATE);
+	register_serial_console(&console_data.chip);
+#endif
+}
+
+TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
+{
+	static_assert(sizeof(plat_huk) == sizeof(hwkey->data));
+
+	if (!huk_is_ready)
+		return TEE_ERROR_GENERIC;
+
+	memcpy(hwkey->data, plat_huk, OTP_DATA_TEE_HUK_SIZE);
+	return TEE_SUCCESS;
+}
+
+static TEE_Result init_huk(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = tcc_otp_read_128(OTP_DATA_TEE_HUK_OFFSET, plat_huk);
+	if (res == TEE_ERROR_NO_DATA) {
+		IMSG("There is no HUK in OTP. Starting HUK Provisioning");
+		if (!crypto_rng_read(plat_huk, OTP_DATA_TEE_HUK_SIZE)) {
+			tcc_otp_write_128(OTP_DATA_TEE_HUK_OFFSET, plat_huk);
+			res = tcc_otp_read_128(OTP_DATA_TEE_HUK_OFFSET,
+					       plat_huk);
+			if (res != TEE_SUCCESS)
+				EMSG("Failed to store HUK to OTP");
+		} else {
+			EMSG("Failed to generate random number for HUK");
+		}
+	}
+
+	if (res == TEE_SUCCESS)
+		huk_is_ready = true;
+	else
+		EMSG("Failed to get HUK from OTP");
+
+	return res;
+}
+service_init(init_huk);
diff --git a/core/arch/arm/plat-telechips/plat_tzc.c b/core/arch/arm/plat-telechips/plat_tzc.c
new file mode 100644
index 0000000000000000000000000000000000000000..8212719b9f6f9414c4e19531650b1d781c2de416
--- /dev/null
+++ b/core/arch/arm/plat-telechips/plat_tzc.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#include <drivers/openedges_omc.h>
+#include <initcall.h>
+#include <kernel/interrupt.h>
+#include <kernel/panic.h>
+#include <mm/core_memprot.h>
+#include <trace.h>
+
+#define NSEC_ALL_ACCESS   UINT32_MAX
+
+static void tzc_protect_teeos(void)
+{
+	struct omc_region_config cfg = {
+		.filters = GENMASK_32(TZC_OMC_FILTERS - 1, 0),
+		.base = CFG_TZDRAM_START - DRAM0_BASE,
+		.top = (CFG_TZDRAM_START + CFG_TZDRAM_SIZE - 1) - DRAM0_BASE,
+		.ns_device_access = 0,
+		.flags = OMC_FLAG_RELATIVE_ADDR,
+	};
+
+	omc_configure_region(TZC_TEEOS_REGION_NUM, &cfg);
+}
+
+static enum itr_return tzc_it_handler(struct itr_handler *h)
+{
+	uint8_t filter = UINT8_MAX;
+	enum itr_return ret = ITRR_NONE;
+
+	switch (h->it) {
+	case TZC_OMC_INT_0:
+		filter = 0;
+		break;
+#if defined(TZC_OMC_INT_1)
+	case TZC_OMC_INT_1:
+		filter = 1;
+		break;
+#endif
+#if defined(TZC_OMC_INT_2)
+	case TZC_OMC_INT_2:
+		filter = 2;
+		break;
+#endif
+#if defined(TZC_OMC_INT_3)
+	case TZC_OMC_INT_3:
+		filter = 3;
+		break;
+#endif
+	default:
+		break;
+	}
+
+	if (filter != UINT8_MAX) {
+		EMSG("OMC(%"PRIu8") TZC permission failure", filter);
+		omc_fail_dump(filter);
+		omc_int_clear(filter);
+
+		ret = ITRR_HANDLED;
+	}
+
+	return ret;
+}
+
+static struct itr_handler tzc_itr_handler[] = {
+	{
+		.it = TZC_OMC_INT_0,
+		.handler = tzc_it_handler,
+	},
+#if defined(TZC_OMC_INT_1)
+	{
+		.it = TZC_OMC_INT_1,
+		.handler = tzc_it_handler,
+	},
+#endif
+#if defined(TZC_OMC_INT_2)
+	{
+		.it = TZC_OMC_INT_2,
+		.handler = tzc_it_handler,
+	},
+#endif
+#if defined(TZC_OMC_INT_3)
+	{
+		.it = TZC_OMC_INT_3,
+		.handler = tzc_it_handler,
+	},
+#endif
+};
+
+static TEE_Result tzc_configure(void)
+{
+	vaddr_t va = 0;
+	uint8_t filter = 0;
+	struct omc_region_config cfg = {
+		.filters = GENMASK_32(TZC_OMC_FILTERS - 1, 0),
+		.base = 0,
+		.top = UINT64_MAX,
+		.ns_device_access = NSEC_ALL_ACCESS,
+		.flags = 0,
+	};
+
+	DMSG("Initializing TZC");
+
+	va = (vaddr_t)phys_to_virt_io(TZC_OMC_BASE,
+				      TZC_OMC_FILTERS * TZC_OMC_FILTER_OFFS);
+	if (!va)
+		panic();
+
+	omc_init(va, TZC_OMC_FILTER_OFFS, TZC_OMC_FILTERS);
+	omc_configure_region(0, &cfg);
+	tzc_protect_teeos();
+
+	for (filter = 0; filter < ARRAY_SIZE(tzc_itr_handler); filter++) {
+		interrupt_add_handler_with_chip(interrupt_get_main_chip(),
+						&tzc_itr_handler[filter]);
+		interrupt_enable(interrupt_get_main_chip(),
+				 tzc_itr_handler[filter].it);
+	}
+	omc_set_action(OMC_ACTION_INT);
+
+	return TEE_SUCCESS;
+}
+service_init(tzc_configure);
diff --git a/core/arch/arm/plat-telechips/scripts/tcmktool.py b/core/arch/arm/plat-telechips/scripts/tcmktool.py
new file mode 100755
index 0000000000000000000000000000000000000000..5934cfe72ce4c5f150980eb6f14336ec2cc82988
--- /dev/null
+++ b/core/arch/arm/plat-telechips/scripts/tcmktool.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2024, Telechips Inc.
+#
+
+import sys
+from hashlib import sha256
+
+ALIGN_SIZE = 64
+FOOTER_SIZE = 128
+
+
+def calc_hash(inputfile):
+    sha = sha256()
+    inputfile.seek(0)
+    while True:
+        buf = inputfile.read(ALIGN_SIZE)
+        if len(buf) == 0:
+            break
+        sha.update(buf.ljust(ALIGN_SIZE, b'\0'))
+    return sha.digest()
+
+
+def fill_dummy_cert(outputfile):
+    outputfile.write(b'CERT'.ljust(256, b'\0'))
+    return 0
+
+
+def fill_header(outputfile, inputfile, argv):
+    imagename = bytes(argv[3], 'utf-8')
+    imageversion = bytes(argv[4], 'utf-8')
+    targetaddress = int(argv[5], 16)
+    socname = bytes(argv[6], 'utf-8')
+    inputfile.seek(0, 2)
+    offset = 4096  # Min: 256
+    length = (inputfile.tell() + (ALIGN_SIZE - 1)) & ~(ALIGN_SIZE - 1)
+    length += FOOTER_SIZE
+    buf = bytearray(offset - outputfile.tell())
+    buf[0:4] = b'HDR\0'  # Marker
+    buf[4:8] = length.to_bytes(4, byteorder='little')
+    buf[8:12] = offset.to_bytes(4, byteorder='little')
+    buf[16:20] = socname.ljust(4, b'\0')[-4:]
+    buf[20:32] = imagename.ljust(12, b'\0')[0:12]
+    buf[32:48] = imageversion.ljust(16, b'\0')[0:16]
+    buf[48:56] = targetaddress.to_bytes(8, byteorder='little')
+    buf[96:128] = calc_hash(inputfile)
+    outputfile.write(buf)
+    return 0
+
+
+def fill_image(outputfile, inputfile):
+    inputfile.seek(0)
+    while True:
+        buf = inputfile.read(ALIGN_SIZE)
+        if len(buf) == 0:
+            break
+        outputfile.write(buf.ljust(ALIGN_SIZE, b'\0'))
+    return 0
+
+
+def fill_dummy_footer(outputfile):
+    outputfile.write(bytearray(FOOTER_SIZE))
+    return 0
+
+
+def make_image(inputfile, outputfile, argv):
+    if fill_dummy_cert(outputfile) != 0:
+        return -1
+    if fill_header(outputfile, inputfile, argv) != 0:
+        return -2
+    if fill_image(outputfile, inputfile) != 0:
+        return -3
+    if fill_dummy_footer(outputfile) != 0:
+        return -4
+    return 0
+
+
+def print_help():
+    print("")
+    print("Telechips Image Maker")
+    print("")
+    print("Usage: python tcmktool.py [INPUT] [OUTPUT] [NAME] [VERSION]" +
+          " [TARGET_ADDRESS] [SOC_NAME]")
+    print("")
+    print("  INPUT                  input file name.")
+    print("  OUTPUT                 output file name.")
+    print("  NAME                   image name.")
+    print("  VERSION                string version. (max 16 bytes)")
+    print("  TARGET_ADDRESS         target address")
+    print("  SOC_NAME               SoC name. (only the last 4 bytes are used")
+
+
+def main(argc, argv):
+    ret = -1
+
+    if argc != 7:
+        print_help()
+        return -1
+
+    try:
+        with open(argv[1], "rb") as inputfile:
+            with open(argv[2], "wb") as outputfile:
+                ret = make_image(inputfile, outputfile, argv)
+    except Exception as e:
+        if 'inputfile' not in locals():
+            print("ERROR: input file open error\n")
+        elif 'outputfile' not in locals():
+            print("ERROR: output file open error\n")
+        else:
+            print(e)
+
+    if ret == 0:
+        print("{} was generated successfilly\n".format(argv[2]))
+    else:
+        print("Failed to generate output file (error code: {})\n".format(ret))
+
+    return ret
+
+
+if (__name__ == "__main__"):
+    exit(main(len(sys.argv), sys.argv))
diff --git a/core/arch/arm/plat-telechips/sub.mk b/core/arch/arm/plat-telechips/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..827fcd79c7fb7d315a721b92f093b72825b2b27e
--- /dev/null
+++ b/core/arch/arm/plat-telechips/sub.mk
@@ -0,0 +1,7 @@
+global-incdirs-y += $(PLATFORM_FLAVOR)
+global-incdirs-y += drivers/include
+
+srcs-y += main.c
+srcs-y += plat_tzc.c
+
+subdirs-y += drivers
diff --git a/core/arch/arm/plat-telechips/tcc805x/otprom.h b/core/arch/arm/plat-telechips/tcc805x/otprom.h
new file mode 100644
index 0000000000000000000000000000000000000000..312f99237c5242ff05caa49437f8eab2253fc9e9
--- /dev/null
+++ b/core/arch/arm/plat-telechips/tcc805x/otprom.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#ifndef TCC805X_OTPROM_H
+#define TCC805X_OTPROM_H
+
+#include <util.h>
+
+#define OTPROM_MAX			U(0x4000)
+#define OTPROM_128_START		U(0x1000)
+#define OTPROM_128_LIMIT		U(0x2000)
+
+/* HUK */
+#define OTP_DATA_TEE_HUK_OFFSET		U(0x1ED0)
+#define OTP_DATA_TEE_HUK_SIZE		U(0x10)
+
+#endif /* TCC805X_OTPROM_H */
diff --git a/core/arch/arm/plat-telechips/tcc805x/platform_config.h b/core/arch/arm/plat-telechips/tcc805x/platform_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..fd2e2a85ce621cea1649463f0881c3a7bb8e6e9d
--- /dev/null
+++ b/core/arch/arm/plat-telechips/tcc805x/platform_config.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#ifndef PLATFORM_CONFIG_H
+#define PLATFORM_CONFIG_H
+
+#include <mm/generic_ram_layout.h>
+#include <util.h>
+
+/* Make stacks aligned to data cache line length */
+#define STACK_ALIGNMENT		64
+
+/* Peripherals */
+#define TCC_IO_BASE		U(0x10000000)
+#define TCC_IO_SIZE		U(0x10000000)
+
+/* GIC */
+#define GICD_BASE		U(0x17301000)
+#define GICC_BASE		U(0x17302000)
+
+/* Console */
+#define CONSOLE_UART_BASE	U(0x16600000)
+#define CONSOLE_UART_CLK_IN_HZ	24000000
+#define CONSOLE_BAUDRATE	115200
+
+/* OTP */
+#define OTP_CTRL_BASE		U(0x19101000)
+#define OTP_CMD_BASE		U(0xE0004000)
+
+/* TZC Cfg */
+#define TZC_BASE		U(0xE8300000)
+#define TZC_SIZE		U(0x00100000)
+#define TZC_OMC_BASE		(TZC_BASE + U(0x80000))
+#define TZC_OMC_FILTERS		U(4)
+#define TZC_OMC_FILTER_OFFS	U(0x10000)
+#define TZC_OMC_INT_0		(U(231) + U(32))
+#define TZC_OMC_INT_1		(U(233) + U(32))
+#define TZC_OMC_INT_2		(U(235) + U(32))
+#define TZC_OMC_INT_3		(U(237) + U(32))
+#define TZC_TEEOS_REGION_NUM    U(1)
+
+/* DRAM Info */
+#define DRAM0_BASE		U(0x20000000)
+#define DRAM0_SIZE		U(0xA0000000)	/* 2.5 GiB */
+#define DRAM1_BASE		U(0x1A0000000)
+#define DRAM1_SIZE		U(0x60000000)   /* 1.5 GiB */
+
+#endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/arm/plat-ti/main.c b/core/arch/arm/plat-ti/main.c
index 5b132ae7ec13bcb67b04364288471ff82425b924..7ae0313e1f4b4aa8542da98e8765316502a8d2be 100644
--- a/core/arch/arm/plat-ti/main.c
+++ b/core/arch/arm/plat-ti/main.c
@@ -108,7 +108,7 @@ void init_sec_mon(unsigned long nsec_entry)
 	memcpy(plat_huk, plat_boot_args->huk, sizeof(plat_boot_args->huk));
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
 			     CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-totalcompute/main.c b/core/arch/arm/plat-totalcompute/main.c
index c3445c0c0bce0b811dbd72736ddb75137beedcc5..92242822950fb5402d105ff7a613b9b8070a9bd3 100644
--- a/core/arch/arm/plat-totalcompute/main.c
+++ b/core/arch/arm/plat-totalcompute/main.c
@@ -32,7 +32,7 @@ void boot_primary_init_intc(void)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
 		   CONSOLE_UART_BAUDRATE);
diff --git a/core/arch/arm/plat-uniphier/main.c b/core/arch/arm/plat-uniphier/main.c
index 080dd83b972c8a26c360fb36742b1e5498956ad4..a01e8ff30ec872b82258174453d230331d2ef12b 100644
--- a/core/arch/arm/plat-uniphier/main.c
+++ b/core/arch/arm/plat-uniphier/main.c
@@ -40,7 +40,7 @@ void boot_primary_init_intc(void)
 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	/* Init UART */
 	serial8250_uart_init(&console_data, CONSOLE_UART_BASE,
diff --git a/core/arch/arm/plat-versal/main.c b/core/arch/arm/plat-versal/main.c
index 37623cb0d8f65bb960c29d7d9865c663055caeb3..b443269bd4aabf7c0412b8598c044cbc19267e07 100644
--- a/core/arch/arm/plat-versal/main.c
+++ b/core/arch/arm/plat-versal/main.c
@@ -51,7 +51,7 @@ void boot_primary_init_intc(void)
 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE,
 		   CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/plat-versal2/conf.mk b/core/arch/arm/plat-versal2/conf.mk
new file mode 100644
index 0000000000000000000000000000000000000000..4325295b147fff1374f5371716a691024d16df77
--- /dev/null
+++ b/core/arch/arm/plat-versal2/conf.mk
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+#
+#
+
+PLATFORM_FLAVOR ?= generic
+
+include core/arch/arm/cpu/cortex-armv8-0.mk
+
+CFG_MMAP_REGIONS ?= 24
+
+# Disable Non-Standard Crypto Algorithms
+$(call force,CFG_CRYPTO_SM2_PKE,n)
+$(call force,CFG_CRYPTO_SM2_DSA,n)
+$(call force,CFG_CRYPTO_SM2_KEP,n)
+$(call force,CFG_CRYPTO_SM3,n)
+$(call force,CFG_CRYPTO_SM4,n)
+
+# platform does not support paging; explicitly disable CFG_WITH_PAGER
+$(call force,CFG_WITH_PAGER,n)
+
+# Platform specific configurations
+$(call force,CFG_SECURE_TIME_SOURCE_CNTPCT,y)
+$(call force,CFG_WITH_ARM_TRUSTED_FW,y)
+$(call force,CFG_TEE_CORE_NB_CORE,8)
+$(call force,CFG_ARM_GICV3,y)
+$(call force,CFG_PL011,y)
+$(call force,CFG_GIC,y)
+
+CFG_CORE_RESERVED_SHM	?= n
+CFG_CORE_DYN_SHM	?= y
+CFG_WITH_STATS		?= y
+CFG_ARM64_core		?= y
+
+# Enable ARM Crypto Extensions(CE)
+$(call force,CFG_CRYPTO_WITH_CE,y)
+$(call force,CFG_CRYPTO_WITH_CE82,y)
+
+# Define the number of cores per cluster used in calculating core position.
+# The cluster number is shifted by this value and added to the core ID,
+# so its value represents log2(cores/cluster).
+# For AMD Versal Gen 2 there are 4 clusters and 2 cores per cluster.
+$(call force,CFG_CORE_CLUSTER_SHIFT,1)
+
+# By default optee_os is located at the following location.
+# This range to contain optee_os, TEE RAM and TA RAM.
+# Default size is 128MB.
+CFG_TZDRAM_START   ?= 0x1800000
+CFG_TZDRAM_SIZE    ?= 0x8000000
+
+# Console selection
+# 0 : UART0[pl011, pl011_0] (default)
+# 1 : UART1[pl011_1]
+CFG_CONSOLE_UART ?= 0
+
+ifeq ($(CFG_ARM64_core),y)
+$(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
+$(call force,CFG_CORE_ARM64_PA_BITS,43)
+endif
+
+CFG_CORE_HEAP_SIZE ?= 262144
diff --git a/core/arch/arm/plat-versal2/main.c b/core/arch/arm/plat-versal2/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..82e35c14ea4165f1fd05a59ad418b6dd7ffef243
--- /dev/null
+++ b/core/arch/arm/plat-versal2/main.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include <arm.h>
+#include <assert.h>
+#include <console.h>
+#include <drivers/gic.h>
+#include <drivers/pl011.h>
+#include <drivers/versal_pm.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/misc.h>
+#include <kernel/tee_time.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <stdint.h>
+#include <string.h>
+#include <tee/tee_fs.h>
+#include <trace.h>
+
+static struct pl011_data console_data;
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC,
+			ROUNDDOWN(CONSOLE_UART_BASE, CORE_MMU_PGDIR_SIZE),
+			CORE_MMU_PGDIR_SIZE);
+
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICD_BASE, GIC_DIST_REG_SIZE);
+register_phys_mem_pgdir(MEM_AREA_IO_SEC, GICR_BASE, GIC_DIST_REG_SIZE);
+
+register_ddr(DRAM0_BASE, DRAM0_SIZE);
+
+void boot_primary_init_intc(void)
+{
+	gic_init_v3(0, GICD_BASE, GICR_BASE);
+}
+
+void plat_console_init(void)
+{
+	pl011_init(&console_data, CONSOLE_UART_BASE,
+		   CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
+	register_serial_console(&console_data.chip);
+}
+
+static TEE_Result platform_banner(void)
+{
+	IMSG("OP-TEE OS Running on Platform AMD Versal Gen 2");
+
+	return TEE_SUCCESS;
+}
+
+service_init(platform_banner);
diff --git a/core/arch/arm/plat-versal2/platform_config.h b/core/arch/arm/plat-versal2/platform_config.h
new file mode 100644
index 0000000000000000000000000000000000000000..8f15ec93741f6763a489a4ddfe8c372f2fb3d638
--- /dev/null
+++ b/core/arch/arm/plat-versal2/platform_config.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#ifndef PLATFORM_CONFIG_H
+#define PLATFORM_CONFIG_H
+
+#include <mm/generic_ram_layout.h>
+
+/* Make stacks aligned to data cache line length */
+#define CACHELINE_LEN		64
+#define STACK_ALIGNMENT		CACHELINE_LEN
+
+#define CONSOLE_UART0		U(0)
+#define CONSOLE_UART1		U(1)
+
+#if defined(PLATFORM_FLAVOR_generic)
+
+#define PLM_RTCA		0xF2014000
+#define PLM_RTCA_LEN		0x1000
+
+#define GICD_BASE		U(0xE2000000)
+#define GICR_BASE		U(0xE2060000)
+
+#define UART0_BASE		U(0xF1920000)
+#define UART1_BASE		U(0xF1930000)
+
+#define IT_UART0		50
+#define IT_UART1		51
+
+#define UART_CLK_IN_HZ		100000000
+
+#if (CFG_CONSOLE_UART == CONSOLE_UART1)
+#define CONSOLE_UART_BASE       UART1_BASE
+#define IT_CONSOLE_UART         IT_UART1
+#else /* CFG_CONSOLE_UART == CONSOLE_UART0 (default) */
+#define CONSOLE_UART_BASE	UART0_BASE
+#define IT_CONSOLE_UART		IT_UART0
+#endif
+
+#define CONSOLE_UART_CLK_IN_HZ	UART_CLK_IN_HZ
+
+#define DRAM0_BASE		0
+#define DRAM0_SIZE		0x80000000
+
+#ifndef ARM64
+#error "Only ARM64 is supported!"
+#endif
+
+#else
+#error "Unknown platform flavor"
+#endif
+
+#ifndef UART_BAUDRATE
+#define UART_BAUDRATE		115200
+#endif
+
+#ifndef CONSOLE_BAUDRATE
+#define CONSOLE_BAUDRATE	UART_BAUDRATE
+#endif
+
+#endif /* PLATFORM_CONFIG_H */
diff --git a/core/arch/arm/plat-versal2/sub.mk b/core/arch/arm/plat-versal2/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..1f906d31e4a00d8271c4723543b49a325b261a73
--- /dev/null
+++ b/core/arch/arm/plat-versal2/sub.mk
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023-2024, Advanced Micro Devices, Inc. All rights reserved.
+#
+#
+
+global-incdirs-y += .
+srcs-y += main.c
diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk
index eefe1e520393c3f50246be48e708b8597d24d842..2a82fafccd74d54fae8a63fdc3a0bab4b427aa3b 100644
--- a/core/arch/arm/plat-vexpress/conf.mk
+++ b/core/arch/arm/plat-vexpress/conf.mk
@@ -79,7 +79,7 @@ $(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
 $(call force,CFG_CORE_ARM64_PA_BITS,36)
 CFG_AUTO_MAX_PA_BITS ?= y
 ifeq ($(CFG_SCMI_SCPFW),y)
-$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp)
+$(call force,CFG_SCMI_SCPFW_PRODUCT,fvp)
 endif
 ifeq ($(CFG_CORE_SEL1_SPMC),y)
 CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 9
@@ -102,6 +102,7 @@ CFG_WITH_SOFTWARE_PRNG ?= n
 endif
 
 ifeq ($(PLATFORM_FLAVOR),qemu_virt)
+CFG_CORE_HEAP_SIZE ?= 98304
 CFG_HALT_CORES_ON_PANIC ?= y
 CFG_TEE_CORE_NB_CORE ?= 4
 # [0e00.0000 0e0f.ffff] is reserved to early boot
@@ -130,6 +131,8 @@ CFG_CORE_ASYNC_NOTIF_GIC_INTID ?= 219
 endif
 
 ifeq ($(PLATFORM_FLAVOR),qemu_armv8a)
+CFG_CORE_TZSRAM_EMUL_SIZE ?= 655360
+CFG_CORE_HEAP_SIZE ?= 196608
 CFG_HALT_CORES_ON_PANIC ?= y
 CFG_TEE_CORE_NB_CORE ?= 4
 CFG_AUTO_MAX_PA_BITS ?= y
@@ -151,7 +154,7 @@ endif
 $(call force,CFG_DT,y)
 CFG_DTB_MAX_SIZE ?= 0x100000
 ifeq ($(CFG_SCMI_SCPFW),y)
-$(call force,CFG_SCMI_SCPFW_PRODUCT,optee-fvp)
+$(call force,CFG_SCMI_SCPFW_PRODUCT,fvp)
 endif
 
 CFG_CORE_ASYNC_NOTIF ?= y
@@ -170,3 +173,4 @@ endif
 endif
 
 CFG_PKCS11_TA ?= y
+CFG_PKCS11_TA_RSA_X_509 ?= y
diff --git a/core/arch/arm/plat-vexpress/main.c b/core/arch/arm/plat-vexpress/main.c
index 63be30aa13839ac342ce315967dbfee063816752..c278978581e74c3a18e18b937788297fb67c1396 100644
--- a/core/arch/arm/plat-vexpress/main.c
+++ b/core/arch/arm/plat-vexpress/main.c
@@ -19,17 +19,19 @@
 #include <kernel/notif.h>
 #include <kernel/panic.h>
 #include <kernel/spinlock.h>
-#include <kernel/tee_time.h>
 #include <kernel/thread_spmc.h>
+#include <kernel/timer.h>
+#include <kernel/virtualization.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <platform_config.h>
 #include <sm/psci.h>
 #include <stdint.h>
-#include <string.h>
 #include <trace.h>
 
 static struct pl011_data console_data __nex_bss;
+static uint16_t console_notif_vm_id __nex_bss;
+static uint16_t console_notif_backup_vm_id __nex_bss;
 
 register_phys_mem_pgdir(MEM_AREA_IO_SEC, CONSOLE_UART_BASE, PL011_REG_SIZE);
 #if defined(PLATFORM_FLAVOR_fvp)
@@ -83,7 +85,7 @@ void boot_primary_init_intc(void)
 }
 #endif
 
-void console_init(void)
+void plat_console_init(void)
 {
 	pl011_init(&console_data, CONSOLE_UART_BASE, CONSOLE_UART_CLK_IN_HZ,
 		   CONSOLE_BAUDRATE);
@@ -92,8 +94,9 @@ void console_init(void)
 
 #if (defined(CFG_GIC) || defined(CFG_CORE_HAFNIUM_INTC)) && \
 	defined(IT_CONSOLE_UART) && \
-	!defined(CFG_NS_VIRTUALIZATION) && \
-	!(defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV2))
+	!(defined(CFG_WITH_ARM_TRUSTED_FW) && defined(CFG_ARM_GICV2)) && \
+	!defined(CFG_SEMIHOSTING_CONSOLE) && \
+	!defined(CFG_FFA_CONSOLE)
 /*
  * This cannot be enabled with TF-A and GICv3 because TF-A then need to
  * assign the interrupt number of the UART to OP-TEE (S-EL1). Currently
@@ -117,22 +120,30 @@ static void read_console(void)
 	}
 }
 
-static enum itr_return console_itr_cb(struct itr_handler *hdl)
+static uint16_t get_console_notif_vm_id(void)
 {
-	if (notif_async_is_started()) {
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+		return console_notif_vm_id;
+	return 0;
+}
+
+static enum itr_return console_itr_cb(struct itr_handler *hdl __unused)
+{
+	if (notif_async_is_started(get_console_notif_vm_id())) {
 		/*
 		 * Asynchronous notifications are enabled, lets read from
 		 * uart in the bottom half instead.
 		 */
-		interrupt_disable(hdl->chip, hdl->it);
-		notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF);
+		console_data.chip.ops->rx_intr_disable(&console_data.chip);
+		notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF,
+				 get_console_notif_vm_id());
 	} else {
 		read_console();
 	}
 	return ITRR_HANDLED;
 }
 
-static struct itr_handler console_itr = {
+static struct itr_handler console_itr __nex_data = {
 	.it = IT_CONSOLE_UART,
 	.flags = ITRF_TRIGGER_LEVEL,
 	.handler = console_itr_cb,
@@ -140,9 +151,24 @@ static struct itr_handler console_itr = {
 DECLARE_KEEP_PAGER(console_itr);
 
 static void atomic_console_notif(struct notif_driver *ndrv __unused,
-				 enum notif_event ev __maybe_unused)
+				 enum notif_event ev, uint16_t vm_id)
 {
-	DMSG("Asynchronous notifications started, event %d", (int)ev);
+	switch (ev) {
+	case NOTIF_EVENT_STARTED:
+		DMSG("Asynchronous notifications started, event %d (vm %#"PRIx16")",
+		     (int)ev, vm_id);
+		break;
+	case NOTIF_EVENT_SHUTDOWN:
+		DMSG("Shutting down partition, event %d (vm %#"PRIx16")",
+		     (int)ev, vm_id);
+		if (vm_id == console_notif_backup_vm_id)
+			console_notif_backup_vm_id = 0;
+		if (vm_id == console_notif_vm_id)
+			console_notif_vm_id = console_notif_backup_vm_id;
+		break;
+	default:
+		EMSG("Unknown event %d", (int)ev);
+	}
 }
 DECLARE_KEEP_PAGER(atomic_console_notif);
 
@@ -151,19 +177,23 @@ static void yielding_console_notif(struct notif_driver *ndrv __unused,
 {
 	switch (ev) {
 	case NOTIF_EVENT_DO_BOTTOM_HALF:
+		if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
+		    console_notif_vm_id != virt_get_current_guest_id())
+			break;
 		read_console();
-		interrupt_enable(console_itr.chip, console_itr.it);
+		console_data.chip.ops->rx_intr_enable(&console_data.chip);
 		break;
 	case NOTIF_EVENT_STOPPED:
 		DMSG("Asynchronous notifications stopped");
-		interrupt_enable(console_itr.chip, console_itr.it);
+		console_data.chip.ops->rx_intr_enable(&console_data.chip);
 		break;
 	default:
 		EMSG("Unknown event %d", (int)ev);
 	}
 }
 
-struct notif_driver console_notif = {
+static unsigned int console_notif_lock __nex_bss __maybe_unused;
+static struct notif_driver console_notif __nex_data = {
 	.atomic_cb = atomic_console_notif,
 	.yielding_cb = yielding_console_notif,
 };
@@ -171,6 +201,8 @@ struct notif_driver console_notif = {
 static TEE_Result init_console_itr(void)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
+	bool have_itr_ctrl = console_data.chip.ops->rx_intr_enable &&
+			     console_data.chip.ops->rx_intr_disable;
 
 	res = interrupt_add_handler_with_chip(interrupt_get_main_chip(),
 					      &console_itr);
@@ -179,11 +211,27 @@ static TEE_Result init_console_itr(void)
 
 	interrupt_enable(console_itr.chip, console_itr.it);
 
-	if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF))
+	if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF) && have_itr_ctrl)
 		notif_register_driver(&console_notif);
 	return TEE_SUCCESS;
 }
-driver_init(init_console_itr);
+nex_driver_init(init_console_itr);
+
+#ifdef CFG_NS_VIRTUALIZATION
+static TEE_Result claim_console(void)
+{
+	uint32_t state = cpu_spin_lock_xsave(&console_notif_lock);
+
+	console_notif_vm_id = virt_get_current_guest_id();
+	if (!console_notif_backup_vm_id)
+		console_notif_backup_vm_id = console_notif_vm_id;
+
+	cpu_spin_unlock_xrestore(&console_notif_lock, state);
+
+	return TEE_SUCCESS;
+}
+driver_init(claim_console);
+#endif
 #endif
 
 #ifdef CFG_TZC400
@@ -256,3 +304,15 @@ int psci_cpu_on(uint32_t core_id, uint32_t entry, uint32_t context_id)
 	return PSCI_RET_SUCCESS;
 }
 #endif /*PLATFORM_FLAVOR_qemu_virt*/
+
+#if defined(CFG_CALLOUT) && defined(IT_SEC_PHY_TIMER) && \
+	!defined(CFG_CORE_SEL2_SPMC)
+static TEE_Result init_callout_service(void)
+{
+	timer_init_callout_service(interrupt_get_main_chip(), IT_SEC_PHY_TIMER);
+
+	return TEE_SUCCESS;
+}
+
+nex_early_init(init_callout_service);
+#endif
diff --git a/core/arch/arm/plat-vexpress/platform_config.h b/core/arch/arm/plat-vexpress/platform_config.h
index 21aa40acdcf7f6d6071098c6b6e06fec1e0fc6f7..95142e67e0f13851af81a09b41d7971bcdea0f51 100644
--- a/core/arch/arm/plat-vexpress/platform_config.h
+++ b/core/arch/arm/plat-vexpress/platform_config.h
@@ -72,6 +72,7 @@
 #define UART1_BASE		0x09040000
 
 #define IT_UART1		40
+#define IT_SEC_PHY_TIMER	29
 
 #define CONSOLE_UART_BASE	UART1_BASE
 #define IT_CONSOLE_UART		IT_UART1
diff --git a/core/arch/arm/plat-zynq7k/main.c b/core/arch/arm/plat-zynq7k/main.c
index 08af994fd03ce42ca1943f8a039df5601ea57bcf..5f71a05f28f6c285f403149b50ab020298d55a4c 100644
--- a/core/arch/arm/plat-zynq7k/main.c
+++ b/core/arch/arm/plat-zynq7k/main.c
@@ -89,7 +89,7 @@ void plat_primary_init_early(void)
 	io_write32(SLCR_LOCK, SLCR_LOCK_MAGIC);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	cdns_uart_init(&console_data, CONSOLE_UART_BASE, 0, 0);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/arm/plat-zynqmp/main.c b/core/arch/arm/plat-zynqmp/main.c
index dcbf6869ddb85db48c8247934743e5688f5e767e..16d7d15182b932156d61f6dbad70957ac5229c5c 100644
--- a/core/arch/arm/plat-zynqmp/main.c
+++ b/core/arch/arm/plat-zynqmp/main.c
@@ -80,7 +80,7 @@ void boot_primary_init_intc(void)
 	gic_init(GIC_BASE + GICC_OFFSET, GIC_BASE + GICD_OFFSET);
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	cdns_uart_init(&console_data, CONSOLE_UART_BASE,
 		       CONSOLE_UART_CLK_IN_HZ, CONSOLE_BAUDRATE);
diff --git a/core/arch/arm/tee/entry_fast.c b/core/arch/arm/tee/entry_fast.c
index 5d54dbebfa9f86e928e51426628e9e8cae717aff..0304013efed97157e82bee977782cdaad09deae7 100644
--- a/core/arch/arm/tee/entry_fast.c
+++ b/core/arch/arm/tee/entry_fast.c
@@ -7,14 +7,12 @@
 #include <config.h>
 #include <drivers/wdt.h>
 #include <kernel/boot.h>
-#include <kernel/misc.h>
 #include <kernel/notif.h>
 #include <kernel/tee_l2cc_mutex.h>
 #include <kernel/virtualization.h>
 #include <mm/core_mmu.h>
 #include <optee_msg.h>
 #include <sm/optee_smc.h>
-#include <sm/watchdog_smc.h>
 #include <tee/entry_fast.h>
 
 #ifdef CFG_CORE_RESERVED_SHM
@@ -30,8 +28,8 @@ static void tee_entry_get_shm_config(struct thread_smc_args *args)
 
 static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
 {
-	TEE_Result ret;
 #ifdef ARM32
+	TEE_Result ret = TEE_ERROR_NOT_SUPPORTED;
 	paddr_t pa = 0;
 
 	switch (args->a1) {
@@ -53,15 +51,16 @@ static void tee_entry_fastcall_l2cc_mutex(struct thread_smc_args *args)
 		args->a0 = OPTEE_SMC_RETURN_EBADCMD;
 		return;
 	}
-#else
-	ret = TEE_ERROR_NOT_SUPPORTED;
-#endif
+
 	if (ret == TEE_ERROR_NOT_SUPPORTED)
 		args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
 	else if (ret)
 		args->a0 = OPTEE_SMC_RETURN_EBADADDR;
 	else
 		args->a0 = OPTEE_SMC_RETURN_OK;
+#else
+	args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
+#endif
 }
 
 static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
@@ -118,6 +117,9 @@ static void tee_entry_exchange_capabilities(struct thread_smc_args *args)
 
 	args->a1 |= OPTEE_SMC_SEC_CAP_RPC_ARG;
 	args->a3 = THREAD_RPC_MAX_NUM_PARAMS;
+
+	if (IS_ENABLED(CFG_RPMB_ANNOUNCE_PROBE_CAP))
+		args->a1 |= OPTEE_SMC_SEC_CAP_RPMB_PROBE;
 }
 
 static void tee_entry_disable_shm_cache(struct thread_smc_args *args)
@@ -289,7 +291,13 @@ void __tee_entry_fast(struct thread_smc_args *args)
 
 	case OPTEE_SMC_ENABLE_ASYNC_NOTIF:
 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
-			notif_deliver_atomic_event(NOTIF_EVENT_STARTED);
+			uint16_t g_id = 0;
+
+			if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+				g_id = args->a7;
+
+			notif_deliver_atomic_event(NOTIF_EVENT_STARTED, g_id);
+
 			args->a0 = OPTEE_SMC_RETURN_OK;
 		} else {
 			args->a0 = OPTEE_SMC_RETURN_UNKNOWN_FUNCTION;
diff --git a/core/arch/riscv/include/encoding.h b/core/arch/riscv/include/encoding.h
index 5ab5c764d00926e1f91f043cda8ce12f76e74ac7..734385389bc57964b38bec0b9a5f81173e4566d9 100644
--- a/core/arch/riscv/include/encoding.h
+++ b/core/arch/riscv/include/encoding.h
@@ -220,6 +220,14 @@
 #define MSECCFG_USEED  0x00000100
 #define MSECCFG_SSEED  0x00000200
 
+#define SEED_OPST      0xC0000000
+#define SEED_ENTROPY   0x0000FFFF
+
+#define SEED_OPST_BIST 0x00000000
+#define SEED_OPST_WAIT 0x40000000
+#define SEED_OPST_ES16 0x80000000
+#define SEED_OPST_DEAD 0xC0000000
+
 #define PRV_U 0
 #define PRV_S 1
 #define PRV_M 3
@@ -291,6 +299,7 @@
 #define PTE_A     0x040 /* Accessed */
 #define PTE_D     0x080 /* Dirty */
 #define PTE_SOFT  0x300 /* Reserved for Software */
+#define PTE_PPN   0x003FFFFFFFFFFC00 /* PPN */
 #define PTE_RSVD  0x1FC0000000000000 /* Reserved for future standard use */
 #define PTE_PBMT  0x6000000000000000 /* Svpbmt: Page-based memory types */
 #define PTE_N     0x8000000000000000 /* Svnapot: NAPOT translation contiguity */
diff --git a/core/arch/riscv/include/kernel/delay_arch.h b/core/arch/riscv/include/kernel/delay_arch.h
index 2ddec10b9afee61b8147a49dfd776c2fe6543d72..3b9e54a6c8e44612a64ed00eefb62dd3e953600f 100644
--- a/core/arch/riscv/include/kernel/delay_arch.h
+++ b/core/arch/riscv/include/kernel/delay_arch.h
@@ -6,19 +6,16 @@
 #ifndef __KERNEL_DELAY_ARCH_H
 #define __KERNEL_DELAY_ARCH_H
 
-#include <platform_config.h>
 #include <riscv.h>
-#include <stdbool.h>
 #include <stdint.h>
 
-static inline uint64_t timeout_init_us(uint32_t us)
+static inline unsigned int delay_cnt_freq(void)
 {
-	return read_time() + ((uint64_t)us * read_cntfrq()) / 1000000ULL;
+	return read_cntfrq();
 }
 
-static inline bool timeout_elapsed(uint64_t expire)
+static inline uint64_t delay_cnt_read(void)
 {
-	return read_time() > expire;
+	return read_time();
 }
-
 #endif /*__KERNEL_DELAY_ARCH_H*/
diff --git a/core/arch/riscv/include/kernel/stmm_sp.h b/core/arch/riscv/include/kernel/stmm_sp.h
index 9b5b09d01bc82b57212256b0a01ad6491969e259..0749800023968aee975af755150ffab2845c3c68 100644
--- a/core/arch/riscv/include/kernel/stmm_sp.h
+++ b/core/arch/riscv/include/kernel/stmm_sp.h
@@ -35,6 +35,12 @@ stmm_init_session(const TEE_UUID *uuid __unused,
 	return TEE_ERROR_ITEM_NOT_FOUND;
 }
 
+static inline TEE_Result
+stmm_complete_session(struct tee_ta_session *s __unused)
+{
+	return TEE_ERROR_GENERIC;
+}
+
 static inline const TEE_UUID *stmm_get_uuid(void) { return NULL; }
 
 #endif /*__KERNEL_STMM_SP_H*/
diff --git a/core/arch/riscv/include/kernel/thread_arch.h b/core/arch/riscv/include/kernel/thread_arch.h
index 1e2da17b726f8bf631cbe78a1a59d96ee4a0aeb5..7bc27872c0a04fc80c323f83d27318bfbb953b2e 100644
--- a/core/arch/riscv/include/kernel/thread_arch.h
+++ b/core/arch/riscv/include/kernel/thread_arch.h
@@ -8,10 +8,22 @@
 
 #ifndef __ASSEMBLER__
 #include <compiler.h>
-#include <riscv.h>
 #include <types_ext.h>
 #endif
 
+#include <platform_config.h>
+#include <riscv.h>
+
+/*
+ * Each RISC-V platform must define their own values.
+ * See core/arch/riscv/plat-virt/platform_config.h for example.
+ */
+#define THREAD_EXCP_FOREIGN_INTR	PLAT_THREAD_EXCP_FOREIGN_INTR
+#define THREAD_EXCP_NATIVE_INTR		PLAT_THREAD_EXCP_NATIVE_INTR
+
+#define THREAD_EXCP_ALL			(THREAD_EXCP_FOREIGN_INTR |\
+					 THREAD_EXCP_NATIVE_INTR)
+
 #ifndef __ASSEMBLER__
 
 #define THREAD_CORE_LOCAL_ALIGNED __aligned(16)
@@ -83,14 +95,14 @@ struct thread_abort_regs {
 	unsigned long t4;
 	unsigned long t5;
 	unsigned long t6;
+	unsigned long epc;
 	unsigned long status;
+	unsigned long ie;
 	unsigned long cause;
-	unsigned long epc;
 	unsigned long tval;
-	unsigned long satp;
-};
+} __aligned(16);
 
-struct thread_trap_regs {
+struct thread_scall_regs {
 	unsigned long ra;
 	unsigned long sp;
 	unsigned long gp;
@@ -98,8 +110,6 @@ struct thread_trap_regs {
 	unsigned long t0;
 	unsigned long t1;
 	unsigned long t2;
-	unsigned long s0;
-	unsigned long s1;
 	unsigned long a0;
 	unsigned long a1;
 	unsigned long a2;
@@ -108,39 +118,13 @@ struct thread_trap_regs {
 	unsigned long a5;
 	unsigned long a6;
 	unsigned long a7;
-	unsigned long s2;
-	unsigned long s3;
-	unsigned long s4;
-	unsigned long s5;
-	unsigned long s6;
-	unsigned long s7;
-	unsigned long s8;
-	unsigned long s9;
-	unsigned long s10;
-	unsigned long s11;
 	unsigned long t3;
 	unsigned long t4;
 	unsigned long t5;
 	unsigned long t6;
 	unsigned long epc;
 	unsigned long status;
-	unsigned long satp;
-} __aligned(16);
-
-struct thread_scall_regs {
-	unsigned long a0;
-	unsigned long a1;
-	unsigned long a2;
-	unsigned long a3;
-	unsigned long a4;
-	unsigned long a5;
-	unsigned long a6;
-	unsigned long a7;
-	unsigned long t0;
-	unsigned long t1;
-	unsigned long ra;
-	unsigned long sp;
-	unsigned long status;
+	unsigned long ie;
 } __aligned(16);
 
 struct thread_ctx_regs {
@@ -175,25 +159,13 @@ struct thread_ctx_regs {
 	unsigned long t4;
 	unsigned long t5;
 	unsigned long t6;
+	unsigned long epc;
 	unsigned long status;
+	unsigned long ie;
 };
 
 struct user_mode_ctx;
 
-/*
- * These flags should vary according to the privilege mode selected
- * to run OP-TEE core on (M/HS/S). For now default to S-Mode.
- */
-
-#define CSR_XIE_SIE	BIT64(IRQ_XSOFT)
-#define CSR_XIE_TIE	BIT64(IRQ_XTIMER)
-#define CSR_XIE_EIE	BIT64(IRQ_XEXT)
-
-#define THREAD_EXCP_FOREIGN_INTR	CSR_XIE_EIE
-#define THREAD_EXCP_NATIVE_INTR	        (CSR_XIE_SIE | CSR_XIE_TIE)
-#define THREAD_EXCP_ALL			(THREAD_EXCP_FOREIGN_INTR |\
-					 THREAD_EXCP_NATIVE_INTR)
-
 #ifdef CFG_WITH_VFP
 uint32_t thread_kernel_enable_vfp(void);
 void thread_kernel_disable_vfp(uint32_t state);
diff --git a/core/arch/riscv/include/kernel/thread_private_arch.h b/core/arch/riscv/include/kernel/thread_private_arch.h
index 96ea6dc636c605570358f0e1e96be181735795bd..208800ae902a26829e3511dabbede99cba6897e2 100644
--- a/core/arch/riscv/include/kernel/thread_private_arch.h
+++ b/core/arch/riscv/include/kernel/thread_private_arch.h
@@ -18,15 +18,26 @@
 #define STACK_TMP_SIZE		(2048 + STACK_TMP_OFFS + CFG_STACK_TMP_EXTRA)
 #endif
 
-#define STACK_THREAD_SIZE	(8192 + CFG_STACK_THREAD_EXTRA)
-
-#if TRACE_LEVEL > 0
-#define STACK_ABT_SIZE		3072
+#ifdef CFG_CORE_DEBUG_CHECK_STACKS
+#define STACK_THREAD_SIZE	(10240 + CFG_STACK_THREAD_EXTRA)
 #else
-#define STACK_ABT_SIZE		1024
+#define STACK_THREAD_SIZE	(8192 + CFG_STACK_THREAD_EXTRA)
 #endif
 
+#define STACK_ABT_SIZE		4096
+
+#ifdef CFG_CORE_DEBUG_CHECK_STACKS
+/*
+ * Extra space added to each stack in order to reliably detect and dump stack
+ * overflows. Should cover the maximum expected overflow size caused by any C
+ * function (say, 512 bytes; no function should have that much local variables),
+ * plus the maximum stack space needed by __cyg_profile_func_exit(): about 1 KB,
+ * a large part of which is used to print the call stack. Total: 1.5 KB.
+ */
+#define STACK_CHECK_EXTRA	1536
+#else
 #define STACK_CHECK_EXTRA	0
+#endif
 
 #define THREAD_RPC_NUM_ARGS     4
 
@@ -40,18 +51,19 @@ struct thread_user_mode_rec {
 	unsigned long pad;
 	/*
 	 * x[] is used to save registers for user/kernel context-switching
-	 * 0-3: ra-tp
-	 * 4-6: s0-s1
-	 * 6-15: s2-s11
+	 * 0: ra
+	 * 1-2: s0-s1
+	 * 3-12: s2-s11
 	 */
-	unsigned long x[16];
+	unsigned long x[13];
 };
 
 extern long thread_user_kcode_offset;
 
-void thread_trap_handler(long cause, unsigned long epc,
-			 struct thread_trap_regs *regs,
-			 bool user);
+void thread_native_interrupt_handler(struct thread_ctx_regs *regs,
+				     unsigned long cause);
+void thread_foreign_interrupt_handler(struct thread_ctx_regs *regs);
+
 /*
  * Initializes TVEC for current hart. Called by thread_init_per_cpu()
  */
@@ -59,12 +71,15 @@ void thread_init_tvec(void);
 void thread_trap_vect(void);
 void thread_trap_vect_end(void);
 
-void thread_return_to_ree(unsigned long arg0, unsigned long arg1,
-			  unsigned long arg2, unsigned long arg3,
-			  unsigned long arg4, unsigned long arg5);
+void thread_return_to_udomain(unsigned long arg0, unsigned long arg1,
+			      unsigned long arg2, unsigned long arg3,
+			      unsigned long arg4, unsigned long arg5);
 
 void __panic_at_abi_return(void);
 
+/* Helper function to prepare CSR status for exception return */
+unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp);
+
 /*
  * Assembly function as the first function in a thread.  Handles a stdcall,
  * a0-a3 holds the parameters. Hands over to __thread_std_abi_entry() when
@@ -104,12 +119,15 @@ void thread_alloc_and_run(uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3,
 			  uint32_t a4, uint32_t a5);
 void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1,
 			    uint32_t a2, uint32_t a3);
-void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]);
+void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS], unsigned long status);
+void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]);
+
+static inline void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS])
+{
+	__thread_rpc(rv);
+}
+
 void thread_scall_handler(struct thread_scall_regs *regs);
-void thread_exit_user_mode(unsigned long a0, unsigned long a1,
-			   unsigned long a2, unsigned long a3,
-			   unsigned long sp, unsigned long pc,
-			   unsigned long status);
 
 #endif /*__ASSEMBLER__*/
 #endif /*__KERNEL_THREAD_PRIVATE_ARCH_H*/
diff --git a/core/arch/riscv/include/mm/core_mmu_arch.h b/core/arch/riscv/include/mm/core_mmu_arch.h
index cc9aa798f2765b695d66635662f33e68ea7d6949..aeea3eef65433f655a6a02018d79f3a0a9979580 100644
--- a/core/arch/riscv/include/mm/core_mmu_arch.h
+++ b/core/arch/riscv/include/mm/core_mmu_arch.h
@@ -84,6 +84,14 @@
 					(level) + \
 					RISCV_PGSHIFT)
 
+#ifdef RV64
+#define CORE_MMU_PAGE_OFFSET_MASK(level) \
+		GENMASK_64(CORE_MMU_SHIFT_OF_LEVEL(level) - 1, 0)
+#else
+#define CORE_MMU_PAGE_OFFSET_MASK(level) \
+		GENMASK_32(CORE_MMU_SHIFT_OF_LEVEL(level) - 1, 0)
+#endif
+
 #define CORE_MMU_USER_CODE_SHIFT	SMALL_PAGE_SHIFT
 #define CORE_MMU_USER_PARAM_SHIFT	SMALL_PAGE_SHIFT
 
@@ -105,7 +113,7 @@
 #ifndef __ASSEMBLER__
 
 struct core_mmu_config {
-	unsigned long satp;
+	unsigned long satp[CFG_TEE_CORE_NB_CORE];
 	uint32_t map_offset;
 };
 
diff --git a/core/arch/riscv/include/riscv.h b/core/arch/riscv/include/riscv.h
index 59fb0c37c105aa635b1730f23ad358869cd23dae..df15adb4c768aa0a1fc3fa15832e89c274f878b8 100644
--- a/core/arch/riscv/include/riscv.h
+++ b/core/arch/riscv/include/riscv.h
@@ -8,6 +8,7 @@
 
 #include <compiler.h>
 #include <encoding.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/cdefs.h>
 #include <util.h>
@@ -68,6 +69,8 @@
 #define CSR_XSTATUS_SUM		BIT(18)
 #define CSR_XSTATUS_MXR		BIT(19)
 
+#define CSR_XCAUSE_INTR_FLAG	BIT64(__riscv_xlen - 1)
+
 #ifndef __ASSEMBLER__
 
 #define read_csr(csr)							\
@@ -90,22 +93,32 @@
 		__tmp;							\
 	})
 
-#define set_csr(csr, bit)						\
+#define read_set_csr(csr, val)						\
 	({								\
 		unsigned long __tmp;					\
 		asm volatile ("csrrs %0, %1, %2"			\
-			      : "=r"(__tmp) : "i"(csr), "rK"(bit));	\
+			      : "=r"(__tmp) : "i"(csr), "rK"(val));	\
 		__tmp;							\
 	})
 
-#define clear_csr(csr, bit)						\
+#define set_csr(csr, val)						\
+	({								\
+		asm volatile ("csrs %0, %1" : : "i"(csr), "rK"(val));	\
+	})
+
+#define read_clear_csr(csr, val)					\
 	({								\
 		unsigned long __tmp;					\
 		asm volatile ("csrrc %0, %1, %2"			\
-			      : "=r"(__tmp) : "i"(csr), "rK"(bit));	\
+			      : "=r"(__tmp) : "i"(csr), "rK"(val));	\
 		__tmp;							\
 	})
 
+#define clear_csr(csr, val)						\
+	({								\
+		asm volatile ("csrc %0, %1" : : "i"(csr), "rK"(val));	\
+	})
+
 #define rdtime() read_csr(CSR_TIME)
 #define rdcycle() read_csr(CSR_CYCLE)
 #define rdinstret() read_csr(CSR_INSTRET)
@@ -115,6 +128,14 @@ static inline __noprof void mb(void)
 	asm volatile ("fence" : : : "memory");
 }
 
+static inline __noprof unsigned long read_gp(void)
+{
+	unsigned long gp = 0;
+
+	asm volatile("mv %0, gp" : "=&r"(gp));
+	return gp;
+}
+
 static inline __noprof unsigned long read_tp(void)
 {
 	unsigned long tp = 0;
@@ -146,6 +167,29 @@ static inline __noprof void wfi(void)
 	asm volatile ("wfi");
 }
 
+static inline __noprof void riscv_cpu_pause(void)
+{
+	unsigned long dummy = 0;
+
+	/*
+	 * Use a divide instruction to force wait
+	 * for multiple CPU cycles.
+	 * Note: RISC-V does not raise an exception
+	 * on divide by zero.
+	 */
+	asm volatile ("div %0, %0, zero" : "=r" (dummy));
+
+	/*
+	 * Use the encoding of the 'pause' instruction,
+	 * thus no need to verify toolchain support for
+	 * zihintpause.
+	 * On hardware platforms that do not implement
+	 * this extension, it will simply serve as a no-op.
+	 */
+	asm volatile (".4byte 0x100000f"); /* pause */
+	barrier();
+}
+
 static inline __noprof void flush_tlb(void)
 {
 	asm volatile("sfence.vma zero, zero");
@@ -387,6 +431,8 @@ static inline __noprof uint32_t read_cntfrq(void)
 	return CFG_RISCV_MTIME_RATE;
 }
 
+__noprof bool riscv_detect_csr_seed(void);
+
 #endif /*__ASSEMBLER__*/
 
 #endif /*__RISCV_H*/
diff --git a/core/arch/riscv/include/sbi.h b/core/arch/riscv/include/sbi.h
index 8b73edee938a6dca8f639c79cfc31c25c9e7d630..a2ae38c1a4a7218190caefa7409ca6738997c29c 100644
--- a/core/arch/riscv/include/sbi.h
+++ b/core/arch/riscv/include/sbi.h
@@ -20,17 +20,39 @@
 #define SBI_ERR_ALREADY_STOPPED		-8
 
 /* SBI Extension IDs */
-#define SBI_EXT_0_1_CONSOLE_PUTCHAR	0x01, 0
+#define SBI_EXT_0_1_CONSOLE_PUTCHAR	0x01
+#define SBI_EXT_BASE			0x10
 #define SBI_EXT_HSM			0x48534D
+#define SBI_EXT_DBCN			0x4442434E
 #define SBI_EXT_TEE			0x544545
 
+#ifndef __ASSEMBLER__
+
+/* SBI function IDs for Base extension */
+enum sbi_ext_base_fid {
+	SBI_EXT_BASE_GET_SPEC_VERSION = 0,
+	SBI_EXT_BASE_GET_IMP_ID,
+	SBI_EXT_BASE_GET_IMP_VERSION,
+	SBI_EXT_BASE_PROBE_EXT,
+	SBI_EXT_BASE_GET_MVENDORID,
+	SBI_EXT_BASE_GET_MARCHID,
+	SBI_EXT_BASE_GET_MIMPID,
+};
+
 /* SBI function IDs for HSM extension */
-#define SBI_EXT_HSM_HART_START		U(0)
-#define SBI_EXT_HSM_HART_STOP		U(1)
-#define SBI_EXT_HSM_HART_GET_STATUS	U(2)
-#define SBI_EXT_HSM_HART_SUSPEND	U(3)
+enum sbi_ext_hsm_fid {
+	SBI_EXT_HSM_HART_START = 0,
+	SBI_EXT_HSM_HART_STOP,
+	SBI_EXT_HSM_HART_GET_STATUS,
+	SBI_EXT_HSM_HART_SUSPEND,
+};
 
-#ifndef __ASSEMBLER__
+/* SBI function IDs for Debug Console extension */
+enum sbi_ext_dbcn_fid {
+	SBI_EXT_DBCN_CONSOLE_WRITE = 0,
+	SBI_EXT_DBCN_CONSOLE_READ = 1,
+	SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2,
+};
 
 #include <compiler.h>
 #include <encoding.h>
@@ -39,8 +61,10 @@
 #include <types_ext.h>
 #include <util.h>
 
+int sbi_probe_extension(int extid);
 void sbi_console_putchar(int ch);
-int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg);
+int sbi_dbcn_write_byte(unsigned char ch);
+int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg);
 
 #endif /*__ASSEMBLER__*/
 #endif /*defined(CFG_RISCV_SBI)*/
diff --git a/core/arch/riscv/kernel/abort.c b/core/arch/riscv/kernel/abort.c
index f0dcf896471ec9e86d762e815c8187e8e2285050..c49a293051371e52e4065305b744eef88de3fc6a 100644
--- a/core/arch/riscv/kernel/abort.c
+++ b/core/arch/riscv/kernel/abort.c
@@ -236,13 +236,10 @@ static void handle_user_mode_panic(struct abort_info *ai)
 	ai->regs->a0 = TEE_ERROR_TARGET_DEAD;
 	ai->regs->a1 = true;
 	ai->regs->a2 = 0xdeadbeef;
-	ai->regs->ra = (vaddr_t)thread_unwind_user_mode;
+	ai->regs->epc = (vaddr_t)thread_unwind_user_mode;
 	ai->regs->sp = thread_get_saved_thread_sp();
-	ai->regs->status = read_csr(CSR_XSTATUS);
-
-	thread_exit_user_mode(ai->regs->a0, ai->regs->a1, ai->regs->a2,
-			      ai->regs->a3, ai->regs->sp, ai->regs->ra,
-			      ai->regs->status);
+	ai->regs->status = xstatus_for_xret(true, PRV_S);
+	ai->regs->ie = 0;
 }
 
 #ifdef CFG_WITH_VFP
diff --git a/core/arch/riscv/kernel/asm-defines.c b/core/arch/riscv/kernel/asm-defines.c
index df8f84b11b5c9244beb05d996345f6437c49a6e9..c517b9e7c6e9bbd47e2fe1bca82da603436d0380 100644
--- a/core/arch/riscv/kernel/asm-defines.c
+++ b/core/arch/riscv/kernel/asm-defines.c
@@ -32,14 +32,19 @@ DEFINES
 	       offsetof(struct thread_core_local, flags));
 	DEFINE(THREAD_CORE_LOCAL_ABT_STACK_VA_END,
 	       offsetof(struct thread_core_local, abt_stack_va_end));
-	DEFINE(THREAD_CORE_LOCAL_X10, offsetof(struct thread_core_local, x[0]));
+	DEFINE(THREAD_CORE_LOCAL_X0, offsetof(struct thread_core_local, x[0]));
+	DEFINE(THREAD_CORE_LOCAL_X1, offsetof(struct thread_core_local, x[1]));
 
 	DEFINE(STACK_TMP_GUARD, STACK_CANARY_SIZE / 2 + STACK_TMP_OFFS);
 
 	/* struct thread_ctx_regs */
 	DEFINE(THREAD_CTX_REG_STATUS, offsetof(struct thread_ctx_regs, status));
+	DEFINE(THREAD_CTX_REG_EPC, offsetof(struct thread_ctx_regs, epc));
+	DEFINE(THREAD_CTX_REG_IE, offsetof(struct thread_ctx_regs, ie));
 	DEFINE(THREAD_CTX_REG_RA, offsetof(struct thread_ctx_regs, ra));
 	DEFINE(THREAD_CTX_REG_SP, offsetof(struct thread_ctx_regs, sp));
+	DEFINE(THREAD_CTX_REG_GP, offsetof(struct thread_ctx_regs, gp));
+	DEFINE(THREAD_CTX_REG_TP, offsetof(struct thread_ctx_regs, tp));
 	DEFINE(THREAD_CTX_REG_T0, offsetof(struct thread_ctx_regs, t0));
 	DEFINE(THREAD_CTX_REG_S0, offsetof(struct thread_ctx_regs, s0));
 	DEFINE(THREAD_CTX_REG_A0, offsetof(struct thread_ctx_regs, a0));
@@ -50,42 +55,51 @@ DEFINES
 	/* struct thread_user_mode_rec */
 	DEFINE(THREAD_USER_MODE_REC_CTX_REGS_PTR,
 	       offsetof(struct thread_user_mode_rec, ctx_regs_ptr));
-	DEFINE(THREAD_USER_MODE_REC_X1,
+	DEFINE(THREAD_USER_MODE_REC_RA,
 	       offsetof(struct thread_user_mode_rec, x[0]));
-	DEFINE(THREAD_USER_MODE_REC_X4,
+	DEFINE(THREAD_USER_MODE_REC_S0,
+	       offsetof(struct thread_user_mode_rec, x[1]));
+	DEFINE(THREAD_USER_MODE_REC_S2,
 	       offsetof(struct thread_user_mode_rec, x[3]));
-	DEFINE(THREAD_USER_MODE_REC_X8,
-	       offsetof(struct thread_user_mode_rec, x[4]));
-	DEFINE(THREAD_USER_MODE_REC_X18,
-	       offsetof(struct thread_user_mode_rec, x[6]));
 	DEFINE(THREAD_USER_MODE_REC_SIZE, sizeof(struct thread_user_mode_rec));
 
-	/* struct thread_trap_regs */
-	DEFINE(THREAD_TRAP_REG_SP, offsetof(struct thread_trap_regs, sp));
-	DEFINE(THREAD_TRAP_REG_RA, offsetof(struct thread_trap_regs, ra));
-	DEFINE(THREAD_TRAP_REG_GP, offsetof(struct thread_trap_regs, gp));
-	DEFINE(THREAD_TRAP_REG_TP, offsetof(struct thread_trap_regs, tp));
-	DEFINE(THREAD_TRAP_REG_T0, offsetof(struct thread_trap_regs, t0));
-	DEFINE(THREAD_TRAP_REG_S0, offsetof(struct thread_trap_regs, s0));
-	DEFINE(THREAD_TRAP_REG_A0, offsetof(struct thread_trap_regs, a0));
-	DEFINE(THREAD_TRAP_REG_T3, offsetof(struct thread_trap_regs, t3));
-	DEFINE(THREAD_TRAP_REG_EPC, offsetof(struct thread_trap_regs, epc));
-	DEFINE(THREAD_TRAP_REG_STATUS,
-	       offsetof(struct thread_trap_regs, status));
-	DEFINE(THREAD_TRAP_REGS_SIZE, sizeof(struct thread_trap_regs));
+	/* struct thread_abort_regs */
+	DEFINE(THREAD_ABT_REG_RA, offsetof(struct thread_abort_regs, ra));
+	DEFINE(THREAD_ABT_REG_SP, offsetof(struct thread_abort_regs, sp));
+	DEFINE(THREAD_ABT_REG_GP, offsetof(struct thread_abort_regs, gp));
+	DEFINE(THREAD_ABT_REG_TP, offsetof(struct thread_abort_regs, tp));
+	DEFINE(THREAD_ABT_REG_T0, offsetof(struct thread_abort_regs, t0));
+	DEFINE(THREAD_ABT_REG_S0, offsetof(struct thread_abort_regs, s0));
+	DEFINE(THREAD_ABT_REG_A0, offsetof(struct thread_abort_regs, a0));
+	DEFINE(THREAD_ABT_REG_S2, offsetof(struct thread_abort_regs, s2));
+	DEFINE(THREAD_ABT_REG_T3, offsetof(struct thread_abort_regs, t3));
+	DEFINE(THREAD_ABT_REG_EPC, offsetof(struct thread_abort_regs, epc));
+	DEFINE(THREAD_ABT_REG_STATUS,
+	       offsetof(struct thread_abort_regs, status));
+	DEFINE(THREAD_ABT_REG_IE, offsetof(struct thread_abort_regs, ie));
+	DEFINE(THREAD_ABT_REG_CAUSE, offsetof(struct thread_abort_regs, cause));
+	DEFINE(THREAD_ABT_REG_TVAL, offsetof(struct thread_abort_regs, tval));
+	DEFINE(THREAD_ABT_REGS_SIZE, sizeof(struct thread_abort_regs));
 
 	/* struct thread_scall_regs */
-	DEFINE(THREAD_SCALL_REG_STATUS,
-	       offsetof(struct thread_scall_regs, status));
 	DEFINE(THREAD_SCALL_REG_RA, offsetof(struct thread_scall_regs, ra));
 	DEFINE(THREAD_SCALL_REG_SP, offsetof(struct thread_scall_regs, sp));
+	DEFINE(THREAD_SCALL_REG_GP, offsetof(struct thread_scall_regs, gp));
+	DEFINE(THREAD_SCALL_REG_TP, offsetof(struct thread_scall_regs, tp));
+	DEFINE(THREAD_SCALL_REG_T0, offsetof(struct thread_scall_regs, t0));
 	DEFINE(THREAD_SCALL_REG_A0, offsetof(struct thread_scall_regs, a0));
+	DEFINE(THREAD_SCALL_REG_T3, offsetof(struct thread_scall_regs, t3));
+	DEFINE(THREAD_SCALL_REG_EPC, offsetof(struct thread_scall_regs, epc));
+	DEFINE(THREAD_SCALL_REG_STATUS,
+	       offsetof(struct thread_scall_regs, status));
+	DEFINE(THREAD_SCALL_REG_IE, offsetof(struct thread_scall_regs, ie));
 	DEFINE(THREAD_SCALL_REGS_SIZE, sizeof(struct thread_scall_regs));
 
 	/* struct core_mmu_config */
 	DEFINE(CORE_MMU_CONFIG_SIZE, sizeof(struct core_mmu_config));
 	DEFINE(CORE_MMU_CONFIG_SATP,
-	       offsetof(struct core_mmu_config, satp));
+	       offsetof(struct core_mmu_config, satp[0]));
+	DEFINE(CORE_MMU_CONFIG_SATP_SIZE, sizeof(unsigned long));
 
 	/* struct thread_abi_args */
 	DEFINE(THREAD_ABI_ARGS_A0, offsetof(struct thread_abi_args, a0));
diff --git a/core/arch/riscv/kernel/boot.c b/core/arch/riscv/kernel/boot.c
index 6530a8b5cb7d5d9120d7a2d3b5ecea5a0138a389..8af125933d7ec0d5e0c6426158cc44ce3bf42e1e 100644
--- a/core/arch/riscv/kernel/boot.c
+++ b/core/arch/riscv/kernel/boot.c
@@ -47,6 +47,11 @@ static void update_external_dt(void)
 	if (!dt || !dt->blob)
 		return;
 
+#ifdef CFG_CORE_RESERVED_SHM
+	if (mark_static_shm_as_reserved(dt))
+		panic("Failed to config non-secure memory");
+#endif
+
 	if (mark_tddram_as_reserved(dt))
 		panic("Failed to config secure memory");
 }
@@ -70,7 +75,7 @@ static void start_secondary_cores(void)
 
 	for (i = 0; i < CFG_TEE_CORE_NB_CORE; i++)
 		if (i != pos && IS_ENABLED(CFG_RISCV_SBI) &&
-		    sbi_boot_hart(i, start_addr, i))
+		    sbi_hsm_hart_start(i, start_addr, i))
 			EMSG("Error starting secondary hart %zu", i);
 }
 #endif
@@ -84,7 +89,7 @@ static void init_runtime(void)
 
 void init_tee_runtime(void)
 {
-	core_mmu_init_ta_ram();
+	core_mmu_init_phys_mem();
 	call_preinitcalls();
 	call_initcalls();
 }
@@ -135,6 +140,7 @@ void boot_init_primary_late(unsigned long fdt,
 			    unsigned long tos_fw_config __unused)
 {
 	init_external_dt(fdt, CFG_DTB_MAX_SIZE);
+	discover_nsec_memory();
 	update_external_dt();
 
 	IMSG("OP-TEE version: %s", core_v_str);
diff --git a/core/arch/riscv/kernel/csr_detect.S b/core/arch/riscv/kernel/csr_detect.S
new file mode 100644
index 0000000000000000000000000000000000000000..d5be55abe7877ff906c654437ba0e1141460ee50
--- /dev/null
+++ b/core/arch/riscv/kernel/csr_detect.S
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+
+#include <asm.S>
+#include <riscv.h>
+
+#define DETECT_OP_CSRR		0
+#define DETECT_OP_CSRRW		1
+
+.macro save_and_disable_xie reg
+	csrrw	\reg, CSR_XIE, zero
+.endm
+
+.macro restore_xie reg
+	csrw	CSR_XIE, \reg
+.endm
+
+.macro save_and_replace_xtvec reg, label
+	la	\reg, \label
+	csrrw	\reg, CSR_XTVEC, \reg
+.endm
+
+.macro restore_xtvec reg
+	csrw	CSR_XTVEC, \reg
+.endm
+
+/**
+ * @brief A temporary trap handler to handle an exception during csr detection.
+ *        If csr read/write instruction leads to a trap, CPU will enter this
+ *        function and XRET with a0 = 0, which means the csr is not detected.
+ *        The caller must expect that a0 is used in this function.
+ */
+FUNC csr_detect_trap_vect , :
+	csrr	a0, CSR_XEPC
+	addi	a0, a0, 4
+	csrw	CSR_XEPC, a0
+	mv	a0, zero
+	XRET
+END_FUNC csr_detect_trap_vect
+
+/* Detect CSR by csrr/csrrw instruction. a0=1 if detected, otherwise a0=0 */
+.macro detect_csr csr, op, reg0, reg1, reg2
+	li	a0, 1
+	save_and_disable_xie \reg0
+	save_and_replace_xtvec \reg1, csr_detect_trap_vect
+.if \op == DETECT_OP_CSRR
+	csrr	\reg2, \csr
+.elseif \op == DETECT_OP_CSRRW
+	csrrw	\reg2, \csr, zero
+.endif
+	restore_xtvec \reg1
+	restore_xie \reg0
+.endm
+
+.macro detect_csr_by_csrr csr, reg0, reg1, reg2
+	detect_csr \csr, DETECT_OP_CSRR, \reg0, \reg1, \reg2
+.endm
+
+.macro detect_csr_by_csrrw csr, reg0, reg1, reg2
+	detect_csr \csr, DETECT_OP_CSRRW, \reg0, \reg1, \reg2
+.endm
+
+/**
+ * bool riscv_detect_csr_seed(void);
+ * @brief A helper function to detect if CSR seed is accessible. The value of a0
+ *        will be cleared by csr_detect_trap_vect() if exception occurs.
+ * @retval 1 if CSR seed is detected, otherwise 0
+ */
+FUNC riscv_detect_csr_seed , :
+	detect_csr_by_csrrw seed, a1, a2, a3
+	ret
+END_FUNC riscv_detect_csr_seed
diff --git a/core/arch/riscv/kernel/entry.S b/core/arch/riscv/kernel/entry.S
index 4e451e06643461f9c69ce488ac1452d40d76bb55..94823220607d4457f9c5055d4d816858e9a75bf6 100644
--- a/core/arch/riscv/kernel/entry.S
+++ b/core/arch/riscv/kernel/entry.S
@@ -71,9 +71,21 @@
 .endm
 
 .macro set_satp
+	/*
+	 * a0 = hartid
+	 * a1 = address of boot_mmu_config.satp[0]
+	 * a2 = size of CSR SATP
+	 *
+	 * This hart's SATP is of value (a1 + (a0 * a2)).
+	 */
+	csrr	a0, CSR_XSCRATCH
 	la	a1, boot_mmu_config
-	LDR	a0, CORE_MMU_CONFIG_SATP(a1)
-	csrw	CSR_SATP, a0
+	addi	a1, a1, CORE_MMU_CONFIG_SATP
+	li	a2, CORE_MMU_CONFIG_SATP_SIZE
+	mul	a0, a0, a2
+	add	a1, a1, a0
+	LDR	a2, 0(a1)
+	csrw	CSR_SATP, a2
 	sfence.vma	zero, zero
 .endm
 
@@ -148,7 +160,12 @@ FUNC _start , :
 #else
 	mv	s1, a1		/* Save device tree address into s1 */
 #endif
-	bnez	a0, reset_secondary
+
+	/* Only first hart who wins lottery runs the primary boot sequence. */
+	la	a3, hart_lottery
+	li	a2, 1
+	amoadd.w a3, a2, (a3)
+	bnez	a3, reset_secondary
 	jal	reset_primary
 	j	.
 END_FUNC _start
@@ -203,7 +220,7 @@ UNWIND(	.cantunwind)
 	mv	sp, a0
 	jal	thread_get_core_local
 	mv	s3, a0
-	STR	x0, THREAD_CORE_LOCAL_FLAGS(s3)
+	sw	zero, THREAD_CORE_LOCAL_FLAGS(s3)
 
 	mv	a0, s1		/* s1 contains saved device tree address */
 	mv	a1, x0		/* unused */
@@ -214,7 +231,7 @@ UNWIND(	.cantunwind)
 	 * restored.
 	 */
 	li	a0, THREAD_CLF_TMP
-	STR	a0, THREAD_CORE_LOCAL_FLAGS(s3)
+	sw	a0, THREAD_CORE_LOCAL_FLAGS(s3)
 	mv	sp, s2
 
 	cpu_is_ready
@@ -225,7 +242,11 @@ UNWIND(	.cantunwind)
 
 	li	a0, TEEABI_OPTEED_RETURN_ENTRY_DONE
 	la	a1, thread_vector_table
-	j	thread_return_to_ree
+	li	a2, 0
+	li	a3, 0
+	li	a4, 0
+	li	a5, 0
+	j	thread_return_to_udomain
 END_FUNC reset_primary
 
 LOCAL_FUNC reset_secondary , : , .identity_map
@@ -238,6 +259,16 @@ UNWIND(	.cantunwind)
 	cpu_is_ready
 
 	jal	boot_init_secondary
+#ifdef CFG_RISCV_WITH_M_MODE_SM
+	/* Return to untrusted domain */
+	li	a0, TEEABI_OPTEED_RETURN_ON_DONE
+	li	a1, 0
+	li	a2, 0
+	li	a3, 0
+	li	a4, 0
+	li	a5, 0
+	j	thread_return_to_udomain
+#endif
 	j	.
 END_FUNC reset_secondary
 
@@ -246,6 +277,13 @@ LOCAL_FUNC unhandled_cpu , :
 	j	unhandled_cpu
 END_FUNC unhandled_cpu
 
+	.section .identity_map.data
+	.balign	8
+LOCAL_DATA hart_lottery , :
+	/* The hart who first increments this variable will be primary hart. */
+	.word	0
+END_DATA hart_lottery
+
 #ifdef CFG_BOOT_SYNC_CPU
 LOCAL_DATA sem_cpu_sync_start , :
 	.word	sem_cpu_sync
diff --git a/core/arch/riscv/kernel/kern.ld.S b/core/arch/riscv/kernel/kern.ld.S
index e429de36f4536c727616cbb6be49b683bb98f171..2c5d8f8f3f18eba414c77adc2d5c878147929a6a 100644
--- a/core/arch/riscv/kernel/kern.ld.S
+++ b/core/arch/riscv/kernel/kern.ld.S
@@ -152,12 +152,15 @@ SECTIONS
 		 * from __global_pointer$.
 		 */
 		PROVIDE(__global_pointer$ = . + 0x800 );
+		*(.sdata .sdata.* .gnu.linkonce.s.*)
 	}
 
 	/* uninitialized data */
 	.bss : {
 		__data_end = .;
 		__bss_start = .;
+		*(.sbss .sbss.*)
+		*(.gnu.linkonce.sb.*)
 		*(.bss .bss.*)
 		*(.gnu.linkonce.b.*)
 		*(COMMON)
@@ -191,6 +194,10 @@ SECTIONS
 		__nozi_stack_end = .;
 	}
 
+	. = ALIGN(SMALL_PAGE_SIZE);
+	__flatmap_free_start = .;
+	__flatmap_rw_size = __flatmap_free_start - __flatmap_rw_start;
+
 #ifdef CFG_CORE_SANITIZE_KADDRESS
 	. = TEE_RAM_START + (TEE_RAM_VA_SIZE * 8) / 9 - 8;
 	. = ALIGN(8);
@@ -215,8 +222,8 @@ SECTIONS
 
 	_end_of_ram = .;
 
-	__flatmap_rw_size = _end_of_ram - __flatmap_rw_start;
 	__get_tee_init_end = .;
+	__flatmap_free_size = _end_of_ram - __flatmap_free_start;
 
 	/*
 	 * These regions will not become a normal part of the dumped
@@ -266,6 +273,10 @@ __vcore_unpg_rw_start = __flatmap_rw_start;
 __vcore_unpg_rw_size = __flatmap_rw_size;
 __vcore_unpg_rw_end = __vcore_unpg_rw_start + __vcore_unpg_rw_size;
 
+__vcore_free_start = __flatmap_free_start;
+__vcore_free_size = __flatmap_free_size;
+__vcore_free_end = __flatmap_free_start + __flatmap_free_size;
+
 #ifdef CFG_CORE_SANITIZE_KADDRESS
 __asan_map_start = (__asan_shadow_start / SMALL_PAGE_SIZE) *
 		   SMALL_PAGE_SIZE;
diff --git a/core/arch/riscv/kernel/link.mk b/core/arch/riscv/kernel/link.mk
index 3d1000d1589f54126816af9f0d18115b4eb6c309..d7b676cbf43169732e3f781a8696fe2149fe9083 100644
--- a/core/arch/riscv/kernel/link.mk
+++ b/core/arch/riscv/kernel/link.mk
@@ -51,39 +51,6 @@ $(link-script-pp): $(link-script) $(link-script-extra-deps)
 	$(q)$(CPPcore) -P -MT $@ -MD -MF $(link-script-dep) \
 		$(link-script-cppflags) $< -o $@
 
-define update-buildcount
-	@$(cmd-echo-silent) '  UPD     $(1)'
-	$(q)if [ ! -f $(1) ]; then \
-		mkdir -p $(dir $(1)); \
-		echo 1 >$(1); \
-	else \
-		expr 0`cat $(1)` + 1 >$(1); \
-	fi
-endef
-
-# filter-out to workaround objdump warning
-version-o-cflags = $(filter-out -g3,$(core-platform-cflags) \
-			$(platform-cflags) $(cflagscore))
-# SOURCE_DATE_EPOCH defined for reproducible builds
-ifneq ($(SOURCE_DATE_EPOCH),)
-date-opts = -d @$(SOURCE_DATE_EPOCH)
-endif
-DATE_STR = `LC_ALL=C date -u $(date-opts)`
-BUILD_COUNT_STR = `cat $(link-out-dir)/.buildcount`
-CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'`
-define gen-version-o
-	$(call update-buildcount,$(link-out-dir)/.buildcount)
-	@$(cmd-echo-silent) '  GEN     $(link-out-dir)/version.o'
-	$(q)echo -e "const char core_v_str[] =" \
-		"\"$(TEE_IMPL_VERSION) \"" \
-		"\"($(CORE_CC_VERSION)) \"" \
-		"\"#$(BUILD_COUNT_STR) \"" \
-		"\"$(DATE_STR) \"" \
-		"\"$(CFG_KERN_LINKER_ARCH)\";\n" \
-		| $(CCcore) $(version-o-cflags) \
-			-xc - -c -o $(link-out-dir)/version.o
-endef
-
 $(link-out-dir)/version.o:
 	$(call gen-version-o)
 
diff --git a/core/arch/riscv/kernel/sbi.c b/core/arch/riscv/kernel/sbi.c
index 8d820400780fe0f3de0b1b95018d006918b135dd..ce0cf3a6ab7b3fa41320f654eb968d6f769c5820 100644
--- a/core/arch/riscv/kernel/sbi.c
+++ b/core/arch/riscv/kernel/sbi.c
@@ -29,16 +29,52 @@ struct sbiret {
 
 #define sbi_ecall(...) _sbi_ecall(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0)
 
+/**
+ * sbi_probe_extension() - Check if an SBI extension ID is supported or not.
+ * @extid: The extension ID to be probed.
+ *
+ * Return: 1 or an extension specific nonzero value if yes, 0 otherwise.
+ */
+int sbi_probe_extension(int extid)
+{
+	struct sbiret ret = { };
+
+	ret = sbi_ecall(SBI_EXT_BASE, SBI_EXT_BASE_PROBE_EXT, extid);
+	if (!ret.error)
+		return ret.value;
+
+	return 0;
+}
+
+/**
+ * sbi_console_putchar() - Writes given character to the console device.
+ * @ch: The data to be written to the console.
+ */
 void sbi_console_putchar(int ch)
 {
-	sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, (unsigned long)ch);
+	sbi_ecall(SBI_EXT_0_1_CONSOLE_PUTCHAR, 0, ch);
+}
+
+/**
+ * sbi_dbcn_write_byte() - Write byte to debug console
+ * @ch:         Byte to be written
+ *
+ * Return:      SBI error code (SBI_SUCCESS = 0 on success)
+ */
+int sbi_dbcn_write_byte(unsigned char ch)
+{
+	struct sbiret ret = { };
+
+	ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE_BYTE, ch);
+	return ret.error;
 }
 
-int sbi_boot_hart(uint32_t hart_id, paddr_t start_addr, unsigned long arg)
+int sbi_hsm_hart_start(uint32_t hartid, paddr_t start_addr, unsigned long arg)
 {
-	struct sbiret ret;
+	struct sbiret ret = { };
 
-	ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hart_id, start_addr, arg);
+	ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_START, hartid, start_addr,
+			arg);
 
 	return ret.error;
 }
diff --git a/core/arch/riscv/kernel/sbi_console.c b/core/arch/riscv/kernel/sbi_console.c
index 18c628d17d8017ff257fb9aca72b4ed89162ed07..0b6ec2774900af5e710f09dda6a467235f79c2b3 100644
--- a/core/arch/riscv/kernel/sbi_console.c
+++ b/core/arch/riscv/kernel/sbi_console.c
@@ -14,52 +14,35 @@
 #include <trace.h>
 #include <util.h>
 
-#ifdef CFG_RISCV_SBI_CONSOLE
-
 struct sbi_console_data {
 	struct serial_chip chip;
 };
 
 static struct sbi_console_data console_data __nex_bss;
-static unsigned int sbi_console_global_lock __nex_bss = SPINLOCK_UNLOCK;
-
-static void sbi_console_lock_global(void)
-{
-	cpu_spin_lock(&sbi_console_global_lock);
-}
-
-static void sbi_console_unlock_global(void)
-{
-	cpu_spin_unlock(&sbi_console_global_lock);
-}
+static struct serial_ops sbi_console_ops __nex_bss;
 
-static void sbi_console_flush(struct serial_chip *chip __unused)
+static void sbi_console_putc_legacy(struct serial_chip *chip __unused, int ch)
 {
+	sbi_console_putchar(ch);
 }
 
-static void sbi_console_putc(struct serial_chip *chip __unused,
-			     int ch)
+static void sbi_console_putc(struct serial_chip *chip __unused, int ch)
 {
-	sbi_console_lock_global();
-	sbi_console_putchar(ch);
-	sbi_console_unlock_global();
+	sbi_dbcn_write_byte(ch);
 }
 
-static const struct serial_ops sbi_console_ops = {
-	.flush = sbi_console_flush,
-	.putc = sbi_console_putc,
-};
-
 static void sbi_console_init(struct sbi_console_data *pd)
 {
+	if (sbi_probe_extension(SBI_EXT_DBCN))
+		sbi_console_ops.putc = sbi_console_putc;
+	else
+		sbi_console_ops.putc = sbi_console_putc_legacy;
+
 	pd->chip.ops = &sbi_console_ops;
 }
 
-void console_init(void)
+void plat_console_init(void)
 {
 	sbi_console_init(&console_data);
 	register_serial_console(&console_data.chip);
 }
-
-#endif /*CFG_RISCV_SBI_CONSOLE*/
-
diff --git a/core/arch/riscv/kernel/semihosting_rv.S b/core/arch/riscv/kernel/semihosting_rv.S
new file mode 100644
index 0000000000000000000000000000000000000000..7adb359246267ce2a5fcad26d188cf09359ecbcd
--- /dev/null
+++ b/core/arch/riscv/kernel/semihosting_rv.S
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+
+#include <asm.S>
+
+/*
+ * uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg)
+ *
+ * Refer to RISC-V Semihosting Binary Interface:
+ * https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc
+ */
+FUNC __do_semihosting , : , .identity_map
+.option push
+.option norvc
+	slli	x0, x0, 0x1f
+	ebreak
+	srai    x0, x0, 0x7
+.option pop
+	ret
+END_FUNC __do_semihosting
diff --git a/core/arch/riscv/kernel/sub.mk b/core/arch/riscv/kernel/sub.mk
index 683e9585a3fd8af57c1d48be32cd1d7df2f99958..ddfe31b3f5de6274c9dfb10201feea6b92c53674 100644
--- a/core/arch/riscv/kernel/sub.mk
+++ b/core/arch/riscv/kernel/sub.mk
@@ -1,5 +1,6 @@
 srcs-y += spinlock.S
 srcs-y += cache_helpers_rv.S
+srcs-y += csr_detect.S
 srcs-y += idle.c
 srcs-$(CFG_RISCV_TIME_SOURCE_RDTIME) += tee_time_rdtime.c
 srcs-$(CFG_RISCV_SBI) += sbi.c
@@ -12,6 +13,7 @@ srcs-y += thread_arch.c
 srcs-y += arch_scall_rv.S
 srcs-y += arch_scall.c
 srcs-$(CFG_UNWIND) += unwind_rv.c
+srcs-$(CFG_SEMIHOSTING) += semihosting_rv.S
 srcs-y += thread_optee_abi.c
 srcs-y += thread_optee_abi_rv.S
 asm-defines-y += asm-defines.c
diff --git a/core/arch/riscv/kernel/tee_time_rdtime.c b/core/arch/riscv/kernel/tee_time_rdtime.c
index 90caf90c320187719ef9dd744139ead769ae55c8..d965861d0bc24d7b2e48795dc5e00a90a091570b 100644
--- a/core/arch/riscv/kernel/tee_time_rdtime.c
+++ b/core/arch/riscv/kernel/tee_time_rdtime.c
@@ -5,7 +5,6 @@
 
 #include <kernel/clint.h>
 #include <kernel/tee_time.h>
-#include <kernel/time_source.h>
 #include <riscv.h>
 #include <utee_defines.h>
 
@@ -35,7 +34,7 @@ __noprof uint64_t read_time(void)
 	return time;
 }
 
-static TEE_Result riscv_get_sys_time(TEE_Time *time)
+TEE_Result tee_time_get_sys_time(TEE_Time *time)
 {
 	uint64_t tm = read_time();
 	uint64_t rate = read_cntfrq();
@@ -46,10 +45,7 @@ static TEE_Result riscv_get_sys_time(TEE_Time *time)
 	return TEE_SUCCESS;
 }
 
-static const struct time_source riscv_time_source_rdtime = {
-	.name = "risc-v rdtime",
-	.protection_level = 1000,
-	.get_sys_time = riscv_get_sys_time,
-};
-
-REGISTER_TIME_SOURCE(riscv_time_source_rdtime)
+uint32_t tee_time_get_sys_time_protection_level(void)
+{
+	return 1000;
+}
diff --git a/core/arch/riscv/kernel/thread_arch.c b/core/arch/riscv/kernel/thread_arch.c
index 38299a6138411b89dab45313242539a80a21adf4..53df6a6dd3e2b48e9f4191d1c28c4269010c3487 100644
--- a/core/arch/riscv/kernel/thread_arch.c
+++ b/core/arch/riscv/kernel/thread_arch.c
@@ -98,12 +98,19 @@ static void thread_lazy_restore_ns_vfp(void)
 
 static void setup_unwind_user_mode(struct thread_scall_regs *regs)
 {
-	regs->ra = (uintptr_t)thread_unwind_user_mode;
-	regs->status = read_csr(CSR_XSTATUS);
-	regs->sp = thread_get_saved_thread_sp();
+	regs->epc = (uintptr_t)thread_unwind_user_mode;
+	regs->status = xstatus_for_xret(true, PRV_S);
+	regs->ie = 0;
+	/*
+	 * We are going to exit user mode. The stack pointer must be set as the
+	 * original value it had before allocating space of scall "regs" and
+	 * calling thread_scall_handler(). Thus, we can simply set stack pointer
+	 * as (regs + 1) value.
+	 */
+	regs->sp = (uintptr_t)(regs + 1);
 }
 
-static void thread_unhandled_trap(struct thread_trap_regs *regs __unused,
+static void thread_unhandled_trap(struct thread_ctx_regs *regs __unused,
 				  unsigned long cause __unused)
 {
 	DMSG("Unhandled trap xepc:0x%016lx xcause:0x%016lx xtval:0x%016lx",
@@ -111,7 +118,7 @@ static void thread_unhandled_trap(struct thread_trap_regs *regs __unused,
 	panic();
 }
 
-void  thread_scall_handler(struct thread_scall_regs *regs)
+void thread_scall_handler(struct thread_scall_regs *regs)
 {
 	struct ts_session *sess = NULL;
 	uint32_t state = 0;
@@ -129,135 +136,15 @@ void  thread_scall_handler(struct thread_scall_regs *regs)
 
 	assert(sess && sess->handle_scall);
 
-	if (!sess->handle_scall(regs)) {
+	if (sess->handle_scall(regs)) {
+		/*
+		 * We're about to switch back to next instruction of ecall in
+		 * user-mode
+		 */
+		regs->epc += 4;
+	} else {
+		/* We're returning from __thread_enter_user_mode() */
 		setup_unwind_user_mode(regs);
-		thread_exit_user_mode(regs->a0, regs->a1, regs->a2,
-				      regs->a3, regs->sp, regs->ra,
-				      regs->status);
-	}
-}
-
-static void copy_scall_to_trap(struct thread_scall_regs *scall_regs,
-			       struct thread_trap_regs *trap_regs)
-{
-	trap_regs->a0 = scall_regs->a0;
-	trap_regs->a1 = scall_regs->a1;
-	trap_regs->a2 = scall_regs->a2;
-	trap_regs->a3 = scall_regs->a3;
-	trap_regs->a4 = scall_regs->a4;
-	trap_regs->a5 = scall_regs->a5;
-	trap_regs->a6 = scall_regs->a6;
-	trap_regs->a7 = scall_regs->a7;
-	trap_regs->t0 = scall_regs->t0;
-	trap_regs->t1 = scall_regs->t1;
-}
-
-static void copy_trap_to_scall(struct thread_trap_regs *trap_regs,
-			       struct thread_scall_regs *scall_regs)
-{
-	*scall_regs = (struct thread_scall_regs) {
-		.status = trap_regs->status,
-		.ra = trap_regs->ra,
-		.a0 = trap_regs->a0,
-		.a1 = trap_regs->a1,
-		.a2 = trap_regs->a2,
-		.a3 = trap_regs->a3,
-		.a4 = trap_regs->a4,
-		.a5 = trap_regs->a5,
-		.a6 = trap_regs->a6,
-		.a7 = trap_regs->a7,
-		.t0 = trap_regs->t0,
-		.t1 = trap_regs->t1,
-	};
-}
-
-static void thread_user_ecall_handler(struct thread_trap_regs *trap_regs)
-{
-	struct thread_scall_regs scall_regs;
-	struct thread_core_local *l = thread_get_core_local();
-	int ct = l->curr_thread;
-
-	copy_trap_to_scall(trap_regs, &scall_regs);
-	thread_scall_handler(&scall_regs);
-	copy_scall_to_trap(&scall_regs, trap_regs);
-	/*
-	 * Save kernel sp we'll had at the beginning of this function.
-	 * This is when this TA has called another TA because
-	 * __thread_enter_user_mode() also saves the stack pointer in this
-	 * field.
-	 */
-	threads[ct].kern_sp = (unsigned long)(trap_regs + 1);
-	/*
-	 * We are returning to U-Mode, on return, the program counter
-	 * is set to xsepc (pc=xepc), we add 4 (size of an instruction)
-	 * to continue to next instruction.
-	 */
-	trap_regs->epc += 4;
-}
-
-static void copy_trap_to_abort(struct thread_trap_regs *trap_regs,
-			       struct thread_abort_regs *abort_regs)
-{
-	*abort_regs = (struct thread_abort_regs) {
-		.status = trap_regs->status,
-		.ra = trap_regs->ra,
-		.sp = trap_regs->sp,
-		.gp = trap_regs->gp,
-		.tp = trap_regs->tp,
-		.t0 = trap_regs->t0,
-		.t1 = trap_regs->t1,
-		.t2 = trap_regs->t2,
-		.s0 = trap_regs->s0,
-		.s1 = trap_regs->s1,
-		.a0 = trap_regs->a0,
-		.a1 = trap_regs->a1,
-		.a2 = trap_regs->a2,
-		.a3 = trap_regs->a3,
-		.a4 = trap_regs->a4,
-		.a5 = trap_regs->a5,
-		.a6 = trap_regs->a6,
-		.a7 = trap_regs->a7,
-		.s2 = trap_regs->s2,
-		.s3 = trap_regs->s3,
-		.s4 = trap_regs->s4,
-		.s5 = trap_regs->s5,
-		.s6 = trap_regs->s6,
-		.s7 = trap_regs->s7,
-		.s8 = trap_regs->s8,
-		.s9 = trap_regs->s9,
-		.s10 = trap_regs->s10,
-		.s11 = trap_regs->s11,
-		.t3 = trap_regs->t3,
-		.t4 = trap_regs->t4,
-		.t5 = trap_regs->t5,
-		.t6 = trap_regs->t6,
-	};
-}
-
-static void thread_abort_handler(struct thread_trap_regs *trap_regs,
-				 unsigned long cause)
-{
-	struct thread_abort_regs abort_regs = { };
-
-	assert(cause == read_csr(CSR_XCAUSE));
-	copy_trap_to_abort(trap_regs, &abort_regs);
-	abort_regs.cause = read_csr(CSR_XCAUSE);
-	abort_regs.epc = read_csr(CSR_XEPC);
-	abort_regs.tval = read_csr(CSR_XTVAL);
-	abort_regs.satp = read_csr(CSR_SATP);
-	abort_handler(cause, &abort_regs);
-}
-
-static void thread_exception_handler(unsigned long cause,
-				     struct thread_trap_regs *regs)
-{
-	switch (cause) {
-	case CAUSE_USER_ECALL:
-		thread_user_ecall_handler(regs);
-		break;
-	default:
-		thread_abort_handler(regs, cause);
-		break;
 	}
 }
 
@@ -266,8 +153,8 @@ static void thread_irq_handler(void)
 	interrupt_main_handler();
 }
 
-static void thread_interrupt_handler(unsigned long cause,
-				     struct thread_trap_regs *regs)
+void thread_native_interrupt_handler(struct thread_ctx_regs *regs,
+				     unsigned long cause)
 {
 	switch (cause & LONG_MAX) {
 	case IRQ_XTIMER:
@@ -284,36 +171,46 @@ static void thread_interrupt_handler(unsigned long cause,
 	}
 }
 
-void thread_trap_handler(long cause, unsigned long epc __unused,
-			 struct thread_trap_regs *regs,
-			 bool user __maybe_unused)
+unsigned long xstatus_for_xret(uint8_t pie, uint8_t pp)
 {
-	/*
-	 * The Interrupt bit (XLEN-1) in the cause register is set
-	 * if the trap was caused by an interrupt.
-	 */
-	if (cause < 0)
-		thread_interrupt_handler(cause, regs);
-	/*
-	 * Otherwise, cause is never written by the implementation,
-	 * though it may be explicitly written by software.
-	 */
-	else
-		thread_exception_handler(cause, regs);
+	unsigned long xstatus = read_csr(CSR_XSTATUS);
+
+	assert(pp == PRV_M || pp == PRV_S || pp == PRV_U);
+
+#ifdef RV32
+	xstatus = set_field_u32(xstatus, CSR_XSTATUS_IE, 0);
+	xstatus = set_field_u32(xstatus, CSR_XSTATUS_PIE, pie);
+	xstatus = set_field_u32(xstatus, CSR_XSTATUS_SPP, pp);
+#else	/* RV64 */
+	xstatus = set_field_u64(xstatus, CSR_XSTATUS_IE, 0);
+	xstatus = set_field_u64(xstatus, CSR_XSTATUS_PIE, pie);
+	xstatus = set_field_u64(xstatus, CSR_XSTATUS_SPP, pp);
+#endif
+
+	return xstatus;
 }
 
 static void init_regs(struct thread_ctx *thread, uint32_t a0, uint32_t a1,
 		      uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5,
 		      uint32_t a6, uint32_t a7, void *pc)
 {
-	thread->regs.ra = (uintptr_t)pc;
+	memset(&thread->regs, 0, sizeof(thread->regs));
+
+	thread->regs.epc = (uintptr_t)pc;
 
 	/* Set up xstatus */
-	thread->regs.status = read_csr(CSR_XSTATUS);
+	thread->regs.status = xstatus_for_xret(true, PRV_S);
+
+	/* Enable native interrupt */
+	thread->regs.ie = THREAD_EXCP_NATIVE_INTR;
 
 	/* Reinitialize stack pointer */
 	thread->regs.sp = thread->stack_va_end;
 
+	/* Set up GP and TP */
+	thread->regs.gp = read_gp();
+	thread->regs.tp = read_tp();
+
 	/*
 	 * Copy arguments into context. This will make the
 	 * arguments appear in a0-a7 when thread is started.
@@ -461,6 +358,13 @@ void thread_resume_from_rpc(uint32_t thread_id, uint32_t a0, uint32_t a1,
 	if (is_user_mode(&threads[n].regs))
 		tee_ta_update_session_utime_resume();
 
+	/*
+	 * We may resume thread at another hart, so we need to re-assign value
+	 * of tp to be current hart's thread_core_local.
+	 */
+	if (!is_user_mode(&threads[n].regs))
+		threads[n].regs.tp = read_tp();
+
 	/*
 	 * Return from RPC to request service of a foreign interrupt must not
 	 * get parameters from non-secure world.
@@ -526,7 +430,7 @@ int thread_state_suspend(uint32_t flags, unsigned long status, vaddr_t pc)
 	assert(threads[ct].state == THREAD_STATE_ACTIVE);
 	threads[ct].flags |= flags;
 	threads[ct].regs.status = status;
-	threads[ct].regs.ra = pc;
+	threads[ct].regs.epc = pc;
 	threads[ct].state = THREAD_STATE_SUSPENDED;
 
 	threads[ct].have_user_map = core_mmu_user_mapping_is_active();
@@ -547,14 +451,6 @@ int thread_state_suspend(uint32_t flags, unsigned long status, vaddr_t pc)
 	return ct;
 }
 
-bool thread_init_stack(uint32_t thread_id, vaddr_t sp)
-{
-	if (thread_id >= CFG_NUM_THREADS)
-		return false;
-	threads[thread_id].stack_va_end = sp;
-	return true;
-}
-
 static void init_user_kcode(void)
 {
 }
@@ -576,7 +472,6 @@ void thread_init_tvec(void)
 {
 	unsigned long tvec = (unsigned long)get_trap_vect();
 
-	static_assert(sizeof(struct thread_trap_regs) % 16 == 0);
 	write_csr(CSR_XTVEC, tvec);
 	assert(read_csr(CSR_XTVEC) == tvec);
 }
@@ -602,7 +497,7 @@ void thread_init_per_cpu(void)
 static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0,
 			 unsigned long a1, unsigned long a2, unsigned long a3,
 			 unsigned long user_sp, unsigned long entry_func,
-			 unsigned long status,
+			 unsigned long status, unsigned long ie,
 			 struct thread_pauth_keys *keys __unused)
 {
 	*regs = (struct thread_ctx_regs){
@@ -610,9 +505,11 @@ static void set_ctx_regs(struct thread_ctx_regs *regs, unsigned long a0,
 		.a1 = a1,
 		.a2 = a2,
 		.a3 = a3,
+		.s0 = 0,
 		.sp = user_sp,
-		.ra = entry_func,
-		.status = status
+		.epc = entry_func,
+		.status = status,
+		.ie = ie,
 	};
 }
 
@@ -625,20 +522,32 @@ uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1,
 				uint32_t *exit_status1)
 {
 	unsigned long status = 0;
+	unsigned long ie = 0;
 	uint32_t exceptions = 0;
 	uint32_t rc = 0;
 	struct thread_ctx_regs *regs = NULL;
 
 	tee_ta_update_session_utime_resume();
 
+	/* Read current interrupt masks */
+	ie = read_csr(CSR_XIE);
+
+	/*
+	 * Mask all exceptions, the CSR_XSTATUS.IE will be set from
+	 * setup_unwind_user_mode() after exiting.
+	 */
 	exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
 	regs = thread_get_ctx_regs();
-	status = read_csr(CSR_XSTATUS);
-	status |= CSR_XSTATUS_PIE;	/* Previous interrupt is enabled */
-	status = set_field_u64(status, CSR_XSTATUS_SPP, PRV_U);
-	set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, status, NULL);
+	status = xstatus_for_xret(true, PRV_U);
+	set_ctx_regs(regs, a0, a1, a2, a3, user_sp, entry_func, status, ie,
+		     NULL);
 	rc = __thread_enter_user_mode(regs, exit_status0, exit_status1);
 	thread_unmask_exceptions(exceptions);
 
 	return rc;
 }
+
+void __thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS])
+{
+	thread_rpc_xstatus(rv, xstatus_for_xret(false, PRV_S));
+}
diff --git a/core/arch/riscv/kernel/thread_optee_abi_rv.S b/core/arch/riscv/kernel/thread_optee_abi_rv.S
index 6ba598c621331bb3491d43151ad05aac89b08e5b..3702940ae77157cf0772a2fd05c7ebe9dba571ad 100644
--- a/core/arch/riscv/kernel/thread_optee_abi_rv.S
+++ b/core/arch/riscv/kernel/thread_optee_abi_rv.S
@@ -23,13 +23,13 @@
  * domains where we return to a messaging callback which parses and handles
  * messages.
  *
- * void thread_return_to_ree(unsigned long arg0, unsigned long arg1,
- *                           unsigned long arg2, unsigned long arg3,
- *                           unsigned long arg4, unsigned long arg5);
+ * void thread_return_to_udomain(unsigned long arg0, unsigned long arg1,
+ *                               unsigned long arg2, unsigned long arg3,
+ *                               unsigned long arg4, unsigned long arg5);
  */
-FUNC thread_return_to_ree , :
+FUNC thread_return_to_udomain , :
 	/* Caller should provide arguments in a0~a5 */
-#if defined(CFG_RISCV_SBI)
+#if defined(CFG_RISCV_WITH_M_MODE_SM)
 	li	a7, SBI_EXT_TEE		/* extension ID */
 	li	a6, 0			/* function ID (unused) */
 	ecall
@@ -38,7 +38,7 @@ FUNC thread_return_to_ree , :
 #endif
 	/* ABI to REE should not return */
 	panic_at_abi_return
-END_FUNC thread_return_to_ree
+END_FUNC thread_return_to_udomain
 
 FUNC thread_std_abi_entry , :
 	jal	__thread_std_abi_entry
@@ -46,8 +46,8 @@ FUNC thread_std_abi_entry , :
 	/* Save return value */
 	mv	s0, a0
 
-	/* Disable all interrupts */
-	csrc	CSR_XSTATUS, CSR_XSTATUS_IE
+	/* Mask all maskable exceptions before switching to temporary stack */
+	csrw	CSR_XIE, x0
 
 	/* Switch to temporary stack */
 	jal	thread_get_tmp_sp
@@ -64,33 +64,42 @@ FUNC thread_std_abi_entry , :
 	li	a2, 0
 	li	a3, 0
 	li	a4, 0
+	li	a5, 0
 	li	a0, TEEABI_OPTEED_RETURN_CALL_DONE
 
 	/* Return to untrusted domain */
-	jal	thread_return_to_ree
+	jal	thread_return_to_udomain
 END_FUNC thread_std_abi_entry
 
-/* void thread_rpc(uint32_t rv[THREAD_RPC_NUM_ARGS]) */
-FUNC thread_rpc , :
+/*
+ * void thread_rpc_xstatus(uint32_t rv[THREAD_RPC_NUM_ARGS],
+ *                         unsigned long status);
+ */
+FUNC thread_rpc_xstatus , :
 	 /* Use stack for temporary storage */
-	addi	sp, sp, -REGOFF(4)
+	addi	sp, sp, -REGOFF(8)
 
 	/* Read xSTATUS */
-	csrr	a1, CSR_XSTATUS
+	csrr	a2, CSR_XSTATUS
 
 	/* Mask all maskable exceptions before switching to temporary stack */
-	csrc	CSR_XSTATUS, CSR_XSTATUS_IE
+	csrw	CSR_XIE, x0
 
 	/* Save return address xSTATUS and pointer to rv */
 	STR	a0, REGOFF(0)(sp)
 	STR	a1, REGOFF(1)(sp)
 	STR	s0, REGOFF(2)(sp)
 	STR	ra, REGOFF(3)(sp)
-	addi	s0, sp, REGOFF(4)
+	STR	a2, REGOFF(4)(sp)
+#ifdef CFG_UNWIND
+	addi	s0, sp, REGOFF(8)
+#endif
 
 	/* Save thread state */
 	jal	thread_get_ctx_regs
-	store_xregs a0, THREAD_CTX_REG_SP, REG_SP
+	LDR	ra, REGOFF(3)(sp)
+	/* Save ra, sp, gp, tp, and s0~s11 */
+	store_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP
 	store_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1
 	store_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11
 
@@ -118,10 +127,11 @@ FUNC thread_rpc , :
 	mv	a1, s2	/* rv[0] */
 	mv	a2, s3	/* rv[1] */
 	mv	a3, s4	/* rv[2] */
+	li	a5, 0
 	li	a0, TEEABI_OPTEED_RETURN_CALL_DONE
 
 	/* Return to untrusted domain */
-	jal	thread_return_to_ree
+	jal	thread_return_to_udomain
 .thread_rpc_return:
 	/*
 	 * Jumps here from thread_resume() above when RPC has returned.
@@ -139,16 +149,16 @@ FUNC thread_rpc , :
 	sw	a3, 12(a4)
 
 	/* Pop saved XSTATUS from stack */
-	LDR	s0, REGOFF(1)(sp)
+	LDR	s0, REGOFF(4)(sp)
 	csrw	CSR_XSTATUS, s0
 
-	/* Pop return address and s0 from stack */
-	LDR	ra, REGOFF(3)(sp)
+	/* Pop s0 from stack */
 	LDR	s0, REGOFF(2)(sp)
 
-	addi	sp, sp, REGOFF(4)
+	addi	sp, sp, REGOFF(8)
 	ret
-END_FUNC thread_rpc
+END_FUNC thread_rpc_xstatus
+DECLARE_KEEP_PAGER thread_rpc_xstatus
 
 LOCAL_FUNC vector_std_abi_entry, : , .identity_map
 	jal	thread_handle_std_abi
@@ -163,10 +173,11 @@ LOCAL_FUNC vector_std_abi_entry, : , .identity_map
 	li	a2, 0
 	li	a3, 0
 	li	a4, 0
+	li	a5, 0
 	li	a0, TEEABI_OPTEED_RETURN_CALL_DONE
 
 	/* Return to untrusted domain */
-	j	thread_return_to_ree
+	j	thread_return_to_udomain
 END_FUNC vector_std_abi_entry
 
 LOCAL_FUNC vector_fast_abi_entry , : , .identity_map
@@ -179,7 +190,7 @@ LOCAL_FUNC vector_fast_abi_entry , : , .identity_map
 
 	li	a0, TEEABI_OPTEED_RETURN_CALL_DONE
 	/* Return to untrusted domain */
-	j	thread_return_to_ree
+	j	thread_return_to_udomain
 END_FUNC vector_fast_abi_entry
 
 LOCAL_FUNC vector_fiq_entry , : , .identity_map
@@ -187,8 +198,14 @@ LOCAL_FUNC vector_fiq_entry , : , .identity_map
 	jal	interrupt_main_handler
 
 	li	a0, TEEABI_OPTEED_RETURN_FIQ_DONE
+	li	a1, 0
+	li	a2, 0
+	li	a3, 0
+	li	a4, 0
+	li	a5, 0
+
 	/* Return to untrusted domain */
-	j	thread_return_to_ree
+	j	thread_return_to_udomain
 END_FUNC vector_fiq_entry
 
 /*
diff --git a/core/arch/riscv/kernel/thread_rv.S b/core/arch/riscv/kernel/thread_rv.S
index e97a5cd7a5a3653b79281e03e787d75a0299c186..f7488b6e2eac6c00d46748c6b8db80f48906c28d 100644
--- a/core/arch/riscv/kernel/thread_rv.S
+++ b/core/arch/riscv/kernel/thread_rv.S
@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
  * Copyright 2022-2023 NXP
+ * Copyright 2024 Andes Technology Corporation
  */
 
 #include <asm.S>
@@ -11,6 +12,9 @@
 #include <mm/core_mmu.h>
 #include <riscv.h>
 #include <riscv_macros.S>
+#include <tee/optee_abi.h>
+#include <tee/teeabi_opteed.h>
+#include <tee/teeabi_opteed_macros.h>
 
 .macro get_thread_ctx res, tmp0
 	lw	\tmp0, THREAD_CORE_LOCAL_CURR_THREAD(tp)
@@ -23,171 +27,632 @@
 2:
 .endm
 
-.macro save_regs, mode
-	addi	sp, sp, -THREAD_TRAP_REGS_SIZE
-.if \mode == TRAP_MODE_USER
+.macro b_if_prev_priv_is_u reg, label
+	andi	\reg, \reg, CSR_XSTATUS_SPP
+	beqz	\reg, \label
+.endm
+
+/* size_t __get_core_pos(void); */
+FUNC __get_core_pos , : , .identity_map
+	lw	a0, THREAD_CORE_LOCAL_HART_ID(tp)
+	ret
+END_FUNC __get_core_pos
+
+FUNC thread_trap_vect , :
+	csrrw	tp, CSR_XSCRATCH, tp
+	bnez	tp, 0f
+	/* Read tp back */
+	csrrw	tp, CSR_XSCRATCH, tp
+	j	trap_from_kernel
+0:
+	/* Now tp is thread_core_local */
+	j	trap_from_user
+thread_trap_vect_end:
+END_FUNC thread_trap_vect
+
+LOCAL_FUNC trap_from_kernel, :
+	/* Save sp, a0, a1 into temporary spaces of thread_core_local */
+	store_xregs tp, THREAD_CORE_LOCAL_X0, REG_SP
+	store_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	csrr	a0, CSR_XCAUSE
+	/* MSB of cause differentiates between interrupts and exceptions */
+	bge	a0, zero, exception_from_kernel
+
+interrupt_from_kernel:
+	/* Get thread context as sp */
+	get_thread_ctx sp, a0
+
+	/* Load and save kernel sp */
+	load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0
+	store_xregs sp, THREAD_CTX_REG_SP, REG_A0
+
+	/* Restore user a0, a1 which can be saved later */
+	load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	/* Save all other GPRs */
+	store_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	store_xregs sp, THREAD_CTX_REG_GP, REG_GP
+	store_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	store_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	store_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	store_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	store_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	/* Save XIE */
+	csrr	t0, CSR_XIE
+	store_xregs sp, THREAD_CTX_REG_IE, REG_T0
+	/* Mask all interrupts */
+	csrw	CSR_XIE, x0
+	/* Save XSTATUS */
+	csrr	t0, CSR_XSTATUS
+	store_xregs sp, THREAD_CTX_REG_STATUS, REG_T0
+	/* Save XEPC */
+	csrr	t0, CSR_XEPC
+	store_xregs sp, THREAD_CTX_REG_EPC, REG_T0
+
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * a1 = cause
+	 */
+	mv	a0, sp
+	csrr	a1, CSR_XCAUSE
+	/* Load tmp_stack_va_end as current sp. */
+	load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_SP
+
+	/*
+	 * Get interrupt code from XCAUSE and build XIP. For example, if the
+	 * value of XCAUSE is 0x8000000000000005 (supervisor timer interrupt),
+	 * we build 0x20, which is (1 << 5) and indicates the sip.STIP signal.
+	 */
+	li	a2, CSR_XCAUSE_INTR_FLAG
+	sub	a2, a1, a2
+	li	a3, 1
+	sll	a3, a3, a2
+	/*
+	 * Compare built XIP with THREAD_EXCP_FOREIGN_INTR. If XIP is one of
+	 * THREAD_EXCP_FOREIGN_INTR, we call thread_foreign_interrupt_handler().
+	 */
+	li	a2, THREAD_EXCP_FOREIGN_INTR
+	and	a2, a3, a2
+	beqz	a2, native_interrupt_from_kernel
+
+foreign_interrupt_from_kernel:
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * Tail call thread_foreign_interrupt_handler(regs) since we will not
+	 * return to here.
+	 */
+	tail	thread_foreign_interrupt_handler
+
+native_interrupt_from_kernel:
+	/* Update 32-bit core local flags */
+	lw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+	slli	a2, a2, THREAD_CLF_SAVED_SHIFT
+	ori	a2, a2, (THREAD_CLF_TMP | THREAD_CLF_IRQ)
+	sw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * a1 = cause
+	 * Call thread_native_interrupt_handler(regs, cause)
+	 */
+	call	thread_native_interrupt_handler
+
+	/* Update 32-bit core local flags */
+	lw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+	srli	a2, a2, THREAD_CLF_SAVED_SHIFT
+	sw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/* Get thread context as sp */
+	get_thread_ctx sp, t0
+	/* Restore XEPC */
+	load_xregs sp, THREAD_CTX_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore XSTATUS */
+	load_xregs sp, THREAD_CTX_REG_STATUS, REG_T0
+	csrw	CSR_XSTATUS, t0
+	/* Restore XIE */
+	load_xregs sp, THREAD_CTX_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+	/* We are going to XRET to kernel mode. Set XSCRATCH as 0 */
+	csrw	CSR_XSCRATCH, 0
+	/* Restore all GPRs */
+	load_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	load_xregs sp, THREAD_CTX_REG_GP, REG_GP
+	load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_CTX_REG_SP, REG_SP
+	XRET
+
+exception_from_kernel:
+	/*
+	 * Update core local flags.
+	 * flags = (flags << THREAD_CLF_SAVED_SHIFT) | THREAD_CLF_ABORT;
+	 */
+	lw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+	slli	a0, a0, THREAD_CLF_SAVED_SHIFT
+	ori	a0, a0, THREAD_CLF_ABORT
+	li	a1, (THREAD_CLF_ABORT << THREAD_CLF_SAVED_SHIFT)
+	and	a1, a0, a1
+	bnez	a1, sel_tmp_sp
+
+	/* Select abort stack */
+	load_xregs tp, THREAD_CORE_LOCAL_ABT_STACK_VA_END, REG_A1
+	j	set_sp
+
+sel_tmp_sp:
+	/* We have an abort while using the abort stack, select tmp stack */
+	load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_A1
+	ori	a0, a0, THREAD_CLF_TMP	/* flags |= THREAD_CLF_TMP; */
+
+set_sp:
+	mv	sp, a1
+	sw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/*
+	 * Save state on stack
+	 */
+	addi	sp, sp, -THREAD_ABT_REGS_SIZE
+
+	/* Save kernel sp */
+	load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0
+	store_xregs sp, THREAD_ABT_REG_SP, REG_A0
+
+	/* Restore kernel a0, a1 which can be saved later */
+	load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	/* Save all other GPRs */
+	store_xregs sp, THREAD_ABT_REG_RA, REG_RA
+	store_xregs sp, THREAD_ABT_REG_GP, REG_GP
+	store_xregs sp, THREAD_ABT_REG_TP, REG_TP
+	store_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2
+	store_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1
+	store_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7
+	store_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11
+	store_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6
+	/* Save XIE */
+	csrr	t0, CSR_XIE
+	store_xregs sp, THREAD_ABT_REG_IE, REG_T0
+	/* Mask all interrupts */
+	csrw	CSR_XIE, x0
+	/* Save XSTATUS */
+	csrr	t0, CSR_XSTATUS
+	store_xregs sp, THREAD_ABT_REG_STATUS, REG_T0
+	/* Save XEPC */
+	csrr	t0, CSR_XEPC
+	store_xregs sp, THREAD_ABT_REG_EPC, REG_T0
+	/* Save XTVAL */
+	csrr	t0, CSR_XTVAL
+	store_xregs sp, THREAD_ABT_REG_TVAL, REG_T0
+	/* Save XCAUSE */
+	csrr	a0, CSR_XCAUSE
+	store_xregs sp, THREAD_ABT_REG_CAUSE, REG_A0
+
+	/*
+	 * a0 = cause
+	 * a1 = sp (struct thread_abort_regs *regs)
+	 * Call abort_handler(cause, regs)
+	 */
+	mv	a1, sp
+	call	abort_handler
+
+	/*
+	 * Restore state from stack
+	 */
+
+	/* Restore XEPC */
+	load_xregs sp, THREAD_ABT_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore XSTATUS */
+	load_xregs sp, THREAD_ABT_REG_STATUS, REG_T0
+	csrw	CSR_XSTATUS, t0
+	/* Restore XIE */
+	load_xregs sp, THREAD_ABT_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+	/* We are going to XRET to kernel mode. Set XSCRATCH as 0 */
+	csrw	CSR_XSCRATCH, 0
+
+	/* Update core local flags */
+	lw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+	srli	a0, a0, THREAD_CLF_SAVED_SHIFT
+	sw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/* Restore all GPRs */
+	load_xregs sp, THREAD_ABT_REG_RA, REG_RA
+	load_xregs sp, THREAD_ABT_REG_GP, REG_GP
+	load_xregs sp, THREAD_ABT_REG_TP, REG_TP
+	load_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_ABT_REG_SP, REG_SP
+	XRET
+END_FUNC trap_from_kernel
+
+LOCAL_FUNC trap_from_user, :
+	/* Save user sp, a0, a1 into temporary spaces of thread_core_local */
+	store_xregs tp, THREAD_CORE_LOCAL_X0, REG_SP
+	store_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	csrr	a0, CSR_XCAUSE
+	/* MSB of cause differentiates between interrupts and exceptions */
+	bge	a0, zero, exception_from_user
 
-	/* Save user thread pointer and load kernel thread pointer */
-	store_xregs sp, THREAD_TRAP_REG_TP, REG_TP
-	addi	tp, sp, THREAD_TRAP_REGS_SIZE
-	/* Now tp is at struct thread_user_mode_rec, which has kernel tp */
-	load_xregs tp, THREAD_USER_MODE_REC_X4, REG_TP
+interrupt_from_user:
+	/* Get thread context as sp */
+	get_thread_ctx sp, a0
 
-	store_xregs sp, THREAD_TRAP_REG_GP, REG_GP
+	/* Save user sp */
+	load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0
+	store_xregs sp, THREAD_CTX_REG_SP, REG_A0
+
+	/* Restore user a0, a1 which can be saved later */
+	load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	/* Save user gp */
+	store_xregs sp, THREAD_CTX_REG_GP, REG_GP
 
 	/*
 	 * Set the scratch register to 0 such in case of a recursive
 	 * exception thread_trap_vect() knows that it is emitted from kernel.
 	 */
 	csrrw	gp, CSR_XSCRATCH, zero
-	store_xregs sp, THREAD_TRAP_REG_SP, REG_GP
+	/* Save user tp we previously swapped into CSR_XSCRATCH */
+	store_xregs sp, THREAD_CTX_REG_TP, REG_GP
+	/* Set kernel gp */
 .option push
 .option norelax
 	la	gp, __global_pointer$
 .option pop
-.endif
-	store_xregs sp, THREAD_TRAP_REG_T3, REG_T3, REG_T6
-	store_xregs sp, THREAD_TRAP_REG_T0, REG_T0, REG_T2
-	store_xregs sp, THREAD_TRAP_REG_A0, REG_A0, REG_A7
-	store_xregs sp, THREAD_TRAP_REG_RA, REG_RA
-#if defined(CFG_UNWIND)
-	/* To unwind stack we need s0, which is frame pointer. */
-	store_xregs sp, THREAD_TRAP_REG_S0, REG_S0
-#endif
-
+	/* Save all other GPRs */
+	store_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	store_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	store_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	store_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	store_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	store_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	/* Save XIE */
+	csrr	t0, CSR_XIE
+	store_xregs sp, THREAD_CTX_REG_IE, REG_T0
+	/* Mask all interrupts */
+	csrw	CSR_XIE, x0
+	/* Save XSTATUS */
 	csrr	t0, CSR_XSTATUS
-	store_xregs sp, THREAD_TRAP_REG_STATUS, REG_T0
+	store_xregs sp, THREAD_CTX_REG_STATUS, REG_T0
+	/* Save XEPC */
+	csrr	t0, CSR_XEPC
+	store_xregs sp, THREAD_CTX_REG_EPC, REG_T0
 
-	csrr	a0, CSR_XCAUSE
-	csrr	a1, CSR_XEPC
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * a1 = cause
+	 */
+	mv	a0, sp
+	csrr	a1, CSR_XCAUSE
+	/* Load tmp_stack_va_end as current sp. */
+	load_xregs tp, THREAD_CORE_LOCAL_TMP_STACK_VA_END, REG_SP
 
-	store_xregs sp, THREAD_TRAP_REG_EPC, REG_A1
+	/*
+	 * Get interrupt code from XCAUSE and build XIP. For example, if the
+	 * value of XCAUSE is 0x8000000000000005 (supervisor timer interrupt),
+	 * we build 0x20, which is (1 << 5) and indicates the sip.STIP signal.
+	 */
+	li	a2, CSR_XCAUSE_INTR_FLAG
+	sub	a2, a1, a2
+	li	a3, 1
+	sll	a3, a3, a2
+	/*
+	 * Compare built XIP with THREAD_EXCP_FOREIGN_INTR. If XIP is one of
+	 * THREAD_EXCP_FOREIGN_INTR, call thread_foreign_interrupt_handler().
+	 */
+	li	a2, THREAD_EXCP_FOREIGN_INTR
+	and	a2, a3, a2
+	beqz	a2, native_interrupt_from_user
 
-	mv	a2, sp
+foreign_interrupt_from_user:
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * Tail call thread_foreign_interrupt_handler(regs) since we will not
+	 * return to here.
+	 */
+	tail	thread_foreign_interrupt_handler
 
-	/* a0 = cause
-	 * a1 = epc
-	 * a2 = sp
-	 * a3 = user
-	 * thread_trap_handler(cause, epc, sp, user)
+native_interrupt_from_user:
+	/* Update 32-bit core local flags */
+	lw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+	slli	a2, a2, THREAD_CLF_SAVED_SHIFT
+	ori	a2, a2, (THREAD_CLF_TMP | THREAD_CLF_IRQ)
+	sw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/*
+	 * a0 = struct thread_ctx_regs *regs
+	 * a1 = cause
+	 * Call thread_native_interrupt_handler(regs, cause)
 	 */
-.endm
+	call	thread_native_interrupt_handler
 
-.macro restore_regs, mode
-	load_xregs sp, THREAD_TRAP_REG_EPC, REG_T0
-	csrw	CSR_XEPC, t0
+	/* Update 32-bit core local flags */
+	lw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
+	srli	a2, a2, THREAD_CLF_SAVED_SHIFT
+	sw	a2, THREAD_CORE_LOCAL_FLAGS(tp)
 
-	load_xregs sp, THREAD_TRAP_REG_STATUS, REG_T0
+	/* Get thread context as sp */
+	get_thread_ctx sp, t0
+	/* Restore XEPC */
+	load_xregs sp, THREAD_CTX_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore XSTATUS */
+	load_xregs sp, THREAD_CTX_REG_STATUS, REG_T0
 	csrw	CSR_XSTATUS, t0
+	/* Restore XIE */
+	load_xregs sp, THREAD_CTX_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+	/* Set scratch as thread_core_local */
+	csrw	CSR_XSCRATCH, tp
+	/* Restore all GPRs */
+	load_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	load_xregs sp, THREAD_CTX_REG_GP, REG_GP
+	load_xregs sp, THREAD_CTX_REG_TP, REG_TP
+	load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_CTX_REG_SP, REG_SP
+	XRET
 
-	load_xregs sp, THREAD_TRAP_REG_RA, REG_RA
-	load_xregs sp, THREAD_TRAP_REG_A0, REG_A0, REG_A7
-	load_xregs sp, THREAD_TRAP_REG_T0, REG_T0, REG_T2
-	load_xregs sp, THREAD_TRAP_REG_T3, REG_T3, REG_T6
-#if defined(CFG_UNWIND)
-	/* To unwind stack we need s0, which is frame pointer. */
-	load_xregs sp, THREAD_TRAP_REG_S0, REG_S0
-#endif
-
-.if \mode == TRAP_MODE_USER
-	addi	gp, sp, THREAD_TRAP_REGS_SIZE
-	csrw	CSR_XSCRATCH, gp
-
-	load_xregs sp, THREAD_TRAP_REG_TP, REG_TP
-	load_xregs sp, THREAD_TRAP_REG_GP, REG_GP
-	load_xregs sp, THREAD_TRAP_REG_SP, REG_SP
-
-.else
-	addi	sp, sp, THREAD_TRAP_REGS_SIZE
-.endif
-.endm
+exception_from_user:
+	/* a0 is CSR_XCAUSE */
+	li	a1, CAUSE_USER_ECALL
+	bne	a0, a1, abort_from_user
+ecall_from_user:
+	/* Load and set kernel sp from thread context */
+	get_thread_ctx a0, a1
+	load_xregs a0, THREAD_CTX_KERN_SP, REG_SP
+
+	/* Now sp is kernel sp, create stack for struct thread_scall_regs */
+	addi	sp, sp, -THREAD_SCALL_REGS_SIZE
+	/* Save user sp */
+	load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0
+	store_xregs sp, THREAD_SCALL_REG_SP, REG_A0
+
+	/* Restore user a0, a1 which can be saved later */
+	load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	/* Save user gp */
+	store_xregs sp, THREAD_SCALL_REG_GP, REG_GP
+	/*
+	 * Set the scratch register to 0 such in case of a recursive
+	 * exception thread_trap_vect() knows that it is emitted from kernel.
+	 */
+	csrrw	gp, CSR_XSCRATCH, zero
+	/* Save user tp we previously swapped into CSR_XSCRATCH */
+	store_xregs sp, THREAD_SCALL_REG_TP, REG_GP
+	/* Set kernel gp */
+.option push
+.option norelax
+	la	gp, __global_pointer$
+.option pop
 
-/* size_t __get_core_pos(void); */
-FUNC __get_core_pos , : , .identity_map
-	lw	a0, THREAD_CORE_LOCAL_HART_ID(tp)
-	ret
-END_FUNC __get_core_pos
+	/* Save other caller-saved registers */
+	store_xregs sp, THREAD_SCALL_REG_RA, REG_RA
+	store_xregs sp, THREAD_SCALL_REG_T0, REG_T0, REG_T2
+	store_xregs sp, THREAD_SCALL_REG_A0, REG_A0, REG_A7
+	store_xregs sp, THREAD_SCALL_REG_T3, REG_T3, REG_T6
+	/* Save XIE */
+	csrr	a0, CSR_XIE
+	store_xregs sp, THREAD_SCALL_REG_IE, REG_A0
+	/* Mask all interrupts */
+	csrw	CSR_XIE, zero
+	/* Save XSTATUS */
+	csrr	a0, CSR_XSTATUS
+	store_xregs sp, THREAD_SCALL_REG_STATUS, REG_A0
+	/* Save XEPC */
+	csrr	a0, CSR_XEPC
+	store_xregs sp, THREAD_SCALL_REG_EPC, REG_A0
 
-FUNC thread_trap_vect , :
-	csrrw	sp, CSR_XSCRATCH, sp
-	bnez	sp, 0f
-	csrrw	sp, CSR_XSCRATCH, sp
-	j	trap_from_kernel
-0:
-	j	trap_from_user
-thread_trap_vect_end:
-END_FUNC thread_trap_vect
+	/*
+	 * a0 = struct thread_scall_regs *regs
+	 * Call thread_scall_handler(regs)
+	 */
+	mv	a0, sp
+	call	thread_scall_handler
 
-LOCAL_FUNC trap_from_kernel, :
-	save_regs TRAP_MODE_KERNEL
-	li	a3, 0
-	jal	thread_trap_handler
-	restore_regs TRAP_MODE_KERNEL
+	/*
+	 * Save kernel sp we'll had at the beginning of this function.
+	 * This is when this TA has called another TA because
+	 * __thread_enter_user_mode() also saves the stack pointer in this
+	 * field.
+	 */
+	get_thread_ctx a0, a1
+	addi	t0, sp, THREAD_SCALL_REGS_SIZE
+	store_xregs a0, THREAD_CTX_KERN_SP, REG_T0
+
+	/* Restore XEPC */
+	load_xregs sp, THREAD_SCALL_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore XSTATUS */
+	load_xregs sp, THREAD_SCALL_REG_STATUS, REG_T0
+	csrw	CSR_XSTATUS, t0
+	/* Restore XIE */
+	load_xregs sp, THREAD_SCALL_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+	/* Check previous privilege mode by status.SPP */
+	csrr	t0, CSR_XSTATUS
+	b_if_prev_priv_is_u t0, 1f
+	/*
+	 * We are going to XRET to kernel mode.
+	 * XSCRATCH is already zero to indicate that we are in kernel mode.
+	 * We must keep kernel gp & tp, so skip restoring user gp & tp.
+	 */
+	j	2f
+1:
+	/*
+	 * We are going to XRET to user mode.
+	 * XSCRATCH must be tp(thread_core_local) to be used in next trap.
+	 * We also need to restore user gp & tp
+	 */
+	csrw	CSR_XSCRATCH, tp
+	load_xregs sp, THREAD_SCALL_REG_GP, REG_GP
+	load_xregs sp, THREAD_SCALL_REG_TP, REG_TP
+2:
+	/* Restore remaining caller-saved registers */
+	load_xregs sp, THREAD_SCALL_REG_RA, REG_RA
+	load_xregs sp, THREAD_SCALL_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_SCALL_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_SCALL_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_SCALL_REG_SP, REG_SP
 	XRET
-END_FUNC trap_from_kernel
 
-LOCAL_FUNC trap_from_user, :
-	save_regs TRAP_MODE_USER
-	li	a3, 1
-	jal	thread_trap_handler
-	restore_regs TRAP_MODE_USER
+abort_from_user:
+	/*
+	 * Update core local flags
+	 */
+	lw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+	slli	a0, a0, THREAD_CLF_SAVED_SHIFT
+	ori	a0, a0, THREAD_CLF_ABORT
+	sw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/*
+	 * Save state on stack
+	 */
+
+	/* Load abt_stack_va_end and set it as sp */
+	load_xregs tp, THREAD_CORE_LOCAL_ABT_STACK_VA_END, REG_SP
+
+	/* Now sp is abort sp, create stack for struct thread_abort_regs */
+	addi	sp, sp, -THREAD_ABT_REGS_SIZE
+
+	/* Save user sp */
+	load_xregs tp, THREAD_CORE_LOCAL_X0, REG_A0
+	store_xregs sp, THREAD_ABT_REG_SP, REG_A0
+
+	/* Restore user a0, a1 which can be saved later */
+	load_xregs tp, THREAD_CORE_LOCAL_X1, REG_A0, REG_A1
+
+	/* Save user gp */
+	store_xregs sp, THREAD_ABT_REG_GP, REG_GP
+
+	/*
+	 * Set the scratch register to 0 such in case of a recursive
+	 * exception thread_trap_vect() knows that it is emitted from kernel.
+	 */
+	csrrw	gp, CSR_XSCRATCH, zero
+	/* Save user tp we previously swapped into CSR_XSCRATCH */
+	store_xregs sp, THREAD_ABT_REG_TP, REG_GP
+	/* Set kernel gp */
+.option push
+.option norelax
+	la	gp, __global_pointer$
+.option pop
+	/* Save all other GPRs */
+	store_xregs sp, THREAD_ABT_REG_RA, REG_RA
+	store_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2
+	store_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1
+	store_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7
+	store_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11
+	store_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6
+	/* Save XIE */
+	csrr	t0, CSR_XIE
+	store_xregs sp, THREAD_ABT_REG_IE, REG_T0
+	/* Mask all interrupts */
+	csrw	CSR_XIE, x0
+	/* Save XSTATUS */
+	csrr	t0, CSR_XSTATUS
+	store_xregs sp, THREAD_ABT_REG_STATUS, REG_T0
+	/* Save XEPC */
+	csrr	t0, CSR_XEPC
+	store_xregs sp, THREAD_ABT_REG_EPC, REG_T0
+	/* Save XTVAL */
+	csrr	t0, CSR_XTVAL
+	store_xregs sp, THREAD_ABT_REG_TVAL, REG_T0
+	/* Save XCAUSE */
+	csrr	a0, CSR_XCAUSE
+	store_xregs sp, THREAD_ABT_REG_CAUSE, REG_A0
+
+	/*
+	 * a0 = cause
+	 * a1 = sp (struct thread_abort_regs *regs)
+	 * Call abort_handler(cause, regs)
+	 */
+	mv	a1, sp
+	call	abort_handler
+
+	/*
+	 * Restore state from stack
+	 */
+
+	/* Restore XEPC */
+	load_xregs sp, THREAD_ABT_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore XSTATUS */
+	load_xregs sp, THREAD_ABT_REG_STATUS, REG_T0
+	csrw	CSR_XSTATUS, t0
+	/* Restore XIE */
+	load_xregs sp, THREAD_ABT_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+
+	/* Update core local flags */
+	lw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+	srli	a0, a0, THREAD_CLF_SAVED_SHIFT
+	sw	a0, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/* Check previous privilege mode by status.SPP */
+	csrr	t0, CSR_XSTATUS
+	b_if_prev_priv_is_u t0, 1f
+	/*
+	 * We are going to XRET to kernel mode.
+	 * XSCRATCH is already zero to indicate that we are in kernel mode.
+	 * We must keep kernel gp & tp, so skip restoring user gp & tp.
+	 */
+	j	2f
+1:
+	/*
+	 * We are going to XRET to user mode.
+	 * XSCRATCH must be tp(thread_core_local) to be used in next trap.
+	 * We also need to restore user gp & tp
+	 */
+	csrw	CSR_XSCRATCH, tp
+	load_xregs sp, THREAD_ABT_REG_GP, REG_GP
+	load_xregs sp, THREAD_ABT_REG_TP, REG_TP
+2:
+	/* Restore remaining GPRs */
+	load_xregs sp, THREAD_ABT_REG_RA, REG_RA
+	load_xregs sp, THREAD_ABT_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_ABT_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_ABT_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_ABT_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_ABT_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_ABT_REG_SP, REG_SP
 	XRET
 END_FUNC trap_from_user
 
 /*
  * void thread_unwind_user_mode(uint32_t ret, uint32_t exit_status0,
- * 		uint32_t exit_status1);
+ * 				uint32_t exit_status1);
  * See description in thread.h
  */
 FUNC thread_unwind_user_mode , :
-
 	/* Store the exit status */
 	load_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A3, REG_A5
 	sw	a1, (a4)
 	sw	a2, (a5)
-
-	/* Save user callee regs */
+	/* Save user callee-saved regs */
 	store_xregs a3, THREAD_CTX_REG_S0, REG_S0, REG_S1
 	store_xregs a3, THREAD_CTX_REG_S2, REG_S2, REG_S11
-	store_xregs a3, THREAD_CTX_REG_SP, REG_SP, REG_TP
-
-	/* Restore kernel callee regs */
-	mv	a1, sp
-
-	load_xregs a1, THREAD_USER_MODE_REC_X1, REG_RA, REG_TP
-	load_xregs a1, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1
-	load_xregs a1, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11
-
+	/* Restore kernel ra(thread_enter_user_mode()) & callee-saved regs */
+	load_xregs sp, THREAD_USER_MODE_REC_RA, REG_RA
+	load_xregs sp, THREAD_USER_MODE_REC_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_USER_MODE_REC_S2, REG_S2, REG_S11
 	add	sp, sp, THREAD_USER_MODE_REC_SIZE
-
-	/*
-	 * Zeroize xSCRATCH to indicate to thread_trap_vect()
-	 * that we are executing in kernel.
-	 */
-	csrw	CSR_XSCRATCH, zero
-
 	/* Return from the call of thread_enter_user_mode() */
 	ret
 END_FUNC thread_unwind_user_mode
 
-/*
- * void thread_exit_user_mode(unsigned long a0, unsigned long a1,
- *			       unsigned long a2, unsigned long a3,
- *			       unsigned long sp, unsigned long pc,
- *			       unsigned long status);
- */
-FUNC thread_exit_user_mode , :
-	/* Set kernel stack pointer */
-	mv	sp, a4
-
-	/* Set xSTATUS */
-	csrw	CSR_XSTATUS, a6
-
-	/* Set return address thread_unwind_user_mode() */
-	mv	ra, a5
-	ret
-END_FUNC thread_exit_user_mode
-
 /*
  * uint32_t __thread_enter_user_mode(struct thread_ctx_regs *regs,
  *				     uint32_t *exit_status0,
@@ -199,9 +664,9 @@ FUNC __thread_enter_user_mode , :
 	 */
 	addi	sp, sp, -THREAD_USER_MODE_REC_SIZE
 	store_xregs sp, THREAD_USER_MODE_REC_CTX_REGS_PTR, REG_A0, REG_A2
-	store_xregs sp, THREAD_USER_MODE_REC_X1, REG_RA, REG_TP
-	store_xregs sp, THREAD_USER_MODE_REC_X8, REG_S0, REG_S1
-	store_xregs sp, THREAD_USER_MODE_REC_X18, REG_S2, REG_S11
+	store_xregs sp, THREAD_USER_MODE_REC_RA, REG_RA
+	store_xregs sp, THREAD_USER_MODE_REC_S0, REG_S0, REG_S1
+	store_xregs sp, THREAD_USER_MODE_REC_S2, REG_S2, REG_S11
 
 	/*
 	 * Save the kernel stack pointer in the thread context
@@ -212,36 +677,38 @@ FUNC __thread_enter_user_mode , :
 
 	/*
 	 * Save kernel stack pointer to ensure that
-	 * thread_exit_user_mode() uses correct stack pointer.
+	 * exception_from_user() uses correct stack pointer.
 	 */
 
 	store_xregs s0, THREAD_CTX_KERN_SP, REG_SP
 	/*
-	 * Save kernel stack pointer in xSCRATCH to ensure that
-	 * thread_trap_vect() uses correct stack pointer.
+	 * Save thread_core_local in xSCRATCH to ensure that thread_trap_vect()
+	 * uses correct core local structure.
 	 */
-	csrw	CSR_XSCRATCH, sp
+	csrw	CSR_XSCRATCH, tp
+
+	/* Move struct thread_ctx_regs *regs to sp to reduce code size */
+	mv	sp, a0
 
+	/* Set exception return PC */
+	load_xregs sp, THREAD_CTX_REG_EPC, REG_S0
+	csrw	CSR_XEPC, s0
 	/* Set user status */
-	load_xregs a0, THREAD_CTX_REG_STATUS, REG_S0
+	load_xregs sp, THREAD_CTX_REG_STATUS, REG_S0
 	csrw	CSR_XSTATUS, s0
-
-	/*
-	 * Save the values for a1 and a2 in struct thread_core_local to be
-	 * restored later just before the xRET.
-	 */
-	store_xregs tp, THREAD_CORE_LOCAL_X10, REG_A1, REG_A2
-
+	/* Set user ie */
+	load_xregs sp, THREAD_CTX_REG_IE, REG_S0
+	csrw	CSR_XIE, s0
 	/* Load the rest of the general purpose registers */
-	load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_TP
-	load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2
-	load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1
-	load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11
-	load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6
-	load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7
-
-	/* Set exception program counter */
-	csrw		CSR_XEPC, ra
+	load_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	load_xregs sp, THREAD_CTX_REG_GP, REG_GP
+	load_xregs sp, THREAD_CTX_REG_TP, REG_TP
+	load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_CTX_REG_SP, REG_SP /* sp must be last one */
 
 	/* Jump into user mode */
 	XRET
@@ -249,16 +716,76 @@ END_FUNC __thread_enter_user_mode
 
 /* void thread_resume(struct thread_ctx_regs *regs) */
 FUNC thread_resume , :
+	/* Move struct thread_ctx_regs *regs to sp to reduce code size */
+	mv	sp, a0
+
+	/* Restore epc */
+	load_xregs sp, THREAD_CTX_REG_EPC, REG_T0
+	csrw	CSR_XEPC, t0
+	/* Restore status */
+	load_xregs sp, THREAD_CTX_REG_STATUS, REG_T0
+	csrw	CSR_XSTATUS, t0
+	/* Restore ie */
+	load_xregs sp, THREAD_CTX_REG_IE, REG_T0
+	csrw	CSR_XIE, t0
+
+	/* Check if previous privilege mode by status.SPP */
+	csrr	t0, CSR_XSTATUS
+	b_if_prev_priv_is_u t0, 1f
+	/* Set scratch as zero to indicate that we are in kernel mode */
+	csrw	CSR_XSCRATCH, zero
+	j	2f
+1:
+	/* Resume to U-mode, set scratch as tp to be used in the trap handler */
+	csrw	CSR_XSCRATCH, tp
+2:
+	/* Restore all general-purpose registers */
+	load_xregs sp, THREAD_CTX_REG_RA, REG_RA
+	load_xregs sp, THREAD_CTX_REG_GP, REG_GP
+	load_xregs sp, THREAD_CTX_REG_TP, REG_TP
+	load_xregs sp, THREAD_CTX_REG_T0, REG_T0, REG_T2
+	load_xregs sp, THREAD_CTX_REG_S0, REG_S0, REG_S1
+	load_xregs sp, THREAD_CTX_REG_A0, REG_A0, REG_A7
+	load_xregs sp, THREAD_CTX_REG_S2, REG_S2, REG_S11
+	load_xregs sp, THREAD_CTX_REG_T3, REG_T3, REG_T6
+	load_xregs sp, THREAD_CTX_REG_SP, REG_SP /* sp must be last one */
+
+	XRET
+END_FUNC thread_resume
+
+/* void thread_foreign_interrupt_handler(struct thread_ctx_regs *regs) */
+FUNC thread_foreign_interrupt_handler , :
+	/* Update 32-bit core local flags */
+	lw	s1, THREAD_CORE_LOCAL_FLAGS(tp)
+	slli	s1, s1, THREAD_CLF_SAVED_SHIFT
+	ori	s1, s1, (THREAD_CLF_TMP | THREAD_CLF_FIQ)
+	sw	s1, THREAD_CORE_LOCAL_FLAGS(tp)
+
 	/*
-	 * Restore all registers assuming that GP
-	 * and TP were not changed.
+	 * Mark current thread as suspended.
+	 * a0 = THREAD_FLAGS_EXIT_ON_FOREIGN_INTR
+	 * a1 = status
+	 * a2 = epc
+	 * thread_state_suspend(flags, status, pc)
 	 */
-	load_xregs a0, THREAD_CTX_REG_RA, REG_RA, REG_SP
-	load_xregs a0, THREAD_CTX_REG_T0, REG_T0, REG_T2
-	load_xregs a0, THREAD_CTX_REG_S0, REG_S0, REG_S1
-	load_xregs a0, THREAD_CTX_REG_S2, REG_S2, REG_S11
-	load_xregs a0, THREAD_CTX_REG_T3, REG_T3, REG_T6
-	load_xregs a0, THREAD_CTX_REG_A0, REG_A0, REG_A7
-	store_xregs tp, THREAD_CORE_LOCAL_X10, REG_A0, REG_A1
-	ret
-END_FUNC thread_resume
+	LDR	a1, THREAD_CTX_REG_STATUS(a0)
+	LDR	a2, THREAD_CTX_REG_EPC(a0)
+	li	a0, THREAD_FLAGS_EXIT_ON_FOREIGN_INTR
+	call	thread_state_suspend
+	/* Now return value a0 contains suspended thread ID. */
+
+	/* Update core local flags */
+	lw	s1, THREAD_CORE_LOCAL_FLAGS(tp)
+	srli	s1, s1, THREAD_CLF_SAVED_SHIFT
+	ori	s1, s1, THREAD_CLF_TMP
+	sw	s1, THREAD_CORE_LOCAL_FLAGS(tp)
+
+	/* Passing thread index in a0, and return to untrusted domain. */
+	mv	a4, a0
+	li	a0, TEEABI_OPTEED_RETURN_CALL_DONE
+	li	a1, OPTEE_ABI_RETURN_RPC_FOREIGN_INTR
+	li	a2, 0
+	li	a3, 0
+	li	a5, 0
+	j	thread_return_to_udomain
+END_FUNC thread_foreign_interrupt_handler
diff --git a/core/arch/riscv/mm/core_mmu_arch.c b/core/arch/riscv/mm/core_mmu_arch.c
index dd6ba4c18fb6e5c73fa67d5674544f0a09b95ab9..a81d153902ea7bfe3a1d783a40cfd76fdaabb5be 100644
--- a/core/arch/riscv/mm/core_mmu_arch.c
+++ b/core/arch/riscv/mm/core_mmu_arch.c
@@ -7,6 +7,7 @@
 #include <bitstring.h>
 #include <config.h>
 #include <kernel/cache_helpers.h>
+#include <kernel/misc.h>
 #include <kernel/panic.h>
 #include <kernel/spinlock.h>
 #include <kernel/tee_l2cc_mutex.h>
@@ -48,7 +49,7 @@ struct mmu_pgt {
 
 #define RISCV_MMU_PGT_SIZE	(sizeof(struct mmu_pgt))
 
-static struct mmu_pgt root_pgt
+static struct mmu_pgt root_pgt[CFG_TEE_CORE_NB_CORE]
 	__aligned(RISCV_PGSIZE)
 	__section(".nozi.mmu.root_pgt");
 
@@ -69,7 +70,7 @@ struct mmu_partition {
 };
 
 static struct mmu_partition default_partition __nex_data  = {
-	.root_pgt = &root_pgt,
+	.root_pgt = root_pgt,
 	.pool_pgts = pool_pgts,
 	.user_pgts = user_pgts,
 	.pgts_used = 0,
@@ -113,20 +114,28 @@ static bool __maybe_unused core_mmu_entry_is_branch(struct mmu_pte *pte)
 	return !core_mmu_entry_is_leaf(pte);
 }
 
-static unsigned long core_mmu_pte_create(unsigned long ppn, uint8_t perm)
+static unsigned long core_mmu_pte_create(unsigned long ppn, uint8_t pte_bits)
 {
-	return SHIFT_U64(ppn, PTE_PPN_SHIFT) | PTE_V | perm;
+	/*
+	 * This function may be called from core_mmu_set_entry(). There is a
+	 * case that MM core wants to clear PTE by calling core_mmu_set_entry()
+	 * with zero physical address and zero memory attributes, which turns
+	 * @ppn and @pte_bits in this function to be both zero. In this case, we
+	 * should create zero PTE without setting its V bit.
+	 */
+
+	return SHIFT_U64(ppn, PTE_PPN_SHIFT) | pte_bits;
 }
 
 static unsigned long core_mmu_ptp_create(unsigned long ppn)
 {
-	/* set perms to 0 since core_mmu_pte_create() already adds PTE_V */
-	return core_mmu_pte_create(ppn, 0);
+	/* Set V bit to create PTE points to next level of the page table. */
+	return core_mmu_pte_create(ppn, PTE_V);
 }
 
 static unsigned long core_mmu_pte_ppn(struct mmu_pte *pte)
 {
-	return pte->entry >> PTE_PPN_SHIFT;
+	return (pte->entry & PTE_PPN) >> PTE_PPN_SHIFT;
 }
 
 static unsigned long pa_to_ppn(paddr_t pa)
@@ -143,9 +152,10 @@ static unsigned long core_mmu_pgt_to_satp(unsigned long asid,
 					  struct mmu_pgt *pgt)
 {
 	unsigned long satp = 0;
-	unsigned long pgt_ppn = virt_to_phys(pgt) >> RISCV_PGSHIFT;
+	unsigned long pgt_ppn = (paddr_t)pgt >> RISCV_PGSHIFT;
+
+	assert(!cpu_mmu_enabled());
 
-	assert(asid & g_asid == asid);
 	satp |= SHIFT_U64(asid, RISCV_SATP_ASID_SHIFT);
 	satp |= SHIFT_U64(RISCV_SATP_MODE, RISCV_SATP_MODE_SHIFT);
 	satp |= pgt_ppn;
@@ -188,35 +198,40 @@ static unsigned long pte_to_mattr(unsigned level __maybe_unused,
 	return mattr;
 }
 
-static uint8_t mattr_to_perms(unsigned level __maybe_unused,
-			      uint32_t attr)
+static uint8_t mattr_to_pte_bits(unsigned level __maybe_unused, uint32_t attr)
 {
-	unsigned long perms = 0;
+	unsigned long pte_bits = 0;
 
 	if (attr & TEE_MATTR_TABLE)
 		return PTE_V;
 
 	if (attr & TEE_MATTR_VALID_BLOCK)
-		perms |= PTE_V;
+		pte_bits |= PTE_V;
 
 	if (attr & TEE_MATTR_UR)
-		perms |= PTE_R | PTE_U;
+		pte_bits |= PTE_R | PTE_U;
 	if (attr & TEE_MATTR_UW)
-		perms |= PTE_W | PTE_U;
+		pte_bits |= PTE_W | PTE_U;
 	if (attr & TEE_MATTR_UX)
-		perms |= PTE_X | PTE_U;
+		pte_bits |= PTE_X | PTE_U;
 
 	if (attr & TEE_MATTR_PR)
-		perms |= PTE_R;
+		pte_bits |= PTE_R;
 	if (attr & TEE_MATTR_PW)
-		perms |= PTE_W | PTE_R;
+		pte_bits |= PTE_W | PTE_R;
 	if (attr & TEE_MATTR_PX)
-		perms |= PTE_X | PTE_R;
+		pte_bits |= PTE_X | PTE_R;
+
+	if (attr & (TEE_MATTR_UR | TEE_MATTR_PR))
+		pte_bits |= PTE_A;
+
+	if (attr & (TEE_MATTR_UW | TEE_MATTR_PW))
+		pte_bits |= PTE_D;
 
 	if (attr & TEE_MATTR_GLOBAL)
-		perms |= PTE_G;
+		pte_bits |= PTE_G;
 
-	return perms;
+	return pte_bits;
 }
 
 static unsigned int core_mmu_pgt_idx(vaddr_t va, unsigned int level)
@@ -233,7 +248,7 @@ static struct mmu_partition *core_mmu_get_prtn(void)
 
 static struct mmu_pgt *core_mmu_get_root_pgt_va(struct mmu_partition *prtn)
 {
-	return prtn->root_pgt;
+	return prtn->root_pgt + get_core_pos();
 }
 
 static struct mmu_pgt *core_mmu_get_ta_pgt_va(struct mmu_partition *prtn)
@@ -274,7 +289,7 @@ static void core_init_mmu_prtn_ta(struct mmu_partition *prtn)
 {
 	unsigned int core = 0;
 
-	assert(user_va_idx != -1);
+	assert(core_mmu_user_va_range_is_defined());
 
 	memset(prtn->user_pgts, 0, CFG_NUM_THREADS * RISCV_MMU_PGT_SIZE);
 	for (core = 0; core < CFG_TEE_CORE_NB_CORE; core++)
@@ -282,17 +297,51 @@ static void core_init_mmu_prtn_ta(struct mmu_partition *prtn)
 }
 
 static void core_init_mmu_prtn_tee(struct mmu_partition *prtn,
-				   struct tee_mmap_region *mm)
+				   struct memory_map *mem_map)
 {
 	size_t n = 0;
 	void *pgt = core_mmu_get_root_pgt_va(prtn);
 
+	/* Clear table before using it. */
+	memset(prtn->root_pgt, 0, RISCV_MMU_PGT_SIZE * CFG_TEE_CORE_NB_CORE);
 	memset(pgt, 0, RISCV_MMU_PGT_SIZE);
 	memset(prtn->pool_pgts, 0, RISCV_MMU_MAX_PGTS * RISCV_MMU_PGT_SIZE);
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++)
-		if (!core_mmu_is_dynamic_vaspace(mm + n))
-			core_mmu_map_region(prtn, mm + n);
+	for (n = 0; n < mem_map->count; n++)
+		if (!core_mmu_is_dynamic_vaspace(mem_map->map + n))
+			core_mmu_map_region(prtn, mem_map->map + n);
+
+	/*
+	 * Primary mapping table is ready at index `get_core_pos()`
+	 * whose value may not be ZERO. Take this index as copy source.
+	 */
+	for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++) {
+		if (n != get_core_pos())
+			memcpy(&prtn->root_pgt[n],
+			       &prtn->root_pgt[get_core_pos()],
+			       RISCV_MMU_PGT_SIZE);
+	}
+}
+
+/*
+ * Given an entry that points to a table.
+ * If mmu is disabled, returns the pa of pointed table.
+ * If mmu is enabled, returns the va of pointed table.
+ * returns NULL otherwise.
+ */
+static struct mmu_pgt *core_mmu_xlat_table_entry_pa2va(struct mmu_pte *pte,
+						       struct mmu_pgt *pgt)
+{
+	if (core_mmu_entry_is_invalid(pte) ||
+	    core_mmu_entry_is_leaf(pte))
+		return NULL;
+
+	if (!cpu_mmu_enabled())
+		return (struct mmu_pgt *)pte_to_pa(pte);
+
+	return phys_to_virt(pte_to_pa(pte),
+			    MEM_AREA_TEE_RAM_RW_DATA,
+			    sizeof(*pgt));
 }
 
 void tlbi_va_range(vaddr_t va, size_t len,
@@ -401,7 +450,7 @@ void asid_free(unsigned int asid)
 	if (asid) {
 		int i = asid - 1;
 
-		assert(i < RISCV_MMU_ASID_WIDTH && bit_test(&g_asid, i));
+		assert(i < RISCV_MMU_ASID_WIDTH && bit_test(g_asid, i));
 		bit_clear(g_asid, i);
 	}
 
@@ -410,12 +459,14 @@ void asid_free(unsigned int asid)
 
 bool arch_va2pa_helper(void *va, paddr_t *pa)
 {
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
 	vaddr_t vaddr = (vaddr_t)va;
 	struct mmu_pgt *pgt = NULL;
 	struct mmu_pte *pte = NULL;
 	int level = 0;
 	unsigned int idx = 0;
 	struct mmu_partition *prtn = core_mmu_get_prtn();
+	vaddr_t offset_mask = 0;
 
 	assert(pa);
 
@@ -426,17 +477,19 @@ bool arch_va2pa_helper(void *va, paddr_t *pa)
 		pte = core_mmu_table_get_entry(pgt, idx);
 
 		if (core_mmu_entry_is_invalid(pte)) {
+			thread_unmask_exceptions(exceptions);
 			return false;
 		} else if (core_mmu_entry_is_leaf(pte)) {
-			*pa = pte_to_pa(pte) |
-			      (vaddr & (BIT64(RISCV_PGSHIFT) - 1));
+			offset_mask = CORE_MMU_PAGE_OFFSET_MASK(level);
+			*pa = pte_to_pa(pte) | (vaddr & offset_mask);
+			thread_unmask_exceptions(exceptions);
 			return true;
 		}
 
-		pgt = phys_to_virt(pte_to_pa(pte),
-				   MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt));
+		pgt = core_mmu_xlat_table_entry_pa2va(pte, pgt);
 	}
 
+	thread_unmask_exceptions(exceptions);
 	return false;
 }
 
@@ -449,6 +502,7 @@ bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va,
 			 unsigned int max_level,
 			 struct core_mmu_table_info *tbl_info)
 {
+	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
 	struct mmu_pgt *pgt = NULL;
 	struct mmu_pte *pte = NULL;
 	unsigned int level = CORE_MMU_BASE_TABLE_LEVEL;
@@ -475,14 +529,14 @@ bool core_mmu_find_table(struct mmu_partition *prtn, vaddr_t va,
 			ret = true;
 			goto out;
 		}
-		pgt = phys_to_virt(pte_to_pa(pte),
-				   MEM_AREA_TEE_RAM_RW_DATA, sizeof(*pgt));
+		pgt = core_mmu_xlat_table_entry_pa2va(pte, pgt);
 		if (!pgt)
 			goto out;
 		va_base += SHIFT_U64(idx, CORE_MMU_SHIFT_OF_LEVEL(level));
 		level--;
 	}
 out:
+	thread_unmask_exceptions(exceptions);
 	return ret;
 }
 
@@ -493,6 +547,7 @@ bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info,
 	struct mmu_pte *pte = NULL;
 	struct mmu_partition *prtn = core_mmu_get_prtn();
 	unsigned long ptp = 0;
+	paddr_t pgt_pa = 0;
 
 	if (!core_mmu_level_in_range(tbl_info->level))
 		return false;
@@ -505,7 +560,12 @@ bool core_mmu_entry_to_finer_grained(struct core_mmu_table_info *tbl_info,
 		if (!pgt)
 			return false;
 
-		ptp = core_mmu_ptp_create(pa_to_ppn((paddr_t)pgt));
+		if (cpu_mmu_enabled())
+			pgt_pa = virt_to_phys(pgt);
+		else
+			pgt_pa = (paddr_t)pgt;
+
+		ptp = core_mmu_ptp_create(pa_to_ppn(pgt_pa));
 		core_mmu_entry_set(pte, ptp);
 	}
 
@@ -548,9 +608,9 @@ void core_mmu_set_entry_primitive(void *table, size_t level, size_t idx,
 {
 	struct mmu_pgt *pgt = (struct mmu_pgt *)table;
 	struct mmu_pte *pte = core_mmu_table_get_entry(pgt, idx);
-	uint8_t perms = mattr_to_perms(level, attr);
+	uint8_t pte_bits = mattr_to_pte_bits(level, attr);
 
-	core_mmu_entry_set(pte, core_mmu_pte_create(pa_to_ppn(pa), perms));
+	core_mmu_entry_set(pte, core_mmu_pte_create(pa_to_ppn(pa), pte_bits));
 }
 
 static void set_user_va_idx(struct mmu_partition *prtn)
@@ -577,7 +637,7 @@ core_mmu_get_user_mapping_entry(struct mmu_partition *prtn)
 {
 	struct mmu_pgt *pgt = core_mmu_get_root_pgt_va(prtn);
 
-	assert(user_va_idx != -1);
+	assert(core_mmu_user_va_range_is_defined());
 
 	return core_mmu_table_get_entry(pgt, user_va_idx);
 }
@@ -609,9 +669,14 @@ void core_mmu_set_user_map(struct core_mmu_user_map *map)
 	thread_unmask_exceptions(exceptions);
 }
 
+bool core_mmu_user_va_range_is_defined(void)
+{
+	return user_va_idx != -1;
+}
+
 void core_mmu_get_user_va_range(vaddr_t *base, size_t *size)
 {
-	assert(user_va_idx != -1);
+	assert(core_mmu_user_va_range_is_defined());
 
 	if (base)
 		*base = SHIFT_U64(user_va_idx, CORE_MMU_BASE_TABLE_SHIFT);
@@ -672,13 +737,13 @@ bool core_mmu_user_mapping_is_active(void)
 	return ret;
 }
 
-void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm)
+void core_init_mmu_prtn(struct mmu_partition *prtn, struct memory_map *mem_map)
 {
-	core_init_mmu_prtn_tee(prtn, mm);
+	core_init_mmu_prtn_tee(prtn, mem_map);
 	core_init_mmu_prtn_ta(prtn);
 }
 
-void core_init_mmu(struct tee_mmap_region *mm)
+void core_init_mmu(struct memory_map *mem_map)
 {
 	uint64_t max_va = 0;
 	size_t n = 0;
@@ -687,10 +752,10 @@ void core_init_mmu(struct tee_mmap_region *mm)
 			    sizeof(pool_pgts));
 
 	/* Initialize default pagetables */
-	core_init_mmu_prtn_tee(&default_partition, mm);
+	core_init_mmu_prtn_tee(&default_partition, mem_map);
 
-	for (n = 0; !core_mmap_is_end_of_table(mm + n); n++) {
-		vaddr_t va_end = mm[n].va + mm[n].size - 1;
+	for (n = 0; n < mem_map->count; n++) {
+		vaddr_t va_end = mem_map->map[n].va + mem_map->map[n].size - 1;
 
 		if (va_end > max_va)
 			max_va = va_end;
@@ -705,10 +770,11 @@ void core_init_mmu(struct tee_mmap_region *mm)
 
 void core_init_mmu_regs(struct core_mmu_config *cfg)
 {
-	struct mmu_partition *prtn = core_mmu_get_prtn();
+	struct mmu_partition *p = core_mmu_get_prtn();
+	unsigned int n = 0;
 
-	cfg->satp = core_mmu_pgt_to_satp(prtn->asid,
-					 core_mmu_get_root_pgt_va(prtn));
+	for (n = 0; n < CFG_TEE_CORE_NB_CORE; n++)
+		cfg->satp[n] = core_mmu_pgt_to_satp(p->asid, p->root_pgt + n);
 }
 
 enum core_mmu_fault core_mmu_get_fault_type(uint32_t fault_descr)
diff --git a/core/arch/riscv/plat-spike/main.c b/core/arch/riscv/plat-spike/main.c
index 40de072ac01fe1afe54c74dad9666711f3b6c4d9..b1dedf76cb0ecdcaf41f99837f51a3a365437f17 100644
--- a/core/arch/riscv/plat-spike/main.c
+++ b/core/arch/riscv/plat-spike/main.c
@@ -13,7 +13,7 @@
 #ifdef CFG_RISCV_M_MODE
 static struct htif_console_data console_data __nex_bss;
 
-void console_init(void)
+void plat_console_init(void)
 {
 #ifdef HTIF_BASE
 	htif_console_init(&console_data, HTIF_BASE);
diff --git a/core/arch/riscv/plat-spike/platform_config.h b/core/arch/riscv/plat-spike/platform_config.h
index 7a3ff4305aabff3502cd410983693434fd7e7a31..528dad5e4833fb20fbf9876ca77b3dfb512398ba 100644
--- a/core/arch/riscv/plat-spike/platform_config.h
+++ b/core/arch/riscv/plat-spike/platform_config.h
@@ -9,6 +9,7 @@
 #define PLATFORM_CONFIG_H
 
 #include <mm/generic_ram_layout.h>
+#include <riscv.h>
 
 #ifndef HTIF_BASE
 #define HTIF_BASE	0x40008000
@@ -19,4 +20,7 @@
 #define CLINT_BASE	0x02000000
 #endif
 
+#define PLAT_THREAD_EXCP_FOREIGN_INTR	(CSR_XIE_EIE)
+#define PLAT_THREAD_EXCP_NATIVE_INTR	(CSR_XIE_SIE | CSR_XIE_TIE)
+
 #endif
diff --git a/core/arch/riscv/plat-virt/conf.mk b/core/arch/riscv/plat-virt/conf.mk
index 15bc09267947a4ad84f40dc2ad144c2c46d58518..9b6048b144fa6afbbb66e7e76c27ee43954304c0 100644
--- a/core/arch/riscv/plat-virt/conf.mk
+++ b/core/arch/riscv/plat-virt/conf.mk
@@ -1,13 +1,20 @@
 $(call force,CFG_RV64_core,y)
 
+# ISA extension flags
+$(call force,CFG_RISCV_ISA_C,y)
+$(call force,CFG_RISCV_FPU,y)
+
 $(call force,CFG_CORE_LARGE_PHYS_ADDR,y)
-$(call force,CFG_TEE_CORE_DEBUG,n)
-$(call force,CFG_CORE_DYN_SHM,n)
+$(call force,CFG_CORE_RESERVED_SHM,n)
+$(call force,CFG_CORE_DYN_SHM,y)
 
 CFG_DT ?= y
 
 # Crypto flags
-$(call force,CFG_WITH_SOFTWARE_PRNG,y)
+$(call force,CFG_WITH_SOFTWARE_PRNG,n)
+$(call force,CFG_HWRNG_PTA,y)
+$(call force,CFG_HWRNG_QUALITY,1024)
+$(call force,CFG_RISCV_ZKR_RNG,y)
 
 # Protection flags
 $(call force,CFG_CORE_ASLR,n)
@@ -17,10 +24,7 @@ $(call force,CFG_CORE_SANITIZE_KADDRESS,n)
 # Hart-related flags
 CFG_TEE_CORE_NB_CORE ?= 1
 CFG_NUM_THREADS ?= 1
-$(call force,CFG_BOOT_SYNC_CPU,y)
-
-# RISC-V-specific flags
-rv64-platform-isa ?= rv64imafdc_zicsr_zifencei
+$(call force,CFG_BOOT_SYNC_CPU,n)
 
 $(call force,CFG_RISCV_M_MODE,n)
 $(call force,CFG_RISCV_S_MODE,y)
@@ -30,6 +34,7 @@ $(call force,CFG_16550_UART,y)
 $(call force,CFG_RISCV_TIME_SOURCE_RDTIME,y)
 CFG_RISCV_MTIME_RATE ?= 10000000
 CFG_RISCV_SBI ?= y
+CFG_RISCV_WITH_M_MODE_SM ?= y
 
 # TA-related flags
 supported-ta-targets = ta_rv64
@@ -37,7 +42,4 @@ supported-ta-targets = ta_rv64
 # Memory layout flags
 CFG_TDDRAM_START ?= 0x8e000000
 CFG_TDDRAM_SIZE  ?= 0x00f00000
-$(call force,CFG_CORE_RESERVED_SHM,y)
-CFG_SHMEM_START  ?= 0x88f00000
-CFG_SHMEM_SIZE   ?= 0x00200000
 CFG_TEE_RAM_VA_SIZE ?= 0x00200000
diff --git a/core/arch/riscv/plat-virt/main.c b/core/arch/riscv/plat-virt/main.c
index edfbf4caaac18d55aea178eef6c38a9b19f95cf2..f6f6120d13d9a42647e5a7a0e82b65d90a86bace 100644
--- a/core/arch/riscv/plat-virt/main.c
+++ b/core/arch/riscv/plat-virt/main.c
@@ -29,7 +29,7 @@ void boot_secondary_init_intc(void)
 }
 #endif /* CFG_RISCV_PLIC */
 
-void console_init(void)
+void plat_console_init(void)
 {
 	ns16550_init(&console_data, UART0_BASE, IO_WIDTH_U8, 0);
 	register_serial_console(&console_data.chip);
diff --git a/core/arch/riscv/plat-virt/platform_config.h b/core/arch/riscv/plat-virt/platform_config.h
index 064cca29cf2601321aa271fe87c83b2a78e494e0..6c37ef204d2d0085a9d391c9e66aaa99889bf14b 100644
--- a/core/arch/riscv/plat-virt/platform_config.h
+++ b/core/arch/riscv/plat-virt/platform_config.h
@@ -9,6 +9,7 @@
 #define PLATFORM_CONFIG_H
 
 #include <mm/generic_ram_layout.h>
+#include <riscv.h>
 
 /* The stack pointer is always kept 16-byte aligned */
 #define STACK_ALIGNMENT		16
@@ -92,4 +93,8 @@
 #define RISCV_MTIME_RATE 1000000
 #endif
 
+#define PLAT_THREAD_EXCP_FOREIGN_INTR	\
+	(CSR_XIE_EIE | CSR_XIE_TIE | CSR_XIE_SIE)
+#define PLAT_THREAD_EXCP_NATIVE_INTR	(0)
+
 #endif /*PLATFORM_CONFIG_H*/
diff --git a/core/arch/riscv/riscv.mk b/core/arch/riscv/riscv.mk
index d9765c9a111df069358bdaeeb1b49d73bf8dc52b..db879e59a08ffe7e8964306c75dfced844d3363d 100644
--- a/core/arch/riscv/riscv.mk
+++ b/core/arch/riscv/riscv.mk
@@ -63,6 +63,13 @@ ifeq ($(CFG_RISCV_SBI_CONSOLE),y)
 $(call force,CFG_RISCV_SBI,y)
 endif
 
+# 'y' to let M-mode secure monitor handle the communication between OP-TEE OS
+# and untrusted domain.
+CFG_RISCV_WITH_M_MODE_SM ?= n
+ifeq ($(CFG_RISCV_WITH_M_MODE_SM),y)
+$(call force,CFG_RISCV_SBI,y)
+endif
+
 # Disable unsupported and other arch-specific flags
 $(call force,CFG_CORE_FFA,n)
 $(call force,CFG_SECURE_PARTITION,n)
@@ -74,29 +81,48 @@ $(call force,CFG_WITH_VFP,n)
 $(call force,CFG_WITH_STMM_SP,n)
 $(call force,CFG_TA_BTI,n)
 
+# Enable generic timer
+$(call force,CFG_CORE_HAS_GENERIC_TIMER,y)
+
 core-platform-cppflags	+= -I$(arch-dir)/include
 core-platform-subdirs += \
 	$(addprefix $(arch-dir)/, kernel mm tee) $(platform-dir)
 
-# Default values for "-mcmodel", "-march", and "-abi" compiler flags.
-# Platform-specific overrides are in core/arch/riscv/plat-*/conf.mk.
+# Default values for "-mcmodel" compiler flag
 riscv-platform-mcmodel ?= medany
-rv64-platform-isa ?= rv64imafd
-rv64-platform-abi ?= lp64d
-rv32-platform-isa ?= rv32imafd
-rv32-platform-abi ?= ilp32d
+
+ifeq ($(CFG_RV64_core),y)
+ISA_BASE = rv64ima
+ABI_BASE = lp64
+else
+ISA_BASE = rv32ima
+ABI_BASE = ilp32
+endif
+ifeq ($(CFG_RISCV_FPU),y)
+ISA_D = fd
+ABI_D = d
+endif
+ifeq ($(CFG_RISCV_ISA_C),y)
+ISA_C = c
+endif
+ifeq ($(CFG_RISCV_ISA_ZBB),y)
+ISA_ZBB = _zbb
+endif
+
+riscv-isa = $(ISA_BASE)$(ISA_D)$(ISA_C)$(ISA_ZBB)_zicsr_zifencei
+riscv-abi = $(ABI_BASE)$(ABI_D)
 
 rv64-platform-cflags += -mcmodel=$(riscv-platform-mcmodel)
-rv64-platform-cflags += -march=$(rv64-platform-isa) -mabi=$(rv64-platform-abi)
+rv64-platform-cflags += -march=$(riscv-isa) -mabi=$(riscv-abi)
 rv64-platform-cflags += -Wno-missing-include-dirs
 rv32-platform-cflags += -mcmodel=$(riscv-platform-mcmodel)
-rv32-platform-cflags += -march=$(rv32-platform-isa) -mabi=$(rv32-platform-abi)
+rv32-platform-cflags += -march=$(riscv-isa) -mabi=$(riscv-abi)
 
 rv64-platform-cppflags += -DRV64=1 -D__LP64__=1
 rv32-platform-cppflags += -DRV32=1 -D__ILP32__=1
 
 platform-cflags-generic ?= -ffunction-sections -fdata-sections -pipe
-platform-aflags-generic ?= -pipe
+platform-aflags-generic ?= -pipe -march=$(riscv-isa) -mabi=$(riscv-abi)
 
 rv64-platform-cflags-generic := -mstrict-align $(call cc-option,)
 
diff --git a/core/arch/riscv/tee/entry_fast.c b/core/arch/riscv/tee/entry_fast.c
index 99faa15f09e099871cb5bcedef06c4ceec2aa2c5..4d194f2da473d3975495da73a6130651f616fe07 100644
--- a/core/arch/riscv/tee/entry_fast.c
+++ b/core/arch/riscv/tee/entry_fast.c
@@ -247,7 +247,7 @@ void __tee_entry_fast(struct thread_abi_args *args)
 
 	case OPTEE_ABI_ENABLE_ASYNC_NOTIF:
 		if (IS_ENABLED(CFG_CORE_ASYNC_NOTIF)) {
-			notif_deliver_atomic_event(NOTIF_EVENT_STARTED);
+			notif_deliver_atomic_event(NOTIF_EVENT_STARTED, 0);
 			args->a0 = OPTEE_ABI_RETURN_OK;
 		} else {
 			args->a0 = OPTEE_ABI_RETURN_UNKNOWN_FUNCTION;
diff --git a/core/core.mk b/core/core.mk
index 71c4699860a6d19a213b051defc760320f06aea4..f085d20b15c150adf80afa3d6f4099f29533059f 100644
--- a/core/core.mk
+++ b/core/core.mk
@@ -11,6 +11,17 @@ include mk/config.mk
 # $(ARCH).mk also sets the compiler for the core module
 include core/arch/$(ARCH)/$(ARCH).mk
 
+ifeq ($(CFG_OS_REV_REPORTS_GIT_SHA1),y)
+ifeq ($(arch-bits-core),64)
+git-sha1-len := 16
+else
+git-sha1-len := 8
+endif
+TEE_IMPL_GIT_SHA1 := 0x$(shell git rev-parse --short=$(git-sha1-len) HEAD 2>/dev/null || echo 0 | cut -c -$(git-sha1-len))
+else
+TEE_IMPL_GIT_SHA1 := 0x0
+endif
+
 PLATFORM_$(PLATFORM) := y
 PLATFORM_FLAVOR_$(PLATFORM_FLAVOR) := y
 
@@ -163,6 +174,12 @@ libdir = core/lib/scmi-server
 include mk/lib.mk
 endif
 
+ifeq ($(CFG_QCBOR),y)
+libname = qcbor
+libdir = core/lib/qcbor
+include mk/lib.mk
+endif
+
 #
 # Do main source
 #
diff --git a/core/crypto.mk b/core/crypto.mk
index ac651eeb94a70cfb3f7ff8c5bfc248717c25793e..f19e97c7626c19ed4dfda1ea31c3101fd8f07d5b 100644
--- a/core/crypto.mk
+++ b/core/crypto.mk
@@ -79,6 +79,13 @@ endif
 # Otherwise, you need to implement hw_get_random_bytes() for your platform
 CFG_WITH_SOFTWARE_PRNG ?= y
 
+# Define the maximum size, in bits, for big numbers in the TEE core (privileged
+# layer).
+# This value is an upper limit for the key size in any cryptographic algorithm
+# implemented by the TEE core.
+# Set this to a lower value to reduce the memory footprint.
+CFG_CORE_BIGNUM_MAX_BITS ?= 4096
+
 ifeq ($(CFG_WITH_PAGER),y)
 ifneq ($(CFG_CRYPTO_SHA256),y)
 $(warning Warning: Enabling CFG_CRYPTO_SHA256 [required by CFG_WITH_PAGER])
@@ -288,9 +295,6 @@ _CFG_CORE_LTC_HWSUPP_PMULL := $(CFG_HWSUPP_PMULL)
 # Assign aggregated variables
 ltc-one-enabled = $(call cfg-one-enabled,$(foreach v,$(1),_CFG_CORE_LTC_$(v)))
 _CFG_CORE_LTC_ACIPHER := $(call ltc-one-enabled, RSA DSA DH ECC)
-_CFG_CORE_LTC_AUTHENC := $(and $(filter y,$(_CFG_CORE_LTC_AES_DESC)), \
-			       $(filter y,$(call ltc-one-enabled, CCM GCM)))
-_CFG_CORE_LTC_CIPHER := $(call ltc-one-enabled, AES_DESC DES)
 _CFG_CORE_LTC_HASH := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \
 					      SHA512 SHA3_224 SHA3_256 \
 					      SHA3_384 SHA3_512)
@@ -300,7 +304,6 @@ _CFG_CORE_LTC_HMAC := $(call ltc-one-enabled, MD5 SHA1 SHA224 SHA256 SHA384 \
 					      SHA3_384 SHA3_512)
 endif
 
-_CFG_CORE_LTC_MAC := $(call ltc-one-enabled, HMAC CMAC CBC_MAC)
 _CFG_CORE_LTC_CBC := $(call ltc-one-enabled, CBC CBC_MAC)
 _CFG_CORE_LTC_ASN1 := $(call ltc-one-enabled, RSA DSA ECC)
 _CFG_CORE_LTC_EC25519 := $(call ltc-one-enabled, ED25519 X25519)
diff --git a/core/crypto/aes-gcm-ghash-tbl.c b/core/crypto/aes-gcm-ghash-tbl.c
index 000ab00a200a1a300eecdf10eeabdbc69075f8d9..47fd61fcbdb0af60f094db4bcc914b3934ca84f6 100644
--- a/core/crypto/aes-gcm-ghash-tbl.c
+++ b/core/crypto/aes-gcm-ghash-tbl.c
@@ -22,7 +22,6 @@
 #include <crypto/crypto.h>
 #include <crypto/internal_aes-gcm.h>
 #include <io.h>
-#include <kernel/panic.h>
 #include <string.h>
 #include <tee_api_types.h>
 #include <types_ext.h>
diff --git a/core/crypto/aes-gcm.c b/core/crypto/aes-gcm.c
index 423b6f332789a8730028149e29271e220ee64cfa..c16c138dc3da7984641d1d546e35ae4c24801570 100644
--- a/core/crypto/aes-gcm.c
+++ b/core/crypto/aes-gcm.c
@@ -346,25 +346,23 @@ TEE_Result internal_aes_gcm_dec_final(struct internal_aes_gcm_ctx *ctx,
 void internal_aes_gcm_inc_ctr(struct internal_aes_gcm_state *state)
 {
 	uint64_t c = 0;
+	uint32_t lower = 0;
 
-	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) + 1;
+	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]);
+	lower = c + 1;
+	c = (c & GENMASK_64(63, 32)) | lower;
 	state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c);
-	if (!c) {
-		c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) + 1;
-		state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c);
-	}
 }
 
 void internal_aes_gcm_dec_ctr(struct internal_aes_gcm_state *state)
 {
 	uint64_t c = 0;
+	uint32_t lower = 0;
 
-	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]) - 1;
+	c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[1]);
+	lower = c - 1;
+	c = (c & GENMASK_64(63, 32)) | lower;
 	state->ctr[1] = TEE_U64_TO_BIG_ENDIAN(c);
-	if (c == UINT64_MAX) {
-		c = TEE_U64_FROM_BIG_ENDIAN(state->ctr[0]) - 1;
-		state->ctr[0] = TEE_U64_TO_BIG_ENDIAN(c);
-	}
 }
 
 TEE_Result internal_aes_gcm_enc(const struct internal_aes_gcm_key *enc_key,
diff --git a/core/crypto/crypto.c b/core/crypto/crypto.c
index 5b16ad4743501620f3466894c6396954317c1cae..25af198a46993f4604582584e5aceba59b33a5ce 100644
--- a/core/crypto/crypto.c
+++ b/core/crypto/crypto.c
@@ -11,7 +11,6 @@
 #include <crypto/crypto_impl.h>
 #include <kernel/panic.h>
 #include <stdlib.h>
-#include <string.h>
 #include <utee_defines.h>
 
 TEE_Result crypto_hash_alloc_ctx(void **ctx, uint32_t algo)
@@ -598,6 +597,7 @@ TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo __unused,
 					struct rsa_keypair *key __unused,
 					const uint8_t *label __unused,
 					size_t label_len __unused,
+					uint32_t mgf_algo __unused,
 					const uint8_t *src __unused,
 					size_t src_len __unused,
 					uint8_t *dst __unused,
@@ -610,6 +610,7 @@ TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo __unused,
 					struct rsa_public_key *key __unused,
 					const uint8_t *label __unused,
 					size_t label_len __unused,
+					uint32_t mgf_algo __unused,
 					const uint8_t *src __unused,
 					size_t src_len __unused,
 					uint8_t *dst __unused,
diff --git a/core/crypto/signed_hdr.c b/core/crypto/signed_hdr.c
index 40c29976c1f5dd2b7be1729135628987bf8185ca..c37a731bf144b34d85f93d7bd00a93411d303420 100644
--- a/core/crypto/signed_hdr.c
+++ b/core/crypto/signed_hdr.c
@@ -29,7 +29,7 @@ struct shdr *shdr_alloc_and_copy(size_t offs, const void *img, size_t img_size)
 		return NULL;
 
 	shdr_size = SHDR_GET_SIZE((const struct shdr *)(img_va + offs));
-	if (ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
+	if (!shdr_size || ADD_OVERFLOW(offs, shdr_size, &end) || end > img_size)
 		return NULL;
 
 	if (ADD_OVERFLOW(img_va, shdr_size, &tmp))
diff --git a/core/crypto/sm3-hmac.c b/core/crypto/sm3-hmac.c
index abe2ac8db767576e89531c99c7c67d4fd95bd4be..0b69d9908c69b10ba89e2a221ef924d51895b957 100644
--- a/core/crypto/sm3-hmac.c
+++ b/core/crypto/sm3-hmac.c
@@ -8,7 +8,6 @@
 #include <compiler.h>
 #include <crypto/crypto.h>
 #include <crypto/crypto_impl.h>
-#include <kernel/panic.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string_ext.h>
diff --git a/core/drivers/atmel_piobu.c b/core/drivers/atmel_piobu.c
index df06620a616ca521fd0ab859174012d0ea5df002..8d4c1dcf396b63a75a20ca6a9f2dff876e13601e 100644
--- a/core/drivers/atmel_piobu.c
+++ b/core/drivers/atmel_piobu.c
@@ -18,7 +18,7 @@
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 
-#define SECUMOD_MAX_PINS		8
+#define SECUMOD_MAX_PINS		(piobu_device->compat->max_pins)
 #define SECUMOD_PIN_MASK		(BIT(SECUMOD_MAX_PINS) - 1)
 #define SECUMOD_PIN_SHIFT		16
 #define SECUMOD_PIN_VAL(pin)		BIT(SECUMOD_PIN_SHIFT + (pin))
@@ -46,15 +46,39 @@
 #define SECUMOD_PIOBU_PULLUP_SHIFT	12
 #define SECUMOD_PIOBU_SWITCH_SHIFT	15
 
-#define SECUMOD_JTAGCR			0x68
 #define SECUMOD_JTAGCR_FNTRST		0x1
 
-#define SECUMOD_BMPR			0x7C
-#define SECUMOD_NMPR			0x80
-#define SECUMOD_NIEPR			0x84
-#define SECUMOD_NIDPR			0x88
-#define SECUMOD_NIMPR			0x8C
-#define SECUMOD_WKPR			0x90
+/*
+ * PIOBU instance data
+ * @compat - Reference to compat data passed at driver initialization
+ */
+struct piobu_instance {
+	struct piobu_compat *compat;
+};
+
+/*
+ * @max_pins	the number of the tamper I/Os
+ * @of_jtagcr	offset of SECUMOD JTAG Protection Control Register
+ * @of_bmpr	offset of SECUMOD Backup Mode Protection Register
+ * @of_nmpr	offset of SECUMOD Normal Mode Protection Register
+ * @of_niepr	offset of SECUMOD Normal Interrupt Enable Protection Register
+ * @of_nidpr	offset of SECUMOD Normal Interrupt Disable Protection Register
+ * @of_nimpr	offset of SECUMOD Normal Interrupt Mask Protection Register
+ * @of_wkpr	offset of SECUMOD Wake-up Register
+ */
+struct piobu_compat {
+	uint8_t max_pins;
+	uint8_t of_jtagcr;
+	uint8_t of_bmpr;
+	uint8_t of_nmpr;
+	uint8_t of_niepr;
+	uint8_t of_nidpr;
+	uint8_t of_nimpr;
+	uint8_t of_wkpr;
+};
+
+/* Expects at most a single instance */
+static struct piobu_instance *piobu_device;
 
 static vaddr_t secumod_base;
 static uint32_t gpio_protected;
@@ -161,7 +185,7 @@ static enum gpio_interrupt
 secumod_gpio_get_interrupt(struct gpio_chip *chip __unused,
 			   unsigned int gpio_pin)
 {
-	vaddr_t nimpr_addr = secumod_base + SECUMOD_NIMPR;
+	vaddr_t nimpr_addr = secumod_base + piobu_device->compat->of_nimpr;
 	uint32_t data = 0;
 
 	assert(gpio_pin < SECUMOD_MAX_PINS &&
@@ -185,7 +209,7 @@ static void secumod_gpio_set_interrupt(struct gpio_chip *chip __unused,
 				       unsigned int gpio_pin,
 				       enum gpio_interrupt interrupt)
 {
-	vaddr_t niepr_addr = secumod_base + SECUMOD_NIEPR;
+	vaddr_t niepr_addr = secumod_base + piobu_device->compat->of_niepr;
 
 	assert(gpio_pin < SECUMOD_MAX_PINS &&
 	       !(gpio_protected & BIT32(gpio_pin)));
@@ -309,11 +333,12 @@ static void secumod_cfg_input_pio(uint8_t gpio_pin, uint32_t config)
 				   GPIO_INTERRUPT_ENABLE);
 
 	/* Enable Intrusion Detection */
-	io_setbits32(secumod_base + SECUMOD_NMPR, SECUMOD_PIN_VAL(gpio_pin));
+	io_setbits32(secumod_base + piobu_device->compat->of_nmpr,
+		     SECUMOD_PIN_VAL(gpio_pin));
 
 	/* Enable Wakeup */
 	if (PIOBU_PIN_WAKEUP(config))
-		io_setbits32(secumod_base + SECUMOD_WKPR,
+		io_setbits32(secumod_base + piobu_device->compat->of_wkpr,
 			     SECUMOD_PIN_VAL(gpio_pin));
 
 	gpio_protected |= BIT32(gpio_pin);
@@ -328,14 +353,15 @@ static void secumod_hw_init(const void *fdt, int node)
 	const uint32_t *prop = NULL;
 
 	/* Disable JTAG Reset and Debug */
-	io_write32(secumod_base + SECUMOD_JTAGCR, SECUMOD_JTAGCR_FNTRST);
+	io_write32(secumod_base + piobu_device->compat->of_jtagcr,
+		   SECUMOD_JTAGCR_FNTRST);
 
 	/* Switch IOs to normal mode */
 	io_write32(secumod_base + SECUMOD_CR, SECUMOD_CR_KEY |
 		   SECUMOD_CR_NORMAL);
 
 	/* Clear all detection intrusion in normal mode */
-	io_write32(secumod_base + SECUMOD_NMPR, 0);
+	io_write32(secumod_base + piobu_device->compat->of_nmpr, 0);
 
 	/* Clear Alarms */
 	io_write32(secumod_base + SECUMOD_SCR,
@@ -385,13 +411,19 @@ static void piobu_register_pm(void) {}
 #endif
 
 static TEE_Result atmel_secumod_probe(const void *fdt, int node,
-				      const void *compat_data __unused)
+				      const void *compat_data)
 {
 	size_t size = 0;
 
 	if (secumod_base)
 		return TEE_ERROR_GENERIC;
 
+	piobu_device = calloc(1, sizeof(*piobu_device));
+	if (!piobu_device)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	piobu_device->compat = (struct piobu_compat *)compat_data;
+
 	if (dt_map_dev(fdt, node, &secumod_base, &size, DT_MAP_AUTO) < 0)
 		return TEE_ERROR_GENERIC;
 
@@ -407,8 +439,37 @@ static TEE_Result atmel_secumod_probe(const void *fdt, int node,
 	return gpio_register_provider(fdt, node, secumod_dt_get, &secumod_chip);
 }
 
+static const struct piobu_compat sama5d2_compat = {
+	.max_pins = 8,
+	.of_jtagcr = 0x68,
+	.of_bmpr = 0x7C,
+	.of_nmpr = 0x80,
+	.of_niepr = 0x84,
+	.of_nidpr = 0x88,
+	.of_nimpr = 0x8C,
+	.of_wkpr = 0x90,
+};
+
+static const struct piobu_compat sama7g54_compat = {
+	.max_pins = 4,
+	.of_jtagcr = 0x70,
+	.of_bmpr = 0x84,
+	.of_nmpr = 0x88,
+	.of_niepr = 0x8C,
+	.of_nidpr = 0x90,
+	.of_nimpr = 0x94,
+	.of_wkpr = 0x98,
+};
+
 static const struct dt_device_match atmel_secumod_match_table[] = {
-	{ .compatible = "atmel,sama5d2-secumod" },
+	{
+		.compatible = "atmel,sama5d2-secumod",
+		.compat_data = &sama5d2_compat,
+	},
+	{
+		.compatible = "microchip,sama7g5-secumod",
+		.compat_data = &sama7g54_compat,
+	},
 	{ }
 };
 
diff --git a/core/drivers/atmel_rstc.c b/core/drivers/atmel_rstc.c
index 5fb81d450fbca2fb1beb4554502cf7801b01d1b0..9e99b519303ca16612e6e5922941edcdd7be38bc 100644
--- a/core/drivers/atmel_rstc.c
+++ b/core/drivers/atmel_rstc.c
@@ -4,11 +4,15 @@
  */
 
 #include <drivers/atmel_rstc.h>
+#include <drivers/rstctrl.h>
 #include <io.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
+#include <malloc.h>
 #include <matrix.h>
-#include <sama5d2.h>
+#include <platform_config.h>
+#include <stdbool.h>
+#include <sys/queue.h>
 #include <tee_api_defines.h>
 #include <tee_api_types.h>
 #include <types_ext.h>
@@ -18,8 +22,124 @@
 #define AT91_RSTC_CR_PROCRST	BIT32(0)
 #define AT91_RSTC_CR_PERRST	BIT32(2)
 
+#define AT91_RSTC_GRSTR		0xE4
+#define AT91_RSTC_GRSTR_USB(x)	SHIFT_U32(1, 4 + (x))
+
 static vaddr_t rstc_base;
 
+struct sam_reset_data {
+	bool rstc_always_secure;
+	const struct rstctrl_ops *ops;
+};
+
+struct sam_rstline {
+	unsigned int reset_id;
+	struct rstctrl rstctrl;
+	SLIST_ENTRY(sam_rstline) link;
+};
+
+static SLIST_HEAD(, sam_rstline) sam_rst_list =
+	SLIST_HEAD_INITIALIZER(sam_rst_list);
+
+static struct sam_rstline *to_sam_rstline(struct rstctrl *ptr)
+{
+	assert(ptr);
+
+	return container_of(ptr, struct sam_rstline, rstctrl);
+}
+
+static struct sam_rstline *find_rstline(unsigned int reset_id)
+{
+	struct sam_rstline *sam_rstline = NULL;
+
+	SLIST_FOREACH(sam_rstline, &sam_rst_list, link)
+		if (sam_rstline->reset_id == reset_id)
+			break;
+
+	return sam_rstline;
+}
+
+static struct
+sam_rstline *find_or_allocate_rstline(unsigned int reset_id,
+				      const struct sam_reset_data *pdata)
+{
+	struct sam_rstline *sam_rstline = find_rstline(reset_id);
+
+	if (sam_rstline)
+		return sam_rstline;
+
+	sam_rstline = calloc(1, sizeof(*sam_rstline));
+	if (sam_rstline) {
+		sam_rstline->reset_id = reset_id;
+		sam_rstline->rstctrl.ops = pdata->ops;
+
+		SLIST_INSERT_HEAD(&sam_rst_list, sam_rstline, link);
+	}
+
+	return sam_rstline;
+}
+
+static TEE_Result sam_rstctrl_dt_get(struct dt_pargs *args, void *data,
+				     struct rstctrl **out_rstctrl)
+{
+	struct sam_rstline *sam_rstline = NULL;
+
+	if (args->args_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	sam_rstline = find_or_allocate_rstline(args->args[0], data);
+	if (!sam_rstline)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	*out_rstctrl = &sam_rstline->rstctrl;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result reset_assert(struct rstctrl *rstctrl,
+			       unsigned int to_us __unused)
+{
+	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
+
+	io_setbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
+	dsb();
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result reset_deassert(struct rstctrl *rstctrl,
+				 unsigned int to_us __unused)
+{
+	unsigned int id = to_sam_rstline(rstctrl)->reset_id;
+
+	io_clrbits32(rstc_base + RESET_OFFSET(id), BIT(RESET_BIT_POS(id)));
+	dsb();
+
+	return TEE_SUCCESS;
+}
+
+static const struct rstctrl_ops sama7_rstc_ops = {
+	.assert_level = reset_assert,
+	.deassert_level = reset_deassert,
+};
+DECLARE_KEEP_PAGER(sama7_rstc_ops);
+
+static const struct sam_reset_data sama7_reset_data = {
+	.rstc_always_secure = true,
+	.ops = &sama7_rstc_ops
+};
+DECLARE_KEEP_PAGER(sama7_reset_data);
+
+struct rstctrl *sam_get_rstctrl(unsigned int reset_id)
+{
+	struct sam_rstline *rstline = NULL;
+
+	rstline = find_or_allocate_rstline(reset_id, &sama7_reset_data);
+	assert(rstline);
+
+	return &rstline->rstctrl;
+}
+
 bool atmel_rstc_available(void)
 {
 	return rstc_base != 0;
@@ -40,31 +160,54 @@ void __noreturn atmel_rstc_reset(void)
 		;
 }
 
+void sam_rstc_usb_por(unsigned char id, bool enable)
+{
+	if (!atmel_rstc_available())
+		panic();
+
+	if (enable)
+		io_setbits32(rstc_base + AT91_RSTC_GRSTR,
+			     AT91_RSTC_GRSTR_USB(id));
+	else
+		io_clrbits32(rstc_base + AT91_RSTC_GRSTR,
+			     AT91_RSTC_GRSTR_USB(id));
+}
+
 static TEE_Result atmel_rstc_probe(const void *fdt, int node,
-				   const void *compat_data __unused)
+				   const void *compat_data)
 
 {
+	struct sam_reset_data *pdata = (struct sam_reset_data *)compat_data;
 	size_t size = 0;
 
 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	matrix_configure_periph_secure(AT91C_ID_SYS);
+	if (pdata && pdata->rstc_always_secure)
+		matrix_configure_periph_secure(AT91C_ID_SYS);
 
 	if (dt_map_dev(fdt, node, &rstc_base, &size, DT_MAP_AUTO) < 0)
 		return TEE_ERROR_GENERIC;
 
+	if (pdata)
+		return rstctrl_register_provider(fdt, node, sam_rstctrl_dt_get,
+						 pdata);
+
 	return TEE_SUCCESS;
 }
 
 static const struct dt_device_match atmel_rstc_match_table[] = {
 	{ .compatible = "atmel,sama5d3-rstc" },
+	{
+		.compatible = "microchip,sama7g5-rstc",
+		.compat_data = &sama7_reset_data,
+	},
 	{ }
 };
 
 DEFINE_DT_DRIVER(atmel_rstc_dt_driver) = {
 	.name = "atmel_rstc",
-	.type = DT_DRIVER_NOTYPE,
+	.type = DT_DRIVER_RSTCTRL,
 	.match_table = atmel_rstc_match_table,
 	.probe = atmel_rstc_probe,
 };
diff --git a/core/drivers/atmel_rtc.c b/core/drivers/atmel_rtc.c
index 3f79bdfcebdef69660b53224578f9920cbe29431..55e5ebb5b0e843bf1f41d0577ea4fb3135352142 100644
--- a/core/drivers/atmel_rtc.c
+++ b/core/drivers/atmel_rtc.c
@@ -13,7 +13,7 @@
 #include <kernel/dt_driver.h>
 #include <matrix.h>
 #include <mm/core_memprot.h>
-#include <sama5d2.h>
+#include <platform_config.h>
 
 #define RTC_VAL(reg, val)	(((val) >> RTC_## reg ## _SHIFT) & \
 				 RTC_## reg ##_MASK)
@@ -281,8 +281,11 @@ static struct rtc atmel_rtc = {
 	.range_max = { 2099, 12, 31, 23, 59, 59, 0 },
 };
 
+/* Non-null reference for compat data */
+static const uint8_t rtc_always_secure;
+
 static TEE_Result atmel_rtc_probe(const void *fdt, int node,
-				  const void *compat_data __unused)
+				  const void *compat_data)
 {
 	size_t size = 0;
 
@@ -292,7 +295,8 @@ static TEE_Result atmel_rtc_probe(const void *fdt, int node,
 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	matrix_configure_periph_secure(AT91C_ID_SYS);
+	if (compat_data != &rtc_always_secure)
+		matrix_configure_periph_secure(AT91C_ID_SYS);
 
 	if (dt_map_dev(fdt, node, &rtc_base, &size, DT_MAP_AUTO) < 0)
 		return TEE_ERROR_GENERIC;
@@ -309,6 +313,10 @@ static TEE_Result atmel_rtc_probe(const void *fdt, int node,
 
 static const struct dt_device_match atmel_rtc_match_table[] = {
 	{ .compatible = "atmel,sama5d2-rtc" },
+	{
+		.compatible = "microchip,sama7g5-rtc",
+		.compat_data = &rtc_always_secure,
+	},
 	{ }
 };
 
diff --git a/core/drivers/atmel_shdwc.c b/core/drivers/atmel_shdwc.c
index b77f934bd618a80a05dca2e7a7290d56db36487a..4606590cc9cef73d0b62921e57d1307805ee035f 100644
--- a/core/drivers/atmel_shdwc.c
+++ b/core/drivers/atmel_shdwc.c
@@ -14,7 +14,7 @@
 #include <kernel/thread.h>
 #include <libfdt.h>
 #include <matrix.h>
-#include <sama5d2.h>
+#include <platform_config.h>
 #include <stdbool.h>
 #include <tee_api_defines.h>
 #include <tee_api_types.h>
@@ -34,6 +34,26 @@
 #define SLOW_CLK_FREQ		32768ULL
 #define DBC_PERIOD_US(x)	DIV_ROUND_UP((1000000ULL * (x)), SLOW_CLK_FREQ)
 
+/*
+ * @type_offset	offset of Memory Device Register
+ * @type_mask	mask of Memory Device Type in Memory Device Register
+ * @compatible	the compatible string in the device tree
+ */
+struct ddrc_reg_config {
+	uint32_t type_offset;
+	uint32_t type_mask;
+	const char *compatible;
+};
+
+/*
+ * @shdwc_always_secure	Is peripheral SHDWC always secured?
+ * @ddrc		DDR controller configurations
+ */
+struct shdwc_compat {
+	bool shdwc_always_secure;
+	struct ddrc_reg_config ddrc;
+};
+
 static vaddr_t shdwc_base;
 static vaddr_t mpddrc_base;
 
@@ -134,6 +154,9 @@ static void at91_shdwc_dt_configure(const void *fdt, int np)
 	if (fdt_getprop(fdt, np, "atmel,wakeup-rtc-timer", &len))
 		mode |= AT91_SHDW_RTCWKEN;
 
+	if (fdt_getprop(fdt, np, "atmel,wakeup-rtt-timer", &len))
+		mode |= AT91_SHDW_RTTWKEN;
+
 	io_write32(shdwc_base + AT91_SHDW_MR, mode);
 
 	input = at91_shdwc_get_wakeup_input(fdt, np);
@@ -141,11 +164,12 @@ static void at91_shdwc_dt_configure(const void *fdt, int np)
 }
 
 static TEE_Result atmel_shdwc_probe(const void *fdt, int node,
-				    const void *compat_data __unused)
+				    const void *compat_data)
 {
 	int ddr_node = 0;
 	size_t size = 0;
 	uint32_t ddr = AT91_DDRSDRC_MD_LPDDR2;
+	struct shdwc_compat *compat = (struct shdwc_compat *)compat_data;
 
 	/*
 	 * Assembly code relies on the fact that there is only one CPU to avoid
@@ -156,30 +180,64 @@ static TEE_Result atmel_shdwc_probe(const void *fdt, int node,
 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	matrix_configure_periph_secure(AT91C_ID_SYS);
+	if (!compat->shdwc_always_secure)
+		matrix_configure_periph_secure(AT91C_ID_SYS);
 
 	if (dt_map_dev(fdt, node, &shdwc_base, &size, DT_MAP_AUTO) < 0)
 		return TEE_ERROR_GENERIC;
 
 	ddr_node = fdt_node_offset_by_compatible(fdt, -1,
-						 "atmel,sama5d3-ddramc");
+						 compat->ddrc.compatible);
 	if (ddr_node < 0)
 		return TEE_ERROR_GENERIC;
 
 	if (dt_map_dev(fdt, ddr_node, &mpddrc_base, &size, DT_MAP_AUTO) < 0)
 		return TEE_ERROR_GENERIC;
 
-	ddr = io_read32(mpddrc_base + AT91_DDRSDRC_MDR) & AT91_DDRSDRC_MD;
-	if (ddr != AT91_DDRSDRC_MD_LPDDR2 && ddr != AT91_DDRSDRC_MD_LPDDR3)
+	if (!compat->ddrc.type_mask) {
+		ddr = io_read32(mpddrc_base + compat->ddrc.type_offset);
+		ddr &= compat->ddrc.type_mask;
+		if (ddr != AT91_DDRSDRC_MD_LPDDR2 &&
+		    ddr != AT91_DDRSDRC_MD_LPDDR3)
+			mpddrc_base = 0;
+	} else {
+		/*
+		 * Set the base to 0 as the code of DRAM controller for power
+		 * down is not implemented yet.
+		 */
 		mpddrc_base = 0;
+	}
 
 	at91_shdwc_dt_configure(fdt, node);
 
-	return sama5d2_pm_init(fdt, shdwc_base);
+	return sam_pm_init(fdt, shdwc_base);
 }
 
+static const struct shdwc_compat sama5d2_compat = {
+	.shdwc_always_secure = false,
+	.ddrc = {
+		.type_offset = AT91_DDRSDRC_MDR,
+		.type_mask = AT91_DDRSDRC_MD,
+		.compatible = "atmel,sama5d3-ddramc",
+	}
+};
+
+static const struct shdwc_compat sama7g5_compat = {
+	.shdwc_always_secure = true,
+	.ddrc = {
+		.compatible = "microchip,sama7g5-uddrc",
+	}
+};
+
 static const struct dt_device_match atmel_shdwc_match_table[] = {
-	{ .compatible = "atmel,sama5d2-shdwc" },
+	{
+		.compatible = "atmel,sama5d2-shdwc",
+		.compat_data = &sama5d2_compat
+	},
+	{
+		.compatible = "microchip,sama7g5-shdwc",
+		.compat_data = &sama7g5_compat,
+	},
 	{ }
 };
 
diff --git a/core/drivers/atmel_tcb.c b/core/drivers/atmel_tcb.c
index 0e87453aa465c2cbbd25e00a1d23c50c2848485f..ca6f750433c4fdb308bf66c8af4271e4d7eb89a1 100644
--- a/core/drivers/atmel_tcb.c
+++ b/core/drivers/atmel_tcb.c
@@ -8,10 +8,10 @@
 #include <drivers/clk_dt.h>
 #include <io.h>
 #include <kernel/boot.h>
-#include <kernel/time_source.h>
+#include <kernel/tee_time.h>
 #include <libfdt.h>
 #include <matrix.h>
-#include <sama5d2.h>
+#include <platform_config.h>
 #include <tee_api_defines.h>
 
 #define TCB_CHAN(chan)		((chan) * 0x40)
@@ -50,7 +50,12 @@
 #define TCB_WPMR		0xe4
 #define  TCB_WPMR_WAKEY		0x54494d
 
+#ifdef CFG_SAMA7G5
+static const char * const tcb_clocks[] = {
+	"t0_clk", "t1_clk", "t2_clk", "slow_clk"};
+#else
 static const char * const tcb_clocks[] = { "t0_clk", "gclk", "slow_clk" };
+#endif
 static vaddr_t tcb_base;
 static uint32_t tcb_rate;
 
@@ -71,7 +76,7 @@ static TEE_Result atmel_tcb_enable_clocks(const void *fdt, int node)
 	return TEE_SUCCESS;
 }
 
-static TEE_Result atmel_tcb_get_sys_time(TEE_Time *time)
+TEE_Result tee_time_get_sys_time(TEE_Time *time)
 {
 	uint64_t cv0 = 0;
 	uint64_t cv1 = 0;
@@ -92,13 +97,10 @@ static TEE_Result atmel_tcb_get_sys_time(TEE_Time *time)
 	return TEE_SUCCESS;
 }
 
-static const struct time_source atmel_tcb_time_source = {
-	.name = "atmel_tcb",
-	.protection_level = 1000,
-	.get_sys_time = atmel_tcb_get_sys_time,
-};
-
-REGISTER_TIME_SOURCE(atmel_tcb_time_source)
+uint32_t tee_time_get_sys_time_protection_level(void)
+{
+	return 1000;
+}
 
 static void atmel_tcb_configure(void)
 {
diff --git a/core/drivers/atmel_trng.c b/core/drivers/atmel_trng.c
index 0b18c301c629eb5c7d58d9e6d3ee1975fdaeba87..2db5ef2d43f2d87b60db0248de89453ead8fa137 100644
--- a/core/drivers/atmel_trng.c
+++ b/core/drivers/atmel_trng.c
@@ -110,6 +110,7 @@ static TEE_Result trng_node_probe(const void *fdt, int node,
 
 static const struct dt_device_match atmel_trng_match_table[] = {
 	{ .compatible = "atmel,at91sam9g45-trng" },
+	{ .compatible = "microchip,sama7g5-trng" },
 	{ }
 };
 
diff --git a/core/drivers/atmel_wdt.c b/core/drivers/atmel_wdt.c
index 9f1aa3047052b4172282b83fc42b69cc0e24e6be..3d29046af89756d5dea6ba31310e8497f24f21a1 100644
--- a/core/drivers/atmel_wdt.c
+++ b/core/drivers/atmel_wdt.c
@@ -4,19 +4,17 @@
  */
 
 #include <assert.h>
-#include <drivers/clk.h>
-#include <drivers/clk_dt.h>
 #include <drivers/wdt.h>
 #include <io.h>
 #include <kernel/delay.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
 #include <kernel/interrupt.h>
+#include <kernel/panic.h>
 #include <kernel/pm.h>
 #include <matrix.h>
 #include <mm/core_mmu.h>
-#include <sama5d2.h>
-#include <tee_api_types.h>
+#include <tee_api_defines.h>
 
 #define WDT_CR			0x0
 #define WDT_CR_KEY		SHIFT_U32(0xA5, 24)
@@ -27,7 +25,8 @@
 #define WDT_MR_WDV_SET(val)	((val) & WDT_MR_WDV)
 #define WDT_MR_WDFIEN		BIT(12)
 #define WDT_MR_WDRSTEN		BIT(13)
-#define WDT_MR_WDDIS		BIT(15)
+#define WDT_MR_WDDIS		BIT(15) /* Watchdog Disable of WDT on bit 15 */
+#define WDT_MR_WDDIS_DWDT	BIT(12) /* Watchdog Disable of DWDT on bit 12 */
 #define WDT_MR_WDD_SHIFT	16
 #define WDT_MR_WDD_MASK		GENMASK_32(11, 0)
 #define WDT_MR_WDD		SHIFT_U32(WDT_MR_WDD_MASK, WDT_MR_WDD_SHIFT)
@@ -40,6 +39,38 @@
 #define WDT_SR_DUNF		BIT(0)
 #define WDT_SR_DERR		BIT(1)
 
+/* DWDT: Watchdog Timer Mode Register */
+#define WDT_MR_PERIODRST	BIT(4)
+#define WDT_MR_RPTHRST		BIT(5)
+
+/* DWDT: Watchdog Timer Value Register (Read-only) */
+#define WDT_VR			0x8
+#define WDT_VR_COUNTER_SHIFT	0
+#define WDT_VR_COUNTER_MASK	GENMASK_32(11, 0)
+
+/* DWDT: Watchdog Timer Window Level Register */
+#define WDT_WL			0xc
+#define WDT_WL_RPTH_SHIFT	16
+#define WDT_WL_RPTH_MASK	GENMASK_32(27, 16)
+#define WDT_WL_PERIOD_SHIFT	0
+#define WDT_WL_PERIOD_MASK	GENMASK_32(11, 0)
+
+/* DWDT: Watchdog Timer Interrupt Level Register */
+#define WDT_IL			0x10
+#define WDT_IL_LVLTH_SHIFT	0
+#define WDT_IL_LVLTH_MASK	GENMASK_32(11, 0)
+
+/* DWDT: Watchdog Timer Interrupt Enable/Disable/Status/Mask Register */
+#define WDT_IER			0x14
+#define WDT_IDR			0x18
+#define WDT_ISR			0x1c
+#define WDT_IMR			0x20
+#define WDT_NSRPTHINT		BIT(4)
+#define WDT_NSPERINT		BIT(3)
+#define WDT_LVLINT		BIT(2)
+#define WDT_RPTHINT		BIT(1)
+#define WDT_PERINT		BIT(0)
+
 /*
  * The watchdog is clocked by a 32768Hz clock/128 and the counter is on
  * 12 bits.
@@ -59,12 +90,24 @@
 
 #define SEC_TO_WDT(sec)		(((sec) * WDT_CLOCK_FREQ) - 1)
 
-#define WDT_ENABLED(mr)		(!((mr) & WDT_MR_WDDIS))
+#define WDT_ENABLED(mr, dis_mask)	(!((mr) & (dis_mask)))
+
+enum wdt_type {
+	WDT_TYPE_WDT,	/* Watchdog Timer */
+	WDT_TYPE_DWDT,	/* Dual Watchdog Timer */
+};
+
+struct wdt_compat {
+	bool wdt_ps; /* Is Peripheral SHDWC Programmable Secure */
+	enum wdt_type type; /* Type of Watchdog Timer */
+	uint32_t dis_mask; /* Mask of Watchdog Disable in Mode Register */
+};
 
 struct atmel_wdt {
 	struct wdt_chip chip;
+	enum wdt_type type;
+	uint32_t dis_mask;
 	vaddr_t base;
-	unsigned long rate;
 	uint32_t mr;
 	bool enabled;
 };
@@ -82,12 +125,17 @@ static TEE_Result atmel_wdt_settimeout(struct wdt_chip *chip,
 {
 	struct atmel_wdt *wdt = container_of(chip, struct atmel_wdt, chip);
 
-	wdt->mr &= ~WDT_MR_WDV;
-	wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(timeout));
+	if (wdt->type == WDT_TYPE_WDT) {
+		wdt->mr &= ~WDT_MR_WDV;
+		wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(timeout));
 
-	/* WDV and WDD can only be updated when the watchdog is running */
-	if (WDT_ENABLED(wdt->mr))
-		atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr);
+		/* WDV and WDD only be updated when the watchdog is running */
+		if (WDT_ENABLED(wdt->mr, wdt->dis_mask))
+			atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr);
+	} else {
+		io_write32(wdt->base + WDT_WL,
+			   SHIFT_U32(SEC_TO_WDT(timeout), WDT_WL_PERIOD_SHIFT));
+	}
 
 	return TEE_SUCCESS;
 }
@@ -101,7 +149,7 @@ static void atmel_wdt_ping(struct wdt_chip *chip)
 
 static void atmel_wdt_start(struct atmel_wdt *wdt)
 {
-	wdt->mr &= ~WDT_MR_WDDIS;
+	wdt->mr &= ~wdt->dis_mask;
 	atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr);
 }
 
@@ -115,7 +163,7 @@ static void atmel_wdt_enable(struct wdt_chip *chip)
 
 static void atmel_wdt_stop(struct atmel_wdt *wdt)
 {
-	wdt->mr |= WDT_MR_WDDIS;
+	wdt->mr |= wdt->dis_mask;
 	atmel_wdt_write_sleep(wdt, WDT_MR, wdt->mr);
 }
 
@@ -130,12 +178,29 @@ static void atmel_wdt_disable(struct wdt_chip *chip)
 static enum itr_return atmel_wdt_itr_cb(struct itr_handler *h)
 {
 	struct atmel_wdt *wdt = h->data;
-	uint32_t sr = io_read32(wdt->base + WDT_SR);
-
-	if (sr & WDT_SR_DUNF)
-		DMSG("Watchdog Underflow !");
-	if (sr & WDT_SR_DERR)
-		DMSG("Watchdog Error !");
+	uint32_t sr = 0;
+
+	if (wdt->type == WDT_TYPE_WDT) {
+		sr = io_read32(wdt->base + WDT_SR);
+
+		if (sr & WDT_SR_DUNF)
+			DMSG("Watchdog Underflow");
+		if (sr & WDT_SR_DERR)
+			DMSG("Watchdog Error");
+	} else if (wdt->type == WDT_TYPE_DWDT) {
+		sr = io_read32(wdt->base + WDT_ISR);
+
+		if (sr & WDT_NSRPTHINT)
+			DMSG("NS Watchdog Repeat Threshold Interrupt");
+		if (sr & WDT_NSPERINT)
+			DMSG("NS Watchdog Period Interrupt");
+		if (sr & WDT_LVLINT)
+			DMSG("Watchdog Level Threshold Interrupt");
+		if (sr & WDT_RPTHINT)
+			DMSG("Watchdog Repeat Threshold Interrupt");
+		if (sr & WDT_PERINT)
+			DMSG("Watchdog Period Interrupt");
+	}
 
 	panic("Watchdog interrupt");
 
@@ -169,24 +234,38 @@ static void atmel_wdt_init_hw(struct atmel_wdt *wdt)
 	 * bootloader might have enabled the watchdog. If so, disable it
 	 * properly.
 	 */
-	if (!WDT_ENABLED(wdt->mr)) {
+	if (!WDT_ENABLED(wdt->mr, wdt->dis_mask)) {
 		mr = io_read32(wdt->base + WDT_MR);
-		if (WDT_ENABLED(mr))
-			io_write32(wdt->base + WDT_MR, mr | WDT_MR_WDDIS);
+		if (WDT_ENABLED(mr, wdt->dis_mask))
+			io_write32(wdt->base + WDT_MR, mr | wdt->dis_mask);
 	}
 
-	/* Enable interrupt, and disable watchdog in debug and idle */
-	wdt->mr |= WDT_MR_WDFIEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT;
-	/* Enable watchdog reset */
-	wdt->mr |= WDT_MR_WDRSTEN;
-	wdt->mr |= WDT_MR_WDD_SET(SEC_TO_WDT(WDT_MAX_TIMEOUT));
-	wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT));
+	if (wdt->type == WDT_TYPE_WDT) {
+		/* Enable interrupt, and disable watchdog in debug and idle */
+		wdt->mr |= WDT_MR_WDFIEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT;
+		/* Enable watchdog reset */
+		wdt->mr |= WDT_MR_WDRSTEN;
+		wdt->mr |= WDT_MR_WDD_SET(SEC_TO_WDT(WDT_MAX_TIMEOUT));
+		wdt->mr |= WDT_MR_WDV_SET(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT));
+	} else if (wdt->type == WDT_TYPE_DWDT) {
+		/* Enable interrupt */
+		io_write32(wdt->base + WDT_ISR, WDT_PERINT);
+		/* Disable watchdog in debug and idle */
+		wdt->mr |= WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT;
+		/* Enable watchdog period reset */
+		wdt->mr |= WDT_MR_PERIODRST;
+		io_write32(wdt->base + WDT_WL,
+			   SHIFT_U32(SEC_TO_WDT(WDT_DEFAULT_TIMEOUT),
+				     WDT_WL_PERIOD_SHIFT));
+	} else {
+		panic("Invalid Watchdog");
+	}
 
 	/*
 	 * If the watchdog was enabled, write the configuration which will ping
 	 * the watchdog.
 	 */
-	if (WDT_ENABLED(wdt->mr))
+	if (WDT_ENABLED(wdt->mr, wdt->dis_mask))
 		io_write32(wdt->base + WDT_MR, wdt->mr);
 }
 
@@ -224,8 +303,9 @@ static void atmel_wdt_register_pm(struct atmel_wdt *wdt __unused)
 #endif
 
 static TEE_Result wdt_node_probe(const void *fdt, int node,
-				 const void *compat_data __unused)
+				 const void *compat_data)
 {
+	const struct wdt_compat *compat = compat_data;
 	size_t size = 0;
 	struct atmel_wdt *wdt;
 	uint32_t irq_type = 0;
@@ -237,13 +317,16 @@ static TEE_Result wdt_node_probe(const void *fdt, int node,
 	if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	matrix_configure_periph_secure(AT91C_ID_WDT);
+	if (compat->wdt_ps)
+		matrix_configure_periph_secure(AT91C_ID_WDT);
 
 	wdt = calloc(1, sizeof(*wdt));
 	if (!wdt)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
 	wdt->chip.ops = &atmel_wdt_ops;
+	wdt->type = compat->type;
+	wdt->dis_mask = compat->dis_mask;
 
 	it = dt_get_irq_type_prio(fdt, node, &irq_type, &irq_prio);
 	if (it == DT_INFO_INVALID_INTERRUPT)
@@ -259,7 +342,7 @@ static TEE_Result wdt_node_probe(const void *fdt, int node,
 		goto err_remove_handler;
 
 	/* Get current state of the watchdog */
-	wdt->mr = io_read32(wdt->base + WDT_MR) & WDT_MR_WDDIS;
+	wdt->mr = io_read32(wdt->base + WDT_MR) & wdt->dis_mask;
 
 	atmel_wdt_init_hw(wdt);
 	interrupt_enable(it_hdlr->chip, it_hdlr->it);
@@ -283,8 +366,27 @@ err_free:
 	return TEE_ERROR_GENERIC;
 }
 
+static const struct wdt_compat sama5d2_compat = {
+	.wdt_ps = true,
+	.type = WDT_TYPE_WDT,
+	.dis_mask = WDT_MR_WDDIS,
+};
+
+static const struct wdt_compat sama7g5_compat = {
+	.wdt_ps = false,
+	.type = WDT_TYPE_DWDT,
+	.dis_mask = WDT_MR_WDDIS_DWDT,
+};
+
 static const struct dt_device_match atmel_wdt_match_table[] = {
-	{ .compatible = "atmel,sama5d4-wdt" },
+	{
+		.compatible = "atmel,sama5d4-wdt",
+		.compat_data = &sama5d2_compat,
+	},
+	{
+		.compatible = "microchip,sama7g5-wdt",
+		.compat_data = &sama7g5_compat,
+	},
 	{ }
 };
 
diff --git a/core/drivers/cbmem_console.c b/core/drivers/cbmem_console.c
index 2e526c6ce2ee88968275db8d4cc6551a01ad0f27..69c2de3be702f58e7bda6a47dcc6c4edce2e35e7 100644
--- a/core/drivers/cbmem_console.c
+++ b/core/drivers/cbmem_console.c
@@ -157,8 +157,8 @@ bool cbmem_console_init_from_dt(void *fdt)
 	if (offset < 0)
 		return false;
 
-	cb_addr = fdt_reg_base_address(fdt, offset);
-	cb_size = fdt_reg_size(fdt, offset);
+	if (fdt_reg_info(fdt, offset, &cb_addr, &cb_size))
+		return false;
 
 	cbmem_console_base = get_cbmem_console_from_coreboot_table(cb_addr,
 								   cb_size);
diff --git a/core/drivers/clk/clk-stm32-core.c b/core/drivers/clk/clk-stm32-core.c
index 536197f80f028dbfe82c7dae5d0e567b7b57720d..5c3188b6b1a0ffbb858f96b3e5d2f7da45389458 100644
--- a/core/drivers/clk/clk-stm32-core.c
+++ b/core/drivers/clk/clk-stm32-core.c
@@ -73,7 +73,12 @@ static void stm32_gate_endisable(uint16_t gate_id, bool enable)
 			io_write32(addr, BIT(gate->bit_idx));
 		else
 			io_setbits32_stm32shregs(addr, BIT(gate->bit_idx));
+		/* Make sure the clock is enabled before returning to caller */
+		dsb();
 	} else {
+		/* Waiting pending operation before disabling clock */
+		dsb();
+
 		if (gate->set_clr)
 			io_write32(addr + RCC_MP_ENCLRR_OFFSET,
 				   BIT(gate->bit_idx));
@@ -82,14 +87,34 @@ static void stm32_gate_endisable(uint16_t gate_id, bool enable)
 	}
 }
 
+void stm32_gate_set_init_state(uint16_t gate_id, bool enable)
+{
+	struct clk_stm32_priv __maybe_unused *priv = clk_stm32_get_priv();
+
+	assert(!priv->gate_cpt[gate_id]);
+	stm32_gate_endisable(gate_id, enable);
+}
+
 void stm32_gate_disable(uint16_t gate_id)
 {
-	stm32_gate_endisable(gate_id, false);
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	uint8_t *gate_cpt = priv->gate_cpt;
+
+	assert(gate_cpt[gate_id] > 0);
+	if (gate_cpt[gate_id] == 1)
+		stm32_gate_endisable(gate_id, false);
+	gate_cpt[gate_id]--;
 }
 
 void stm32_gate_enable(uint16_t gate_id)
 {
-	stm32_gate_endisable(gate_id, true);
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	uint8_t *gate_cpt = priv->gate_cpt;
+
+	assert(gate_cpt[gate_id] < 0xFF);
+	if (gate_cpt[gate_id] == 0)
+		stm32_gate_endisable(gate_id, true);
+	gate_cpt[gate_id]++;
 }
 
 bool stm32_gate_is_enabled(uint16_t gate_id)
@@ -127,10 +152,20 @@ TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on)
 static TEE_Result stm32_gate_ready_endisable(uint16_t gate_id, bool enable,
 					     bool wait_rdy)
 {
+	TEE_Result res = TEE_ERROR_GENERIC;
+
 	stm32_gate_endisable(gate_id, enable);
 
-	if (wait_rdy)
-		return stm32_gate_wait_ready(gate_id + 1, enable);
+	if (wait_rdy) {
+		res = stm32_gate_wait_ready(gate_id + 1, enable);
+		if (res) {
+			stm32_gate_endisable(gate_id, !enable);
+			if (stm32_gate_wait_ready(gate_id + 1, !enable))
+				panic("Gate failed to sync");
+
+			return res;
+		}
+	}
 
 	return TEE_SUCCESS;
 }
@@ -487,11 +522,14 @@ int clk_stm32_parse_fdt_by_name(const void *fdt, int node, const char *name,
 	uint32_t i = 0;
 
 	cell = fdt_getprop(fdt, node, name, &len);
-	if (cell)
+	if (cell && len > 0) {
 		for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++)
 			tab[i] = fdt32_to_cpu(cell[i]);
 
-	*nb = (uint32_t)len / sizeof(uint32_t);
+		*nb = (uint32_t)len / sizeof(uint32_t);
+	} else {
+		*nb = 0;
+	}
 
 	return 0;
 }
@@ -502,6 +540,10 @@ TEE_Result clk_stm32_init(struct clk_stm32_priv *priv, uintptr_t base)
 
 	priv->base = base;
 
+	priv->gate_cpt = calloc(priv->nb_gates, sizeof(*priv->gate_cpt));
+	if (!priv->gate_cpt)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
 	return TEE_SUCCESS;
 }
 
diff --git a/core/drivers/clk/clk-stm32-core.h b/core/drivers/clk/clk-stm32-core.h
index c540d6c3008e15191c3502f952f27c4390ed8765..7e08ad2cab3d198272628202b08ea8bed2325df3 100644
--- a/core/drivers/clk/clk-stm32-core.h
+++ b/core/drivers/clk/clk-stm32-core.h
@@ -42,6 +42,7 @@ struct clk_stm32_priv {
 	const struct mux_cfg *muxes;
 	const uint32_t nb_muxes;
 	const struct gate_cfg *gates;
+	uint8_t *gate_cpt;
 	const uint32_t nb_gates;
 	const struct div_cfg *div;
 	const uint32_t nb_div;
@@ -119,6 +120,13 @@ TEE_Result stm32_gate_wait_ready(uint16_t gate_id, bool ready_on);
 TEE_Result stm32_gate_rdy_enable(uint16_t gate_id);
 TEE_Result stm32_gate_rdy_disable(uint16_t gate_id);
 
+/*
+ * Set gate to an enable or disable state without updating its
+ * refcount. This is exclusively intended to be used during initialization
+ * where refcount value are 0.
+ */
+void stm32_gate_set_init_state(uint16_t gate_id, bool enable);
+
 size_t stm32_mux_get_parent(uint32_t mux_id);
 TEE_Result stm32_mux_set_parent(uint16_t pid, uint8_t sel);
 
diff --git a/core/drivers/clk/clk-stm32mp13.c b/core/drivers/clk/clk-stm32mp13.c
index 0a3d6c7f116a0d10c67e6930ed9b4518ac565db6..8698b0c8fd42b5f27053fb16b5eb29b856202a04 100644
--- a/core/drivers/clk/clk-stm32mp13.c
+++ b/core/drivers/clk/clk-stm32mp13.c
@@ -964,10 +964,7 @@ static int stm32_clk_configure_clk(struct clk_stm32_priv *priv __maybe_unused,
 	if (stm32_mux_set_parent(mux, sel))
 		return -1;
 
-	if (enable)
-		stm32_gate_enable(gate);
-	else
-		stm32_gate_disable(gate);
+	stm32_gate_set_init_state(gate, enable);
 
 	return 0;
 }
@@ -1486,8 +1483,14 @@ static int stm32_clk_parse_fdt_all_oscillator(const void *fdt,
 
 		fdt_err = clk_stm32_parse_oscillator_fdt(fdt, osc_node,
 							 osc_data->name, osci);
-		if (fdt_err < 0)
-			panic();
+		if (fdt_err) {
+			if (fdt_err == -FDT_ERR_NOTFOUND) {
+				/* Oscillator not found means it is not wired */
+				osci->freq = 0;
+			} else {
+				panic();
+			}
+		}
 	}
 
 	return 0;
@@ -1744,7 +1747,7 @@ static unsigned long clk_stm32_pll_get_rate(struct clk *clk,
 		fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U));
 	}
 
-	return fvco;
+	return UDIV_ROUND_NEAREST(fvco, 100000) * 100000;
 };
 
 static bool clk_stm32_pll_is_enabled(struct clk *clk)
@@ -1787,6 +1790,29 @@ static const struct clk_ops clk_stm32_pll_ops = {
 	.disable	= clk_stm32_pll_disable,
 };
 
+static TEE_Result
+clk_stm32_composite_get_duty_cycle(struct clk *clk,
+				   struct clk_duty_cycle *duty_cycle)
+{
+	struct clk_stm32_composite_cfg *cfg = clk->priv;
+	uint32_t val = stm32_div_get_value(cfg->div_id);
+
+	duty_cycle->num = (val + 1) / 2;
+	duty_cycle->den = val + 1;
+
+	return TEE_SUCCESS;
+}
+
+static const struct clk_ops clk_stm32_composite_duty_cycle_ops = {
+	.get_parent	= clk_stm32_composite_get_parent,
+	.set_parent	= clk_stm32_composite_set_parent,
+	.get_rate	= clk_stm32_composite_get_rate,
+	.set_rate	= clk_stm32_composite_set_rate,
+	.enable		= clk_stm32_composite_gate_enable,
+	.disable	= clk_stm32_composite_gate_disable,
+	.get_duty_cycle	= clk_stm32_composite_get_duty_cycle,
+};
+
 static struct
 stm32_clk_opp_cfg *clk_stm32_get_opp_config(struct stm32_clk_opp_cfg *opp_cfg,
 					    unsigned long rate)
@@ -1957,7 +1983,7 @@ const struct clk_ops ck_timer_ops = {
 #define STM32_PLL_OUPUT(_name, _nb_parents, _parents, _flags,\
 			_gate_id, _div_id, _mux_id)\
 	struct clk _name = {\
-		.ops	= &clk_stm32_composite_ops,\
+		.ops	= &clk_stm32_composite_duty_cycle_ops,\
 		.priv	= &(struct clk_stm32_composite_cfg) {\
 			.gate_id	= (_gate_id),\
 			.div_id		= (_div_id),\
@@ -1970,11 +1996,53 @@ const struct clk_ops ck_timer_ops = {
 	}
 
 /* Oscillator clocks */
-static STM32_GATE_READY(ck_hsi, NULL, 0, GATE_HSI);
-static STM32_GATE_READY(ck_hse, NULL, 0, GATE_HSE);
-static STM32_GATE_READY(ck_csi, NULL, 0, GATE_CSI);
-static STM32_GATE_READY(ck_lsi, NULL, 0, GATE_LSI);
-static STM32_GATE_READY(ck_lse, NULL, 0, GATE_LSE);
+
+static TEE_Result clk_stm32_oscillator_enable(struct clk *clk)
+{
+	struct clk_stm32_gate_cfg *cfg = clk->priv;
+
+	if (clk->rate == 0U)
+		return TEE_SUCCESS;
+
+	return stm32_gate_rdy_enable(cfg->gate_id);
+}
+
+static void clk_stm32_oscillator_disable(struct clk *clk)
+{
+	struct clk_stm32_gate_cfg *cfg = clk->priv;
+
+	if (clk->rate == 0U)
+		return;
+
+	if (stm32_gate_rdy_disable(cfg->gate_id))
+		panic();
+}
+
+static const struct clk_ops clk_stm32_oscillator_ops = {
+	.enable		= clk_stm32_oscillator_enable,
+	.disable	= clk_stm32_oscillator_disable,
+};
+
+/*
+ * Each oscillator has 1 parent which reference is NULL here
+ * but set during initialization.
+ */
+#define STM32_OSCILLATOR(_name, _gate_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_oscillator_ops,\
+		.priv = &(struct clk_stm32_gate_cfg) {\
+			.gate_id = (_gate_id),\
+		},\
+		.name = #_name,\
+		.num_parents = 1, \
+		.parents = { NULL }, \
+	}
+
+static STM32_OSCILLATOR(ck_hsi, GATE_HSI);
+static STM32_OSCILLATOR(ck_hse, GATE_HSE);
+static STM32_OSCILLATOR(ck_csi, GATE_CSI);
+static STM32_OSCILLATOR(ck_lsi, GATE_LSI);
+static STM32_OSCILLATOR(ck_lse, GATE_LSE);
 
 static STM32_FIXED_FACTOR(ck_i2sckin, NULL, 0, 1, 1);
 static STM32_FIXED_FACTOR(ck_hse_div2, &ck_hse, 0, 1, 2);
@@ -2004,7 +2072,7 @@ static struct clk ck_pll1p = {
 		.mux_id		= NO_MUX,
 	},
 	.name		= "ck_pll1p",
-	.flags		= 0,
+	.flags		= CLK_SET_RATE_PARENT,
 	.num_parents	= 1,
 	.parents	= { &ck_pll1_vco },
 };
@@ -2019,7 +2087,7 @@ static struct clk ck_pll1p_div = {
 		.div_id	= DIV_MPU,
 	},
 	.name	= "ck_pll1p_div",
-	.flags	= 0,
+	.flags	= CLK_SET_RATE_PARENT,
 	.num_parents	= 1,
 	.parents	= { &ck_pll1p },
 };
@@ -2070,7 +2138,7 @@ static struct clk ck_mpu = {
 		.mux_id	= MUX_MPU,
 	},
 	.name		= "ck_mpu",
-	.flags		= 0,
+	.flags		= CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT,
 	.num_parents	= 4,
 	.parents	= { &ck_hsi, &ck_hse, &ck_pll1p, &ck_pll1p_div },
 };
@@ -2082,7 +2150,7 @@ static struct clk ck_axi = {
 		.div_id	= DIV_AXI,
 	},
 	.name		= "ck_axi",
-	.flags		= 0,
+	.flags		= CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT,
 	.num_parents	= 3,
 	.parents	= { &ck_hsi, &ck_hse, &ck_pll2p },
 };
@@ -2094,7 +2162,7 @@ static struct clk ck_mlahb = {
 		.div_id	= DIV_MLAHB,
 	},
 	.name		= "ck_mlahb",
-	.flags		= 0,
+	.flags		= CLK_SET_PARENT_PRE_ENABLE | CLK_SET_RATE_PARENT,
 	.num_parents	= 4,
 	.parents	= { &ck_hsi, &ck_hse, &ck_csi, &ck_pll3p },
 };
@@ -2116,74 +2184,81 @@ static STM32_TIMER(ck_timg2, &ck_pclk2, 0, RCC_APB2DIVR, RCC_TIMG2PRER);
 static STM32_TIMER(ck_timg3, &ck_pclk6, 0, RCC_APB6DIVR, RCC_TIMG3PRER);
 
 /* Peripheral and Kernel Clocks */
-static  STM32_GATE(ck_ddrc1, &ck_axi, 0, GATE_DDRC1);
-static  STM32_GATE(ck_ddrc1lp, &ck_axi, 0, GATE_DDRC1LP);
-static  STM32_GATE(ck_ddrphyc, &ck_pll2r, 0, GATE_DDRPHYC);
-static  STM32_GATE(ck_ddrphyclp, &ck_pll2r, 0, GATE_DDRPHYCLP);
-static  STM32_GATE(ck_ddrcapb, &ck_pclk4, 0, GATE_DDRCAPB);
-static  STM32_GATE(ck_ddrcapblp, &ck_pclk4, 0, GATE_DDRCAPBLP);
-static  STM32_GATE(ck_axidcg, &ck_axi, 0, GATE_AXIDCG);
-static  STM32_GATE(ck_ddrphycapb, &ck_pclk4, 0, 0);
-static  STM32_GATE(ck_ddrphycapblp, &ck_pclk4, 0, GATE_DDRPHYCAPBLP);
-static  STM32_GATE(ck_syscfg, &ck_pclk3, 0, GATE_SYSCFG);
-static  STM32_GATE(ck_ddrperfm, &ck_pclk4, 0, GATE_DDRPERFM);
-static  STM32_GATE(ck_iwdg2, &ck_pclk4, 0, GATE_IWDG2APB);
-static  STM32_GATE(ck_rtcapb, &ck_pclk5, 0, GATE_RTCAPB);
-static  STM32_GATE(ck_tzc, &ck_pclk5, 0, GATE_TZC);
-static  STM32_GATE(ck_etzpcb, &ck_pclk5, 0, GATE_ETZPC);
-static  STM32_GATE(ck_iwdg1apb, &ck_pclk5, 0, GATE_IWDG1APB);
-static  STM32_GATE(ck_bsec, &ck_pclk5, 0, GATE_BSEC);
-static  STM32_GATE(ck_tim12_k, &ck_timg3, 0, GATE_TIM12);
-static  STM32_GATE(ck_tim15_k, &ck_timg3, 0, GATE_TIM15);
-static  STM32_GATE(ck_gpioa, &ck_mlahb, 0, GATE_GPIOA);
-static  STM32_GATE(ck_gpiob, &ck_mlahb, 0, GATE_GPIOB);
-static  STM32_GATE(ck_gpioc, &ck_mlahb, 0, GATE_GPIOC);
-static  STM32_GATE(ck_gpiod, &ck_mlahb, 0, GATE_GPIOD);
-static  STM32_GATE(ck_gpioe, &ck_mlahb, 0, GATE_GPIOE);
-static  STM32_GATE(ck_gpiof, &ck_mlahb, 0, GATE_GPIOF);
-static  STM32_GATE(ck_gpiog, &ck_mlahb, 0, GATE_GPIOG);
-static  STM32_GATE(ck_gpioh, &ck_mlahb, 0, GATE_GPIOH);
-static  STM32_GATE(ck_gpioi, &ck_mlahb, 0, GATE_GPIOI);
-static  STM32_GATE(ck_pka, &ck_axi, 0, GATE_PKA);
-static  STM32_GATE(ck_cryp1, &ck_pclk5, 0, GATE_CRYP1);
-static  STM32_GATE(ck_hash1, &ck_pclk5, 0, GATE_HASH1);
-static  STM32_GATE(ck_bkpsram, &ck_pclk5, 0, GATE_BKPSRAM);
-static  STM32_GATE(ck_dbg, &ck_axi, 0, GATE_DBGCK);
-static  STM32_GATE(ck_mce, &ck_axi, 0, GATE_MCE);
-static  STM32_GATE(ck_tim2_k, &ck_timg1, 0, GATE_TIM2);
-static  STM32_GATE(ck_tim3_k, &ck_timg1, 0, GATE_TIM3);
-static  STM32_GATE(ck_tim4_k, &ck_timg1, 0, GATE_TIM4);
-static  STM32_GATE(ck_tim5_k, &ck_timg1, 0, GATE_TIM5);
-static  STM32_GATE(ck_tim6_k, &ck_timg1, 0, GATE_TIM6);
-static  STM32_GATE(ck_tim7_k, &ck_timg1, 0, GATE_TIM7);
-static  STM32_GATE(ck_tim13_k, &ck_timg3, 0, GATE_TIM13);
-static  STM32_GATE(ck_tim14_k, &ck_timg3, 0, GATE_TIM14);
-static  STM32_GATE(ck_tim1_k, &ck_timg2, 0, GATE_TIM1);
-static  STM32_GATE(ck_tim8_k, &ck_timg2, 0, GATE_TIM8);
-static  STM32_GATE(ck_tim16_k, &ck_timg3, 0, GATE_TIM16);
-static  STM32_GATE(ck_tim17_k, &ck_timg3, 0, GATE_TIM17);
-static  STM32_GATE(ck_ltdc_px, &ck_pll4q, 0, GATE_LTDC);
-static  STM32_GATE(ck_dma1, &ck_mlahb, 0, GATE_DMA1);
-static  STM32_GATE(ck_dma2, &ck_mlahb, 0, GATE_DMA2);
-static  STM32_GATE(ck_mdma, &ck_axi, 0, GATE_MDMA);
-static  STM32_GATE(ck_eth1mac, &ck_axi, 0, GATE_ETH1MAC);
-static  STM32_GATE(ck_usbh, &ck_axi, 0, GATE_USBH);
-static  STM32_GATE(ck_vref, &ck_pclk3, 0, GATE_VREF);
-static  STM32_GATE(ck_tmpsens, &ck_pclk3, 0, GATE_DTS);
-static  STM32_GATE(ck_pmbctrl, &ck_pclk3, 0, GATE_HDP);
-static  STM32_GATE(ck_hdp, &ck_pclk3, 0, GATE_PMBCTRL);
-static  STM32_GATE(ck_stgenro, &ck_pclk4, 0, GATE_DCMIPP);
-static  STM32_GATE(ck_dmamux1, &ck_axi, 0, GATE_DMAMUX1);
-static  STM32_GATE(ck_dmamux2, &ck_axi, 0, GATE_DMAMUX2);
-static  STM32_GATE(ck_dma3, &ck_axi, 0, GATE_DMAMUX2);
-static  STM32_GATE(ck_tsc, &ck_axi, 0, GATE_TSC);
-static  STM32_GATE(ck_aximc, &ck_axi, 0, GATE_AXIMC);
-static  STM32_GATE(ck_crc1, &ck_axi, 0, GATE_ETH1TX);
-static  STM32_GATE(ck_eth1tx, &ck_axi, 0, GATE_ETH1TX);
-static  STM32_GATE(ck_eth1rx, &ck_axi, 0, GATE_ETH1RX);
-static  STM32_GATE(ck_eth2tx, &ck_axi, 0, GATE_ETH2TX);
-static  STM32_GATE(ck_eth2rx, &ck_axi, 0, GATE_ETH2RX);
-static  STM32_GATE(ck_eth2mac, &ck_axi, 0, GATE_ETH2MAC);
+static STM32_GATE(ck_ddrc1, &ck_axi, 0, GATE_DDRC1);
+static STM32_GATE(ck_ddrc1lp, &ck_axi, 0, GATE_DDRC1LP);
+static STM32_GATE(ck_ddrphyc, &ck_pll2r, 0, GATE_DDRPHYC);
+static STM32_GATE(ck_ddrphyclp, &ck_pll2r, 0, GATE_DDRPHYCLP);
+static STM32_GATE(ck_ddrcapb, &ck_pclk4, 0, GATE_DDRCAPB);
+static STM32_GATE(ck_ddrcapblp, &ck_pclk4, 0, GATE_DDRCAPBLP);
+static STM32_GATE(ck_axidcg, &ck_axi, 0, GATE_AXIDCG);
+static STM32_GATE(ck_ddrphycapb, &ck_pclk4, 0, 0);
+static STM32_GATE(ck_ddrphycapblp, &ck_pclk4, 0, GATE_DDRPHYCAPBLP);
+static STM32_GATE(ck_syscfg, &ck_pclk3, 0, GATE_SYSCFG);
+static STM32_GATE(ck_ddrperfm, &ck_pclk4, 0, GATE_DDRPERFM);
+static STM32_GATE(ck_iwdg2, &ck_pclk4, 0, GATE_IWDG2APB);
+static STM32_GATE(ck_rtcapb, &ck_pclk5, 0, GATE_RTCAPB);
+static STM32_GATE(ck_tzc, &ck_pclk5, 0, GATE_TZC);
+static STM32_GATE(ck_etzpcb, &ck_pclk5, 0, GATE_ETZPC);
+static STM32_GATE(ck_iwdg1apb, &ck_pclk5, 0, GATE_IWDG1APB);
+static STM32_GATE(ck_bsec, &ck_pclk5, 0, GATE_BSEC);
+static STM32_GATE(ck_tim12_k, &ck_timg3, 0, GATE_TIM12);
+static STM32_GATE(ck_tim15_k, &ck_timg3, 0, GATE_TIM15);
+static STM32_GATE(ck_gpioa, &ck_mlahb, 0, GATE_GPIOA);
+static STM32_GATE(ck_gpiob, &ck_mlahb, 0, GATE_GPIOB);
+static STM32_GATE(ck_gpioc, &ck_mlahb, 0, GATE_GPIOC);
+static STM32_GATE(ck_gpiod, &ck_mlahb, 0, GATE_GPIOD);
+static STM32_GATE(ck_gpioe, &ck_mlahb, 0, GATE_GPIOE);
+static STM32_GATE(ck_gpiof, &ck_mlahb, 0, GATE_GPIOF);
+static STM32_GATE(ck_gpiog, &ck_mlahb, 0, GATE_GPIOG);
+static STM32_GATE(ck_gpioh, &ck_mlahb, 0, GATE_GPIOH);
+static STM32_GATE(ck_gpioi, &ck_mlahb, 0, GATE_GPIOI);
+static STM32_GATE(ck_pka, &ck_axi, 0, GATE_PKA);
+static STM32_GATE(ck_cryp1, &ck_pclk5, 0, GATE_CRYP1);
+static STM32_GATE(ck_hash1, &ck_pclk5, 0, GATE_HASH1);
+static STM32_GATE(ck_bkpsram, &ck_pclk5, 0, GATE_BKPSRAM);
+static STM32_GATE(ck_dbg, &ck_axi, 0, GATE_DBGCK);
+static STM32_GATE(ck_mce, &ck_axi, 0, GATE_MCE);
+static STM32_GATE(ck_tim2_k, &ck_timg1, 0, GATE_TIM2);
+static STM32_GATE(ck_tim3_k, &ck_timg1, 0, GATE_TIM3);
+static STM32_GATE(ck_tim4_k, &ck_timg1, 0, GATE_TIM4);
+static STM32_GATE(ck_tim5_k, &ck_timg1, 0, GATE_TIM5);
+static STM32_GATE(ck_tim6_k, &ck_timg1, 0, GATE_TIM6);
+static STM32_GATE(ck_tim7_k, &ck_timg1, 0, GATE_TIM7);
+static STM32_GATE(ck_tim13_k, &ck_timg3, 0, GATE_TIM13);
+static STM32_GATE(ck_tim14_k, &ck_timg3, 0, GATE_TIM14);
+static STM32_GATE(ck_tim1_k, &ck_timg2, 0, GATE_TIM1);
+static STM32_GATE(ck_tim8_k, &ck_timg2, 0, GATE_TIM8);
+static STM32_GATE(ck_tim16_k, &ck_timg3, 0, GATE_TIM16);
+static STM32_GATE(ck_tim17_k, &ck_timg3, 0, GATE_TIM17);
+static STM32_GATE(ck_ltdc_px, &ck_pll4q, 0, GATE_LTDC);
+static STM32_GATE(ck_dma1, &ck_mlahb, 0, GATE_DMA1);
+static STM32_GATE(ck_dma2, &ck_mlahb, 0, GATE_DMA2);
+static STM32_GATE(ck_adc1, &ck_mlahb, 0, GATE_ADC1);
+static STM32_GATE(ck_adc2, &ck_mlahb, 0, GATE_ADC2);
+static STM32_GATE(ck_mdma, &ck_axi, 0, GATE_MDMA);
+static STM32_GATE(ck_eth1mac, &ck_axi, 0, GATE_ETH1MAC);
+static STM32_GATE(ck_usbh, &ck_axi, 0, GATE_USBH);
+static STM32_GATE(ck_vref, &ck_pclk3, 0, GATE_VREF);
+static STM32_GATE(ck_tmpsens, &ck_pclk3, 0, GATE_DTS);
+static STM32_GATE(ck_pmbctrl, &ck_pclk3, 0, GATE_PMBCTRL);
+static STM32_GATE(ck_hdp, &ck_pclk3, 0, GATE_HDP);
+static STM32_GATE(ck_stgenro, &ck_pclk4, 0, GATE_STGENRO);
+static STM32_GATE(ck_dmamux1, &ck_axi, 0, GATE_DMAMUX1);
+static STM32_GATE(ck_dmamux2, &ck_axi, 0, GATE_DMAMUX2);
+static STM32_GATE(ck_dma3, &ck_axi, 0, GATE_DMA3);
+static STM32_GATE(ck_tsc, &ck_axi, 0, GATE_TSC);
+static STM32_GATE(ck_aximc, &ck_axi, 0, GATE_AXIMC);
+static STM32_GATE(ck_crc1, &ck_axi, 0, GATE_CRC1);
+static STM32_GATE(ck_eth1tx, &ck_axi, 0, GATE_ETH1TX);
+static STM32_GATE(ck_eth1rx, &ck_axi, 0, GATE_ETH1RX);
+static STM32_GATE(ck_eth2tx, &ck_axi, 0, GATE_ETH2TX);
+static STM32_GATE(ck_eth2rx, &ck_axi, 0, GATE_ETH2RX);
+static STM32_GATE(ck_eth2mac, &ck_axi, 0, GATE_ETH2MAC);
+static STM32_GATE(ck_spi1, &ck_pclk2, 0, GATE_SPI1);
+static STM32_GATE(ck_spi2, &ck_pclk1, 0, GATE_SPI2);
+static STM32_GATE(ck_spi3, &ck_pclk1, 0, GATE_SPI3);
+static STM32_GATE(ck_spi4, &ck_pclk6, 0, GATE_SPI4);
+static STM32_GATE(ck_spi5, &ck_pclk6, 0, GATE_SPI5);
 
 /* Kernel Clocks */
 static STM32_KCLK(ck_usbphy_k, 3,
@@ -2220,7 +2295,7 @@ static STM32_KCLK(ck_saes_k, 4,
 		  0, GATE_SAES, MUX_SAES);
 
 static STM32_KCLK(ck_rng1_k, 4,
-		  PARENT(&ck_csi, &ck_pll4r, &ck_lse, &ck_lsi),
+		  PARENT(&ck_csi, &ck_pll4r, &ck_off, &ck_lsi),
 		  0, GATE_RNG1, MUX_RNG1);
 
 static STM32_KCLK(ck_sdmmc1_k, 4,
@@ -2479,6 +2554,8 @@ static struct clk *stm32mp13_clk_provided[STM32MP13_ALL_CLK_NB] = {
 	[LTDC_PX]	= &ck_ltdc_px,
 	[DMA1]		= &ck_dma1,
 	[DMA2]		= &ck_dma2,
+	[ADC1]		= &ck_adc1,
+	[ADC2]		= &ck_adc2,
 	[MDMA]		= &ck_mdma,
 	[ETH1MAC]	= &ck_eth1mac,
 	[USBH]		= &ck_usbh,
@@ -2531,6 +2608,11 @@ static struct clk *stm32mp13_clk_provided[STM32MP13_ALL_CLK_NB] = {
 	[ADC2_K]	= &ck_adc2_k,
 	[ETH1CK_K]	= &ck_eth1ck_k,
 	[ETH2CK_K]	= &ck_eth2ck_k,
+	[SPI1]		= &ck_spi1,
+	[SPI2]		= &ck_spi2,
+	[SPI3]		= &ck_spi3,
+	[SPI4]		= &ck_spi4,
+	[SPI5]		= &ck_spi5,
 	[CK_MCO1]	= &ck_mco1,
 	[CK_MCO2]	= &ck_mco2,
 	[CK_TRACE]	= &ck_trace,
diff --git a/core/drivers/clk/clk-stm32mp15.c b/core/drivers/clk/clk-stm32mp15.c
index a5b7270b9cc024149c73782f3fc63738366dece2..166902b16bebe15404858afa419c9a8c325a221b 100644
--- a/core/drivers/clk/clk-stm32mp15.c
+++ b/core/drivers/clk/clk-stm32mp15.c
@@ -144,20 +144,6 @@ static const uint8_t parent_id_clock_id[_PARENT_NB] = {
 	[_CK_MCU] = CK_MCU,
 };
 
-static enum stm32mp1_parent_id osc_id2parent_id(enum stm32mp_osc_id osc_id)
-{
-	assert(osc_id >= OSC_HSI && osc_id < NB_OSC);
-	COMPILE_TIME_ASSERT((int)OSC_HSI == (int)_HSI &&
-			    (int)OSC_HSE == (int)_HSE &&
-			    (int)OSC_CSI == (int)_CSI &&
-			    (int)OSC_LSI == (int)_LSI &&
-			    (int)OSC_LSE == (int)_LSE &&
-			    (int)OSC_I2S_CKIN == (int)_I2S_CKIN &&
-			    (int)OSC_USB_PHY_48 == (int)_USB_PHY_48);
-
-	return (enum stm32mp1_parent_id)osc_id;
-}
-
 static enum stm32mp1_parent_id clock_id2parent_id(unsigned long id)
 {
 	size_t n = 0;
@@ -1027,142 +1013,6 @@ static unsigned long _stm32_clock_get_rate(unsigned long id)
 	return rate;
 }
 
-/*
- * Get the parent ID of the target parent clock, or -1 if no parent found.
- */
-static enum stm32mp1_parent_id get_parent_id_parent(enum stm32mp1_parent_id id)
-{
-	enum stm32mp1_parent_sel s = _UNKNOWN_SEL;
-	enum stm32mp1_pll_id pll_id = _PLL_NB;
-	uint32_t p_sel = 0;
-
-	switch (id) {
-	case _ACLK:
-	case _HCLK5:
-	case _HCLK6:
-	case _PCLK4:
-	case _PCLK5:
-		s = _AXISS_SEL;
-		break;
-	case _PLL1_P:
-	case _PLL1_Q:
-	case _PLL1_R:
-		pll_id = _PLL1;
-		break;
-	case _PLL2_P:
-	case _PLL2_Q:
-	case _PLL2_R:
-		pll_id = _PLL2;
-		break;
-	case _PLL3_P:
-	case _PLL3_Q:
-	case _PLL3_R:
-		pll_id = _PLL3;
-		break;
-	case _PLL4_P:
-	case _PLL4_Q:
-	case _PLL4_R:
-		pll_id = _PLL4;
-		break;
-	case _PCLK1:
-	case _PCLK2:
-	case _HCLK2:
-	case _CK_PER:
-	case _CK_MPU:
-	case _CK_MCU:
-	case _USB_PHY_48:
-		/* We do not expected to access these */
-		panic();
-		break;
-	default:
-		/* Other parents have no parent */
-		return -1;
-	}
-
-	if (s != _UNKNOWN_SEL) {
-		const struct stm32mp1_clk_sel *sel = clk_sel_ref(s);
-		vaddr_t rcc_base = stm32_rcc_base();
-
-		p_sel = (io_read32(rcc_base + sel->offset) >> sel->src) &
-			sel->msk;
-
-		if (p_sel < sel->nb_parent)
-			return sel->parent[p_sel];
-	} else {
-		const struct stm32mp1_clk_pll *pll = pll_ref(pll_id);
-
-		p_sel = io_read32(stm32_rcc_base() + pll->rckxselr) &
-			RCC_SELR_REFCLK_SRC_MASK;
-
-		if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID)
-			return osc_id2parent_id(pll->refclk[p_sel]);
-	}
-
-	FMSG("No parent found for %s", stm32mp1_clk_parent_name[id]);
-	return -1;
-}
-
-/* We are only interested in knowing if PLL3 shall be secure or not */
-static void secure_parent_clocks(enum stm32mp1_parent_id parent_id)
-{
-	enum stm32mp1_parent_id grandparent_id = _UNKNOWN_ID;
-
-	switch (parent_id) {
-	case _ACLK:
-	case _HCLK2:
-	case _HCLK5:
-	case _HCLK6:
-	case _PCLK4:
-	case _PCLK5:
-		/* Intermediate clock mux or clock, go deeper in clock tree */
-		break;
-	case _HSI:
-	case _HSI_KER:
-	case _LSI:
-	case _CSI:
-	case _CSI_KER:
-	case _HSE:
-	case _HSE_KER:
-	case _HSE_KER_DIV2:
-	case _HSE_RTC:
-	case _LSE:
-	case _PLL1_P:
-	case _PLL1_Q:
-	case _PLL1_R:
-	case _PLL2_P:
-	case _PLL2_Q:
-	case _PLL2_R:
-		/* Always secure clocks, no need to go further */
-		return;
-	case _PLL3_P:
-	case _PLL3_Q:
-	case _PLL3_R:
-		/* PLL3 is a shared resource, registered and don't go further */
-		stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3);
-		return;
-	default:
-		DMSG("Cannot lookup parent clock %s",
-		     stm32mp1_clk_parent_name[parent_id]);
-		panic();
-	}
-
-	grandparent_id = get_parent_id_parent(parent_id);
-	if (grandparent_id >= 0)
-		secure_parent_clocks(grandparent_id);
-}
-
-void stm32mp_register_clock_parents_secure(unsigned long clock_id)
-{
-	enum stm32mp1_parent_id parent_id = stm32mp1_clk_get_parent(clock_id);
-
-	if (parent_id < 0) {
-		DMSG("No parent for clock %lu", clock_id);
-		return;
-	}
-
-	secure_parent_clocks(parent_id);
-}
-
 static const char *stm32mp_osc_node_label[NB_OSC] = {
 	[OSC_LSI] = "clk-lsi",
 	[OSC_LSE] = "clk-lse",
@@ -1232,10 +1082,8 @@ static void enable_static_secure_clocks(void)
 		BSEC,
 	};
 
-	for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++) {
+	for (idx = 0; idx < ARRAY_SIZE(secure_enable); idx++)
 		clk_enable(stm32mp_rcc_clock_id_to_clk(secure_enable[idx]));
-		stm32mp_register_clock_parents_secure(secure_enable[idx]);
-	}
 
 	if (CFG_TEE_CORE_NB_CORE > 1)
 		clk_enable(stm32mp_rcc_clock_id_to_clk(RTCAPB));
@@ -1459,17 +1307,25 @@ static unsigned long clk_op_compute_rate(struct clk *clk,
 
 static TEE_Result clk_op_enable(struct clk *clk)
 {
-	if (clk_is_gate(clk))
+	if (clk_is_gate(clk)) {
 		__clk_enable(clk_to_gate_ref(clk));
 
+		/* Make sure the clock is enabled before returning to caller */
+		dsb();
+	}
+
 	return TEE_SUCCESS;
 }
 DECLARE_KEEP_PAGER(clk_op_enable);
 
 static void clk_op_disable(struct clk *clk)
 {
-	if (clk_is_gate(clk))
+	if (clk_is_gate(clk)) {
+		/* Make sure the previous operations are visible */
+		dsb();
+
 		__clk_disable(clk_to_gate_ref(clk));
+	}
 }
 DECLARE_KEEP_PAGER(clk_op_disable);
 
@@ -1531,6 +1387,12 @@ static TEE_Result stm32mp1_clock_provider_probe(const void *fdt, int offs,
 	else
 		enable_rcc_tzen();
 
+	/*
+	 * Default disable MCKPROT, it may be enabled later from
+	 * STM32 remoteproc driver.
+	 */
+	stm32_rcc_set_mckprot(false);
+
 	res = stm32mp1_clk_fdt_init(fdt, offs);
 	if (res) {
 		EMSG("Failed to initialize clocks from DT: %#"PRIx32, res);
diff --git a/core/drivers/clk/clk-stm32mp25.c b/core/drivers/clk/clk-stm32mp25.c
new file mode 100644
index 0000000000000000000000000000000000000000..66b619524287487af5d77eefb6476f632c8eb623
--- /dev/null
+++ b/core/drivers/clk/clk-stm32mp25.c
@@ -0,0 +1,3713 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <config.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_rif.h>
+#include <drivers/stm32_shared_io.h>
+#include <drivers/stm32mp25_rcc.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <initcall.h>
+#include <io.h>
+#include <kernel/dt.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stm32_sysconf.h>
+#include <stm32_util.h>
+#include <trace.h>
+#include <util.h>
+
+#include "clk-stm32-core.h"
+
+#define MAX_OPP			CFG_STM32MP_OPP_COUNT
+
+#define RCC_SECCFGR(x)		(U(0x0) + U(0x4) * (x))
+#define RCC_PRIVCFGR(x)		(U(0x10) + U(0x4) * (x))
+#define RCC_RCFGLOCKR(x)	(U(0x20) + U(0x4) * (x))
+#define RCC_CIDCFGR(x)		(U(0x030) + U(0x08) * (x))
+#define RCC_SEMCR(x)		(U(0x034) + U(0x08) * (x))
+
+#define TIMEOUT_US_100MS	U(100000)
+#define TIMEOUT_US_200MS	U(200000)
+#define TIMEOUT_US_1S		U(1000000)
+
+#define PLLRDY_TIMEOUT		TIMEOUT_US_200MS
+#define CLKSRC_TIMEOUT		TIMEOUT_US_200MS
+#define CLKDIV_TIMEOUT		TIMEOUT_US_200MS
+#define OSCRDY_TIMEOUT		TIMEOUT_US_1S
+
+/* PLL minimal frequencies for clock sources */
+#define PLL_REFCLK_MIN			UL(5000000)
+#define PLL_FRAC_REFCLK_MIN		UL(10000000)
+
+/* Parameters from XBAR_CFG in st,cksrc field */
+#define XBAR_CKSRC_CHANNEL		GENMASK_32(5, 0)
+#define XBAR_CKSRC_SRC			GENMASK_32(9, 6)
+#define XBAR_CKSRC_SRC_OFFSET		U(6)
+#define XBAR_CKSRC_PREDIV		GENMASK_32(19, 10)
+#define XBAR_CKSRC_PREDIV_OFFSET	U(10)
+#define XBAR_CKSRC_FINDIV		GENMASK_32(25, 20)
+#define XBAR_CKSRC_FINDIV_OFFSET	U(20)
+
+#define XBAR_CHANNEL_NB			U(64)
+#define XBAR_ROOT_CHANNEL_NB		U(7)
+
+#define FLEX_STGEN			U(33)
+
+#define RCC_0_MHZ	UL(0)
+#define RCC_4_MHZ	UL(4000000)
+#define RCC_16_MHZ	UL(16000000)
+
+/* CIDCFGR register bitfields */
+#define RCC_CIDCFGR_SEMWL_MASK		GENMASK_32(23, 16)
+#define RCC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
+#define RCC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	\
+					 _CIDCFGR_SEMEN |	\
+					 RCC_CIDCFGR_SCID_MASK |\
+					 RCC_CIDCFGR_SEMWL_MASK)
+
+/* SECCFGR register bitfields */
+#define RCC_SECCFGR_EN			BIT(0)
+
+/* SEMCR register bitfields */
+#define RCC_SEMCR_SCID_MASK		GENMASK_32(6, 4)
+#define RCC_SEMCR_SCID_SHIFT		U(4)
+
+/* RIF miscellaneous */
+#define RCC_NB_RIF_RES			U(114)
+#define RCC_NB_CONFS			ROUNDUP_DIV(RCC_NB_RIF_RES, 32)
+
+enum pll_cfg {
+	FBDIV,
+	REFDIV,
+	POSTDIV1,
+	POSTDIV2,
+	PLLCFG_NB
+};
+
+enum pll_csg {
+	DIVVAL,
+	SPREAD,
+	DOWNSPREAD,
+	PLLCSG_NB
+};
+
+struct stm32_pll_dt_cfg {
+	bool enabled;
+	uint32_t cfg[PLLCFG_NB];
+	uint32_t csg[PLLCSG_NB];
+	uint32_t frac;
+	bool csg_enabled;
+	uint32_t src;
+};
+
+struct stm32_osci_dt_cfg {
+	unsigned long freq;
+	bool bypass;
+	bool digbyp;
+	bool css;
+	uint32_t drive;
+};
+
+struct stm32_clk_opp_cfg {
+	uint32_t frq;
+	uint32_t src;
+	struct stm32_pll_dt_cfg pll_cfg;
+};
+
+struct stm32_clk_opp_dt_cfg {
+	struct stm32_clk_opp_cfg cpu1_opp[MAX_OPP];
+};
+
+struct stm32_clk_platdata {
+	uintptr_t rcc_base;
+	uint32_t nosci;
+	struct stm32_osci_dt_cfg *osci;
+	uint32_t npll;
+	struct stm32_pll_dt_cfg *pll;
+	struct stm32_clk_opp_dt_cfg *opp;
+	struct rif_conf_data conf_data;
+	unsigned int nb_res;
+	uint32_t nbusclk;
+	uint32_t *busclk;
+	uint32_t nkernelclk;
+	uint32_t *kernelclk;
+	uint32_t nflexgen;
+	uint32_t *flexgen;
+	uint32_t c1msrd;
+	bool safe_rst;
+};
+
+/*
+ * GATE CONFIG
+ */
+
+/* WARNING GATE_XXX_RDY MUST FOLLOW GATE_XXX */
+
+enum enum_gate_cfg {
+	GATE_HSI,
+	GATE_HSI_RDY,
+	GATE_HSE,
+	GATE_HSE_RDY,
+	GATE_LSE,
+	GATE_LSE_RDY,
+	GATE_LSI,
+	GATE_LSI_RDY,
+	GATE_MSI,
+	GATE_MSI_RDY,
+	GATE_PLL1,
+	GATE_PLL1_RDY,
+	GATE_PLL2,
+	GATE_PLL2_RDY,
+	GATE_PLL3,
+	GATE_PLL3_RDY,
+	GATE_PLL4,
+	GATE_PLL4_RDY,
+	GATE_PLL5,
+	GATE_PLL5_RDY,
+	GATE_PLL6,
+	GATE_PLL6_RDY,
+	GATE_PLL7,
+	GATE_PLL7_RDY,
+	GATE_PLL8,
+	GATE_PLL8_RDY,
+	GATE_PLL4_CKREFST,
+	GATE_PLL5_CKREFST,
+	GATE_PLL6_CKREFST,
+	GATE_PLL7_CKREFST,
+	GATE_PLL8_CKREFST,
+	GATE_HSEDIV2,
+	GATE_APB1DIV_RDY,
+	GATE_APB2DIV_RDY,
+	GATE_APB3DIV_RDY,
+	GATE_APB4DIV_RDY,
+	GATE_APBDBGDIV_RDY,
+	GATE_TIMG1PRE_RDY,
+	GATE_TIMG2PRE_RDY,
+	GATE_LSMCUDIV_RDY,
+	GATE_RTCCK,
+	GATE_C3,
+	GATE_LPTIM3C3,
+	GATE_LPTIM4C3,
+	GATE_LPTIM5C3,
+	GATE_SPI8C3,
+	GATE_LPUART1C3,
+	GATE_I2C8C3,
+	GATE_ADF1C3,
+	GATE_GPIOZC3,
+	GATE_LPDMAC3,
+	GATE_RTCC3,
+	GATE_I3C4C3,
+	GATE_MCO1,
+	GATE_MCO2,
+	GATE_DDRCP,
+	GATE_DDRCAPB,
+	GATE_DDRPHYCAPB,
+	GATE_DDRPHYC,
+	GATE_DDRCFG,
+	GATE_SYSRAM,
+	GATE_VDERAM,
+	GATE_SRAM1,
+	GATE_SRAM2,
+	GATE_RETRAM,
+	GATE_BKPSRAM,
+	GATE_LPSRAM1,
+	GATE_LPSRAM2,
+	GATE_LPSRAM3,
+	GATE_OSPI1,
+	GATE_OSPI2,
+	GATE_FMC,
+	GATE_DBG,
+	GATE_TRACE,
+	GATE_STM,
+	GATE_ETR,
+	GATE_GPIOA,
+	GATE_GPIOB,
+	GATE_GPIOC,
+	GATE_GPIOD,
+	GATE_GPIOE,
+	GATE_GPIOF,
+	GATE_GPIOG,
+	GATE_GPIOH,
+	GATE_GPIOI,
+	GATE_GPIOJ,
+	GATE_GPIOK,
+	GATE_GPIOZ,
+	GATE_HPDMA1,
+	GATE_HPDMA2,
+	GATE_HPDMA3,
+	GATE_LPDMA,
+	GATE_HSEM,
+	GATE_IPCC1,
+	GATE_IPCC2,
+	GATE_RTC,
+	GATE_SYSCPU1,
+	GATE_BSEC,
+	GATE_IS2M,
+	GATE_HSIMON,
+	GATE_TIM1,
+	GATE_TIM2,
+	GATE_TIM3,
+	GATE_TIM4,
+	GATE_TIM5,
+	GATE_TIM6,
+	GATE_TIM7,
+	GATE_TIM8,
+	GATE_TIM10,
+	GATE_TIM11,
+	GATE_TIM12,
+	GATE_TIM13,
+	GATE_TIM14,
+	GATE_TIM15,
+	GATE_TIM16,
+	GATE_TIM17,
+	GATE_TIM20,
+	GATE_LPTIM1,
+	GATE_LPTIM2,
+	GATE_LPTIM3,
+	GATE_LPTIM4,
+	GATE_LPTIM5,
+	GATE_SPI1,
+	GATE_SPI2,
+	GATE_SPI3,
+	GATE_SPI4,
+	GATE_SPI5,
+	GATE_SPI6,
+	GATE_SPI7,
+	GATE_SPI8,
+	GATE_SPDIFRX,
+	GATE_USART1,
+	GATE_USART2,
+	GATE_USART3,
+	GATE_UART4,
+	GATE_UART5,
+	GATE_USART6,
+	GATE_UART7,
+	GATE_UART8,
+	GATE_UART9,
+	GATE_LPUART1,
+	GATE_I2C1,
+	GATE_I2C2,
+	GATE_I2C3,
+	GATE_I2C4,
+	GATE_I2C5,
+	GATE_I2C6,
+	GATE_I2C7,
+	GATE_I2C8,
+	GATE_SAI1,
+	GATE_SAI2,
+	GATE_SAI3,
+	GATE_SAI4,
+	GATE_MDF1,
+	GATE_ADF1,
+	GATE_FDCAN,
+	GATE_HDP,
+	GATE_ADC12,
+	GATE_ADC3,
+	GATE_ETH1MAC,
+	GATE_ETH1,
+	GATE_ETH1TX,
+	GATE_ETH1RX,
+	GATE_ETH1STP,
+	GATE_ETH2MAC,
+	GATE_ETH2,
+	GATE_ETH2STP,
+	GATE_ETH2TX,
+	GATE_ETH2RX,
+	GATE_USB2,
+	GATE_USB2PHY1,
+	GATE_USB2PHY2,
+	GATE_USB3DR,
+	GATE_USB3PCIEPHY,
+	GATE_PCIE,
+	GATE_USBTC,
+	GATE_ETHSWMAC,
+	GATE_ETHSW,
+	GATE_ETHSWREF,
+	GATE_STGEN,
+	GATE_SDMMC1,
+	GATE_SDMMC2,
+	GATE_SDMMC3,
+	GATE_GPU,
+	GATE_LTDC,
+	GATE_DSI,
+	GATE_LVDS,
+	GATE_CSI,
+	GATE_DCMIPP,
+	GATE_CCI,
+	GATE_VDEC,
+	GATE_VENC,
+	GATE_RNG,
+	GATE_PKA,
+	GATE_SAES,
+	GATE_HASH,
+	GATE_CRYP1,
+	GATE_CRYP2,
+	GATE_IWDG1,
+	GATE_IWDG2,
+	GATE_IWDG3,
+	GATE_IWDG4,
+	GATE_IWDG5,
+	GATE_WWDG1,
+	GATE_WWDG2,
+	GATE_VREF,
+	GATE_DTS,
+	GATE_CRC,
+	GATE_SERC,
+	GATE_OSPIIOM,
+	GATE_GICV2M,
+	GATE_I3C1,
+	GATE_I3C2,
+	GATE_I3C3,
+	GATE_I3C4,
+	GATE_NB
+};
+
+#define GATE_CFG(_id, _offset, _bit_idx, _offset_clr)\
+	[(_id)] = {\
+		.offset = (_offset),\
+		.bit_idx = (_bit_idx),\
+		.set_clr = (_offset_clr),\
+	}
+
+static const struct gate_cfg gates_mp25[GATE_NB] = {
+	GATE_CFG(GATE_LSE,		RCC_BDCR,		0,	0),
+	GATE_CFG(GATE_LSE_RDY,		RCC_BDCR,		2,	0),
+	GATE_CFG(GATE_LSI,		RCC_BDCR,		9,	0),
+	GATE_CFG(GATE_LSI_RDY,		RCC_BDCR,		10,	0),
+	GATE_CFG(GATE_RTCCK,		RCC_BDCR,		20,	0),
+	GATE_CFG(GATE_MSI,		RCC_D3DCR,		0,	0),
+	GATE_CFG(GATE_MSI_RDY,		RCC_D3DCR,		2,	0),
+	GATE_CFG(GATE_PLL1,		RCC_PLL2CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL1_RDY,		RCC_PLL2CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL2,		RCC_PLL2CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL2_RDY,		RCC_PLL2CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL3,		RCC_PLL3CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL3_RDY,		RCC_PLL3CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL4,		RCC_PLL4CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL4_RDY,		RCC_PLL4CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL5,		RCC_PLL5CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL5_RDY,		RCC_PLL5CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL6,		RCC_PLL6CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL6_RDY,		RCC_PLL6CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL7,		RCC_PLL7CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL7_RDY,		RCC_PLL7CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL8,		RCC_PLL8CFGR1,		8,	0),
+	GATE_CFG(GATE_PLL8_RDY,		RCC_PLL8CFGR1,		24,	0),
+	GATE_CFG(GATE_PLL4_CKREFST,	RCC_PLL4CFGR1,		28,	0),
+	GATE_CFG(GATE_PLL5_CKREFST,	RCC_PLL5CFGR1,		28,	0),
+	GATE_CFG(GATE_PLL6_CKREFST,	RCC_PLL6CFGR1,		28,	0),
+	GATE_CFG(GATE_PLL7_CKREFST,	RCC_PLL7CFGR1,		28,	0),
+	GATE_CFG(GATE_PLL8_CKREFST,	RCC_PLL8CFGR1,		28,	0),
+	GATE_CFG(GATE_C3,		RCC_C3CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM3C3,		RCC_C3CFGR,		16,	0),
+	GATE_CFG(GATE_LPTIM4C3,		RCC_C3CFGR,		17,	0),
+	GATE_CFG(GATE_LPTIM5C3,		RCC_C3CFGR,		18,	0),
+	GATE_CFG(GATE_SPI8C3,		RCC_C3CFGR,		19,	0),
+	GATE_CFG(GATE_LPUART1C3,	RCC_C3CFGR,		20,	0),
+	GATE_CFG(GATE_I2C8C3,		RCC_C3CFGR,		21,	0),
+	GATE_CFG(GATE_ADF1C3,		RCC_C3CFGR,		23,	0),
+	GATE_CFG(GATE_GPIOZC3,		RCC_C3CFGR,		24,	0),
+	GATE_CFG(GATE_LPDMAC3,		RCC_C3CFGR,		25,	0),
+	GATE_CFG(GATE_RTCC3,		RCC_C3CFGR,		26,	0),
+	GATE_CFG(GATE_I3C4C3,		RCC_C3CFGR,		27,	0),
+	GATE_CFG(GATE_MCO1,		RCC_MCO1CFGR,		8,	0),
+	GATE_CFG(GATE_MCO2,		RCC_MCO2CFGR,		8,	0),
+	GATE_CFG(GATE_HSI,		RCC_OCENSETR,		0,	1),
+	GATE_CFG(GATE_HSEDIV2,		RCC_OCENSETR,		5,	1),
+	GATE_CFG(GATE_HSE,		RCC_OCENSETR,		8,	1),
+	GATE_CFG(GATE_HSI_RDY,		RCC_OCRDYR,		0,	0),
+	GATE_CFG(GATE_HSE_RDY,		RCC_OCRDYR,		8,	0),
+	GATE_CFG(GATE_APB1DIV_RDY,	RCC_APB1DIVR,		31,	0),
+	GATE_CFG(GATE_APB2DIV_RDY,	RCC_APB2DIVR,		31,	0),
+	GATE_CFG(GATE_APB3DIV_RDY,	RCC_APB3DIVR,		31,	0),
+	GATE_CFG(GATE_APB4DIV_RDY,	RCC_APB4DIVR,		31,	0),
+	GATE_CFG(GATE_APBDBGDIV_RDY,	RCC_APBDBGDIVR,		31,	0),
+	GATE_CFG(GATE_TIMG1PRE_RDY,	RCC_TIMG1PRER,		31,	0),
+	GATE_CFG(GATE_TIMG2PRE_RDY,	RCC_TIMG2PRER,		31,	0),
+	GATE_CFG(GATE_LSMCUDIV_RDY,	RCC_LSMCUDIVR,		31,	0),
+	GATE_CFG(GATE_DDRCP,		RCC_DDRCPCFGR,		1,	0),
+	GATE_CFG(GATE_DDRCAPB,		RCC_DDRCAPBCFGR,	1,	0),
+	GATE_CFG(GATE_DDRPHYCAPB,	RCC_DDRPHYCAPBCFGR,	1,	0),
+	GATE_CFG(GATE_DDRPHYC,		RCC_DDRPHYCCFGR,	1,	0),
+	GATE_CFG(GATE_DDRCFG,		RCC_DDRCFGR,		1,	0),
+	GATE_CFG(GATE_SYSRAM,		RCC_SYSRAMCFGR,		1,	0),
+	GATE_CFG(GATE_VDERAM,		RCC_VDERAMCFGR,		1,	0),
+	GATE_CFG(GATE_SRAM1,		RCC_SRAM1CFGR,		1,	0),
+	GATE_CFG(GATE_SRAM2,		RCC_SRAM2CFGR,		1,	0),
+	GATE_CFG(GATE_RETRAM,		RCC_RETRAMCFGR,		1,	0),
+	GATE_CFG(GATE_BKPSRAM,		RCC_BKPSRAMCFGR,	1,	0),
+	GATE_CFG(GATE_LPSRAM1,		RCC_LPSRAM1CFGR,	1,	0),
+	GATE_CFG(GATE_LPSRAM2,		RCC_LPSRAM2CFGR,	1,	0),
+	GATE_CFG(GATE_LPSRAM3,		RCC_LPSRAM3CFGR,	1,	0),
+	GATE_CFG(GATE_OSPI1,		RCC_OSPI1CFGR,		1,	0),
+	GATE_CFG(GATE_OSPI2,		RCC_OSPI2CFGR,		1,	0),
+	GATE_CFG(GATE_FMC,		RCC_FMCCFGR,		1,	0),
+	GATE_CFG(GATE_DBG,		RCC_DBGCFGR,		8,	0),
+	GATE_CFG(GATE_TRACE,		RCC_DBGCFGR,		9,	0),
+	GATE_CFG(GATE_STM,		RCC_STMCFGR,		1,	0),
+	GATE_CFG(GATE_ETR,		RCC_ETRCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOA,		RCC_GPIOACFGR,		1,	0),
+	GATE_CFG(GATE_GPIOB,		RCC_GPIOBCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOC,		RCC_GPIOCCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOD,		RCC_GPIODCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOE,		RCC_GPIOECFGR,		1,	0),
+	GATE_CFG(GATE_GPIOF,		RCC_GPIOFCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOG,		RCC_GPIOGCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOH,		RCC_GPIOHCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOI,		RCC_GPIOICFGR,		1,	0),
+	GATE_CFG(GATE_GPIOJ,		RCC_GPIOJCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOK,		RCC_GPIOKCFGR,		1,	0),
+	GATE_CFG(GATE_GPIOZ,		RCC_GPIOZCFGR,		1,	0),
+	GATE_CFG(GATE_HPDMA1,		RCC_HPDMA1CFGR,		1,	0),
+	GATE_CFG(GATE_HPDMA2,		RCC_HPDMA2CFGR,		1,	0),
+	GATE_CFG(GATE_HPDMA3,		RCC_HPDMA3CFGR,		1,	0),
+	GATE_CFG(GATE_LPDMA,		RCC_LPDMACFGR,		1,	0),
+	GATE_CFG(GATE_HSEM,		RCC_HSEMCFGR,		1,	0),
+	GATE_CFG(GATE_IPCC1,		RCC_IPCC1CFGR,		1,	0),
+	GATE_CFG(GATE_IPCC2,		RCC_IPCC2CFGR,		1,	0),
+	GATE_CFG(GATE_RTC,		RCC_RTCCFGR,		1,	0),
+	GATE_CFG(GATE_SYSCPU1,		RCC_SYSCPU1CFGR,	1,	0),
+	GATE_CFG(GATE_BSEC,		RCC_BSECCFGR,		1,	0),
+	GATE_CFG(GATE_IS2M,		RCC_IS2MCFGR,		1,	0),
+	GATE_CFG(GATE_HSIMON,		RCC_HSIFMONCR,		15,	0),
+	GATE_CFG(GATE_TIM1,		RCC_TIM1CFGR,		1,	0),
+	GATE_CFG(GATE_TIM2,		RCC_TIM2CFGR,		1,	0),
+	GATE_CFG(GATE_TIM3,		RCC_TIM3CFGR,		1,	0),
+	GATE_CFG(GATE_TIM4,		RCC_TIM4CFGR,		1,	0),
+	GATE_CFG(GATE_TIM5,		RCC_TIM5CFGR,		1,	0),
+	GATE_CFG(GATE_TIM6,		RCC_TIM6CFGR,		1,	0),
+	GATE_CFG(GATE_TIM7,		RCC_TIM7CFGR,		1,	0),
+	GATE_CFG(GATE_TIM8,		RCC_TIM8CFGR,		1,	0),
+	GATE_CFG(GATE_TIM10,		RCC_TIM10CFGR,		1,	0),
+	GATE_CFG(GATE_TIM11,		RCC_TIM11CFGR,		1,	0),
+	GATE_CFG(GATE_TIM12,		RCC_TIM12CFGR,		1,	0),
+	GATE_CFG(GATE_TIM13,		RCC_TIM13CFGR,		1,	0),
+	GATE_CFG(GATE_TIM14,		RCC_TIM14CFGR,		1,	0),
+	GATE_CFG(GATE_TIM15,		RCC_TIM15CFGR,		1,	0),
+	GATE_CFG(GATE_TIM16,		RCC_TIM16CFGR,		1,	0),
+	GATE_CFG(GATE_TIM17,		RCC_TIM17CFGR,		1,	0),
+	GATE_CFG(GATE_TIM20,		RCC_TIM20CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM1,		RCC_LPTIM1CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM2,		RCC_LPTIM2CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM3,		RCC_LPTIM3CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM4,		RCC_LPTIM4CFGR,		1,	0),
+	GATE_CFG(GATE_LPTIM5,		RCC_LPTIM5CFGR,		1,	0),
+	GATE_CFG(GATE_SPI1,		RCC_SPI1CFGR,		1,	0),
+	GATE_CFG(GATE_SPI2,		RCC_SPI2CFGR,		1,	0),
+	GATE_CFG(GATE_SPI3,		RCC_SPI3CFGR,		1,	0),
+	GATE_CFG(GATE_SPI4,		RCC_SPI4CFGR,		1,	0),
+	GATE_CFG(GATE_SPI5,		RCC_SPI5CFGR,		1,	0),
+	GATE_CFG(GATE_SPI6,		RCC_SPI6CFGR,		1,	0),
+	GATE_CFG(GATE_SPI7,		RCC_SPI7CFGR,		1,	0),
+	GATE_CFG(GATE_SPI8,		RCC_SPI8CFGR,		1,	0),
+	GATE_CFG(GATE_SPDIFRX,		RCC_SPDIFRXCFGR,	1,	0),
+	GATE_CFG(GATE_USART1,		RCC_USART1CFGR,		1,	0),
+	GATE_CFG(GATE_USART2,		RCC_USART2CFGR,		1,	0),
+	GATE_CFG(GATE_USART3,		RCC_USART3CFGR,		1,	0),
+	GATE_CFG(GATE_UART4,		RCC_UART4CFGR,		1,	0),
+	GATE_CFG(GATE_UART5,		RCC_UART5CFGR,		1,	0),
+	GATE_CFG(GATE_USART6,		RCC_USART6CFGR,		1,	0),
+	GATE_CFG(GATE_UART7,		RCC_UART7CFGR,		1,	0),
+	GATE_CFG(GATE_UART8,		RCC_UART8CFGR,		1,	0),
+	GATE_CFG(GATE_UART9,		RCC_UART9CFGR,		1,	0),
+	GATE_CFG(GATE_LPUART1,		RCC_LPUART1CFGR,	1,	0),
+	GATE_CFG(GATE_I2C1,		RCC_I2C1CFGR,		1,	0),
+	GATE_CFG(GATE_I2C2,		RCC_I2C2CFGR,		1,	0),
+	GATE_CFG(GATE_I2C3,		RCC_I2C3CFGR,		1,	0),
+	GATE_CFG(GATE_I2C4,		RCC_I2C4CFGR,		1,	0),
+	GATE_CFG(GATE_I2C5,		RCC_I2C5CFGR,		1,	0),
+	GATE_CFG(GATE_I2C6,		RCC_I2C6CFGR,		1,	0),
+	GATE_CFG(GATE_I2C7,		RCC_I2C7CFGR,		1,	0),
+	GATE_CFG(GATE_I2C8,		RCC_I2C8CFGR,		1,	0),
+	GATE_CFG(GATE_SAI1,		RCC_SAI1CFGR,		1,	0),
+	GATE_CFG(GATE_SAI2,		RCC_SAI2CFGR,		1,	0),
+	GATE_CFG(GATE_SAI3,		RCC_SAI3CFGR,		1,	0),
+	GATE_CFG(GATE_SAI4,		RCC_SAI4CFGR,		1,	0),
+	GATE_CFG(GATE_MDF1,		RCC_MDF1CFGR,		1,	0),
+	GATE_CFG(GATE_ADF1,		RCC_ADF1CFGR,		1,	0),
+	GATE_CFG(GATE_FDCAN,		RCC_FDCANCFGR,		1,	0),
+	GATE_CFG(GATE_HDP,		RCC_HDPCFGR,		1,	0),
+	GATE_CFG(GATE_ADC12,		RCC_ADC12CFGR,		1,	0),
+	GATE_CFG(GATE_ADC3,		RCC_ADC3CFGR,		1,	0),
+	GATE_CFG(GATE_ETH1MAC,		RCC_ETH1CFGR,		1,	0),
+	GATE_CFG(GATE_ETH1STP,		RCC_ETH1CFGR,		4,	0),
+	GATE_CFG(GATE_ETH1,		RCC_ETH1CFGR,		5,	0),
+	GATE_CFG(GATE_ETH1TX,		RCC_ETH1CFGR,		8,	0),
+	GATE_CFG(GATE_ETH1RX,		RCC_ETH1CFGR,		10,	0),
+	GATE_CFG(GATE_ETH2MAC,		RCC_ETH2CFGR,		1,	0),
+	GATE_CFG(GATE_ETH2STP,		RCC_ETH2CFGR,		4,	0),
+	GATE_CFG(GATE_ETH2,		RCC_ETH2CFGR,		5,	0),
+	GATE_CFG(GATE_ETH2TX,		RCC_ETH2CFGR,		8,	0),
+	GATE_CFG(GATE_ETH2RX,		RCC_ETH2CFGR,		10,	0),
+	GATE_CFG(GATE_USB2,		RCC_USB2CFGR,		1,	0),
+	GATE_CFG(GATE_USB2PHY1,		RCC_USB2PHY1CFGR,	1,	0),
+	GATE_CFG(GATE_USB2PHY2,		RCC_USB2PHY2CFGR,	1,	0),
+	GATE_CFG(GATE_USB3DR,		RCC_USB3DRCFGR,		1,	0),
+	GATE_CFG(GATE_USB3PCIEPHY,	RCC_USB3PCIEPHYCFGR,	1,	0),
+	GATE_CFG(GATE_PCIE,		RCC_PCIECFGR,		1,	0),
+	GATE_CFG(GATE_USBTC,		RCC_USBTCCFGR,		1,	0),
+	GATE_CFG(GATE_ETHSWMAC,		RCC_ETHSWCFGR,		1,	0),
+	GATE_CFG(GATE_ETHSW,		RCC_ETHSWCFGR,		5,	0),
+	GATE_CFG(GATE_ETHSWREF,		RCC_ETHSWCFGR,		21,	0),
+	GATE_CFG(GATE_STGEN,		RCC_STGENCFGR,		1,	0),
+	GATE_CFG(GATE_SDMMC1,		RCC_SDMMC1CFGR,		1,	0),
+	GATE_CFG(GATE_SDMMC2,		RCC_SDMMC2CFGR,		1,	0),
+	GATE_CFG(GATE_SDMMC3,		RCC_SDMMC3CFGR,		1,	0),
+	GATE_CFG(GATE_GPU,		RCC_GPUCFGR,		1,	0),
+	GATE_CFG(GATE_LTDC,		RCC_LTDCCFGR,		1,	0),
+	GATE_CFG(GATE_DSI,		RCC_DSICFGR,		1,	0),
+	GATE_CFG(GATE_LVDS,		RCC_LVDSCFGR,		1,	0),
+	GATE_CFG(GATE_CSI,		RCC_CSICFGR,		1,	0),
+	GATE_CFG(GATE_DCMIPP,		RCC_DCMIPPCFGR,		1,	0),
+	GATE_CFG(GATE_CCI,		RCC_CCICFGR,		1,	0),
+	GATE_CFG(GATE_VDEC,		RCC_VDECCFGR,		1,	0),
+	GATE_CFG(GATE_VENC,		RCC_VENCCFGR,		1,	0),
+	GATE_CFG(GATE_RNG,		RCC_RNGCFGR,		1,	0),
+	GATE_CFG(GATE_PKA,		RCC_PKACFGR,		1,	0),
+	GATE_CFG(GATE_SAES,		RCC_SAESCFGR,		1,	0),
+	GATE_CFG(GATE_HASH,		RCC_HASHCFGR,		1,	0),
+	GATE_CFG(GATE_CRYP1,		RCC_CRYP1CFGR,		1,	0),
+	GATE_CFG(GATE_CRYP2,		RCC_CRYP2CFGR,		1,	0),
+	GATE_CFG(GATE_IWDG1,		RCC_IWDG1CFGR,		1,	0),
+	GATE_CFG(GATE_IWDG2,		RCC_IWDG2CFGR,		1,	0),
+	GATE_CFG(GATE_IWDG3,		RCC_IWDG3CFGR,		1,	0),
+	GATE_CFG(GATE_IWDG4,		RCC_IWDG4CFGR,		1,	0),
+	GATE_CFG(GATE_IWDG5,		RCC_IWDG5CFGR,		1,	0),
+	GATE_CFG(GATE_WWDG1,		RCC_WWDG1CFGR,		1,	0),
+	GATE_CFG(GATE_WWDG2,		RCC_WWDG2CFGR,		1,	0),
+	GATE_CFG(GATE_VREF,		RCC_VREFCFGR,		1,	0),
+	GATE_CFG(GATE_DTS,		RCC_DTSCFGR,		1,	0),
+	GATE_CFG(GATE_CRC,		RCC_CRCCFGR,		1,	0),
+	GATE_CFG(GATE_SERC,		RCC_SERCCFGR,		1,	0),
+	GATE_CFG(GATE_OSPIIOM,		RCC_OSPIIOMCFGR,	1,	0),
+	GATE_CFG(GATE_GICV2M,		RCC_GICV2MCFGR,		1,	0),
+	GATE_CFG(GATE_I3C1,		RCC_I3C1CFGR,		1,	0),
+	GATE_CFG(GATE_I3C2,		RCC_I3C2CFGR,		1,	0),
+	GATE_CFG(GATE_I3C3,		RCC_I3C3CFGR,		1,	0),
+	GATE_CFG(GATE_I3C4,		RCC_I3C4CFGR,		1,	0),
+};
+
+/*
+ * MUX CONFIG
+ */
+
+#define _MUX_CFG(_id, _offset, _shift, _width, _rdy)\
+	[(_id)] = {\
+		.offset = (_offset),\
+		.shift = (_shift),\
+		.width = (_width),\
+		.ready = (_rdy),\
+	}
+
+static const struct mux_cfg parent_mp25[MUX_NB] = {
+	_MUX_CFG(MUX_MUXSEL0, RCC_MUXSELCFGR, 0, 2, GATE_PLL4_CKREFST),
+	_MUX_CFG(MUX_MUXSEL1, RCC_MUXSELCFGR, 4, 2, GATE_PLL5_CKREFST),
+	_MUX_CFG(MUX_MUXSEL2, RCC_MUXSELCFGR, 8, 2, GATE_PLL6_CKREFST),
+	_MUX_CFG(MUX_MUXSEL3, RCC_MUXSELCFGR, 12, 2, GATE_PLL7_CKREFST),
+	_MUX_CFG(MUX_MUXSEL4, RCC_MUXSELCFGR, 16, 2, GATE_PLL8_CKREFST),
+	_MUX_CFG(MUX_MUXSEL5, RCC_MUXSELCFGR, 20, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_MUXSEL6, RCC_MUXSELCFGR, 24, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_MUXSEL7, RCC_MUXSELCFGR, 28, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_XBARSEL, RCC_XBAR0CFGR, 0, 4, MUX_NO_RDY),
+	_MUX_CFG(MUX_RTC, RCC_BDCR, 16, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_D3PER, RCC_D3DCR, 16, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_MCO1, RCC_MCO1CFGR, 0, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_MCO2, RCC_MCO2CFGR, 0, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_ADC12, RCC_ADC12CFGR, 12, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_ADC3, RCC_ADC3CFGR, 12, 2, MUX_NO_RDY),
+	_MUX_CFG(MUX_USB2PHY1, RCC_USB2PHY1CFGR, 15, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_USB2PHY2, RCC_USB2PHY2CFGR, 15, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_USB3PCIEPHY, RCC_USB3PCIEPHYCFGR, 15, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_DSIBLANE, RCC_DSICFGR, 12, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_DSIPHY, RCC_DSICFGR, 15, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_LVDSPHY, RCC_LVDSCFGR, 15, 1, MUX_NO_RDY),
+	_MUX_CFG(MUX_DTS, RCC_DTSCFGR, 12, 2, MUX_NO_RDY),
+};
+
+/*
+ * DIV CONFIG
+ */
+
+static const struct div_table_cfg apb_div_table[] = {
+	{ .val = 0, .div = 1 },
+	{ .val = 1, .div = 2 },
+	{ .val = 2, .div = 4 },
+	{ .val = 3, .div = 8 },
+	{ .val = 4, .div = 16 },
+	{ .val = 5, .div = 16 },
+	{ .val = 6, .div = 16 },
+	{ .val = 7, .div = 16 },
+	/* .div = 0 termination cell */
+	{ }
+};
+
+#define _DIV_CFG(_id, _offset, _shift, _width, _flags, _table, _ready)\
+	[(_id)] = {\
+		.offset = (_offset),\
+		.shift = (_shift),\
+		.width = (_width),\
+		.flags = (_flags),\
+		.table = (_table),\
+		.ready = (_ready),\
+	}
+
+static const struct div_cfg dividers_mp25[DIV_NB] = {
+	_DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_RDY),
+	_DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table,
+		 GATE_APB1DIV_RDY),
+	_DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table,
+		 GATE_APB2DIV_RDY),
+	_DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table,
+		 GATE_APB3DIV_RDY),
+	_DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table,
+		 GATE_APB4DIV_RDY),
+	_DIV_CFG(DIV_APBDBG, RCC_APBDBGDIVR, 0, 3, 0, apb_div_table,
+		 GATE_APBDBGDIV_RDY),
+	_DIV_CFG(DIV_LSMCU, RCC_LSMCUDIVR, 0, 1, 0, NULL, GATE_LSMCUDIV_RDY),
+};
+
+enum stm32_osc {
+	OSC_HSI,
+	OSC_HSE,
+	OSC_MSI,
+	OSC_LSI,
+	OSC_LSE,
+	NB_OSCILLATOR
+};
+
+struct clk_stm32_bypass {
+	uint16_t offset;
+	uint8_t bit_byp;
+	uint8_t bit_digbyp;
+};
+
+struct clk_stm32_css {
+	uint16_t offset;
+	uint8_t bit_css;
+};
+
+struct clk_stm32_drive {
+	uint16_t offset;
+	uint8_t drv_shift;
+	uint8_t drv_width;
+	uint8_t drv_default;
+};
+
+struct clk_oscillator_data {
+	const char *name;
+	unsigned long frequency;
+	uint16_t gate_id;
+	struct clk_stm32_bypass *bypass;
+	struct clk_stm32_css *css;
+	struct clk_stm32_drive *drive;
+};
+
+#define BYPASS(_offset, _bit_byp, _bit_digbyp) \
+	(&(struct clk_stm32_bypass){\
+		.offset = (_offset),\
+		.bit_byp = (_bit_byp),\
+		.bit_digbyp = (_bit_digbyp),\
+	})
+
+#define CSS(_offset, _bit_css) \
+	(&(struct clk_stm32_css){\
+		.offset = (_offset),\
+		.bit_css = (_bit_css),\
+	})
+
+#define DRIVE(_offset, _shift, _width, _default) \
+	(&(struct clk_stm32_drive){\
+		.offset = (_offset),\
+		.drv_shift = (_shift),\
+		.drv_width = (_width),\
+		.drv_default = (_default),\
+	})
+
+#define OSCILLATOR(idx_osc, _name, _gate_id, _bypass, _css, _drive) \
+	[(idx_osc)] = (struct clk_oscillator_data){\
+		.name = (_name),\
+		.gate_id = (_gate_id),\
+		.bypass = (_bypass),\
+		.css = (_css),\
+		.drive = (_drive),\
+	}
+
+static struct clk_oscillator_data stm32mp25_osc_data[NB_OSCILLATOR] = {
+	OSCILLATOR(OSC_HSI, "clk-hsi", GATE_HSI,
+		   NULL, NULL, NULL),
+
+	OSCILLATOR(OSC_LSI, "clk-lsi", GATE_LSI,
+		   NULL, NULL, NULL),
+
+	OSCILLATOR(OSC_MSI, "clk-msi", GATE_MSI,
+		   NULL, NULL, NULL),
+
+	OSCILLATOR(OSC_LSE, "clk-lse", GATE_LSE,
+		   BYPASS(RCC_BDCR, RCC_BDCR_LSEBYP_BIT,
+			  RCC_BDCR_LSEDIGBYP_BIT),
+		   CSS(RCC_BDCR, RCC_BDCR_LSECSSON_BIT),
+		   DRIVE(RCC_BDCR, RCC_BDCR_LSEDRV_SHIFT,
+			 RCC_BDCR_LSEDRV_WIDTH, LSEDRV_MEDIUM_HIGH)),
+
+	OSCILLATOR(OSC_HSE, "clk-hse", GATE_HSE,
+		   BYPASS(RCC_OCENSETR, RCC_OCENSETR_HSEBYP_BIT,
+			  RCC_OCENSETR_HSEDIGBYP_BIT),
+		   CSS(RCC_OCENSETR, RCC_OCENSETR_HSECSSON_BIT),
+		   NULL),
+};
+
+static struct clk_oscillator_data *clk_oscillator_get_data(unsigned int osc_id)
+{
+	assert(osc_id < ARRAY_SIZE(stm32mp25_osc_data));
+
+	return &stm32mp25_osc_data[osc_id];
+}
+
+static unsigned long clk_stm32_get_rate_oscillator(unsigned int osc_id)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[osc_id];
+
+	return osci->freq;
+}
+
+static unsigned long clk_stm32_pll_get_oscillator_rate(unsigned int sel)
+{
+	unsigned int osc[] = { OSC_HSI, OSC_HSE, OSC_MSI };
+
+	assert(sel < ARRAY_SIZE(osc));
+
+	return clk_stm32_get_rate_oscillator(osc[sel]);
+}
+
+static void clk_oscillator_set_bypass(struct clk_stm32_priv *priv,
+				      struct clk_oscillator_data *osc_data,
+				      bool digbyp, bool bypass)
+{
+	struct clk_stm32_bypass *bypass_data = osc_data->bypass;
+	uintptr_t address = 0;
+
+	if (!bypass_data)
+		return;
+
+	address = priv->base + bypass_data->offset;
+
+	if (digbyp)
+		io_setbits32(address, BIT(bypass_data->bit_digbyp));
+
+	if (bypass || digbyp)
+		io_setbits32(address, BIT(bypass_data->bit_byp));
+}
+
+static void clk_oscillator_set_css(struct clk_stm32_priv *priv,
+				   struct clk_oscillator_data *osc_data,
+				   bool css)
+{
+	struct clk_stm32_css *css_data = osc_data->css;
+
+	if (css_data && css)
+		io_setbits32(priv->base + css_data->offset,
+			     BIT(css_data->bit_css));
+}
+
+static void clk_oscillator_set_drive(struct clk_stm32_priv *priv,
+				     struct clk_oscillator_data *osc_data,
+				     uint8_t lsedrv)
+{
+	struct clk_stm32_drive *drive_data = osc_data->drive;
+	uintptr_t address = 0;
+	uint32_t mask = 0;
+	uint32_t value = 0;
+
+	if (!drive_data)
+		return;
+
+	address = priv->base + drive_data->offset;
+
+	mask = SHIFT_U32(BIT(drive_data->drv_width) - 1, drive_data->drv_shift);
+
+	/*
+	 * Warning: not recommended to switch directly from "high drive"
+	 * to "medium low drive", and vice-versa.
+	 */
+	value = (io_read32(address) & mask) >> drive_data->drv_shift;
+
+	while (value != lsedrv) {
+		if (value > lsedrv)
+			value--;
+		else
+			value++;
+
+		io_clrsetbits32(address, mask,
+				SHIFT_U32(value, drive_data->drv_shift));
+	}
+}
+
+static void stm32_enable_oscillator_hse(struct clk_stm32_priv *priv,
+					struct stm32_clk_platdata *pdata)
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_HSE);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE];
+
+	if (!osci->freq)
+		return;
+
+	clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass);
+
+	/* Enable clock and wait ready bit */
+	if (stm32_gate_rdy_enable(osc_data->gate_id))
+		panic("timeout to enable hse clock");
+
+	clk_oscillator_set_css(priv, osc_data, osci->css);
+}
+
+static void stm32_enable_oscillator_lse(struct clk_stm32_priv *priv,
+					struct stm32_clk_platdata *pdata)
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE];
+
+	if (!osci->freq)
+		return;
+
+	if (stm32_gate_is_enabled(osc_data->gate_id))
+		return;
+
+	clk_oscillator_set_bypass(priv, osc_data, osci->digbyp, osci->bypass);
+
+	clk_oscillator_set_drive(priv, osc_data, osci->drive);
+
+	/* Enable LSE clock, but don't wait ready bit */
+	stm32_gate_enable(osc_data->gate_id);
+}
+
+static void stm32_enable_oscillator_lsi(struct clk_stm32_priv *priv __unused,
+					struct stm32_clk_platdata *pdata)
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSI);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSI];
+
+	if (!osci->freq)
+		return;
+
+	/* Enable clock and wait ready bit */
+	if (stm32_gate_rdy_enable(osc_data->gate_id))
+		panic("timeout to enable lsi clock");
+}
+
+static TEE_Result clk_stm32_osc_msi_set_rate(struct clk_stm32_priv *priv,
+					     unsigned long rate)
+{
+	uintptr_t address = priv->base + RCC_BDCR;
+	uint32_t mask = RCC_BDCR_MSIFREQSEL;
+
+	switch (rate) {
+	case RCC_4_MHZ:
+		io_clrbits32_stm32shregs(address, mask);
+		break;
+	case RCC_16_MHZ:
+		io_setbits32_stm32shregs(address, mask);
+		break;
+	default:
+		return TEE_ERROR_GENERIC;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void stm32_enable_oscillator_msi(struct clk_stm32_priv *priv,
+					struct stm32_clk_platdata *pdata)
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_MSI);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_MSI];
+
+	if (!osci->freq)
+		return;
+
+	if (clk_stm32_osc_msi_set_rate(priv, osci->freq) != TEE_SUCCESS) {
+		EMSG("invalid rate %ld Hz for MSI ! (4000000 or 16000000 only)",
+		     osci->freq);
+		panic();
+	}
+
+	/* Enable clock and wait ready bit */
+	if (stm32_gate_rdy_enable(osc_data->gate_id))
+		panic("timeout to enable msi clock");
+}
+
+static void stm32_clk_oscillators_lse_set_css(struct clk_stm32_priv  *priv,
+					      struct stm32_clk_platdata *pdata)
+
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE];
+
+	clk_oscillator_set_css(priv, osc_data, osci->css);
+}
+
+static int
+stm32_clk_oscillators_wait_lse_ready(struct clk_stm32_priv *priv __unused,
+				     struct stm32_clk_platdata *pdata)
+{
+	struct clk_oscillator_data *osc_data = clk_oscillator_get_data(OSC_LSE);
+	struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE];
+	int ret = 0;
+
+	if (osci->freq && stm32_gate_wait_ready(osc_data->gate_id, true))
+		ret = -1;
+
+	return ret;
+}
+
+static void stm32_clk_oscillators_enable(struct clk_stm32_priv *priv,
+					 struct stm32_clk_platdata *pdata)
+{
+	stm32_enable_oscillator_hse(priv, pdata);
+	stm32_enable_oscillator_lse(priv, pdata);
+	stm32_enable_oscillator_lsi(priv, pdata);
+	stm32_enable_oscillator_msi(priv, pdata);
+}
+
+enum stm32_pll_id {
+	PLL1_ID,
+	PLL2_ID,
+	PLL3_ID,
+	PLL4_ID,
+	PLL5_ID,
+	PLL6_ID,
+	PLL7_ID,
+	PLL8_ID,
+	PLL_NB
+};
+
+/* PLL configuration registers offsets from RCC_PLLxCFGR1 */
+#define RCC_OFFSET_PLLXCFGR1		0x00
+#define RCC_OFFSET_PLLXCFGR2		0x04
+#define RCC_OFFSET_PLLXCFGR3		0x08
+#define RCC_OFFSET_PLLXCFGR4		0x0C
+#define RCC_OFFSET_PLLXCFGR5		0x10
+#define RCC_OFFSET_PLLXCFGR6		0x18
+#define RCC_OFFSET_PLLXCFGR7		0x1C
+
+struct stm32_clk_pll {
+	uint16_t gate_id;
+	uint16_t mux_id;
+	uint16_t reg_pllxcfgr1;
+};
+
+#define CLK_PLL_CFG(_idx, _gate_id, _mux_id, _reg)\
+	[(_idx)] = {\
+		.gate_id = (_gate_id),\
+		.mux_id = (_mux_id),\
+		.reg_pllxcfgr1 = (_reg),\
+	}
+
+static const struct stm32_clk_pll stm32mp25_clk_pll[PLL_NB] = {
+	CLK_PLL_CFG(PLL1_ID, GATE_PLL1, MUX_MUXSEL5, 0),
+	CLK_PLL_CFG(PLL2_ID, GATE_PLL2, MUX_MUXSEL6, RCC_PLL2CFGR1),
+	CLK_PLL_CFG(PLL3_ID, GATE_PLL3, MUX_MUXSEL7, RCC_PLL3CFGR1),
+	CLK_PLL_CFG(PLL4_ID, GATE_PLL4, MUX_MUXSEL0, RCC_PLL4CFGR1),
+	CLK_PLL_CFG(PLL5_ID, GATE_PLL5, MUX_MUXSEL1, RCC_PLL5CFGR1),
+	CLK_PLL_CFG(PLL6_ID, GATE_PLL6, MUX_MUXSEL2, RCC_PLL6CFGR1),
+	CLK_PLL_CFG(PLL7_ID, GATE_PLL7, MUX_MUXSEL3, RCC_PLL7CFGR1),
+	CLK_PLL_CFG(PLL8_ID, GATE_PLL8, MUX_MUXSEL4, RCC_PLL8CFGR1),
+};
+
+static const struct stm32_clk_pll *clk_stm32_pll_data(unsigned int idx)
+{
+	assert(idx < ARRAY_SIZE(stm32mp25_clk_pll));
+
+	return &stm32mp25_clk_pll[idx];
+}
+
+static int stm32_clk_parse_oscillator_fdt(const void *fdt, int node,
+					  const char *name,
+					  struct stm32_osci_dt_cfg *osci)
+{
+	int subnode = 0;
+
+	/* default value when oscillator is not found */
+	osci->freq = 0;
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		const char *cchar = NULL;
+		const fdt32_t *cuint = NULL;
+		int ret = 0;
+
+		cchar = fdt_get_name(fdt, subnode, &ret);
+		if (!cchar)
+			return ret;
+
+		if (strncmp(cchar, name, (size_t)ret) ||
+		    fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED)
+			continue;
+
+		cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret);
+		if (!cuint)
+			return ret;
+
+		osci->freq = fdt32_to_cpu(*cuint);
+
+		if (fdt_getprop(fdt, subnode, "st,bypass", NULL))
+			osci->bypass = true;
+
+		if (fdt_getprop(fdt, subnode, "st,digbypass", NULL))
+			osci->digbyp = true;
+
+		if (fdt_getprop(fdt, subnode, "st,css", NULL))
+			osci->css = true;
+
+		osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive",
+						      LSEDRV_MEDIUM_HIGH);
+
+		return 0;
+	}
+
+	return 0;
+}
+
+static const char *stm32_clk_get_oscillator_name(enum stm32_osc id)
+{
+	if (id < NB_OSCILLATOR)
+		return stm32mp25_osc_data[id].name;
+
+	return NULL;
+}
+
+static int stm32_clk_parse_fdt_all_oscillator(const void *fdt,
+					      int node __unused,
+					      struct stm32_clk_platdata *pdata)
+{
+	int fdt_err = 0;
+	size_t i = 0;
+	int osc_node = 0;
+
+	osc_node = fdt_path_offset(fdt, "/clocks");
+	if (osc_node < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	for (i = 0; i < pdata->nosci; i++) {
+		const char *name = NULL;
+
+		name = stm32_clk_get_oscillator_name((enum stm32_osc)i);
+		if (!name)
+			continue;
+
+		fdt_err = stm32_clk_parse_oscillator_fdt(fdt, osc_node, name,
+							 &pdata->osci[i]);
+		if (fdt_err < 0)
+			panic();
+	}
+
+	return 0;
+}
+
+static int clk_stm32_parse_pll_fdt(const void *fdt, int subnode,
+				   struct stm32_pll_dt_cfg *pll)
+{
+	const fdt32_t *cuint = NULL;
+	int subnode_pll = 0;
+	int err = 0;
+
+	cuint = fdt_getprop(fdt, subnode, "st,pll", NULL);
+	if (!cuint)
+		return 0;
+
+	subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+	if (subnode_pll < 0)
+		return -FDT_ERR_NOTFOUND;
+
+	if (fdt_read_uint32_array(fdt, subnode_pll, "cfg", pll->cfg,
+				  PLLCFG_NB) != 0)
+		panic("cfg property is mandatory");
+
+	err = fdt_read_uint32_array(fdt, subnode_pll, "csg", pll->csg,
+				    PLLCSG_NB);
+
+	pll->csg_enabled = (err == 0);
+
+	if (err == -FDT_ERR_NOTFOUND)
+		err = 0;
+
+	if (err != 0)
+		return err;
+
+	pll->enabled = true;
+
+	pll->frac = fdt_read_uint32_default(fdt, subnode_pll, "frac", 0);
+
+	if (fdt_read_uint32(fdt, subnode_pll, "src", &pll->src))
+		panic("src property is mandatory");
+
+	return 0;
+}
+
+#define RCC_PLL_NAME_SIZE 20
+
+static int stm32_clk_parse_fdt_all_pll(const void *fdt, int node,
+				       struct stm32_clk_platdata *pdata)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < pdata->npll; i++) {
+		struct stm32_pll_dt_cfg *pll = pdata->pll + i;
+		char name[RCC_PLL_NAME_SIZE] = { };
+		int subnode = 0;
+
+		snprintf(name, sizeof(name), "st,pll-%u", i + 1);
+
+		subnode = fdt_subnode_offset(fdt, node, name);
+		if (subnode < 0)
+			continue;
+
+		if (clk_stm32_parse_pll_fdt(fdt, subnode, pll))
+			panic();
+	}
+
+	return 0;
+}
+
+static int stm32_clk_parse_fdt_opp(const void *fdt, int node,
+				   const char *opp_name,
+				   struct stm32_clk_opp_cfg *opp_cfg)
+{
+	int subnode = 0;
+	int nb_opp = 0;
+	int ret = 0;
+
+	node = fdt_subnode_offset(fdt, node, opp_name);
+	if (node == -FDT_ERR_NOTFOUND)
+		return 0;
+
+	if (node < 0)
+		return node;
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		assert(nb_opp <= MAX_OPP);
+
+		if (fdt_read_uint32(fdt, subnode, "hz", &opp_cfg->frq))
+			panic("hz property is mandatory");
+
+		if (fdt_read_uint32(fdt, subnode, "st,clksrc", &opp_cfg->src))
+			panic("st,clksrc property is mandatory");
+
+		ret = clk_stm32_parse_pll_fdt(fdt, subnode, &opp_cfg->pll_cfg);
+		if (ret < 0)
+			return ret;
+
+		opp_cfg++;
+		nb_opp++;
+	}
+
+	return 0;
+}
+
+static int stm32_clk_parse_fdt_all_opp(const void *fdt, int node,
+				       struct stm32_clk_platdata *pdata)
+{
+	struct stm32_clk_opp_dt_cfg *opp = pdata->opp;
+
+	node = fdt_subnode_offset(fdt, node, "st,clk_opp");
+	if (node == -FDT_ERR_NOTFOUND)
+		return 0;
+
+	if (node < 0)
+		return node;
+
+	return stm32_clk_parse_fdt_opp(fdt, node, "st,ck_cpu1", opp->cpu1_opp);
+}
+
+static int stm32_clk_parse_fdt(const void *fdt, int node,
+			       struct stm32_clk_platdata *pdata)
+{
+	const fdt32_t *cuint = NULL;
+	unsigned int i = 0;
+	int lenp = 0;
+	int err = 0;
+
+	err = stm32_clk_parse_fdt_all_oscillator(fdt, node, pdata);
+	if (err != 0)
+		return err;
+
+	err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata);
+	if (err != 0)
+		return err;
+
+	err = stm32_clk_parse_fdt_all_opp(fdt, node, pdata);
+	if (err != 0)
+		return err;
+
+	err = clk_stm32_parse_fdt_by_name(fdt, node, "st,busclk",
+					  pdata->busclk,
+					  &pdata->nbusclk);
+	if (err != 0)
+		return err;
+
+	err = clk_stm32_parse_fdt_by_name(fdt, node, "st,flexgen",
+					  pdata->flexgen,
+					  &pdata->nflexgen);
+	if (err != 0)
+		return err;
+
+	err = clk_stm32_parse_fdt_by_name(fdt, node, "st,kerclk",
+					  pdata->kernelclk,
+					  &pdata->nkernelclk);
+	if (err != 0)
+		return err;
+
+	pdata->c1msrd = fdt_read_uint32_default(fdt, node, "st,c1msrd", 0);
+
+	if (fdt_getprop(fdt, node, "st,safe_rst", NULL))
+		pdata->safe_rst = true;
+
+	pdata->rcc_base = stm32_rcc_base();
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (lenp < 0) {
+		if (lenp != -FDT_ERR_NOTFOUND)
+			return lenp;
+
+		lenp = 0;
+		DMSG("No RIF configuration available");
+	}
+
+	pdata->nb_res = (unsigned int)(lenp / sizeof(uint32_t));
+
+	assert(pdata->nb_res <= RCC_NB_RIF_RES);
+
+	pdata->conf_data.cid_confs = calloc(RCC_NB_RIF_RES, sizeof(uint32_t));
+	pdata->conf_data.sec_conf = calloc(RCC_NB_CONFS, sizeof(uint32_t));
+	pdata->conf_data.priv_conf = calloc(RCC_NB_CONFS, sizeof(uint32_t));
+	pdata->conf_data.lock_conf = calloc(RCC_NB_CONFS, sizeof(uint32_t));
+	pdata->conf_data.access_mask = calloc(RCC_NB_CONFS, sizeof(uint32_t));
+	if (!pdata->conf_data.cid_confs || !pdata->conf_data.sec_conf ||
+	    !pdata->conf_data.priv_conf || !pdata->conf_data.access_mask ||
+	    !pdata->conf_data.lock_conf)
+		panic("Missing memory capacity for RCC RIF configuration");
+
+	for (i = 0; i < pdata->nb_res; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &pdata->conf_data,
+				    RCC_NB_RIF_RES);
+
+	return 0;
+}
+
+static void stm32mp2_a35_ss_on_hsi(void)
+{
+	uint64_t timeout = 0;
+
+	/* Nothing to do if clock source is already set on bypass clock */
+	if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) &
+	    A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK)
+		return;
+
+	stm32mp_syscfg_write(A35SS_SSC_CHGCLKREQ,
+			     A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_EN,
+			     A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK);
+
+	timeout = timeout_init_us(CLKSRC_TIMEOUT);
+	while (!timeout_elapsed(timeout))
+		if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) &
+		    A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK)
+			break;
+
+	if (!(stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) &
+	      A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK))
+		panic("Cannot switch A35 to bypass clock");
+
+	stm32mp_syscfg_write(A35SS_SSC_PLL_EN,
+			     0,
+			     A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK);
+}
+
+static void stm32mp2_clk_xbar_on_hsi(struct clk_stm32_priv *priv)
+{
+	uintptr_t xbar0cfgr = priv->base + RCC_XBAR0CFGR;
+	uint32_t i = 0;
+
+	for (i = 0; i < XBAR_ROOT_CHANNEL_NB; i++)
+		io_clrsetbits32(xbar0cfgr + (0x4 * i),
+				RCC_XBAR0CFGR_XBAR0SEL_MASK, XBAR_SRC_HSI);
+}
+
+static int stm32mp2_a35_pll1_start(void)
+{
+	uint64_t timeout = 0;
+
+	stm32mp_syscfg_write(A35SS_SSC_PLL_EN,
+			     A35SS_SSC_PLL_ENABLE_PD_EN,
+			     A35SS_SSC_PLL_ENABLE_PD_EN);
+
+	/* Wait PLL lock */
+	timeout = timeout_init_us(PLLRDY_TIMEOUT);
+	while (!timeout_elapsed(timeout))
+		if (stm32mp_syscfg_read(A35SS_SSC_PLL_EN) &
+		    A35SS_SSC_PLL_ENABLE_LOCKP_MASK)
+			break;
+
+	if (!(stm32mp_syscfg_read(A35SS_SSC_PLL_EN) &
+	      A35SS_SSC_PLL_ENABLE_LOCKP_MASK)) {
+		EMSG("PLL1 not locked");
+		return -1;
+	}
+
+	/* De-assert reset on PLL output clock path */
+	stm32mp_syscfg_write(A35SS_SSC_PLL_EN,
+			     A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_EN,
+			     A35SS_SSC_PLL_ENABLE_NRESET_SWPLL_FF_MASK);
+
+	/* Switch CPU clock to PLL clock */
+	stm32mp_syscfg_write(A35SS_SSC_CHGCLKREQ,
+			     0,
+			     A35SS_SSC_CHGCLKREQ_ARM_CHGCLKREQ_MASK);
+
+	/* Wait for clock change acknowledge */
+	timeout = timeout_init_us(CLKSRC_TIMEOUT);
+	while (!timeout_elapsed(timeout))
+		if (!(stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) &
+		      A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK))
+			break;
+
+	if (stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ) &
+	    A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) {
+		EMSG("A35 switch to PLL1 failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void stm32mp2_a35_pll1_config(uint32_t fbdiv, uint32_t refdiv,
+				     uint32_t postdiv1, uint32_t postdiv2)
+{
+	stm32mp_syscfg_write(A35SS_SSC_PLL_FREQ1,
+			     SHIFT_U32(refdiv,
+				       A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT) |
+			     SHIFT_U32(fbdiv, A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT),
+			     A35SS_SSC_PLL_FREQ1_MASK);
+
+	stm32mp_syscfg_write(A35SS_SSC_PLL_FREQ2,
+			     SHIFT_U32(postdiv1,
+				       A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT) |
+			     SHIFT_U32(postdiv2,
+				       A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT),
+			     A35SS_SSC_PLL_FREQ2_MASK);
+}
+
+static void clk_stm32_pll_config_output(struct clk_stm32_priv *priv,
+					const struct stm32_clk_pll *pll,
+					uint32_t pllsrc,
+					uint32_t *pllcfg,
+					uint32_t fracv)
+{
+	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+	uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
+	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+	uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
+	uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
+	int sel = (pllsrc & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+	unsigned long refclk = clk_stm32_pll_get_oscillator_rate(sel);
+
+	if (fracv == 0) {
+		/* PLL in integer mode */
+
+		/*
+		 * No need to check max clock, as oscillator reference clocks
+		 * will always be less than 1.2GHz
+		 */
+		if (refclk < PLL_REFCLK_MIN)
+			panic();
+
+		io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK);
+		io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+		io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
+		io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+		io_setbits32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
+	} else {
+		/* PLL in frac mode */
+
+		/*
+		 * No need to check max clock, as oscillator reference clocks
+		 * will always be less than 1.2GHz
+		 */
+		if (refclk < PLL_FRAC_REFCLK_MIN)
+			panic();
+
+		io_clrsetbits32(pllxcfgr3, RCC_PLLxCFGR3_FRACIN_MASK,
+				fracv & RCC_PLLxCFGR3_FRACIN_MASK);
+		io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+		io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+	}
+
+	assert(pllcfg[REFDIV]);
+
+	io_clrsetbits32(pllxcfgr2, RCC_PLLxCFGR2_FBDIV_MASK,
+			SHIFT_U32(pllcfg[FBDIV], RCC_PLLxCFGR2_FBDIV_SHIFT) &
+			RCC_PLLxCFGR2_FBDIV_MASK);
+	io_clrsetbits32(pllxcfgr2, RCC_PLLxCFGR2_FREFDIV_MASK,
+			pllcfg[REFDIV] & RCC_PLLxCFGR2_FREFDIV_MASK);
+	io_clrsetbits32(pllxcfgr6, RCC_PLLxCFGR6_POSTDIV1_MASK,
+			pllcfg[POSTDIV1] & RCC_PLLxCFGR6_POSTDIV1_MASK);
+	io_clrsetbits32(pllxcfgr7, RCC_PLLxCFGR7_POSTDIV2_MASK,
+			pllcfg[POSTDIV2] & RCC_PLLxCFGR7_POSTDIV2_MASK);
+
+	if (pllcfg[POSTDIV1] == 0 || pllcfg[POSTDIV2] == 0) {
+		/* Bypass mode */
+		io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
+		io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
+	} else {
+		io_clrbits32(pllxcfgr4, RCC_PLLxCFGR4_BYPASS);
+		io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_FOUTPOSTDIVEN);
+	}
+}
+
+static void clk_stm32_pll_config_csg(struct clk_stm32_priv *priv,
+				     const struct stm32_clk_pll *pll,
+				     uint32_t *csg)
+{
+	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+	uintptr_t pllxcfgr5 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR5;
+
+	io_clrsetbits32(pllxcfgr5, RCC_PLLxCFGR5_DIVVAL_MASK,
+			csg[DIVVAL] & RCC_PLLxCFGR5_DIVVAL_MASK);
+	io_clrsetbits32(pllxcfgr5, RCC_PLLxCFGR5_SPREAD_MASK,
+			SHIFT_U32(csg[SPREAD], RCC_PLLxCFGR5_SPREAD_SHIFT) &
+			RCC_PLLxCFGR5_SPREAD_MASK);
+
+	if (csg[DOWNSPREAD] != 0)
+		io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
+	else
+		io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_DOWNSPREAD);
+
+	io_clrbits32(pllxcfgr3, RCC_PLLxCFGR3_SSCGDIS);
+
+	io_clrbits32(pllxcfgr1, RCC_PLLxCFGR1_PLLEN);
+	udelay(1);
+
+	io_setbits32(pllxcfgr4, RCC_PLLxCFGR4_DSMEN);
+	io_setbits32(pllxcfgr3, RCC_PLLxCFGR3_DACEN);
+}
+
+static struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(unsigned int pll_idx)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	struct stm32_clk_platdata *pdata = priv->pdata;
+
+	assert(pll_idx < pdata->npll);
+
+	return &pdata->pll[pll_idx];
+}
+
+static int clk_stm32_pll_set_mux(struct clk_stm32_priv *priv __unused,
+				 uint32_t src)
+{
+	int mux = (src & MUX_ID_MASK) >> MUX_ID_SHIFT;
+	int sel = (src & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+
+	if (stm32_mux_set_parent(mux, sel))
+		return -1;
+	else
+		return 0;
+
+}
+
+static void clk_stm32_pll1_init(struct clk_stm32_priv *priv,
+				int pll_idx __unused,
+				struct stm32_pll_dt_cfg *pll_conf)
+{
+	int sel = (pll_conf->src & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+	unsigned long refclk = 0;
+
+	/*
+	 * TODO: check if pll has already good parameters or if we could make
+	 * a configuration on the fly.
+	 */
+
+	stm32mp2_a35_ss_on_hsi();
+
+	if (clk_stm32_pll_set_mux(priv, pll_conf->src))
+		panic();
+
+	refclk = clk_stm32_pll_get_oscillator_rate(sel);
+
+	/*
+	 * No need to check max clock, as oscillator reference clocks will
+	 * always be less than 1.2GHz
+	 */
+	if (refclk < PLL_REFCLK_MIN)
+		panic();
+
+	stm32mp2_a35_pll1_config(pll_conf->cfg[FBDIV],
+				 pll_conf->cfg[REFDIV],
+				 pll_conf->cfg[POSTDIV1],
+				 pll_conf->cfg[POSTDIV2]);
+
+	if (stm32mp2_a35_pll1_start())
+		panic();
+}
+
+static void clk_stm32_pll_init(struct clk_stm32_priv *priv, int pll_idx,
+			       struct stm32_pll_dt_cfg *pll_conf)
+{
+	const struct stm32_clk_pll *pll = clk_stm32_pll_data(pll_idx);
+	uintptr_t pllxcfgr1 = priv->base + pll->reg_pllxcfgr1;
+	bool spread_spectrum = false;
+
+	/*
+	 * TODO: check if pll has already good parameters or if we could make
+	 * a configuration on the fly.
+	 */
+
+	if (stm32_gate_rdy_disable(pll->gate_id))
+		panic();
+
+	if (clk_stm32_pll_set_mux(priv, pll_conf->src))
+		panic();
+
+	clk_stm32_pll_config_output(priv, pll, pll_conf->src,
+				    pll_conf->cfg, pll_conf->frac);
+
+	if (pll_conf->csg_enabled) {
+		clk_stm32_pll_config_csg(priv, pll, pll_conf->csg);
+		spread_spectrum = true;
+	}
+
+	if (stm32_gate_rdy_enable(pll->gate_id))
+		panic();
+
+	if (spread_spectrum)
+		io_clrbits32(pllxcfgr1, RCC_PLLxCFGR1_SSMODRST);
+}
+
+static int stm32_clk_pll_configure(struct clk_stm32_priv *priv)
+{
+	struct stm32_pll_dt_cfg *pll_conf = NULL;
+	size_t i = 0;
+
+	for (i = 0; i < PLL_NB; i++) {
+		pll_conf = clk_stm32_pll_get_pdata(i);
+
+		if (pll_conf->enabled) {
+			/* Skip the pll3 (need GPU regulator to configure) */
+			if (i == PLL3_ID)
+				continue;
+
+			/* Skip the pll2 (reserved to DDR) */
+			if (i == PLL2_ID)
+				continue;
+
+			if (i == PLL1_ID)
+				clk_stm32_pll1_init(priv, i, pll_conf);
+			else
+				clk_stm32_pll_init(priv, i, pll_conf);
+		}
+	}
+
+	return 0;
+}
+
+#define __WORD_BIT 32
+
+static int wait_predivsr(uint16_t channel)
+{
+	uintptr_t rcc_base = stm32_rcc_base();
+	uintptr_t previvsr = 0;
+	uint32_t channel_bit = 0;
+	uint32_t value = 0;
+
+	if (channel < __WORD_BIT) {
+		previvsr = rcc_base + RCC_PREDIVSR1;
+		channel_bit = BIT(channel);
+	} else {
+		previvsr = rcc_base + RCC_PREDIVSR2;
+		channel_bit = BIT(channel - __WORD_BIT);
+	}
+
+	if (IO_READ32_POLL_TIMEOUT(previvsr, value, !(value & channel_bit), 0,
+				   CLKDIV_TIMEOUT)) {
+		EMSG("Pre divider status: %#"PRIx32, io_read32(previvsr));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int wait_findivsr(uint16_t channel)
+{
+	uintptr_t rcc_base = stm32_rcc_base();
+	uintptr_t finvivsr = 0;
+	uint32_t channel_bit = 0;
+	uint32_t value = 0;
+
+	if (channel < __WORD_BIT) {
+		finvivsr = rcc_base + RCC_FINDIVSR1;
+		channel_bit = BIT(channel);
+	} else {
+		finvivsr = rcc_base + RCC_FINDIVSR2;
+		channel_bit = BIT(channel - __WORD_BIT);
+	}
+
+	if (IO_READ32_POLL_TIMEOUT(finvivsr, value, !(value & channel_bit), 0,
+				   CLKDIV_TIMEOUT)) {
+		EMSG("Final divider status: %#"PRIx32, io_read32(finvivsr));
+		return -1;
+	}
+
+	return 0;
+}
+
+static int wait_xbar_sts(uint16_t channel)
+{
+	uintptr_t rcc_base = stm32_rcc_base();
+	uintptr_t xbar_cfgr = rcc_base + RCC_XBAR0CFGR + (0x4 * channel);
+	uint32_t value = 0;
+
+	if (IO_READ32_POLL_TIMEOUT(xbar_cfgr, value,
+				   !(value & RCC_XBAR0CFGR_XBAR0STS), 0,
+				   CLKDIV_TIMEOUT)) {
+		EMSG("XBAR%"PRIu16"CFGR: %#"PRIx32, channel,
+		     io_read32(xbar_cfgr));
+		return -1;
+	}
+
+	return 0;
+}
+
+static void flexclkgen_config_channel(uint16_t channel, unsigned int clk_src,
+				      unsigned int prediv, unsigned int findiv)
+{
+	uintptr_t rcc_base = stm32_rcc_base();
+
+	if (wait_predivsr(channel) != 0)
+		panic();
+
+	io_clrsetbits32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel),
+			RCC_PREDIV0CFGR_PREDIV0_MASK, prediv);
+
+	if (wait_predivsr(channel) != 0)
+		panic();
+
+	if (wait_findivsr(channel) != 0)
+		panic();
+
+	io_clrsetbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel),
+			RCC_FINDIV0CFGR_FINDIV0_MASK,
+			findiv);
+
+	if (wait_findivsr(channel) != 0)
+		panic();
+
+	if (wait_xbar_sts(channel) != 0)
+		panic();
+
+	io_clrsetbits32(rcc_base + RCC_XBAR0CFGR + (0x4 * channel),
+			RCC_XBAR0CFGR_XBAR0SEL_MASK,
+			clk_src);
+
+	io_setbits32(rcc_base + RCC_XBAR0CFGR + (0x4 * channel),
+		     RCC_XBAR0CFGR_XBAR0EN);
+
+	if (wait_xbar_sts(channel) != 0)
+		panic();
+}
+
+static int stm32mp2_clk_flexgen_configure(struct clk_stm32_priv *priv)
+{
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	uint32_t i = 0;
+
+	for (i = 0; i < pdata->nflexgen; i++) {
+		uint32_t val = pdata->flexgen[i];
+		uint32_t cmd = 0;
+		uint32_t cmd_data = 0;
+		unsigned int channel = 0;
+		unsigned int clk_src = 0;
+		unsigned int pdiv = 0;
+		unsigned int fdiv = 0;
+
+		cmd = (val & CMD_MASK) >> CMD_SHIFT;
+		cmd_data = val & ~CMD_MASK;
+
+		if (cmd != CMD_FLEXGEN)
+			continue;
+
+		channel = (cmd_data & FLEX_ID_MASK) >> FLEX_ID_SHIFT;
+
+		/*
+		 * Skip ck_ker_stgen configuration, will be done by
+		 * stgen driver.
+		 */
+		if (channel == FLEX_STGEN)
+			continue;
+
+		clk_src = (cmd_data & FLEX_SEL_MASK) >> FLEX_SEL_SHIFT;
+		pdiv = (cmd_data & FLEX_PDIV_MASK) >> FLEX_PDIV_SHIFT;
+		fdiv = (cmd_data & FLEX_FDIV_MASK) >> FLEX_FDIV_SHIFT;
+
+		flexclkgen_config_channel(channel, clk_src, pdiv, fdiv);
+	}
+
+	return 0;
+}
+
+static int stm32_clk_configure_div(struct clk_stm32_priv *priv __unused,
+				   uint32_t data)
+{
+	uint32_t div_id = 0;
+	uint32_t div_n = 0;
+
+	div_id = (data & DIV_ID_MASK) >> DIV_ID_SHIFT;
+	div_n = (data & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT;
+
+	return stm32_div_set_value(div_id, div_n);
+}
+
+static int stm32_clk_configure_mux(struct clk_stm32_priv *priv __unused,
+				   uint32_t data)
+{
+	int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT;
+	int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT;
+
+	if (stm32_mux_set_parent(mux, sel))
+		return -1;
+	else
+		return 0;
+}
+
+static int stm32_clk_configure_by_addr_val(struct clk_stm32_priv *priv,
+					   uint32_t data)
+{
+	uint32_t addr = data >> CLK_ADDR_SHIFT;
+	uint32_t val = data & CLK_ADDR_VAL_MASK;
+
+	io_setbits32(priv->base + addr, val);
+
+	return 0;
+}
+
+static void stm32_clk_configure_obs(struct clk_stm32_priv *priv,
+				    uint32_t data)
+{
+	uint32_t id = (data & OBS_ID_MASK) >> OBS_ID_SHIFT;
+	uint32_t status = (data & OBS_STATUS_MASK) >> OBS_STATUS_SHIFT;
+	uint32_t int_ext = (data & OBS_INTEXT_MASK) >> OBS_INTEXT_SHIFT;
+	uint32_t div = (data & OBS_DIV_MASK) >> OBS_DIV_SHIFT;
+	uint32_t inv = (data & OBS_INV_MASK) >> OBS_INV_SHIFT;
+	uint32_t sel = (data & OBS_SEL_MASK) >> OBS_SEL_SHIFT;
+	uint32_t reg = 0;
+	uint32_t val = 0;
+
+	if (!id)
+		reg = RCC_FCALCOBS0CFGR;
+	else
+		reg = RCC_FCALCOBS1CFGR;
+
+	if (status)
+		val |= RCC_FCALCOBS0CFGR_CKOBSEN;
+
+	if (int_ext == OBS_EXT) {
+		val |= RCC_FCALCOBS0CFGR_CKOBSEXTSEL;
+		val |= SHIFT_U32(sel, RCC_FCALCOBS0CFGR_CKEXTSEL_SHIFT);
+	} else {
+		val |= SHIFT_U32(sel, RCC_FCALCOBS0CFGR_CKINTSEL_SHIFT);
+	}
+
+	if (inv)
+		val |= RCC_FCALCOBS0CFGR_CKOBSINV;
+
+	val |= SHIFT_U32(div, RCC_FCALCOBS0CFGR_CKOBSDIV_SHIFT);
+
+	io_write32(priv->base + reg, val);
+}
+
+static int stm32_clk_configure(struct clk_stm32_priv *priv, uint32_t val)
+{
+	uint32_t cmd_data = 0;
+	uint32_t cmd = 0;
+	int ret = 0;
+
+	if (val & CMD_ADDR_BIT) {
+		cmd_data = val & ~CMD_ADDR_BIT;
+
+		return stm32_clk_configure_by_addr_val(priv, cmd_data);
+	}
+
+	cmd = (val & CMD_MASK) >> CMD_SHIFT;
+	cmd_data = val & ~CMD_MASK;
+
+	switch (cmd) {
+	case CMD_DIV:
+		ret = stm32_clk_configure_div(priv, cmd_data);
+		break;
+
+	case CMD_MUX:
+		ret = stm32_clk_configure_mux(priv, cmd_data);
+		break;
+
+	case CMD_OBS:
+		stm32_clk_configure_obs(priv, cmd_data);
+		break;
+
+	default:
+		EMSG("cmd unknown ! : %#"PRIx32, val);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+static int stm32_clk_bus_configure(struct clk_stm32_priv *priv)
+{
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	uint32_t i = 0;
+
+	for (i = 0; i < pdata->nbusclk; i++) {
+		int ret = 0;
+
+		ret = stm32_clk_configure(priv, pdata->busclk[i]);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int stm32_clk_kernel_configure(struct clk_stm32_priv *priv)
+{
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	uint32_t i = 0;
+
+	for (i = 0; i < pdata->nkernelclk; i++) {
+		int ret = 0;
+
+		ret = stm32_clk_configure(priv, pdata->kernelclk[i]);
+		if (ret != 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static void stm32mp2_init_clock_tree(struct clk_stm32_priv *priv,
+				     struct stm32_clk_platdata *pdata)
+{
+	stm32_clk_oscillators_enable(priv, pdata);
+
+	/* Come back to HSI for flexgen */
+	stm32mp2_clk_xbar_on_hsi(priv);
+
+	if (stm32_clk_pll_configure(priv))
+		panic("Cannot configure plls");
+
+	/* Wait LSE ready before to use it */
+	if (stm32_clk_oscillators_wait_lse_ready(priv, pdata))
+		panic("Timeout: to enable LSE");
+
+	if (stm32mp2_clk_flexgen_configure(priv))
+		panic("Cannot configure flexgen");
+
+	if (stm32_clk_bus_configure(priv))
+		panic("Cannot config bus clocks");
+
+	if (stm32_clk_kernel_configure(priv))
+		panic("Cannot configure kernel clocks");
+
+	/* Configure LSE css after RTC source configuration */
+	stm32_clk_oscillators_lse_set_css(priv, pdata);
+}
+
+static TEE_Result clk_stm32_osc_enable(struct clk *clk)
+{
+	return clk_stm32_gate_ready_ops.enable(clk);
+}
+
+static void clk_stm32_osc_disable(struct clk *clk)
+{
+	clk_stm32_gate_ready_ops.disable(clk);
+}
+
+static const struct clk_ops clk_stm32_osc_ops = {
+	.enable = clk_stm32_osc_enable,
+	.disable = clk_stm32_osc_disable,
+};
+
+static unsigned long clk_stm32_msi_get_rate(struct clk *clk __unused,
+					    unsigned long prate __unused)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	uintptr_t address = priv->base + RCC_BDCR;
+
+	if ((io_read32(address) & RCC_BDCR_MSIFREQSEL))
+		return RCC_16_MHZ;
+
+	return RCC_4_MHZ;
+}
+
+static TEE_Result clk_stm32_msi_set_rate(struct clk *clk __unused,
+					 unsigned long rate,
+					 unsigned long prate __unused)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+
+	return clk_stm32_osc_msi_set_rate(priv, rate);
+}
+
+static const struct clk_ops clk_stm32_oscillator_msi_ops = {
+	.enable = clk_stm32_osc_enable,
+	.disable = clk_stm32_osc_disable,
+	.get_rate = clk_stm32_msi_get_rate,
+	.set_rate = clk_stm32_msi_set_rate,
+};
+
+static TEE_Result clk_stm32_hse_div_set_rate(struct clk *clk,
+					     unsigned long rate,
+					     unsigned long parent_rate)
+{
+	return clk_stm32_divider_set_rate(clk, rate, parent_rate);
+}
+
+static const struct clk_ops clk_stm32_hse_div_ops = {
+	.get_rate = clk_stm32_divider_get_rate,
+	.set_rate = clk_stm32_hse_div_set_rate,
+};
+
+static TEE_Result clk_stm32_hsediv2_enable(struct clk *clk)
+{
+	return clk_stm32_gate_ops.enable(clk);
+}
+
+static void clk_stm32_hsediv2_disable(struct clk *clk)
+{
+	clk_stm32_gate_ops.disable(clk);
+}
+
+static unsigned long clk_stm32_hsediv2_get_rate(struct clk *clk __unused,
+						unsigned long prate)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	uintptr_t addr = priv->base + RCC_OCENSETR;
+
+	if (io_read32(addr) & RCC_OCENSETR_HSEDIV2BYP)
+		return prate;
+
+	return prate / 2;
+}
+
+static const struct clk_ops clk_hsediv2_ops = {
+	.enable = clk_stm32_hsediv2_enable,
+	.disable = clk_stm32_hsediv2_disable,
+	.get_rate = clk_stm32_hsediv2_get_rate,
+};
+
+struct clk_stm32_pll_cfg {
+	uint32_t pll_offset;
+	int gate_id;
+	int mux_id;
+};
+
+static unsigned long clk_get_pll1_fvco_rate(unsigned long refclk)
+{
+	uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_PLL_FREQ1);
+	uint32_t fbdiv = 0;
+	uint32_t refdiv = 0;
+	unsigned long freq = 0;
+
+	fbdiv = (reg & A35SS_SSC_PLL_FREQ1_FBDIV_MASK) >>
+		A35SS_SSC_PLL_FREQ1_FBDIV_SHIFT;
+
+	refdiv = (reg & A35SS_SSC_PLL_FREQ1_REFDIV_MASK) >>
+		 A35SS_SSC_PLL_FREQ1_REFDIV_SHIFT;
+
+	if (!refdiv || MUL_OVERFLOW(refclk, fbdiv, &freq))
+		panic();
+
+	return freq / refdiv;
+}
+
+static unsigned long clk_stm32_pll1_get_rate(struct clk *clk __unused,
+					     unsigned long prate)
+{
+	uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_PLL_FREQ2);
+	unsigned long dfout = 0;
+	uint32_t postdiv1 = 0;
+	uint32_t postdiv2 = 0;
+
+	postdiv1 = (reg & A35SS_SSC_PLL_FREQ2_POSTDIV1_MASK) >>
+		   A35SS_SSC_PLL_FREQ2_POSTDIV1_SHIFT;
+
+	postdiv2 = (reg & A35SS_SSC_PLL_FREQ2_POSTDIV2_MASK) >>
+		   A35SS_SSC_PLL_FREQ2_POSTDIV2_SHIFT;
+
+	if (postdiv1 == 0 || postdiv2 == 0)
+		dfout = prate;
+	else
+		dfout = clk_get_pll1_fvco_rate(prate) / (postdiv1 * postdiv2);
+
+	return dfout;
+}
+
+static struct stm32_clk_opp_cfg *
+clk_stm32_get_opp_config(struct stm32_clk_opp_cfg *opp_cfg, unsigned long rate)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < MAX_OPP && opp_cfg->frq; i++, opp_cfg++)
+		if (opp_cfg->frq == rate)
+			return opp_cfg;
+
+	return NULL;
+}
+
+static TEE_Result clk_stm32_pll1_set_rate(struct clk *clk __unused,
+					  unsigned long rate,
+					  unsigned long parent_rate __unused)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	struct stm32_clk_platdata *pdata = priv->pdata;
+	struct stm32_pll_dt_cfg *pll_conf = NULL;
+	struct stm32_clk_opp_cfg *opp = NULL;
+
+	opp = clk_stm32_get_opp_config(pdata->opp->cpu1_opp, rate);
+	if (!opp)
+		return TEE_ERROR_GENERIC;
+
+	pll_conf = &opp->pll_cfg;
+
+	clk_stm32_pll1_init(priv, PLL1_ID, pll_conf);
+
+	return TEE_SUCCESS;
+}
+
+static size_t clk_stm32_pll_get_parent(struct clk *clk)
+{
+	struct clk_stm32_pll_cfg *cfg = clk->priv;
+
+	return stm32_mux_get_parent(cfg->mux_id);
+}
+
+static const struct clk_ops clk_stm32_pll1_ops = {
+	.get_parent = clk_stm32_pll_get_parent,
+	.get_rate = clk_stm32_pll1_get_rate,
+	.set_rate = clk_stm32_pll1_set_rate,
+};
+
+static unsigned long clk_get_pll_fvco(uint32_t offset_base,
+				      unsigned long prate)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	uintptr_t pllxcfgr1 = priv->base + offset_base;
+	uintptr_t pllxcfgr2 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR2;
+	uintptr_t pllxcfgr3 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR3;
+	unsigned long fvco = 0;
+	uint32_t fracin = 0;
+	uint32_t fbdiv = 0;
+	uint32_t refdiv = 0;
+
+	fracin = io_read32(pllxcfgr3) & RCC_PLLxCFGR3_FRACIN_MASK;
+	fbdiv = (io_read32(pllxcfgr2) & RCC_PLLxCFGR2_FBDIV_MASK) >>
+		RCC_PLLxCFGR2_FBDIV_SHIFT;
+
+	refdiv = io_read32(pllxcfgr2) & RCC_PLLxCFGR2_FREFDIV_MASK;
+
+	assert(refdiv);
+
+	if (fracin) {
+		unsigned long long numerator = 0;
+		unsigned long long denominator = 0;
+
+		numerator = SHIFT_U64(fbdiv, 24) + fracin;
+		numerator = prate * numerator;
+		denominator = SHIFT_U64(refdiv, 24);
+		fvco = (unsigned long)(numerator / denominator);
+	} else {
+		fvco = (unsigned long)(prate * fbdiv / refdiv);
+	}
+
+	return fvco;
+}
+
+static unsigned long clk_stm32_pll_get_rate(struct clk *clk __unused,
+					    unsigned long prate)
+{
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	struct clk_stm32_pll_cfg *cfg = clk->priv;
+	uintptr_t pllxcfgr1 = priv->base + cfg->pll_offset;
+	uintptr_t pllxcfgr4 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR4;
+	uintptr_t pllxcfgr6 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR6;
+	uintptr_t pllxcfgr7 = pllxcfgr1 + RCC_OFFSET_PLLXCFGR7;
+	unsigned long dfout = 0;
+	uint32_t postdiv1 = 0;
+	uint32_t postdiv2 = 0;
+
+	postdiv1 = io_read32(pllxcfgr6) & RCC_PLLxCFGR6_POSTDIV1_MASK;
+	postdiv2 = io_read32(pllxcfgr7) & RCC_PLLxCFGR7_POSTDIV2_MASK;
+
+	if ((io_read32(pllxcfgr4) & RCC_PLLxCFGR4_BYPASS) ||
+	    !postdiv1 || !postdiv2)
+		dfout = prate;
+	else
+		dfout = clk_get_pll_fvco(cfg->pll_offset,
+					 prate) / (postdiv1 * postdiv2);
+
+	return dfout;
+}
+
+static TEE_Result clk_stm32_pll_enable(struct clk *clk)
+{
+	struct clk_stm32_pll_cfg *cfg = clk->priv;
+
+	if (stm32_gate_rdy_enable(cfg->gate_id)) {
+		EMSG("%s timeout", clk_get_name(clk));
+		return TEE_ERROR_TIMEOUT;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void clk_stm32_pll_disable(struct clk *clk)
+{
+	struct clk_stm32_pll_cfg *cfg = clk->priv;
+
+	if (stm32_gate_rdy_disable(cfg->gate_id)) {
+		EMSG("%s timeout", clk_get_name(clk));
+		panic();
+	}
+}
+
+static const struct clk_ops clk_stm32_pll_ops = {
+	.get_parent = clk_stm32_pll_get_parent,
+	.get_rate = clk_stm32_pll_get_rate,
+	.enable = clk_stm32_pll_enable,
+	.disable = clk_stm32_pll_disable,
+};
+
+static TEE_Result clk_stm32_pll3_enable(struct clk *clk)
+{
+	struct clk_stm32_pll_cfg *cfg = clk->priv;
+	struct clk_stm32_priv *priv = clk_stm32_get_priv();
+	struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(PLL3_ID);
+	struct clk *parent = NULL;
+	size_t pidx = 0;
+
+	/* ck_icn_p_gpu activate */
+	stm32_gate_enable(GATE_GPU);
+
+	clk_stm32_pll_init(priv, PLL3_ID, pll_conf);
+
+	if (stm32_gate_rdy_enable(cfg->gate_id)) {
+		EMSG("%s timeout", clk_get_name(clk));
+		return TEE_ERROR_TIMEOUT;
+	}
+
+	/* Update parent */
+	pidx = clk_stm32_pll_get_parent(clk);
+	parent = clk_get_parent_by_index(clk, pidx);
+
+	clk->parent = parent;
+
+	return TEE_SUCCESS;
+}
+
+static void clk_stm32_pll3_disable(struct clk *clk)
+{
+	clk_stm32_pll_disable(clk);
+	stm32_gate_disable(GATE_GPU);
+}
+
+static const struct clk_ops clk_stm32_pll3_ops = {
+	.get_parent = clk_stm32_pll_get_parent,
+	.get_rate = clk_stm32_pll_get_rate,
+	.enable = clk_stm32_pll3_enable,
+	.disable = clk_stm32_pll3_disable,
+};
+
+struct clk_stm32_flexgen_cfg {
+	int flex_id;
+};
+
+static size_t clk_stm32_flexgen_get_parent(struct clk *clk)
+{
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	uint32_t address = 0;
+
+	address = rcc_base + RCC_XBAR0CFGR + (cfg->flex_id * 4);
+
+	return io_read32(address) & RCC_XBAR0CFGR_XBAR0SEL_MASK;
+}
+
+static TEE_Result clk_stm32_flexgen_set_parent(struct clk *clk, size_t pidx)
+{
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uint16_t channel = cfg->flex_id * 4;
+
+	io_clrsetbits32(rcc_base + RCC_XBAR0CFGR + (channel),
+			RCC_XBAR0CFGR_XBAR0SEL_MASK, pidx);
+
+	if (wait_xbar_sts(channel))
+		return TEE_ERROR_GENERIC;
+
+	return TEE_SUCCESS;
+}
+
+static unsigned long clk_stm32_flexgen_get_rate(struct clk *clk __unused,
+						unsigned long prate)
+{
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	uint32_t prediv = 0;
+	uint32_t findiv = 0;
+	uint8_t channel = cfg->flex_id;
+	unsigned long freq = prate;
+
+	prediv = io_read32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel)) &
+		RCC_PREDIV0CFGR_PREDIV0_MASK;
+	findiv = io_read32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel)) &
+		RCC_FINDIV0CFGR_FINDIV0_MASK;
+
+	if (freq == 0)
+		return 0;
+
+	switch (prediv) {
+	case 0x0:
+		break;
+
+	case 0x1:
+		freq /= 2;
+		break;
+
+	case 0x3:
+		freq /= 4;
+		break;
+
+	case 0x3FF:
+		freq /= 1024;
+		break;
+
+	default:
+		EMSG("Unsupported PREDIV value (%#"PRIx32")", prediv);
+		panic();
+		break;
+	}
+
+	freq /= findiv + 1;
+
+	return freq;
+}
+
+static unsigned long clk_stm32_flexgen_get_round_rate(unsigned long rate,
+						      unsigned long prate,
+						      unsigned int *prediv,
+						      unsigned int *findiv)
+{
+	unsigned int pre_val[] = { 0x0, 0x1, 0x3, 0x3FF };
+	unsigned int pre_div[] = { 1, 2, 4, 1024 };
+	long best_diff = LONG_MAX;
+	unsigned int i = 0;
+
+	*prediv = 0;
+	*findiv = 0;
+
+	for (i = 0; i < ARRAY_SIZE(pre_div); i++) {
+		unsigned long freq = 0;
+		unsigned long ratio = 0;
+		long diff = 0L;
+
+		freq = UDIV_ROUND_NEAREST((uint64_t)prate, pre_div[i]);
+		ratio = UDIV_ROUND_NEAREST((uint64_t)freq, rate);
+
+		if (ratio == 0)
+			ratio = 1;
+		else if (ratio > 64)
+			ratio = 64;
+
+		freq = UDIV_ROUND_NEAREST((uint64_t)freq, ratio);
+		if (freq < rate)
+			diff = rate - freq;
+		else
+			diff = freq - rate;
+
+		if (diff < best_diff) {
+			best_diff = diff;
+			*prediv = pre_val[i];
+			*findiv = ratio - 1;
+
+			if (diff == 0)
+				break;
+		}
+	}
+
+	return (prate / (*prediv + 1)) / (*findiv + 1);
+}
+
+static TEE_Result clk_stm32_flexgen_set_rate(struct clk *clk,
+					     unsigned long rate,
+					     unsigned long parent_rate)
+{
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uint8_t channel = cfg->flex_id;
+	uintptr_t rcc_base = stm32_rcc_base();
+	unsigned int prediv = 0;
+	unsigned int findiv = 0;
+
+	clk_stm32_flexgen_get_round_rate(rate, parent_rate, &prediv, &findiv);
+
+	if (wait_predivsr(channel) != 0)
+		panic();
+
+	io_clrsetbits32(rcc_base + RCC_PREDIV0CFGR + (0x4 * channel),
+			RCC_PREDIV0CFGR_PREDIV0_MASK,
+			prediv);
+
+	if (wait_predivsr(channel) != 0)
+		panic();
+
+	if (wait_findivsr(channel) != 0)
+		panic();
+
+	io_clrsetbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel),
+			RCC_FINDIV0CFGR_FINDIV0_MASK,
+			findiv);
+
+	if (wait_findivsr(channel) != 0)
+		panic();
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result clk_stm32_flexgen_enable(struct clk *clk)
+{
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	uint8_t channel = cfg->flex_id;
+
+	io_setbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel),
+		     RCC_FINDIV0CFGR_FINDIV0EN);
+
+	return TEE_SUCCESS;
+}
+
+static void clk_stm32_flexgen_disable(struct clk *clk)
+{
+	struct clk_stm32_flexgen_cfg *cfg = clk->priv;
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	uint8_t channel = cfg->flex_id;
+
+	io_clrbits32(rcc_base + RCC_FINDIV0CFGR + (0x4 * channel),
+		     RCC_FINDIV0CFGR_FINDIV0EN);
+}
+
+static const struct clk_ops clk_stm32_flexgen_ops = {
+	.get_rate = clk_stm32_flexgen_get_rate,
+	.set_rate = clk_stm32_flexgen_set_rate,
+	.get_parent = clk_stm32_flexgen_get_parent,
+	.set_parent = clk_stm32_flexgen_set_parent,
+	.enable = clk_stm32_flexgen_enable,
+	.disable = clk_stm32_flexgen_disable,
+};
+
+static size_t clk_cpu1_get_parent(struct clk *clk __unused)
+{
+	uint32_t reg = stm32mp_syscfg_read(A35SS_SSC_CHGCLKREQ);
+
+	return (reg & A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_MASK) >>
+		A35SS_SSC_CHGCLKREQ_ARM_CHGCLKACK_SHIFT;
+}
+
+static const struct clk_ops clk_stm32_cpu1_ops = {
+	.get_parent = clk_cpu1_get_parent,
+};
+
+#define APB_DIV_MASK	GENMASK_32(2, 0)
+#define TIM_PRE_MASK	BIT(0)
+
+static unsigned long ck_timer_get_rate_ops(struct clk *clk, unsigned long prate)
+{
+	struct clk_stm32_timer_cfg *cfg = clk->priv;
+	uintptr_t rcc_base = clk_stm32_get_rcc_base();
+	uint32_t prescaler = 0;
+	uint32_t timpre = 0;
+
+	prescaler = io_read32(rcc_base + cfg->apbdiv) & APB_DIV_MASK;
+
+	timpre = io_read32(rcc_base + cfg->timpre) & TIM_PRE_MASK;
+
+	if (prescaler == 0)
+		return prate;
+
+	return prate * (timpre + 1) * 2;
+};
+
+static const struct clk_ops ck_timer_ops = {
+	.get_rate = ck_timer_get_rate_ops,
+};
+
+#define PLL_PARENTS	{ &ck_hsi, &ck_hse, &ck_msi }
+#define PLL_NUM_PATENTS	3
+
+#define STM32_OSC(_name, _flags, _gate_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_osc_ops,\
+		.priv = &(struct clk_stm32_gate_cfg){\
+			.gate_id = (_gate_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = 1,\
+		.parents = { NULL },\
+	}
+
+#define STM32_OSC_MSI(_name, _flags, _gate_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_oscillator_msi_ops,\
+		.priv = &(struct clk_stm32_gate_cfg){\
+			.gate_id = (_gate_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = 1,\
+		.parents = { NULL },\
+	}
+
+#define STM32_HSE_DIV2(_name, _parent, _flags, _gate_id)\
+	struct clk _name = {\
+		.ops = &clk_hsediv2_ops,\
+		.priv = &(struct clk_stm32_gate_cfg){\
+			.gate_id = (_gate_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = 1,\
+		.parents = { (_parent) },\
+	}
+
+#define STM32_HSE_RTC(_name, _parent, _flags, _div_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_hse_div_ops,\
+		.priv = &(struct clk_stm32_div_cfg){\
+			.div_id = (_div_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = 1,\
+		.parents = { (_parent) },\
+	}
+
+#define STM32_PLL1(_name, _flags, _mux_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_pll1_ops,\
+		.priv = &(struct clk_stm32_pll_cfg){\
+			.mux_id = (_mux_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = PLL_NUM_PATENTS,\
+		.parents = PLL_PARENTS,\
+	}
+
+#define STM32_PLL2(_name, _flags, _reg, _gate_id, _mux_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_pll_ops,\
+		.priv = &(struct clk_stm32_pll_cfg){\
+			.pll_offset = (_reg),\
+			.gate_id = (_gate_id),\
+			.mux_id = (_mux_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = PLL_NUM_PATENTS,\
+		.parents = PLL_PARENTS,\
+	}
+
+#define STM32_PLL3(_name, _flags, _reg, _gate_id, _mux_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_pll3_ops,\
+		.priv = &(struct clk_stm32_pll_cfg){\
+			.pll_offset = (_reg),\
+			.gate_id = (_gate_id),\
+			.mux_id = (_mux_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = PLL_NUM_PATENTS,\
+		.parents = PLL_PARENTS,\
+	}
+
+#define STM32_PLLS(_name, _flags, _reg, _gate_id, _mux_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_pll_ops,\
+		.priv = &(struct clk_stm32_pll_cfg){\
+			.pll_offset = (_reg),\
+			.gate_id = (_gate_id),\
+			.mux_id = (_mux_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = PLL_NUM_PATENTS,\
+		.parents = PLL_PARENTS,\
+	}
+
+static STM32_FIXED_RATE(ck_off, RCC_0_MHZ);
+
+static STM32_FIXED_RATE(ck_obser0, 0);
+static STM32_FIXED_RATE(ck_obser1, 0);
+static STM32_FIXED_RATE(spdifsymb, 0);
+static STM32_FIXED_RATE(txbyteclk, 27000000);
+
+/* Oscillator clocks */
+static STM32_OSC(ck_hsi, 0, GATE_HSI);
+static STM32_OSC(ck_hse, 0, GATE_HSE);
+static STM32_OSC_MSI(ck_msi, 0, GATE_MSI);
+static STM32_OSC(ck_lsi, 0, GATE_LSI);
+static STM32_OSC(ck_lse, 0, GATE_LSE);
+
+static STM32_HSE_DIV2(ck_hse_div2, &ck_hse, 0, GATE_HSEDIV2);
+static STM32_HSE_RTC(ck_hse_rtc, &ck_hse, 0, DIV_RTC);
+
+static STM32_FIXED_FACTOR(i2sckin, NULL, 0, 1, 1);
+
+static STM32_PLL1(ck_pll1, 0, MUX_MUXSEL5);
+static STM32_PLL2(ck_pll2, 0, RCC_PLL2CFGR1, GATE_PLL2, MUX_MUXSEL6);
+static STM32_PLL3(ck_pll3, 0, RCC_PLL3CFGR1, GATE_PLL3, MUX_MUXSEL7);
+static STM32_PLLS(ck_pll4, 0, RCC_PLL4CFGR1, GATE_PLL4, MUX_MUXSEL0);
+static STM32_PLLS(ck_pll5, 0, RCC_PLL5CFGR1, GATE_PLL5, MUX_MUXSEL1);
+static STM32_PLLS(ck_pll6, 0, RCC_PLL6CFGR1, GATE_PLL6, MUX_MUXSEL2);
+static STM32_PLLS(ck_pll7, 0, RCC_PLL7CFGR1, GATE_PLL7, MUX_MUXSEL3);
+static STM32_PLLS(ck_pll8, 0, RCC_PLL8CFGR1, GATE_PLL8, MUX_MUXSEL4);
+
+#define STM32_FLEXGEN(_name, _flags, _flex_id)\
+	struct clk _name = {\
+		.ops = &clk_stm32_flexgen_ops,\
+		.priv = &(struct clk_stm32_flexgen_cfg){\
+			.flex_id = (_flex_id),\
+		},\
+		.name = #_name,\
+		.flags = (_flags) | CLK_SET_RATE_UNGATE,\
+		.num_parents = 15,\
+		.parents = {\
+			&ck_pll4, &ck_pll5, &ck_pll6, &ck_pll7, &ck_pll8,\
+			&ck_hsi, &ck_hse, &ck_msi, &ck_hsi, &ck_hse, &ck_msi,\
+			&spdifsymb, &i2sckin, &ck_lsi, &ck_lse\
+		},\
+	}
+
+static STM32_FLEXGEN(ck_icn_hs_mcu, 0, 0);
+static STM32_FLEXGEN(ck_icn_sdmmc, 0, 1);
+static STM32_FLEXGEN(ck_icn_ddr, 0, 2);
+static STM32_FLEXGEN(ck_icn_display, 0, 3);
+static STM32_FLEXGEN(ck_icn_hsl, 0, 4);
+static STM32_FLEXGEN(ck_icn_nic, 0, 5);
+static STM32_FLEXGEN(ck_icn_vid, 0, 6);
+
+static STM32_DIVIDER(ck_icn_ls_mcu, &ck_icn_hs_mcu, 0, DIV_LSMCU);
+
+static STM32_FLEXGEN(ck_flexgen_07, 0, 7);
+static STM32_FLEXGEN(ck_flexgen_08, 0, 8);
+static STM32_FLEXGEN(ck_flexgen_09, 0, 9);
+static STM32_FLEXGEN(ck_flexgen_10, 0, 10);
+static STM32_FLEXGEN(ck_flexgen_11, 0, 11);
+static STM32_FLEXGEN(ck_flexgen_12, 0, 12);
+static STM32_FLEXGEN(ck_flexgen_13, 0, 13);
+static STM32_FLEXGEN(ck_flexgen_14, 0, 14);
+static STM32_FLEXGEN(ck_flexgen_15, 0, 15);
+static STM32_FLEXGEN(ck_flexgen_16, 0, 16);
+static STM32_FLEXGEN(ck_flexgen_17, 0, 17);
+static STM32_FLEXGEN(ck_flexgen_18, 0, 18);
+static STM32_FLEXGEN(ck_flexgen_19, 0, 19);
+static STM32_FLEXGEN(ck_flexgen_20, 0, 20);
+static STM32_FLEXGEN(ck_flexgen_21, 0, 21);
+static STM32_FLEXGEN(ck_flexgen_22, 0, 22);
+static STM32_FLEXGEN(ck_flexgen_23, 0, 23);
+static STM32_FLEXGEN(ck_flexgen_24, 0, 24);
+static STM32_FLEXGEN(ck_flexgen_25, 0, 25);
+static STM32_FLEXGEN(ck_flexgen_26, 0, 26);
+static STM32_FLEXGEN(ck_flexgen_27, 0, 27);
+static STM32_FLEXGEN(ck_flexgen_28, 0, 28);
+static STM32_FLEXGEN(ck_flexgen_29, 0, 29);
+static STM32_FLEXGEN(ck_flexgen_30, 0, 30);
+static STM32_FLEXGEN(ck_flexgen_31, 0, 31);
+static STM32_FLEXGEN(ck_flexgen_32, 0, 32);
+static STM32_FLEXGEN(ck_flexgen_33, 0, 33);
+static STM32_FLEXGEN(ck_flexgen_34, 0, 34);
+static STM32_FLEXGEN(ck_flexgen_35, 0, 35);
+static STM32_FLEXGEN(ck_flexgen_36, 0, 36);
+static STM32_FLEXGEN(ck_flexgen_37, 0, 37);
+static STM32_FLEXGEN(ck_flexgen_38, 0, 38);
+static STM32_FLEXGEN(ck_flexgen_39, 0, 39);
+static STM32_FLEXGEN(ck_flexgen_40, 0, 40);
+static STM32_FLEXGEN(ck_flexgen_41, 0, 41);
+static STM32_FLEXGEN(ck_flexgen_42, 0, 42);
+static STM32_FLEXGEN(ck_flexgen_43, 0, 43);
+static STM32_FLEXGEN(ck_flexgen_44, 0, 44);
+static STM32_FLEXGEN(ck_flexgen_45, 0, 45);
+static STM32_FLEXGEN(ck_flexgen_46, 0, 46);
+static STM32_FLEXGEN(ck_flexgen_47, 0, 47);
+static STM32_FLEXGEN(ck_flexgen_48, 0, 48);
+static STM32_FLEXGEN(ck_flexgen_49, 0, 49);
+static STM32_FLEXGEN(ck_flexgen_50, 0, 50);
+static STM32_FLEXGEN(ck_flexgen_51, 0, 51);
+static STM32_FLEXGEN(ck_flexgen_52, 0, 52);
+static STM32_FLEXGEN(ck_flexgen_53, 0, 53);
+static STM32_FLEXGEN(ck_flexgen_54, 0, 54);
+static STM32_FLEXGEN(ck_flexgen_55, 0, 55);
+static STM32_FLEXGEN(ck_flexgen_56, 0, 56);
+static STM32_FLEXGEN(ck_flexgen_57, 0, 57);
+static STM32_FLEXGEN(ck_flexgen_58, 0, 58);
+static STM32_FLEXGEN(ck_flexgen_59, 0, 59);
+static STM32_FLEXGEN(ck_flexgen_60, 0, 60);
+static STM32_FLEXGEN(ck_flexgen_61, 0, 61);
+static STM32_FLEXGEN(ck_flexgen_62, 0, 62);
+static STM32_FLEXGEN(ck_flexgen_63, 0, 63);
+
+static struct clk ck_cpu1 = {
+	.ops		= &clk_stm32_cpu1_ops,
+	.name		= "ck_cpu1",
+	.flags		= CLK_SET_RATE_PARENT,
+	.num_parents	= 2,
+	.parents	= { &ck_pll1, &ck_flexgen_63 },
+};
+
+static STM32_DIVIDER(ck_icn_apb1, &ck_icn_ls_mcu, 0, DIV_APB1);
+static STM32_DIVIDER(ck_icn_apb2, &ck_icn_ls_mcu, 0, DIV_APB2);
+static STM32_DIVIDER(ck_icn_apb3, &ck_icn_ls_mcu, 0, DIV_APB3);
+static STM32_DIVIDER(ck_icn_apb4, &ck_icn_ls_mcu, 0, DIV_APB4);
+static STM32_COMPOSITE(ck_icn_apbdbg, 1, { &ck_icn_ls_mcu }, 0,
+		       GATE_DBG, DIV_APBDBG, NO_MUX);
+
+#define STM32_TIMER(_name, _parent, _flags, _apbdiv, _timpre)\
+	struct clk _name = {\
+		.ops = &ck_timer_ops,\
+		.priv = &(struct clk_stm32_timer_cfg){\
+			.apbdiv = (_apbdiv),\
+			.timpre = (_timpre),\
+		},\
+		.name = #_name,\
+		.flags = (_flags),\
+		.num_parents = 1,\
+		.parents = { _parent },\
+	}
+
+/* Kernel Timers */
+static STM32_TIMER(ck_timg1, &ck_icn_apb1, 0, RCC_APB1DIVR, RCC_TIMG1PRER);
+static STM32_TIMER(ck_timg2, &ck_icn_apb2, 0, RCC_APB2DIVR, RCC_TIMG2PRER);
+
+/* Clocks under RCC RIF protection */
+static STM32_GATE(ck_sys_dbg, &ck_icn_apbdbg, 0, GATE_DBG);
+static STM32_GATE(ck_icn_p_stm, &ck_icn_apbdbg, 0, GATE_STM);
+static STM32_GATE(ck_icn_s_stm, &ck_icn_ls_mcu, 0, GATE_STM);
+static STM32_GATE(ck_ker_tsdbg, &ck_flexgen_43, 0, GATE_DBG);
+static STM32_GATE(ck_ker_tpiu, &ck_flexgen_44, 0, GATE_TRACE);
+static STM32_GATE(ck_icn_p_etr, &ck_icn_apbdbg, 0, GATE_ETR);
+static STM32_GATE(ck_icn_m_etr, &ck_flexgen_45, 0, GATE_ETR);
+static STM32_GATE(ck_sys_atb, &ck_flexgen_45, 0, GATE_DBG);
+
+static STM32_GATE(ck_icn_s_sysram, &ck_icn_hs_mcu, 0, GATE_SYSRAM);
+static STM32_GATE(ck_icn_s_vderam, &ck_icn_hs_mcu, 0, GATE_VDERAM);
+static STM32_GATE(ck_icn_s_retram, &ck_icn_hs_mcu, 0, GATE_RETRAM);
+static STM32_GATE(ck_icn_s_bkpsram, &ck_icn_ls_mcu, 0, GATE_BKPSRAM);
+static STM32_GATE(ck_icn_s_sram1, &ck_icn_hs_mcu, 0, GATE_SRAM1);
+static STM32_GATE(ck_icn_s_sram2, &ck_icn_hs_mcu, 0, GATE_SRAM2);
+static STM32_GATE(ck_icn_s_lpsram1, &ck_icn_ls_mcu, 0, GATE_LPSRAM1);
+static STM32_GATE(ck_icn_s_lpsram2, &ck_icn_ls_mcu, 0, GATE_LPSRAM2);
+static STM32_GATE(ck_icn_s_lpsram3, &ck_icn_ls_mcu, 0, GATE_LPSRAM3);
+static STM32_GATE(ck_icn_p_hpdma1, &ck_icn_ls_mcu, 0, GATE_HPDMA1);
+static STM32_GATE(ck_icn_p_hpdma2, &ck_icn_ls_mcu, 0, GATE_HPDMA2);
+static STM32_GATE(ck_icn_p_hpdma3, &ck_icn_ls_mcu, 0, GATE_HPDMA3);
+static STM32_GATE(ck_icn_p_lpdma, &ck_icn_ls_mcu, 0, GATE_LPDMA);
+static STM32_GATE(ck_icn_p_ipcc1, &ck_icn_ls_mcu, 0, GATE_IPCC1);
+static STM32_GATE(ck_icn_p_ipcc2, &ck_icn_ls_mcu, 0, GATE_IPCC2);
+static STM32_GATE(ck_icn_p_hsem, &ck_icn_ls_mcu, 0, GATE_HSEM);
+static STM32_GATE(ck_icn_p_gpioa, &ck_icn_ls_mcu, 0, GATE_GPIOA);
+static STM32_GATE(ck_icn_p_gpiob, &ck_icn_ls_mcu, 0, GATE_GPIOB);
+static STM32_GATE(ck_icn_p_gpioc, &ck_icn_ls_mcu, 0, GATE_GPIOC);
+static STM32_GATE(ck_icn_p_gpiod, &ck_icn_ls_mcu, 0, GATE_GPIOD);
+static STM32_GATE(ck_icn_p_gpioe, &ck_icn_ls_mcu, 0, GATE_GPIOE);
+static STM32_GATE(ck_icn_p_gpiof, &ck_icn_ls_mcu, 0, GATE_GPIOF);
+static STM32_GATE(ck_icn_p_gpiog, &ck_icn_ls_mcu, 0, GATE_GPIOG);
+static STM32_GATE(ck_icn_p_gpioh, &ck_icn_ls_mcu, 0, GATE_GPIOH);
+static STM32_GATE(ck_icn_p_gpioi, &ck_icn_ls_mcu, 0, GATE_GPIOI);
+static STM32_GATE(ck_icn_p_gpioj, &ck_icn_ls_mcu, 0, GATE_GPIOJ);
+static STM32_GATE(ck_icn_p_gpiok, &ck_icn_ls_mcu, 0, GATE_GPIOK);
+static STM32_GATE(ck_icn_p_gpioz, &ck_icn_ls_mcu, 0, GATE_GPIOZ);
+static STM32_GATE(ck_icn_p_rtc, &ck_icn_ls_mcu, 0, GATE_RTC);
+static STM32_COMPOSITE(ck_rtc, 4,
+		       PARENT(&ck_off, &ck_lse, &ck_lsi, &ck_hse_rtc),
+		       0, GATE_RTCCK, NO_DIV, MUX_RTC);
+static STM32_GATE(ck_icn_p_bsec, &ck_icn_apb3, 0, GATE_BSEC);
+static STM32_GATE(ck_icn_p_ddrphyc, &ck_icn_ls_mcu, 0, GATE_DDRPHYCAPB);
+static STM32_GATE(ck_icn_p_risaf4, &ck_icn_ls_mcu, 0, GATE_DDRCP);
+static STM32_GATE(ck_icn_s_ddr, &ck_icn_ddr, 0, GATE_DDRCP);
+static STM32_GATE(ck_icn_p_ddrc, &ck_icn_apb4, 0, GATE_DDRCAPB);
+static STM32_GATE(ck_icn_p_ddrcfg, &ck_icn_apb4, 0, GATE_DDRCFG);
+static STM32_GATE(ck_icn_p_syscpu1, &ck_icn_ls_mcu, 0, GATE_SYSCPU1);
+static STM32_GATE(ck_icn_p_is2m, &ck_icn_apb3, 0, GATE_IS2M);
+static STM32_COMPOSITE(ck_mco1, 2, PARENT(&ck_flexgen_61, &ck_obser0), 0,
+		       GATE_MCO1, NO_DIV, MUX_MCO1);
+static STM32_COMPOSITE(ck_mco2, 2, PARENT(&ck_flexgen_62, &ck_obser1), 0,
+		       GATE_MCO2, NO_DIV, MUX_MCO2);
+static STM32_GATE(ck_icn_s_ospi1, &ck_icn_hs_mcu, 0, GATE_OSPI1);
+static STM32_GATE(ck_ker_ospi1, &ck_flexgen_48, 0, GATE_OSPI1);
+static STM32_GATE(ck_icn_s_ospi2, &ck_icn_hs_mcu, 0, GATE_OSPI2);
+static STM32_GATE(ck_ker_ospi2, &ck_flexgen_49, 0, GATE_OSPI2);
+static STM32_GATE(ck_icn_p_fmc, &ck_icn_ls_mcu, 0, GATE_FMC);
+static STM32_GATE(ck_ker_fmc, &ck_flexgen_50, 0, GATE_FMC);
+
+/* Kernel Clocks */
+static STM32_GATE(ck_icn_p_cci, &ck_icn_ls_mcu, 0, GATE_CCI);
+static STM32_GATE(ck_icn_p_crc, &ck_icn_ls_mcu, 0, GATE_CRC);
+static STM32_GATE(ck_icn_p_ospiiom, &ck_icn_ls_mcu, 0, GATE_OSPIIOM);
+static STM32_GATE(ck_icn_p_hash, &ck_icn_ls_mcu, 0, GATE_HASH);
+static STM32_GATE(ck_icn_p_rng, &ck_icn_ls_mcu, 0, GATE_RNG);
+static STM32_GATE(ck_icn_p_cryp1, &ck_icn_ls_mcu, 0, GATE_CRYP1);
+static STM32_GATE(ck_icn_p_cryp2, &ck_icn_ls_mcu, 0, GATE_CRYP2);
+static STM32_GATE(ck_icn_p_saes, &ck_icn_ls_mcu, 0, GATE_SAES);
+static STM32_GATE(ck_icn_p_pka, &ck_icn_ls_mcu, 0, GATE_PKA);
+static STM32_GATE(ck_icn_p_adf1, &ck_icn_ls_mcu, 0, GATE_ADF1);
+static STM32_GATE(ck_icn_p_iwdg5, &ck_icn_ls_mcu, 0, GATE_IWDG5);
+static STM32_GATE(ck_icn_p_wwdg2, &ck_icn_ls_mcu, 0, GATE_WWDG2);
+static STM32_GATE(ck_icn_p_eth1, &ck_icn_ls_mcu, 0, GATE_ETH1);
+static STM32_GATE(ck_icn_p_ethsw, &ck_icn_ls_mcu, 0, GATE_ETHSWMAC);
+static STM32_GATE(ck_icn_p_eth2, &ck_icn_ls_mcu, 0, GATE_ETH2);
+static STM32_GATE(ck_icn_p_pcie, &ck_icn_ls_mcu, 0, GATE_PCIE);
+static STM32_GATE(ck_icn_p_adc12, &ck_icn_ls_mcu, 0, GATE_ADC12);
+static STM32_GATE(ck_icn_p_adc3, &ck_icn_ls_mcu, 0, GATE_ADC3);
+static STM32_GATE(ck_icn_p_mdf1, &ck_icn_ls_mcu, 0, GATE_MDF1);
+static STM32_GATE(ck_icn_p_spi8, &ck_icn_ls_mcu, 0, GATE_SPI8);
+static STM32_GATE(ck_icn_p_lpuart1, &ck_icn_ls_mcu, 0, GATE_LPUART1);
+static STM32_GATE(ck_icn_p_i2c8, &ck_icn_ls_mcu, 0, GATE_I2C8);
+static STM32_GATE(ck_icn_p_lptim3, &ck_icn_ls_mcu, 0, GATE_LPTIM3);
+static STM32_GATE(ck_icn_p_lptim4, &ck_icn_ls_mcu, 0, GATE_LPTIM4);
+static STM32_GATE(ck_icn_p_lptim5, &ck_icn_ls_mcu, 0, GATE_LPTIM5);
+static STM32_GATE(ck_icn_m_sdmmc1, &ck_icn_sdmmc, 0, GATE_SDMMC1);
+static STM32_GATE(ck_icn_m_sdmmc2, &ck_icn_sdmmc, 0, GATE_SDMMC2);
+static STM32_GATE(ck_icn_m_sdmmc3, &ck_icn_sdmmc, 0, GATE_SDMMC3);
+static STM32_GATE(ck_icn_m_usb2ohci, &ck_icn_hsl, 0, GATE_USB2);
+static STM32_GATE(ck_icn_m_usb2ehci, &ck_icn_hsl, 0, GATE_USB2);
+static STM32_GATE(ck_icn_m_usb3dr, &ck_icn_hsl, 0, GATE_USB3DR);
+
+static STM32_GATE(ck_icn_p_tim2, &ck_icn_apb1, 0, GATE_TIM2);
+static STM32_GATE(ck_icn_p_tim3, &ck_icn_apb1, 0, GATE_TIM3);
+static STM32_GATE(ck_icn_p_tim4, &ck_icn_apb1, 0, GATE_TIM4);
+static STM32_GATE(ck_icn_p_tim5, &ck_icn_apb1, 0, GATE_TIM5);
+static STM32_GATE(ck_icn_p_tim6, &ck_icn_apb1, 0, GATE_TIM6);
+static STM32_GATE(ck_icn_p_tim7, &ck_icn_apb1, 0, GATE_TIM7);
+static STM32_GATE(ck_icn_p_tim10, &ck_icn_apb1, 0, GATE_TIM10);
+static STM32_GATE(ck_icn_p_tim11, &ck_icn_apb1, 0, GATE_TIM11);
+static STM32_GATE(ck_icn_p_tim12, &ck_icn_apb1, 0, GATE_TIM12);
+static STM32_GATE(ck_icn_p_tim13, &ck_icn_apb1, 0, GATE_TIM13);
+static STM32_GATE(ck_icn_p_tim14, &ck_icn_apb1, 0, GATE_TIM14);
+static STM32_GATE(ck_icn_p_lptim1, &ck_icn_apb1, 0, GATE_LPTIM1);
+static STM32_GATE(ck_icn_p_lptim2, &ck_icn_apb1, 0, GATE_LPTIM2);
+static STM32_GATE(ck_icn_p_spi2, &ck_icn_apb1, 0, GATE_SPI2);
+static STM32_GATE(ck_icn_p_spi3, &ck_icn_apb1, 0, GATE_SPI3);
+static STM32_GATE(ck_icn_p_spdifrx, &ck_icn_apb1, 0, GATE_SPDIFRX);
+static STM32_GATE(ck_icn_p_usart2, &ck_icn_apb1, 0, GATE_USART2);
+static STM32_GATE(ck_icn_p_usart3, &ck_icn_apb1, 0, GATE_USART3);
+static STM32_GATE(ck_icn_p_uart4, &ck_icn_apb1, 0, GATE_UART4);
+static STM32_GATE(ck_icn_p_uart5, &ck_icn_apb1, 0, GATE_UART5);
+static STM32_GATE(ck_icn_p_i2c1, &ck_icn_apb1, 0, GATE_I2C1);
+static STM32_GATE(ck_icn_p_i2c2, &ck_icn_apb1, 0, GATE_I2C2);
+static STM32_GATE(ck_icn_p_i2c3, &ck_icn_apb1, 0, GATE_I2C3);
+static STM32_GATE(ck_icn_p_i2c4, &ck_icn_apb1, 0, GATE_I2C4);
+static STM32_GATE(ck_icn_p_i2c5, &ck_icn_apb1, 0, GATE_I2C5);
+static STM32_GATE(ck_icn_p_i2c6, &ck_icn_apb1, 0, GATE_I2C6);
+static STM32_GATE(ck_icn_p_i2c7, &ck_icn_apb1, 0, GATE_I2C7);
+static STM32_GATE(ck_icn_p_i3c1, &ck_icn_apb1, 0, GATE_I3C1);
+static STM32_GATE(ck_icn_p_i3c2, &ck_icn_apb1, 0, GATE_I3C2);
+static STM32_GATE(ck_icn_p_i3c3, &ck_icn_apb1, 0, GATE_I3C3);
+
+static STM32_GATE(ck_icn_p_i3c4, &ck_icn_ls_mcu, 0, GATE_I3C4);
+
+static STM32_GATE(ck_icn_p_tim1, &ck_icn_apb2, 0, GATE_TIM1);
+static STM32_GATE(ck_icn_p_tim8, &ck_icn_apb2, 0, GATE_TIM8);
+static STM32_GATE(ck_icn_p_tim15, &ck_icn_apb2, 0, GATE_TIM15);
+static STM32_GATE(ck_icn_p_tim16, &ck_icn_apb2, 0, GATE_TIM16);
+static STM32_GATE(ck_icn_p_tim17, &ck_icn_apb2, 0, GATE_TIM17);
+static STM32_GATE(ck_icn_p_tim20, &ck_icn_apb2, 0, GATE_TIM20);
+static STM32_GATE(ck_icn_p_sai1, &ck_icn_apb2, 0, GATE_SAI1);
+static STM32_GATE(ck_icn_p_sai2, &ck_icn_apb2, 0, GATE_SAI2);
+static STM32_GATE(ck_icn_p_sai3, &ck_icn_apb2, 0, GATE_SAI3);
+static STM32_GATE(ck_icn_p_sai4, &ck_icn_apb2, 0, GATE_SAI4);
+static STM32_GATE(ck_icn_p_usart1, &ck_icn_apb2, 0, GATE_USART1);
+static STM32_GATE(ck_icn_p_usart6, &ck_icn_apb2, 0, GATE_USART6);
+static STM32_GATE(ck_icn_p_uart7, &ck_icn_apb2, 0, GATE_UART7);
+static STM32_GATE(ck_icn_p_uart8, &ck_icn_apb2, 0, GATE_UART8);
+static STM32_GATE(ck_icn_p_uart9, &ck_icn_apb2, 0, GATE_UART9);
+static STM32_GATE(ck_icn_p_fdcan, &ck_icn_apb2, 0, GATE_FDCAN);
+static STM32_GATE(ck_icn_p_spi1, &ck_icn_apb2, 0, GATE_SPI1);
+static STM32_GATE(ck_icn_p_spi4, &ck_icn_apb2, 0, GATE_SPI4);
+static STM32_GATE(ck_icn_p_spi5, &ck_icn_apb2, 0, GATE_SPI5);
+static STM32_GATE(ck_icn_p_spi6, &ck_icn_apb2, 0, GATE_SPI6);
+static STM32_GATE(ck_icn_p_spi7, &ck_icn_apb2, 0, GATE_SPI7);
+static STM32_GATE(ck_icn_p_iwdg1, &ck_icn_apb3, 0, GATE_IWDG1);
+static STM32_GATE(ck_icn_p_iwdg2, &ck_icn_apb3, 0, GATE_IWDG2);
+static STM32_GATE(ck_icn_p_iwdg3, &ck_icn_apb3, 0, GATE_IWDG3);
+static STM32_GATE(ck_icn_p_iwdg4, &ck_icn_apb3, 0, GATE_IWDG4);
+static STM32_GATE(ck_icn_p_wwdg1, &ck_icn_apb3, 0, GATE_WWDG1);
+static STM32_GATE(ck_icn_p_vref, &ck_icn_apb3, 0, GATE_VREF);
+static STM32_GATE(ck_icn_p_dts, &ck_icn_apb3, 0, GATE_DTS);
+static STM32_GATE(ck_icn_p_serc, &ck_icn_apb3, 0, GATE_SERC);
+static STM32_GATE(ck_icn_p_hdp, &ck_icn_apb3, 0, GATE_HDP);
+static STM32_GATE(ck_icn_p_dsi, &ck_icn_apb4, 0, GATE_DSI);
+static STM32_GATE(ck_icn_p_ltdc, &ck_icn_apb4, 0, GATE_LTDC);
+static STM32_GATE(ck_icn_p_csi, &ck_icn_apb4, 0, GATE_CSI);
+static STM32_GATE(ck_icn_p_dcmipp, &ck_icn_apb4, 0, GATE_DCMIPP);
+static STM32_GATE(ck_icn_p_lvds, &ck_icn_apb4, 0, GATE_LVDS);
+static STM32_GATE(ck_icn_p_gicv2m, &ck_icn_apb4, 0, GATE_GICV2M);
+static STM32_GATE(ck_icn_p_usbtc, &ck_icn_apb4, 0, GATE_USBTC);
+static STM32_GATE(ck_icn_p_usb3pciephy, &ck_icn_apb4, 0, GATE_USB3PCIEPHY);
+static STM32_GATE(ck_icn_p_stgen, &ck_icn_apb4, 0, GATE_STGEN);
+static STM32_GATE(ck_icn_p_vdec, &ck_icn_apb4, 0, GATE_VDEC);
+static STM32_GATE(ck_icn_p_venc, &ck_icn_apb4, 0, GATE_VENC);
+
+static STM32_GATE(ck_ker_tim2, &ck_timg1, 0, GATE_TIM2);
+static STM32_GATE(ck_ker_tim3, &ck_timg1, 0, GATE_TIM3);
+static STM32_GATE(ck_ker_tim4, &ck_timg1, 0, GATE_TIM4);
+static STM32_GATE(ck_ker_tim5, &ck_timg1, 0, GATE_TIM5);
+static STM32_GATE(ck_ker_tim6, &ck_timg1, 0, GATE_TIM6);
+static STM32_GATE(ck_ker_tim7, &ck_timg1, 0, GATE_TIM7);
+static STM32_GATE(ck_ker_tim10, &ck_timg1, 0, GATE_TIM10);
+static STM32_GATE(ck_ker_tim11, &ck_timg1, 0, GATE_TIM11);
+static STM32_GATE(ck_ker_tim12, &ck_timg1, 0, GATE_TIM12);
+static STM32_GATE(ck_ker_tim13, &ck_timg1, 0, GATE_TIM13);
+static STM32_GATE(ck_ker_tim14, &ck_timg1, 0, GATE_TIM14);
+static STM32_GATE(ck_ker_tim1, &ck_timg2, 0, GATE_TIM1);
+static STM32_GATE(ck_ker_tim8, &ck_timg2, 0, GATE_TIM8);
+static STM32_GATE(ck_ker_tim15, &ck_timg2, 0, GATE_TIM15);
+static STM32_GATE(ck_ker_tim16, &ck_timg2, 0, GATE_TIM16);
+static STM32_GATE(ck_ker_tim17, &ck_timg2, 0, GATE_TIM17);
+static STM32_GATE(ck_ker_tim20, &ck_timg2, 0, GATE_TIM20);
+static STM32_GATE(ck_ker_lptim1, &ck_flexgen_07, 0, GATE_LPTIM1);
+static STM32_GATE(ck_ker_lptim2, &ck_flexgen_07, 0, GATE_LPTIM2);
+static STM32_GATE(ck_ker_usart2, &ck_flexgen_08, 0, GATE_USART2);
+static STM32_GATE(ck_ker_uart4, &ck_flexgen_08, 0, GATE_UART4);
+static STM32_GATE(ck_ker_usart3, &ck_flexgen_09, 0, GATE_USART3);
+static STM32_GATE(ck_ker_uart5, &ck_flexgen_09, 0, GATE_UART5);
+static STM32_GATE(ck_ker_spi2, &ck_flexgen_10, 0, GATE_SPI2);
+static STM32_GATE(ck_ker_spi3, &ck_flexgen_10, 0, GATE_SPI3);
+static STM32_GATE(ck_ker_spdifrx, &ck_flexgen_11, 0, GATE_SPDIFRX);
+static STM32_GATE(ck_ker_i2c1, &ck_flexgen_12, 0, GATE_I2C1);
+static STM32_GATE(ck_ker_i2c2, &ck_flexgen_12, 0, GATE_I2C2);
+static STM32_GATE(ck_ker_i3c1, &ck_flexgen_12, 0, GATE_I3C1);
+static STM32_GATE(ck_ker_i3c2, &ck_flexgen_12, 0, GATE_I3C2);
+static STM32_GATE(ck_ker_i2c3, &ck_flexgen_13, 0, GATE_I2C3);
+static STM32_GATE(ck_ker_i2c5, &ck_flexgen_13, 0, GATE_I2C5);
+static STM32_GATE(ck_ker_i3c3, &ck_flexgen_13, 0, GATE_I3C3);
+static STM32_GATE(ck_ker_i2c4, &ck_flexgen_14, 0, GATE_I2C4);
+static STM32_GATE(ck_ker_i2c6, &ck_flexgen_14, 0, GATE_I2C6);
+static STM32_GATE(ck_ker_i2c7, &ck_flexgen_15, 0, GATE_I2C7);
+static STM32_GATE(ck_ker_spi1, &ck_flexgen_16, 0, GATE_SPI1);
+static STM32_GATE(ck_ker_spi4, &ck_flexgen_17, 0, GATE_SPI4);
+static STM32_GATE(ck_ker_spi5, &ck_flexgen_17, 0, GATE_SPI5);
+static STM32_GATE(ck_ker_spi6, &ck_flexgen_18, 0, GATE_SPI6);
+static STM32_GATE(ck_ker_spi7, &ck_flexgen_18, 0, GATE_SPI7);
+static STM32_GATE(ck_ker_usart1, &ck_flexgen_19, 0, GATE_USART1);
+static STM32_GATE(ck_ker_usart6, &ck_flexgen_20, 0, GATE_USART6);
+static STM32_GATE(ck_ker_uart7, &ck_flexgen_21, 0, GATE_UART7);
+static STM32_GATE(ck_ker_uart8, &ck_flexgen_21, 0, GATE_UART8);
+static STM32_GATE(ck_ker_uart9, &ck_flexgen_22, 0, GATE_UART9);
+static STM32_GATE(ck_ker_mdf1, &ck_flexgen_23, 0, GATE_MDF1);
+static STM32_GATE(ck_ker_sai1, &ck_flexgen_23, 0, GATE_SAI1);
+static STM32_GATE(ck_ker_sai2, &ck_flexgen_24, 0, GATE_SAI2);
+static STM32_GATE(ck_ker_sai3, &ck_flexgen_25, 0, GATE_SAI3);
+static STM32_GATE(ck_ker_sai4, &ck_flexgen_25, 0, GATE_SAI4);
+static STM32_GATE(ck_ker_fdcan, &ck_flexgen_26, 0, GATE_FDCAN);
+static STM32_GATE(ck_ker_csi, &ck_flexgen_29, 0, GATE_CSI);
+static STM32_GATE(ck_ker_csitxesc, &ck_flexgen_30, 0, GATE_CSI);
+static STM32_GATE(ck_ker_csiphy, &ck_flexgen_31, 0, GATE_CSI);
+static STM32_GATE(ck_ker_stgen, &ck_flexgen_33, CLK_SET_RATE_PARENT,
+		  GATE_STGEN);
+static STM32_GATE(ck_ker_usbtc, &ck_flexgen_35, 0, GATE_USBTC);
+static STM32_GATE(ck_ker_i3c4, &ck_flexgen_36, 0, GATE_I3C4);
+static STM32_GATE(ck_ker_spi8, &ck_flexgen_37, 0, GATE_SPI8);
+static STM32_GATE(ck_ker_i2c8, &ck_flexgen_38, 0, GATE_I2C8);
+static STM32_GATE(ck_ker_lpuart1, &ck_flexgen_39, 0, GATE_LPUART1);
+static STM32_GATE(ck_ker_lptim3, &ck_flexgen_40, 0, GATE_LPTIM3);
+static STM32_GATE(ck_ker_lptim4, &ck_flexgen_41, 0, GATE_LPTIM4);
+static STM32_GATE(ck_ker_lptim5, &ck_flexgen_41, 0, GATE_LPTIM5);
+static STM32_GATE(ck_ker_adf1, &ck_flexgen_42, 0, GATE_ADF1);
+static STM32_GATE(ck_ker_sdmmc1, &ck_flexgen_51, 0, GATE_SDMMC1);
+static STM32_GATE(ck_ker_sdmmc2, &ck_flexgen_52, 0, GATE_SDMMC2);
+static STM32_GATE(ck_ker_sdmmc3, &ck_flexgen_53, 0, GATE_SDMMC3);
+static STM32_GATE(ck_ker_eth1, &ck_flexgen_54, 0, GATE_ETH1);
+static STM32_GATE(ck_ker_ethsw, &ck_flexgen_54, 0, GATE_ETHSW);
+static STM32_GATE(ck_ker_eth2, &ck_flexgen_55, 0, GATE_ETH2);
+static STM32_GATE(ck_ker_eth1ptp, &ck_flexgen_56, 0, GATE_ETH1);
+static STM32_GATE(ck_ker_eth2ptp, &ck_flexgen_56, 0, GATE_ETH2);
+static STM32_GATE(ck_ker_usb2phy2, &ck_flexgen_58, 0, GATE_USB3DR);
+static STM32_GATE(ck_icn_m_gpu, &ck_flexgen_59, 0, GATE_GPU);
+static STM32_GATE(ck_ker_gpu, &ck_pll3, 0, GATE_GPU);
+static STM32_GATE(ck_ker_ethswref, &ck_flexgen_60, 0, GATE_ETHSWREF);
+
+static STM32_GATE(ck_ker_eth1stp, &ck_icn_ls_mcu, 0, GATE_ETH1STP);
+static STM32_GATE(ck_ker_eth2stp, &ck_icn_ls_mcu, 0, GATE_ETH2STP);
+
+static STM32_GATE(ck_ker_ltdc, &ck_flexgen_27, CLK_SET_RATE_PARENT,
+		  GATE_LTDC);
+
+static STM32_COMPOSITE(ck_ker_adc12, 2, PARENT(&ck_flexgen_46, &ck_icn_ls_mcu),
+		       0, GATE_ADC12, NO_DIV, MUX_ADC12);
+
+static STM32_COMPOSITE(ck_ker_adc3, 3, PARENT(&ck_flexgen_47, &ck_icn_ls_mcu,
+		       &ck_flexgen_46),
+		       0, GATE_ADC3, NO_DIV, MUX_ADC3);
+
+static STM32_COMPOSITE(ck_ker_usb2phy1, 2, PARENT(&ck_flexgen_57,
+		       &ck_hse_div2),
+		       0, GATE_USB2PHY1, NO_DIV, MUX_USB2PHY1);
+
+static STM32_COMPOSITE(ck_ker_usb2phy2_en, 2, PARENT(&ck_flexgen_58,
+		       &ck_hse_div2),
+		       0, GATE_USB2PHY2, NO_DIV, MUX_USB2PHY2);
+
+static STM32_COMPOSITE(ck_ker_usb3pciephy, 2, PARENT(&ck_flexgen_34,
+		       &ck_hse_div2),
+		       0, GATE_USB3PCIEPHY, NO_DIV, MUX_USB3PCIEPHY);
+
+static STM32_COMPOSITE(clk_lanebyte, 2, PARENT(&txbyteclk, &ck_ker_ltdc),
+		       0, GATE_DSI, NO_DIV, MUX_DSIBLANE);
+
+static STM32_COMPOSITE(ck_phy_dsi, 2, PARENT(&ck_flexgen_28, &ck_hse),
+		       0, GATE_DSI, NO_DIV, MUX_DSIPHY);
+
+static STM32_COMPOSITE(ck_ker_lvdsphy, 2, PARENT(&ck_flexgen_32, &ck_hse),
+		       0, GATE_LVDS, NO_DIV, MUX_LVDSPHY);
+
+static STM32_COMPOSITE(ck_ker_dts, 3, PARENT(&ck_hsi, &ck_hse, &ck_msi),
+		       0, GATE_DTS, NO_DIV, MUX_DTS);
+
+enum {
+	CK_OFF = STM32MP25_LAST_CLK,
+	I2SCKIN,
+	SPDIFSYMB,
+	CK_HSE_RTC,
+	TXBYTECLK,
+	CK_OBSER0,
+	CK_OBSER1,
+	STM32MP25_ALL_CLK_NB
+};
+
+static STM32_GATE(ck_ker_eth1mac, &ck_icn_ls_mcu, 0, GATE_ETH1MAC);
+static STM32_GATE(ck_ker_eth1tx, &ck_icn_ls_mcu, 0, GATE_ETH1TX);
+static STM32_GATE(ck_ker_eth1rx, &ck_icn_ls_mcu, 0, GATE_ETH1RX);
+static STM32_GATE(ck_ker_eth2mac, &ck_icn_ls_mcu, 0, GATE_ETH2MAC);
+static STM32_GATE(ck_ker_eth2tx, &ck_icn_ls_mcu, 0, GATE_ETH2TX);
+static STM32_GATE(ck_ker_eth2rx, &ck_icn_ls_mcu, 0, GATE_ETH2RX);
+
+static struct clk *stm32mp25_clk_provided[STM32MP25_ALL_CLK_NB] = {
+	[HSI_CK]		= &ck_hsi,
+	[HSE_CK]		= &ck_hse,
+	[MSI_CK]		= &ck_msi,
+	[LSI_CK]		= &ck_lsi,
+	[LSE_CK]		= &ck_lse,
+
+	[HSE_DIV2_CK]		= &ck_hse_div2,
+
+	[PLL1_CK]		= &ck_pll1,
+	[PLL2_CK]		= &ck_pll2,
+	[PLL3_CK]		= &ck_pll3,
+	[PLL4_CK]		= &ck_pll4,
+	[PLL5_CK]		= &ck_pll5,
+	[PLL6_CK]		= &ck_pll6,
+	[PLL7_CK]		= &ck_pll7,
+	[PLL8_CK]		= &ck_pll8,
+
+	[CK_ICN_HS_MCU]		= &ck_icn_hs_mcu,
+	[CK_ICN_LS_MCU]		= &ck_icn_ls_mcu,
+
+	[CK_ICN_SDMMC]		= &ck_icn_sdmmc,
+	[CK_ICN_DDR]		= &ck_icn_ddr,
+	[CK_ICN_DISPLAY]	= &ck_icn_display,
+	[CK_ICN_HSL]		= &ck_icn_hsl,
+	[CK_ICN_NIC]		= &ck_icn_nic,
+	[CK_ICN_VID]		= &ck_icn_vid,
+	[CK_FLEXGEN_07]		= &ck_flexgen_07,
+	[CK_FLEXGEN_08]		= &ck_flexgen_08,
+	[CK_FLEXGEN_09]		= &ck_flexgen_09,
+	[CK_FLEXGEN_10]		= &ck_flexgen_10,
+	[CK_FLEXGEN_11]		= &ck_flexgen_11,
+	[CK_FLEXGEN_12]		= &ck_flexgen_12,
+	[CK_FLEXGEN_13]		= &ck_flexgen_13,
+	[CK_FLEXGEN_14]		= &ck_flexgen_14,
+	[CK_FLEXGEN_15]		= &ck_flexgen_15,
+	[CK_FLEXGEN_16]		= &ck_flexgen_16,
+	[CK_FLEXGEN_17]		= &ck_flexgen_17,
+	[CK_FLEXGEN_18]		= &ck_flexgen_18,
+	[CK_FLEXGEN_19]		= &ck_flexgen_19,
+	[CK_FLEXGEN_20]		= &ck_flexgen_20,
+	[CK_FLEXGEN_21]		= &ck_flexgen_21,
+	[CK_FLEXGEN_22]		= &ck_flexgen_22,
+	[CK_FLEXGEN_23]		= &ck_flexgen_23,
+	[CK_FLEXGEN_24]		= &ck_flexgen_24,
+	[CK_FLEXGEN_25]		= &ck_flexgen_25,
+	[CK_FLEXGEN_26]		= &ck_flexgen_26,
+	[CK_FLEXGEN_27]		= &ck_flexgen_27,
+	[CK_FLEXGEN_28]		= &ck_flexgen_28,
+	[CK_FLEXGEN_29]		= &ck_flexgen_29,
+	[CK_FLEXGEN_30]		= &ck_flexgen_30,
+	[CK_FLEXGEN_31]		= &ck_flexgen_31,
+	[CK_FLEXGEN_32]		= &ck_flexgen_32,
+	[CK_FLEXGEN_33]		= &ck_flexgen_33,
+	[CK_FLEXGEN_34]		= &ck_flexgen_34,
+	[CK_FLEXGEN_35]		= &ck_flexgen_35,
+	[CK_FLEXGEN_36]		= &ck_flexgen_36,
+	[CK_FLEXGEN_37]		= &ck_flexgen_37,
+	[CK_FLEXGEN_38]		= &ck_flexgen_38,
+	[CK_FLEXGEN_39]		= &ck_flexgen_39,
+	[CK_FLEXGEN_40]		= &ck_flexgen_40,
+	[CK_FLEXGEN_41]		= &ck_flexgen_41,
+	[CK_FLEXGEN_42]		= &ck_flexgen_42,
+	[CK_FLEXGEN_43]		= &ck_flexgen_43,
+	[CK_FLEXGEN_44]		= &ck_flexgen_44,
+	[CK_FLEXGEN_45]		= &ck_flexgen_45,
+	[CK_FLEXGEN_46]		= &ck_flexgen_46,
+	[CK_FLEXGEN_47]		= &ck_flexgen_47,
+	[CK_FLEXGEN_48]		= &ck_flexgen_48,
+	[CK_FLEXGEN_49]		= &ck_flexgen_49,
+	[CK_FLEXGEN_50]		= &ck_flexgen_50,
+	[CK_FLEXGEN_51]		= &ck_flexgen_51,
+	[CK_FLEXGEN_52]		= &ck_flexgen_52,
+	[CK_FLEXGEN_53]		= &ck_flexgen_53,
+	[CK_FLEXGEN_54]		= &ck_flexgen_54,
+	[CK_FLEXGEN_55]		= &ck_flexgen_55,
+	[CK_FLEXGEN_56]		= &ck_flexgen_56,
+	[CK_FLEXGEN_57]		= &ck_flexgen_57,
+	[CK_FLEXGEN_58]		= &ck_flexgen_58,
+	[CK_FLEXGEN_59]		= &ck_flexgen_59,
+	[CK_FLEXGEN_60]		= &ck_flexgen_60,
+	[CK_FLEXGEN_61]		= &ck_flexgen_61,
+	[CK_FLEXGEN_62]		= &ck_flexgen_62,
+	[CK_FLEXGEN_63]		= &ck_flexgen_63,
+
+	[CK_CPU1]		= &ck_cpu1,
+
+	[CK_ICN_APB1]		= &ck_icn_apb1,
+	[CK_ICN_APB2]		= &ck_icn_apb2,
+	[CK_ICN_APB3]		= &ck_icn_apb3,
+	[CK_ICN_APB4]		= &ck_icn_apb4,
+	[CK_ICN_APBDBG]		= &ck_icn_apbdbg,
+
+	[TIMG1_CK]		= &ck_timg1,
+	[TIMG2_CK]		= &ck_timg2,
+
+	[CK_BUS_SYSRAM]		= &ck_icn_s_sysram,
+	[CK_BUS_VDERAM]		= &ck_icn_s_vderam,
+	[CK_BUS_RETRAM]		= &ck_icn_s_retram,
+	[CK_BUS_SRAM1]		= &ck_icn_s_sram1,
+	[CK_BUS_SRAM2]		= &ck_icn_s_sram2,
+	[CK_BUS_OSPI1]		= &ck_icn_s_ospi1,
+	[CK_BUS_OSPI2]		= &ck_icn_s_ospi2,
+	[CK_BUS_BKPSRAM]	= &ck_icn_s_bkpsram,
+	[CK_BUS_DDRPHYC]	= &ck_icn_p_ddrphyc,
+	[CK_BUS_SYSCPU1]	= &ck_icn_p_syscpu1,
+	[CK_BUS_HPDMA1]		= &ck_icn_p_hpdma1,
+	[CK_BUS_HPDMA2]		= &ck_icn_p_hpdma2,
+	[CK_BUS_HPDMA3]		= &ck_icn_p_hpdma3,
+	[CK_BUS_IPCC1]		= &ck_icn_p_ipcc1,
+	[CK_BUS_IPCC2]		= &ck_icn_p_ipcc2,
+	[CK_BUS_CCI]		= &ck_icn_p_cci,
+	[CK_BUS_CRC]		= &ck_icn_p_crc,
+	[CK_BUS_OSPIIOM]	= &ck_icn_p_ospiiom,
+	[CK_BUS_HASH]		= &ck_icn_p_hash,
+	[CK_BUS_RNG]		= &ck_icn_p_rng,
+	[CK_BUS_CRYP1]		= &ck_icn_p_cryp1,
+	[CK_BUS_CRYP2]		= &ck_icn_p_cryp2,
+	[CK_BUS_SAES]		= &ck_icn_p_saes,
+	[CK_BUS_PKA]		= &ck_icn_p_pka,
+	[CK_BUS_GPIOA]		= &ck_icn_p_gpioa,
+	[CK_BUS_GPIOB]		= &ck_icn_p_gpiob,
+	[CK_BUS_GPIOC]		= &ck_icn_p_gpioc,
+	[CK_BUS_GPIOD]		= &ck_icn_p_gpiod,
+	[CK_BUS_GPIOE]		= &ck_icn_p_gpioe,
+	[CK_BUS_GPIOF]		= &ck_icn_p_gpiof,
+	[CK_BUS_GPIOG]		= &ck_icn_p_gpiog,
+	[CK_BUS_GPIOH]		= &ck_icn_p_gpioh,
+	[CK_BUS_GPIOI]		= &ck_icn_p_gpioi,
+	[CK_BUS_GPIOJ]		= &ck_icn_p_gpioj,
+	[CK_BUS_GPIOK]		= &ck_icn_p_gpiok,
+	[CK_BUS_LPSRAM1]	= &ck_icn_s_lpsram1,
+	[CK_BUS_LPSRAM2]	= &ck_icn_s_lpsram2,
+	[CK_BUS_LPSRAM3]	= &ck_icn_s_lpsram3,
+	[CK_BUS_GPIOZ]		= &ck_icn_p_gpioz,
+	[CK_BUS_LPDMA]		= &ck_icn_p_lpdma,
+	[CK_BUS_ADF1]		= &ck_icn_p_adf1,
+	[CK_BUS_HSEM]		= &ck_icn_p_hsem,
+	[CK_BUS_RTC]		= &ck_icn_p_rtc,
+	[CK_BUS_IWDG5]		= &ck_icn_p_iwdg5,
+	[CK_BUS_WWDG2]		= &ck_icn_p_wwdg2,
+	[CK_BUS_STM]		= &ck_icn_p_stm,
+	[CK_KER_STM]		= &ck_icn_s_stm,
+	[CK_BUS_FMC]		= &ck_icn_p_fmc,
+	[CK_BUS_ETH1]		= &ck_icn_p_eth1,
+	[CK_BUS_ETHSW]		= &ck_icn_p_ethsw,
+	[CK_BUS_ETH2]		= &ck_icn_p_eth2,
+	[CK_BUS_PCIE]		= &ck_icn_p_pcie,
+	[CK_BUS_ADC12]		= &ck_icn_p_adc12,
+	[CK_BUS_ADC3]		= &ck_icn_p_adc3,
+	[CK_BUS_MDF1]		= &ck_icn_p_mdf1,
+	[CK_BUS_SPI8]		= &ck_icn_p_spi8,
+	[CK_BUS_LPUART1]	= &ck_icn_p_lpuart1,
+	[CK_BUS_I2C8]		= &ck_icn_p_i2c8,
+	[CK_BUS_LPTIM3]		= &ck_icn_p_lptim3,
+	[CK_BUS_LPTIM4]		= &ck_icn_p_lptim4,
+	[CK_BUS_LPTIM5]		= &ck_icn_p_lptim5,
+	[CK_BUS_RISAF4]		= &ck_icn_p_risaf4,
+	[CK_BUS_SDMMC1]		= &ck_icn_m_sdmmc1,
+	[CK_BUS_SDMMC2]		= &ck_icn_m_sdmmc2,
+	[CK_BUS_SDMMC3]		= &ck_icn_m_sdmmc3,
+	[CK_BUS_DDR]		= &ck_icn_s_ddr,
+	[CK_BUS_USB2OHCI]	= &ck_icn_m_usb2ohci,
+	[CK_BUS_USB2EHCI]	= &ck_icn_m_usb2ehci,
+	[CK_BUS_USB3DR]		= &ck_icn_m_usb3dr,
+	[CK_BUS_TIM2]		= &ck_icn_p_tim2,
+	[CK_BUS_TIM3]		= &ck_icn_p_tim3,
+	[CK_BUS_TIM4]		= &ck_icn_p_tim4,
+	[CK_BUS_TIM5]		= &ck_icn_p_tim5,
+	[CK_BUS_TIM6]		= &ck_icn_p_tim6,
+	[CK_BUS_TIM7]		= &ck_icn_p_tim7,
+	[CK_BUS_TIM10]		= &ck_icn_p_tim10,
+	[CK_BUS_TIM11]		= &ck_icn_p_tim11,
+	[CK_BUS_TIM12]		= &ck_icn_p_tim12,
+	[CK_BUS_TIM13]		= &ck_icn_p_tim13,
+	[CK_BUS_TIM14]		= &ck_icn_p_tim14,
+	[CK_BUS_LPTIM1]		= &ck_icn_p_lptim1,
+	[CK_BUS_LPTIM2]		= &ck_icn_p_lptim2,
+	[CK_BUS_SPI2]		= &ck_icn_p_spi2,
+	[CK_BUS_SPI3]		= &ck_icn_p_spi3,
+	[CK_BUS_SPDIFRX]	= &ck_icn_p_spdifrx,
+	[CK_BUS_USART2]		= &ck_icn_p_usart2,
+	[CK_BUS_USART3]		= &ck_icn_p_usart3,
+	[CK_BUS_UART4]		= &ck_icn_p_uart4,
+	[CK_BUS_UART5]		= &ck_icn_p_uart5,
+	[CK_BUS_I2C1]		= &ck_icn_p_i2c1,
+	[CK_BUS_I2C2]		= &ck_icn_p_i2c2,
+	[CK_BUS_I2C3]		= &ck_icn_p_i2c3,
+	[CK_BUS_I2C4]		= &ck_icn_p_i2c4,
+	[CK_BUS_I2C5]		= &ck_icn_p_i2c5,
+	[CK_BUS_I2C6]		= &ck_icn_p_i2c6,
+	[CK_BUS_I2C7]		= &ck_icn_p_i2c7,
+	[CK_BUS_I3C1]		= &ck_icn_p_i3c1,
+	[CK_BUS_I3C2]		= &ck_icn_p_i3c2,
+	[CK_BUS_I3C3]		= &ck_icn_p_i3c3,
+	[CK_BUS_I3C4]		= &ck_icn_p_i3c4,
+	[CK_BUS_TIM1]		= &ck_icn_p_tim1,
+	[CK_BUS_TIM8]		= &ck_icn_p_tim8,
+	[CK_BUS_TIM15]		= &ck_icn_p_tim15,
+	[CK_BUS_TIM16]		= &ck_icn_p_tim16,
+	[CK_BUS_TIM17]		= &ck_icn_p_tim17,
+	[CK_BUS_TIM20]		= &ck_icn_p_tim20,
+	[CK_BUS_SAI1]		= &ck_icn_p_sai1,
+	[CK_BUS_SAI2]		= &ck_icn_p_sai2,
+	[CK_BUS_SAI3]		= &ck_icn_p_sai3,
+	[CK_BUS_SAI4]		= &ck_icn_p_sai4,
+	[CK_BUS_USART1]		= &ck_icn_p_usart1,
+	[CK_BUS_USART6]		= &ck_icn_p_usart6,
+	[CK_BUS_UART7]		= &ck_icn_p_uart7,
+	[CK_BUS_UART8]		= &ck_icn_p_uart8,
+	[CK_BUS_UART9]		= &ck_icn_p_uart9,
+	[CK_BUS_FDCAN]		= &ck_icn_p_fdcan,
+	[CK_BUS_SPI1]		= &ck_icn_p_spi1,
+	[CK_BUS_SPI4]		= &ck_icn_p_spi4,
+	[CK_BUS_SPI5]		= &ck_icn_p_spi5,
+	[CK_BUS_SPI6]		= &ck_icn_p_spi6,
+	[CK_BUS_SPI7]		= &ck_icn_p_spi7,
+	[CK_BUS_BSEC]		= &ck_icn_p_bsec,
+	[CK_BUS_IWDG1]		= &ck_icn_p_iwdg1,
+	[CK_BUS_IWDG2]		= &ck_icn_p_iwdg2,
+	[CK_BUS_IWDG3]		= &ck_icn_p_iwdg3,
+	[CK_BUS_IWDG4]		= &ck_icn_p_iwdg4,
+	[CK_BUS_WWDG1]		= &ck_icn_p_wwdg1,
+	[CK_BUS_VREF]		= &ck_icn_p_vref,
+	[CK_BUS_SERC]		= &ck_icn_p_serc,
+	[CK_BUS_DTS]		= &ck_icn_p_dts,
+	[CK_BUS_HDP]		= &ck_icn_p_hdp,
+	[CK_BUS_IS2M]		= &ck_icn_p_is2m,
+	[CK_BUS_DSI]		= &ck_icn_p_dsi,
+	[CK_BUS_LTDC]		= &ck_icn_p_ltdc,
+	[CK_BUS_CSI]		= &ck_icn_p_csi,
+	[CK_BUS_DCMIPP]		= &ck_icn_p_dcmipp,
+	[CK_BUS_DDRC]		= &ck_icn_p_ddrc,
+	[CK_BUS_DDRCFG]		= &ck_icn_p_ddrcfg,
+	[CK_BUS_LVDS]		= &ck_icn_p_lvds,
+	[CK_BUS_GICV2M]		= &ck_icn_p_gicv2m,
+	[CK_BUS_USBTC]		= &ck_icn_p_usbtc,
+	[CK_BUS_USB3PCIEPHY]	= &ck_icn_p_usb3pciephy,
+	[CK_BUS_STGEN]		= &ck_icn_p_stgen,
+	[CK_BUS_VDEC]		= &ck_icn_p_vdec,
+	[CK_BUS_VENC]		= &ck_icn_p_venc,
+	[CK_SYSDBG]		= &ck_sys_dbg,
+	[CK_KER_TIM2]		= &ck_ker_tim2,
+	[CK_KER_TIM3]		= &ck_ker_tim3,
+	[CK_KER_TIM4]		= &ck_ker_tim4,
+	[CK_KER_TIM5]		= &ck_ker_tim5,
+	[CK_KER_TIM6]		= &ck_ker_tim6,
+	[CK_KER_TIM7]		= &ck_ker_tim7,
+	[CK_KER_TIM10]		= &ck_ker_tim10,
+	[CK_KER_TIM11]		= &ck_ker_tim11,
+	[CK_KER_TIM12]		= &ck_ker_tim12,
+	[CK_KER_TIM13]		= &ck_ker_tim13,
+	[CK_KER_TIM14]		= &ck_ker_tim14,
+	[CK_KER_TIM1]		= &ck_ker_tim1,
+	[CK_KER_TIM8]		= &ck_ker_tim8,
+	[CK_KER_TIM15]		= &ck_ker_tim15,
+	[CK_KER_TIM16]		= &ck_ker_tim16,
+	[CK_KER_TIM17]		= &ck_ker_tim17,
+	[CK_KER_TIM20]		= &ck_ker_tim20,
+	[CK_KER_LPTIM1]		= &ck_ker_lptim1,
+	[CK_KER_LPTIM2]		= &ck_ker_lptim2,
+	[CK_KER_USART2]		= &ck_ker_usart2,
+	[CK_KER_UART4]		= &ck_ker_uart4,
+	[CK_KER_USART3]		= &ck_ker_usart3,
+	[CK_KER_UART5]		= &ck_ker_uart5,
+	[CK_KER_SPI2]		= &ck_ker_spi2,
+	[CK_KER_SPI3]		= &ck_ker_spi3,
+	[CK_KER_SPDIFRX]	= &ck_ker_spdifrx,
+	[CK_KER_I2C1]		= &ck_ker_i2c1,
+	[CK_KER_I2C2]		= &ck_ker_i2c2,
+	[CK_KER_I3C1]		= &ck_ker_i3c1,
+	[CK_KER_I3C2]		= &ck_ker_i3c2,
+	[CK_KER_I2C3]		= &ck_ker_i2c3,
+	[CK_KER_I2C5]		= &ck_ker_i2c5,
+	[CK_KER_I3C3]		= &ck_ker_i3c3,
+	[CK_KER_I2C4]		= &ck_ker_i2c4,
+	[CK_KER_I2C6]		= &ck_ker_i2c6,
+	[CK_KER_I2C7]		= &ck_ker_i2c7,
+	[CK_KER_SPI1]		= &ck_ker_spi1,
+	[CK_KER_SPI4]		= &ck_ker_spi4,
+	[CK_KER_SPI5]		= &ck_ker_spi5,
+	[CK_KER_SPI6]		= &ck_ker_spi6,
+	[CK_KER_SPI7]		= &ck_ker_spi7,
+	[CK_KER_USART1]		= &ck_ker_usart1,
+	[CK_KER_USART6]		= &ck_ker_usart6,
+	[CK_KER_UART7]		= &ck_ker_uart7,
+	[CK_KER_UART8]		= &ck_ker_uart8,
+	[CK_KER_UART9]		= &ck_ker_uart9,
+	[CK_KER_MDF1]		= &ck_ker_mdf1,
+	[CK_KER_SAI1]		= &ck_ker_sai1,
+	[CK_KER_SAI2]		= &ck_ker_sai2,
+	[CK_KER_SAI3]		= &ck_ker_sai3,
+	[CK_KER_SAI4]		= &ck_ker_sai4,
+	[CK_KER_FDCAN]		= &ck_ker_fdcan,
+	[CK_KER_CSI]		= &ck_ker_csi,
+	[CK_KER_CSITXESC]	= &ck_ker_csitxesc,
+	[CK_KER_CSIPHY]		= &ck_ker_csiphy,
+	[CK_KER_STGEN]		= &ck_ker_stgen,
+	[CK_KER_USBTC]		= &ck_ker_usbtc,
+	[CK_KER_I3C4]		= &ck_ker_i3c4,
+	[CK_KER_SPI8]		= &ck_ker_spi8,
+	[CK_KER_I2C8]		= &ck_ker_i2c8,
+	[CK_KER_LPUART1]	= &ck_ker_lpuart1,
+	[CK_KER_LPTIM3]		= &ck_ker_lptim3,
+	[CK_KER_LPTIM4]		= &ck_ker_lptim4,
+	[CK_KER_LPTIM5]		= &ck_ker_lptim5,
+	[CK_KER_ADF1]		= &ck_ker_adf1,
+	[CK_KER_TSDBG]		= &ck_ker_tsdbg,
+	[CK_KER_TPIU]		= &ck_ker_tpiu,
+	[CK_BUS_ETR]		= &ck_icn_p_etr,
+	[CK_KER_ETR]		= &ck_icn_m_etr,
+	[CK_BUS_SYSATB]		= &ck_sys_atb,
+	[CK_KER_OSPI1]		= &ck_ker_ospi1,
+	[CK_KER_OSPI2]		= &ck_ker_ospi2,
+	[CK_KER_FMC]		= &ck_ker_fmc,
+	[CK_KER_SDMMC1]		= &ck_ker_sdmmc1,
+	[CK_KER_SDMMC2]		= &ck_ker_sdmmc2,
+	[CK_KER_SDMMC3]		= &ck_ker_sdmmc3,
+	[CK_KER_ETH1]		= &ck_ker_eth1,
+	[CK_ETH1_STP]		= &ck_ker_eth1stp,
+	[CK_KER_ETHSW]		= &ck_ker_ethsw,
+	[CK_KER_ETH2]		= &ck_ker_eth2,
+	[CK_ETH2_STP]		= &ck_ker_eth2stp,
+	[CK_KER_ETH1PTP]	= &ck_ker_eth1ptp,
+	[CK_KER_ETH2PTP]	= &ck_ker_eth2ptp,
+	[CK_BUS_GPU]		= &ck_icn_m_gpu,
+	[CK_KER_GPU]		= &ck_ker_gpu,
+	[CK_KER_ETHSWREF]	= &ck_ker_ethswref,
+
+	[CK_MCO1]		= &ck_mco1,
+	[CK_MCO2]		= &ck_mco2,
+	[CK_KER_ADC12]		= &ck_ker_adc12,
+	[CK_KER_ADC3]		= &ck_ker_adc3,
+	[CK_KER_USB2PHY1]	= &ck_ker_usb2phy1,
+	[CK_KER_USB2PHY2]	= &ck_ker_usb2phy2,
+	[CK_KER_USB2PHY2EN]	= &ck_ker_usb2phy2_en,
+	[CK_KER_USB3PCIEPHY]	= &ck_ker_usb3pciephy,
+	[CK_KER_LTDC]		= &ck_ker_ltdc,
+	[CK_KER_DSIBLANE]	= &clk_lanebyte,
+	[CK_KER_DSIPHY]		= &ck_phy_dsi,
+	[CK_KER_LVDSPHY]	= &ck_ker_lvdsphy,
+	[CK_KER_DTS]		= &ck_ker_dts,
+	[RTC_CK]		= &ck_rtc,
+
+	[CK_ETH1_MAC]		= &ck_ker_eth1mac,
+	[CK_ETH1_TX]		= &ck_ker_eth1tx,
+	[CK_ETH1_RX]		= &ck_ker_eth1rx,
+	[CK_ETH2_MAC]		= &ck_ker_eth2mac,
+	[CK_ETH2_TX]		= &ck_ker_eth2tx,
+	[CK_ETH2_RX]		= &ck_ker_eth2rx,
+
+	[CK_HSE_RTC]		= &ck_hse_rtc,
+	[CK_OBSER0]		= &ck_obser0,
+	[CK_OBSER1]		= &ck_obser1,
+	[CK_OFF]		= &ck_off,
+	[I2SCKIN]		= &i2sckin,
+	[SPDIFSYMB]		= &spdifsymb,
+	[TXBYTECLK]		= &txbyteclk,
+};
+
+static bool clk_stm32_clock_is_critical(struct clk *clk)
+{
+	struct clk *clk_criticals[] = {
+		&ck_hsi,
+		&ck_hse,
+		&ck_msi,
+		&ck_lsi,
+		&ck_lse,
+		&ck_cpu1,
+		&ck_icn_p_syscpu1,
+		&ck_icn_s_ddr,
+		&ck_icn_p_ddrc,
+		&ck_icn_p_ddrcfg,
+		&ck_icn_p_ddrphyc,
+		&ck_icn_s_sysram,
+		&ck_icn_s_bkpsram,
+		&ck_ker_fmc,
+		&ck_ker_ospi1,
+		&ck_ker_ospi2,
+		&ck_icn_s_vderam,
+		&ck_icn_s_lpsram1,
+		&ck_icn_s_lpsram2,
+		&ck_icn_s_lpsram3,
+		&ck_icn_p_hpdma1,
+		&ck_icn_p_hpdma2,
+		&ck_icn_p_hpdma3,
+		&ck_icn_p_gpioa,
+		&ck_icn_p_gpiob,
+		&ck_icn_p_gpioc,
+		&ck_icn_p_gpiod,
+		&ck_icn_p_gpioe,
+		&ck_icn_p_gpiof,
+		&ck_icn_p_gpiog,
+		&ck_icn_p_gpioh,
+		&ck_icn_p_gpioi,
+		&ck_icn_p_gpioj,
+		&ck_icn_p_gpiok,
+		&ck_icn_p_gpioz,
+		&ck_icn_p_ipcc1,
+		&ck_icn_p_ipcc2,
+		&ck_icn_p_gicv2m,
+		&ck_icn_p_rtc
+	};
+	size_t i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(clk_criticals); i++)
+		if (clk == clk_criticals[i])
+			return true;
+	return false;
+}
+
+static void clk_stm32_init_oscillators(const void *fdt, int node)
+{
+	size_t i = 0;
+	static const char * const name[] = {
+		"clk-hse", "clk-hsi", "clk-lse",
+		"clk-lsi", "clk-msi", "clk-i2sin"
+	};
+	struct clk *clks[ARRAY_SIZE(name)] = {
+		&ck_hse, &ck_hsi, &ck_lse,
+		&ck_lsi, &ck_msi, &i2sckin
+	};
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		struct clk *clk = NULL;
+
+		if (clk_dt_get_by_name(fdt, node, name[i], &clk))
+			panic();
+
+		clks[i]->parents[0] = clk;
+	}
+}
+
+static TEE_Result clk_stm32_apply_rcc_config(struct stm32_clk_platdata *pdata)
+{
+	if (pdata->safe_rst)
+		stm32mp25_syscfg_set_safe_reset(true);
+
+	return TEE_SUCCESS;
+}
+
+static struct stm32_pll_dt_cfg mp25_pll[PLL_NB];
+static struct stm32_clk_opp_dt_cfg mp25_clk_opp;
+static struct stm32_osci_dt_cfg mp25_osci[NB_OSCILLATOR];
+
+#define DT_FLEXGEN_CLK_MAX	64
+static uint32_t mp25_flexgen[DT_FLEXGEN_CLK_MAX];
+
+#define DT_BUS_CLK_MAX		6
+static uint32_t mp25_busclk[DT_BUS_CLK_MAX];
+
+#define DT_KERNEL_CLK_MAX	20
+static uint32_t mp25_kernelclk[DT_KERNEL_CLK_MAX];
+
+static struct stm32_clk_platdata stm32mp25_clock_pdata = {
+	.osci		= mp25_osci,
+	.nosci		= NB_OSCILLATOR,
+	.pll		= mp25_pll,
+	.npll		= PLL_NB,
+	.opp		= &mp25_clk_opp,
+	.busclk		= mp25_busclk,
+	.nbusclk	= DT_BUS_CLK_MAX,
+	.kernelclk	= mp25_kernelclk,
+	.nkernelclk	= DT_KERNEL_CLK_MAX,
+	.flexgen	= mp25_flexgen,
+	.nflexgen	= DT_FLEXGEN_CLK_MAX,
+};
+
+static struct clk_stm32_priv stm32mp25_clock_data = {
+	.muxes			= parent_mp25,
+	.nb_muxes		= ARRAY_SIZE(parent_mp25),
+	.gates			= gates_mp25,
+	.nb_gates		= ARRAY_SIZE(gates_mp25),
+	.div			= dividers_mp25,
+	.nb_div			= ARRAY_SIZE(dividers_mp25),
+	.pdata			= &stm32mp25_clock_pdata,
+	.nb_clk_refs		= STM32MP25_ALL_CLK_NB,
+	.clk_refs		= stm32mp25_clk_provided,
+	.is_critical		= clk_stm32_clock_is_critical,
+};
+
+static TEE_Result handle_available_semaphores(void)
+{
+	struct stm32_clk_platdata *pdata = &stm32mp25_clock_pdata;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int index = 0;
+	uint32_t cidcfgr = 0;
+	unsigned int i = 0;
+
+	for (i = 0; i < RCC_NB_RIF_RES; i++) {
+		vaddr_t reg_offset = pdata->rcc_base + RCC_SEMCR(i);
+
+		index = i / 32;
+
+		if (!(BIT(i % 32) & pdata->conf_data.access_mask[index]))
+			continue;
+
+		cidcfgr = io_read32(pdata->rcc_base + RCC_CIDCFGR(i));
+
+		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+			continue;
+
+		if (!(io_read32(pdata->rcc_base + RCC_SECCFGR(index)) &
+		      BIT(i % 32))) {
+			res = stm32_rif_release_semaphore(reg_offset,
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot release semaphore for res %u", i);
+				return res;
+			}
+		} else {
+			res = stm32_rif_acquire_semaphore(reg_offset,
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot acquire semaphore for res %u", i);
+				return res;
+			}
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result apply_rcc_rif_config(bool is_tdcid)
+{
+	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
+	struct stm32_clk_platdata *pdata = &stm32mp25_clock_pdata;
+	unsigned int i = 0;
+	unsigned int index = 0;
+
+	if (is_tdcid) {
+		/*
+		 * When TDCID, OP-TEE should be the one to set the CID
+		 * filtering configuration. Clearing previous configuration
+		 * prevents undesired events during the only legitimate
+		 * configuration.
+		 */
+		for (i = 0; i < RCC_NB_RIF_RES; i++) {
+			if (BIT(i % 32) & pdata->conf_data.access_mask[i / 32])
+				io_clrbits32(pdata->rcc_base + RCC_CIDCFGR(i),
+					     RCC_CIDCFGR_CONF_MASK);
+		}
+	} else {
+		res = handle_available_semaphores();
+		if (res)
+			panic();
+	}
+
+	/* Security and privilege RIF configuration */
+	for (index = 0; index < RCC_NB_CONFS; index++) {
+		io_clrsetbits32(pdata->rcc_base + RCC_PRIVCFGR(index),
+				pdata->conf_data.access_mask[index],
+				pdata->conf_data.priv_conf[index]);
+		io_clrsetbits32(pdata->rcc_base + RCC_SECCFGR(index),
+				pdata->conf_data.access_mask[index],
+				pdata->conf_data.sec_conf[index]);
+	}
+
+	if (!is_tdcid)
+		goto end;
+
+	for (i = 0; i < RCC_NB_RIF_RES; i++) {
+		if (BIT(i % 32) & pdata->conf_data.access_mask[i / 32])
+			io_clrsetbits32(pdata->rcc_base + RCC_CIDCFGR(i),
+					RCC_CIDCFGR_CONF_MASK,
+					pdata->conf_data.cid_confs[i]);
+	}
+
+	for (index = 0; index < RCC_NB_CONFS; index++)
+		io_setbits32(pdata->rcc_base + RCC_RCFGLOCKR(index),
+			     pdata->conf_data.lock_conf[index]);
+
+	res = handle_available_semaphores();
+	if (res)
+		panic();
+end:
+	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
+		for (index = 0; index < RCC_NB_CONFS; index++) {
+			/* Check that RIF config are applied, panic otherwise */
+			if ((io_read32(pdata->rcc_base + RCC_PRIVCFGR(index)) &
+			     pdata->conf_data.access_mask[index]) !=
+			    pdata->conf_data.priv_conf[index])
+				panic("rcc resource prv conf is incorrect");
+
+			if ((io_read32(pdata->rcc_base + RCC_SECCFGR(index)) &
+			     pdata->conf_data.access_mask[index]) !=
+			    pdata->conf_data.sec_conf[index])
+				panic("rcc resource sec conf is incorrect");
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rcc_rif_pm_suspend(void)
+{
+	struct stm32_clk_platdata *pdata = &stm32mp25_clock_pdata;
+	unsigned int i = 0;
+
+	if (!pdata->nb_res)
+		return TEE_SUCCESS;
+
+	for (i = 0; i < RCC_NB_RIF_RES; i++)
+		pdata->conf_data.cid_confs[i] = io_read32(pdata->rcc_base +
+							  RCC_CIDCFGR(i));
+
+	for (i = 0; i < RCC_NB_CONFS; i++) {
+		pdata->conf_data.priv_conf[i] = io_read32(pdata->rcc_base +
+							  RCC_PRIVCFGR(i));
+		pdata->conf_data.sec_conf[i] = io_read32(pdata->rcc_base +
+							 RCC_SECCFGR(i));
+		pdata->conf_data.lock_conf[i] = io_read32(pdata->rcc_base +
+							  RCC_RCFGLOCKR(i));
+		pdata->conf_data.access_mask[i] = GENMASK_32(31, 0);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rcc_rif_pm(enum pm_op op, unsigned int pm_hint,
+				   const struct pm_callback_handle *h __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool is_tdcid = false;
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
+		return TEE_SUCCESS;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	if (op == PM_OP_RESUME) {
+		if (is_tdcid)
+			res = apply_rcc_rif_config(true);
+		else
+			res = handle_available_semaphores();
+	} else {
+		if (!is_tdcid)
+			return TEE_SUCCESS;
+
+		res = stm32_rcc_rif_pm_suspend();
+	}
+
+	return res;
+}
+
+static TEE_Result rcc_rif_config(void)
+{
+	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
+	bool is_tdcid = false;
+
+	/* Not expected to fail at this stage */
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		panic();
+
+	res = apply_rcc_rif_config(is_tdcid);
+	if (res)
+		panic();
+
+	register_pm_core_service_cb(stm32_rcc_rif_pm, NULL, "stm32-rcc-rif");
+
+	return TEE_SUCCESS;
+}
+
+driver_init_late(rcc_rif_config);
+
+static TEE_Result stm32mp2_clk_probe(const void *fdt, int node,
+				     const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	int fdt_rc = 0;
+	int rc = 0;
+	struct clk_stm32_priv *priv = &stm32mp25_clock_data;
+	struct stm32_clk_platdata *pdata = &stm32mp25_clock_pdata;
+
+	fdt_rc = stm32_clk_parse_fdt(fdt, node, pdata);
+	if (fdt_rc) {
+		EMSG("Failed to parse clock node %s: %d",
+		     fdt_get_name(fdt, node, NULL), fdt_rc);
+		return TEE_ERROR_GENERIC;
+	}
+
+	rc = clk_stm32_init(priv, stm32_rcc_base());
+	if (rc)
+		return TEE_ERROR_GENERIC;
+
+	stm32mp2_init_clock_tree(priv, pdata);
+
+	clk_stm32_init_oscillators(fdt, node);
+
+	res = clk_stm32_apply_rcc_config(pdata);
+	if (res)
+		panic("Error when applying RCC config");
+
+	stm32mp_clk_provider_probe_final(fdt, node, priv);
+
+	if (IS_ENABLED(CFG_STM32_CLK_DEBUG))
+		clk_print_tree();
+
+	return TEE_SUCCESS;
+}
+
+CLK_DT_DECLARE(stm32mp25_clk, "st,stm32mp25-rcc", stm32mp2_clk_probe);
diff --git a/core/drivers/clk/clk.c b/core/drivers/clk/clk.c
index 8f5a6a5d28b22c86a50af8816548f978eef79e5c..b44a5d088354df0162756e27d990163a7917605a 100644
--- a/core/drivers/clk/clk.c
+++ b/core/drivers/clk/clk.c
@@ -7,20 +7,30 @@
 #include <config.h>
 #include <drivers/clk.h>
 #include <kernel/boot.h>
+#include <kernel/mutex_pm_aware.h>
 #include <kernel/panic.h>
-#include <kernel/spinlock.h>
-#include <libfdt.h>
+#include <kernel/thread.h>
 #include <malloc.h>
 #include <stddef.h>
 #include <stdio.h>
 
-/* Global clock tree lock */
-static unsigned int clk_lock = SPINLOCK_UNLOCK;
+/* Global clock tree access protection complying the power state transitions */
+static struct mutex_pm_aware mu = MUTEX_PM_AWARE_INITIALIZER;
 
 #ifdef CFG_DRIVERS_CLK_PRINT_TREE
 static SLIST_HEAD(, clk) clock_list = SLIST_HEAD_INITIALIZER(clock_list);
 #endif
 
+static void lock_clk(void)
+{
+	mutex_pm_aware_lock(&mu);
+}
+
+static void unlock_clk(void)
+{
+	mutex_pm_aware_unlock(&mu);
+}
+
 struct clk *clk_alloc(const char *name, const struct clk_ops *ops,
 		      struct clk **parent_clks, size_t parent_count)
 {
@@ -174,23 +184,20 @@ static TEE_Result clk_enable_no_lock(struct clk *clk)
 
 TEE_Result clk_enable(struct clk *clk)
 {
-	uint32_t exceptions = 0;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
-	exceptions = cpu_spin_lock_xsave(&clk_lock);
+	lock_clk();
 	res = clk_enable_no_lock(clk);
-	cpu_spin_unlock_xrestore(&clk_lock, exceptions);
+	unlock_clk();
 
 	return res;
 }
 
 void clk_disable(struct clk *clk)
 {
-	uint32_t exceptions = 0;
-
-	exceptions = cpu_spin_lock_xsave(&clk_lock);
+	lock_clk();
 	clk_disable_no_lock(clk);
-	cpu_spin_unlock_xrestore(&clk_lock, exceptions);
+	unlock_clk();
 }
 
 unsigned long clk_get_rate(struct clk *clk)
@@ -206,9 +213,29 @@ static TEE_Result clk_set_rate_no_lock(struct clk *clk, unsigned long rate)
 	if (clk->parent)
 		parent_rate = clk_get_rate(clk->parent);
 
-	res = clk->ops->set_rate(clk, rate, parent_rate);
-	if (res)
-		return res;
+	assert(!(clk->flags & CLK_SET_RATE_PARENT) || clk->parent);
+	if (clk->flags & CLK_SET_RATE_PARENT) {
+		res = clk_set_rate_no_lock(clk->parent, rate);
+		if (res)
+			return res;
+		rate = clk_get_rate(clk->parent);
+	}
+
+	if (clk->ops->set_rate) {
+		if (clk->flags & CLK_SET_RATE_UNGATE) {
+			res = clk_enable_no_lock(clk);
+			if (res)
+				return res;
+		}
+
+		res = clk->ops->set_rate(clk, rate, parent_rate);
+
+		if (clk->flags & CLK_SET_RATE_UNGATE)
+			clk_disable_no_lock(clk);
+
+		if (res)
+			return res;
+	}
 
 	clk_compute_rate_no_lock(clk);
 
@@ -217,20 +244,16 @@ static TEE_Result clk_set_rate_no_lock(struct clk *clk, unsigned long rate)
 
 TEE_Result clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	uint32_t exceptions = 0;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
-	if (!clk->ops->set_rate)
-		return TEE_ERROR_NOT_SUPPORTED;
-
-	exceptions =  cpu_spin_lock_xsave(&clk_lock);
+	lock_clk();
 
 	if (clk->flags & CLK_SET_RATE_GATE && clk_is_enabled_no_lock(clk))
 		res = TEE_ERROR_BAD_STATE;
 	else
 		res = clk_set_rate_no_lock(clk, rate);
 
-	cpu_spin_unlock_xrestore(&clk_lock, exceptions);
+	unlock_clk();
 
 	return res;
 }
@@ -268,8 +291,15 @@ static TEE_Result clk_set_parent_no_lock(struct clk *clk, struct clk *parent,
 
 	was_enabled = clk_is_enabled_no_lock(clk);
 	/* Call is needed to decrement refcount on current parent tree */
-	if (was_enabled)
+	if (was_enabled) {
+		if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) {
+			res = clk_enable_no_lock(parent);
+			if (res)
+				return res;
+		}
+
 		clk_disable_no_lock(clk);
+	}
 
 	res = clk->ops->set_parent(clk, pidx);
 	if (res)
@@ -286,6 +316,11 @@ out:
 		res = clk_enable_no_lock(clk);
 		if (res)
 			panic("Failed to re-enable clock after setting parent");
+
+		if (clk->flags & CLK_SET_PARENT_PRE_ENABLE) {
+			/* Balance refcount when new parent was pre-enabled */
+			clk_disable_no_lock(parent);
+		}
 	}
 
 	return res;
@@ -294,13 +329,12 @@ out:
 TEE_Result clk_set_parent(struct clk *clk, struct clk *parent)
 {
 	size_t pidx = 0;
-	uint32_t exceptions = 0;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
 	if (clk_get_parent_idx(clk, parent, &pidx) || !clk->ops->set_parent)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	exceptions = cpu_spin_lock_xsave(&clk_lock);
+	lock_clk();
 	if (clk->flags & CLK_SET_PARENT_GATE && clk_is_enabled_no_lock(clk)) {
 		res = TEE_ERROR_BAD_STATE;
 		goto out;
@@ -308,7 +342,7 @@ TEE_Result clk_set_parent(struct clk *clk, struct clk *parent)
 
 	res = clk_set_parent_no_lock(clk, parent, pidx);
 out:
-	cpu_spin_unlock_xrestore(&clk_lock, exceptions);
+	unlock_clk();
 
 	return res;
 }
@@ -322,6 +356,31 @@ TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
 	return clk->ops->get_rates_array(clk, start_index, rates, nb_elts);
 }
 
+TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min,
+			       unsigned long *max, unsigned long *step)
+{
+	if (!clk->ops->get_rates_steps)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return clk->ops->get_rates_steps(clk, min, max, step);
+}
+
+TEE_Result clk_get_duty_cycle(struct clk *clk,
+			      struct clk_duty_cycle *duty_cycle)
+{
+	if (clk->ops->get_duty_cycle)
+		return clk->ops->get_duty_cycle(clk, duty_cycle);
+
+	if (clk->parent && (clk->flags & CLK_DUTY_CYCLE_PARENT))
+		return clk_get_duty_cycle(clk->parent, duty_cycle);
+
+	/* Default set 50% duty cycle */
+	duty_cycle->num = 1;
+	duty_cycle->den = 2;
+
+	return TEE_SUCCESS;
+}
+
 /* Return updated message buffer position of NULL on failure */
 static __printf(3, 4) char *add_msg(char *cur, char *end, const char *fmt, ...)
 {
@@ -436,7 +495,7 @@ out:
 	if (!msg)
 		snprintf(msg_end - 4, 4, "...");
 
-	DMSG("%s", msg_buf);
+	IMSG("%s", msg_buf);
 }
 
 static void print_tree(void)
@@ -448,7 +507,7 @@ static void print_tree(void)
 
 #ifdef CFG_DRIVERS_CLK_PRINT_TREE
 	if (SLIST_EMPTY(&clock_list)) {
-		DMSG("-- No registered clock");
+		IMSG("-- No registered clock");
 		return;
 	}
 #endif
@@ -482,8 +541,8 @@ static void print_tree(void)
 void clk_print_tree(void)
 {
 	if (IS_ENABLED(CFG_DRIVERS_CLK_PRINT_TREE) &&
-	    TRACE_LEVEL >= TRACE_DEBUG) {
-		DMSG("Clock tree summary (informative):");
+	    TRACE_LEVEL >= TRACE_INFO) {
+		IMSG("Clock tree summary (informative):");
 		print_tree();
 	}
 }
diff --git a/core/drivers/clk/clk_dt.c b/core/drivers/clk/clk_dt.c
index 5197a91719f7879b63b4e28f1cc100fdbd4b0120..fcb3d3ca28a7d5aedd7907ce1081b86f51d818f0 100644
--- a/core/drivers/clk/clk_dt.c
+++ b/core/drivers/clk/clk_dt.c
@@ -7,7 +7,6 @@
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
 #include <initcall.h>
-#include <kernel/boot.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
 #include <kernel/panic.h>
diff --git a/core/drivers/clk/sam/at91_clk.h b/core/drivers/clk/sam/at91_clk.h
index 98ff77e2bf32e9146dd10808105060f75fd73371..2da411b7145760839020b7d2c4cdc19c278d3fd6 100644
--- a/core/drivers/clk/sam/at91_clk.h
+++ b/core/drivers/clk/sam/at91_clk.h
@@ -158,11 +158,36 @@ struct clk *
 at91_clk_register_plldiv(struct pmc_data *pmc, const char *name,
 			 struct clk *parent);
 
+struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc,
+					  const char *name,
+					  struct clk *parent,
+					  uint8_t id,
+					  const struct clk_pll_charac *charac,
+					  const struct clk_pll_layout *layout,
+					  uint32_t flags);
+
+struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc,
+					 const char *name,
+					 struct clk *parent,
+					 uint8_t id,
+					 const struct clk_pll_charac *charac,
+					 const struct clk_pll_layout *layout,
+					 uint32_t flags,
+					 uint32_t safe_div);
+
 /* UTMI */
 struct clk *
 at91_clk_register_utmi(struct pmc_data *pmc, const char *name,
 		       struct clk *parent);
 
+struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc,
+					   const char *name,
+					   struct clk *parent);
+
+struct clk *sama7_utmi_clk_register(const char *name,
+				    struct clk *parent,
+				    uint8_t id);
+
 /* Master */
 struct clk *
 at91_clk_register_master_pres(struct pmc_data *pmc,
@@ -178,6 +203,17 @@ at91_clk_register_master_div(struct pmc_data *pmc,
 			     const struct clk_master_layout *layout,
 			     const struct clk_master_charac *charac);
 
+/*
+ * @mux_table: when @mux_table is not NULL it shall hold @num_parents cells
+ */
+struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc,
+					     const char *name,
+					     int num_parents,
+					     struct clk **parent,
+					     uint32_t *mux_table,
+					     uint8_t id,
+					     int chg_pid);
+
 /* H32MX */
 struct clk *
 at91_clk_register_h32mx(struct pmc_data *pmc, const char *name,
@@ -209,6 +245,7 @@ struct clk *
 at91_clk_register_generated(struct pmc_data *pmc,
 			    const struct clk_pcr_layout *layout,
 			    const char *name, struct clk **parents,
+			    uint32_t *mux_table,
 			    uint8_t num_parents, uint8_t id,
 			    const struct clk_range *range,
 			    int chg_pid);
@@ -230,6 +267,12 @@ struct clk *
 at91_clk_register_audio_pll_pmc(struct pmc_data *pmc, const char *name,
 				struct clk *parent);
 
+/* CPU OPP (Operation Performance Points) */
+struct clk *at91_cpu_opp_clk_get(void);
+
+TEE_Result at91_clk_register_cpu_opp(const void *fdt, int node,
+				     struct clk *clk);
+
 #ifdef CFG_PM_ARM32
 void pmc_register_id(uint8_t id);
 void pmc_register_pck(uint8_t pck);
diff --git a/core/drivers/clk/sam/at91_cpu_opp.c b/core/drivers/clk/sam/at91_cpu_opp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6265b265a41a39c93cffcb066b5dfe0ad744cca
--- /dev/null
+++ b/core/drivers/clk/sam/at91_cpu_opp.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ *  Copyright (C) 2024 Microchip Technology Inc.
+ */
+
+#include <at91_clk.h>
+#include <kernel/misc.h>
+#include <kernel/panic.h>
+#include <malloc.h>
+#include <libfdt.h>
+#include <trace.h>
+
+#define OPP_RATES_MAX 8
+
+/* the clock rates for CPU OPP */
+struct clk_rates {
+	size_t rate_num; /* the number of valid clock rates in @rates */
+	unsigned long rates[OPP_RATES_MAX];
+};
+
+static struct clk_rates *opp_rates;
+
+static TEE_Result get_rates_array(struct clk *clk __unused, size_t start_index,
+				  unsigned long *rates, size_t *nb_elts)
+{
+	if (!opp_rates)
+		panic("Invalid CPU OPP Rates Array");
+
+	if (!rates) {
+		*nb_elts = opp_rates->rate_num;
+
+		return TEE_SUCCESS;
+	}
+
+	if (start_index + *nb_elts > opp_rates->rate_num) {
+		EMSG("Bad parameter(s): start_index %zu, nb_elts %zu",
+		     start_index, *nb_elts);
+
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+	memcpy(rates, &opp_rates->rates[start_index],
+	       *nb_elts * sizeof(*rates));
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result cpu_opp_clk_set_rate(struct clk *clk, unsigned long rate,
+				       unsigned long parent_rate)
+{
+	size_t n = 0;
+
+	assert(clk->parent);
+
+	for (n = 0; n < opp_rates->rate_num; n++)
+		if (rate == opp_rates->rates[n])
+			break;
+	if (n == opp_rates->rate_num)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return clk->parent->ops->set_rate(clk->parent, rate, parent_rate);
+}
+
+static const struct clk_ops cpu_opp_clk_ops = {
+	.set_rate = cpu_opp_clk_set_rate,
+	.get_rates_array = get_rates_array,
+};
+
+static TEE_Result dt_get_opp_hz(const void *fdt, int node, unsigned long *value)
+{
+	const char *property = "opp-hz";
+	const fdt64_t *p = NULL;
+	int len = 0;
+
+	p = fdt_getprop(fdt, node, property, &len);
+	if (!p)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (len != sizeof(*p))
+		return TEE_ERROR_BAD_FORMAT;
+
+	*value = fdt64_ld(p);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result opp_rates_setup(const void *fdt, int node)
+{
+	const char *compatible = "operating-points-v2";
+	const fdt32_t *cuint = NULL;
+	size_t rate_num = 0;
+	int opp_table = 0;
+	int offset = 0;
+
+	cuint = fdt_getprop(fdt, node, compatible, NULL);
+	if (!cuint)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	opp_rates = calloc(1, sizeof(*opp_rates));
+	if (!opp_rates) {
+		EMSG("Fail to alloc opp_rates");
+
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	offset = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
+	if (offset < 0)
+		panic("Invalid offset of opp-table");
+
+	if (fdt_node_check_compatible(fdt, offset, compatible))
+		panic("Invalid opp-table");
+
+	fdt_for_each_subnode(opp_table, fdt, offset) {
+		if (rate_num >= OPP_RATES_MAX)
+			panic("CPU OPP rate array shortage");
+
+		if (dt_get_opp_hz(fdt, opp_table, opp_rates->rates + rate_num))
+			panic("Get opp-hz failed");
+
+		rate_num++;
+	}
+
+	/* Ensure rates are in ascending order */
+	qsort_ul(opp_rates->rates, rate_num);
+
+	opp_rates->rate_num = rate_num;
+
+	return TEE_SUCCESS;
+}
+
+static struct clk *cpu_opp_clk;
+
+struct clk *at91_cpu_opp_clk_get(void)
+{
+	return cpu_opp_clk;
+}
+
+TEE_Result at91_clk_register_cpu_opp(const void *fdt, int node, struct clk *clk)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = opp_rates_setup(fdt, node);
+	if (res == TEE_ERROR_NOT_SUPPORTED)
+		return TEE_SUCCESS;
+	if (res)
+		return res;
+
+	cpu_opp_clk = clk_alloc("cpu-opp", &cpu_opp_clk_ops, &clk, 1);
+	if (!cpu_opp_clk)
+		panic("CPU OPP clock alloc failed");
+
+	res = clk_register(cpu_opp_clk);
+	if (res) {
+		clk_free(cpu_opp_clk);
+		return res;
+	}
+
+	/* CPU clock is likely always enabled so set its refcount */
+	if (clk_enable(cpu_opp_clk))
+		panic("CPU clock should always enabled");
+
+	return TEE_SUCCESS;
+}
diff --git a/core/drivers/clk/sam/at91_generated.c b/core/drivers/clk/sam/at91_generated.c
index 3c4c2af4b93347a6731ff64fa956cc1ccdaa4800..1f30c5c2b60ffd7176828645a38ef9b3eb3d043f 100644
--- a/core/drivers/clk/sam/at91_generated.c
+++ b/core/drivers/clk/sam/at91_generated.c
@@ -72,7 +72,10 @@ static TEE_Result clk_generated_set_parent(struct clk *clk, size_t index)
 	if (index >= clk_get_num_parents(clk))
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	gck->parent_id = index;
+	if (gck->mux_table)
+		gck->parent_id = gck->mux_table[index];
+	else
+		gck->parent_id = index;
 
 	return TEE_SUCCESS;
 }
@@ -80,8 +83,16 @@ static TEE_Result clk_generated_set_parent(struct clk *clk, size_t index)
 static size_t clk_generated_get_parent(struct clk *clk)
 {
 	struct clk_generated *gck = clk->priv;
-
-	return gck->parent_id;
+	unsigned int i = 0;
+
+	if (gck->mux_table) {
+		for (i = 0; i < clk_get_num_parents(clk); i++)
+			if (gck->mux_table[i] == gck->parent_id)
+				return i;
+		panic("Can't get correct parent of clock");
+	} else {
+		return gck->parent_id;
+	}
 }
 
 /* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
@@ -102,6 +113,7 @@ static TEE_Result clk_generated_set_rate(struct clk *clk, unsigned long rate,
 		return TEE_ERROR_GENERIC;
 
 	gck->gckdiv = div - 1;
+
 	return TEE_SUCCESS;
 }
 
@@ -140,6 +152,7 @@ struct clk *
 at91_clk_register_generated(struct pmc_data *pmc,
 			    const struct clk_pcr_layout *layout,
 			    const char *name, struct clk **parents,
+			    uint32_t *mux_table,
 			    uint8_t num_parents, uint8_t id,
 			    const struct clk_range *range,
 			    int chg_pid)
@@ -164,6 +177,7 @@ at91_clk_register_generated(struct pmc_data *pmc,
 	memcpy(&gck->range, range, sizeof(gck->range));
 	gck->chg_pid = chg_pid;
 	gck->layout = layout;
+	gck->mux_table = mux_table;
 
 	clk->priv = gck;
 
diff --git a/core/drivers/clk/sam/at91_master.c b/core/drivers/clk/sam/at91_master.c
index 1780d480a9b842f133c7c44aa2dc6ef8810cd971..c84a9739a0200cb67ff069a31b2395987fdead6b 100644
--- a/core/drivers/clk/sam/at91_master.c
+++ b/core/drivers/clk/sam/at91_master.c
@@ -15,6 +15,7 @@
 #define MASTER_PRES_MAX		MASTER_PRES_MASK
 #define MASTER_DIV_SHIFT	8
 #define MASTER_DIV_MASK		0x7
+#define MASTER_MAX_ID		4 /* Total 5 MCK clocks for SAMA7G5 */
 
 struct clk_master {
 	vaddr_t base;
@@ -24,6 +25,8 @@ struct clk_master {
 	uint32_t mckr;
 	int chg_pid;
 	uint8_t div;
+	uint8_t id; /* ID of MCK clocks for SAMA7G5, MCK0 ~ MCK4 */
+	uint8_t parent; /* the source clock for SAMA7G5 MCKx */
 };
 
 static bool clk_master_ready(struct clk_master *master)
@@ -179,3 +182,126 @@ const struct clk_master_layout at91sam9x5_master_layout = {
 	.pres_shift = 4,
 	.offset = AT91_PMC_MCKR,
 };
+
+static size_t clk_sama7g5_master_get_parent(struct clk *hw)
+{
+	struct clk_master *master = hw->priv;
+	size_t i = 0;
+
+	for (i = 0; i < hw->num_parents; i++)
+		if (master->mux_table[i] == master->parent)
+			return i;
+
+	panic("Can't get correct parent of clock");
+}
+
+static TEE_Result clk_sama7g5_master_set_parent(struct clk *hw, size_t index)
+{
+	struct clk_master *master = hw->priv;
+
+	if (index >= hw->num_parents)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	master->parent = master->mux_table[index];
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result clk_sama7g5_master_set_rate(struct clk *hw,
+					      unsigned long rate,
+					      unsigned long parent_rate)
+{
+	struct clk_master *master = hw->priv;
+	unsigned long div = 0;
+
+	div = UDIV_ROUND_NEAREST(parent_rate, rate);
+	if (div > (1 << (MASTER_PRES_MAX - 1)) ||
+	    (!IS_POWER_OF_TWO(div) && div != 3))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * Divisor Value: Select the division ratio to be applied to the
+	 * selected clock to generate the corresponding MCKx.
+	 *  Value  |    Description
+	 *    0    | Selected clock divided by 1
+	 *    1    | Selected clock divided by 2
+	 *    2    | Selected clock divided by 4
+	 *    3    | Selected clock divided by 8
+	 *    4    | Selected clock divided by 16
+	 *    5    | Selected clock divided by 32
+	 *    6    | Selected clock divided by 64
+	 *    7    | Selected clock divided by 3
+	 */
+	if (div == 3)
+		master->div = MASTER_PRES_MAX;
+	else
+		master->div = ffs(div) - 1;
+
+	return TEE_SUCCESS;
+}
+
+static unsigned long clk_sama7g5_master_get_rate(struct clk *hw,
+						 unsigned long parent_rate)
+{
+	struct clk_master *master = hw->priv;
+	unsigned long rate = parent_rate >> master->div;
+
+	if (master->div == 7)
+		rate = parent_rate / 3;
+
+	return rate;
+}
+
+static const struct clk_ops sama7g5_master_ops = {
+	.set_rate = clk_sama7g5_master_set_rate,
+	.get_rate = clk_sama7g5_master_get_rate,
+	.get_parent = clk_sama7g5_master_get_parent,
+	.set_parent = clk_sama7g5_master_set_parent,
+};
+
+struct clk *at91_clk_sama7g5_register_master(struct pmc_data *pmc,
+					     const char *name,
+					     int num_parents,
+					     struct clk **parent,
+					     uint32_t *mux_table,
+					     uint8_t id,
+					     int chg_pid)
+{
+	struct clk_master *master = NULL;
+	struct clk *hw = NULL;
+	unsigned int val = 0;
+
+	if (!name || !num_parents || !parent || !mux_table ||
+	    id > MASTER_MAX_ID)
+		return NULL;
+
+	master = calloc(1, sizeof(*master));
+	if (!master)
+		return NULL;
+
+	hw = clk_alloc(name, &sama7g5_master_ops, parent, num_parents);
+	if (!hw) {
+		free(master);
+		return NULL;
+	}
+
+	hw->priv = master;
+	master->base = pmc->base;
+	master->id = id;
+	master->chg_pid = chg_pid;
+	master->mux_table = mux_table;
+
+	io_write32(master->base + AT91_PMC_MCR_V2, master->id);
+	val = io_read32(master->base + AT91_PMC_MCR_V2);
+	master->parent = (val & AT91_PMC_MCR_V2_CSS_MASK) >>
+			 AT91_PMC_MCR_V2_CSS_SHIFT;
+	master->div = (val & AT91_PMC_MCR_V2_DIV_MASK) >> MASTER_DIV_SHIFT;
+
+	if (clk_register(hw)) {
+		clk_free(hw);
+		free(master);
+		return NULL;
+	}
+
+	return hw;
+}
diff --git a/core/drivers/clk/sam/at91_pmc.c b/core/drivers/clk/sam/at91_pmc.c
index da0046dc0d5ff414211394cc2346c048d7ed68bc..34983b43ae8f83e3957a4067877af4019f5008ac 100644
--- a/core/drivers/clk/sam/at91_pmc.c
+++ b/core/drivers/clk/sam/at91_pmc.c
@@ -36,7 +36,7 @@ struct clk *pmc_clk_get_by_name(struct pmc_clk *clks, unsigned int nclk,
 	unsigned int i = 0;
 
 	for (i = 0; i < nclk; i++)
-		if (strcmp(clks[i].clk->name, name) == 0)
+		if (clks[i].clk && strcmp(clks[i].clk->name, name) == 0)
 			return clks[i].clk;
 
 	return NULL;
diff --git a/core/drivers/clk/sam/at91_pmc.h b/core/drivers/clk/sam/at91_pmc.h
index 5b4a5547ad6ea653ca5cd3eb1508dae28e2557ed..7b174cba3f8b4529d9da9782ca55132410763fb5 100644
--- a/core/drivers/clk/sam/at91_pmc.h
+++ b/core/drivers/clk/sam/at91_pmc.h
@@ -32,6 +32,11 @@
 #define	  AT91_PMC_PCK4				BIT(12)
 #define	  AT91_PMC_HCK0				BIT(16)
 #define	  AT91_PMC_HCK1				BIT(17)
+#ifdef CFG_SAMA7G5
+#define	AT91_PMC_PCK_COUNT			8
+#else
+#define	AT91_PMC_PCK_COUNT			4
+#endif
 
 #define AT91_PMC_PLL_CTRL0			0x0C
 #define	  AT91_PMC_PLL_CTRL0_ENPLL		BIT(28)
@@ -59,7 +64,7 @@
 #define AT91_PMC_PLL_UPDT			0x1C
 #define	  AT91_PMC_PLL_UPDT_UPDATE		BIT(8)
 #define	  AT91_PMC_PLL_UPDT_ID			BIT(0)
-#define	  AT91_PMC_PLL_UPDT_ID_MSK		(0xf)
+#define	  AT91_PMC_PLL_UPDT_ID_MASK		GENMASK_32(3, 0)
 #define	  AT91_PMC_PLL_UPDT_STUPTIM		(0xff << 16)
 
 #define	AT91_CKGR_MOR				0x20
@@ -94,7 +99,11 @@
 
 #define AT91_PMC_CPU_CKR			0x28
 
+#ifdef CFG_SAMA7G5
+#define	AT91_PMC_MCKR				0x28
+#else
 #define	AT91_PMC_MCKR				0x30
+#endif
 #define	  AT91_PMC_CSS				(3 << 0)
 #define     AT91_PMC_CSS_SLOW			(0 << 0)
 #define     AT91_PMC_CSS_MAIN			BIT(0)
@@ -137,7 +146,36 @@
 #define     AT91_PMC_PLLADIV2_ON		BIT(12)
 #define	  AT91_PMC_H32MXDIV	BIT(24)
 
+/* definitions for the PMC register of SAMA7G5 */
+#define AT91_PMC_MCR_V2			0x30
+#define AT91_PMC_MCR_V2_ID_MASK		GENMASK_32(3, 0)
+#define AT91_PMC_MCR_V2_ID(_id)		((_id) & AT91_PMC_MCR_V2_ID_MASK)
+#define AT91_PMC_MCR_V2_CMD		BIT(7)
+#define AT91_PMC_MCR_V2_DIV_MASK	GENMASK_32(10, 8)
+#define AT91_PMC_MCR_V2_DIV1		SHIFT_U32(0, 8)
+#define AT91_PMC_MCR_V2_DIV2		SHIFT_U32(1, 8)
+#define AT91_PMC_MCR_V2_DIV4		SHIFT_U32(2, 8)
+#define AT91_PMC_MCR_V2_DIV8		SHIFT_U32(3, 8)
+#define AT91_PMC_MCR_V2_DIV16		SHIFT_U32(4, 8)
+#define AT91_PMC_MCR_V2_DIV32		SHIFT_U32(5, 8)
+#define AT91_PMC_MCR_V2_DIV64		SHIFT_U32(6, 8)
+#define AT91_PMC_MCR_V2_DIV3		SHIFT_U32(7, 8)
+#define AT91_PMC_MCR_V2_CSS_SHIFT	16
+#define AT91_PMC_MCR_V2_CSS_MASK	GENMASK_32(20, 16)
+#define AT91_PMC_MCR_V2_CSS_MD_SLCK	SHIFT_U32(0, 16)
+#define AT91_PMC_MCR_V2_CSS_TD_SLCK	SHIFT_U32(1, 16)
+#define AT91_PMC_MCR_V2_CSS_MAINCK	SHIFT_U32(2, 16)
+#define AT91_PMC_MCR_V2_CSS_MCK0	SHIFT_U32(3, 16)
+#define AT91_PMC_MCR_V2_CSS_SYSPLL	SHIFT_U32(5, 16)
+#define AT91_PMC_MCR_V2_CSS_DDRPLL	SHIFT_U32(6, 16)
+#define AT91_PMC_MCR_V2_CSS_IMGPLL	SHIFT_U32(7, 16)
+#define AT91_PMC_MCR_V2_CSS_BAUDPLL	SHIFT_U32(8, 16)
+#define AT91_PMC_MCR_V2_CSS_AUDIOPLL	SHIFT_U32(9, 16)
+#define AT91_PMC_MCR_V2_CSS_ETHPLL	SHIFT_U32(10, 16)
+#define AT91_PMC_MCR_V2_EN		BIT(28)
+
 #define AT91_PMC_XTALF				0x34
+#define AT91_PMC_XTALF_XTALF			7
 
 #define	AT91_PMC_USB				0x38
 #define	  AT91_PMC_USBS				(0x1 << 0)
diff --git a/core/drivers/clk/sam/at91_sckc.c b/core/drivers/clk/sam/at91_sckc.c
index f2fc1073857a82338980cffd38c1e5e7b825af4e..59a63404086686b1957742affd991e092108c5b8 100644
--- a/core/drivers/clk/sam/at91_sckc.c
+++ b/core/drivers/clk/sam/at91_sckc.c
@@ -56,4 +56,15 @@ static TEE_Result sckc_pmc_setup(const void *fdt __unused, int offs,
 	return TEE_SUCCESS;
 }
 
-CLK_DT_DECLARE(at91_sckc, "atmel,sama5d4-sckc", sckc_pmc_setup);
+static const struct dt_device_match at91_sckc_match_table[] = {
+	{ .compatible = "atmel,sama5d4-sckc" },
+	{ .compatible = "microchip,sama7g5-sckc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(at91_sckc_dt_driver) = {
+	.name = "at91_sckc",
+	.type = DT_DRIVER_CLK,
+	.match_table = at91_sckc_match_table,
+	.probe = sckc_pmc_setup,
+};
diff --git a/core/drivers/clk/sam/at91_utmi.c b/core/drivers/clk/sam/at91_utmi.c
index d5be9452a2a26da13fcdfd96660842b36a984ee4..d2e603bf883af9e35914435c8e9b67798df67d97 100644
--- a/core/drivers/clk/sam/at91_utmi.c
+++ b/core/drivers/clk/sam/at91_utmi.c
@@ -105,14 +105,15 @@ static const struct clk_ops utmi_ops = {
 	.get_rate = clk_utmi_get_rate,
 };
 
-struct clk *
-at91_clk_register_utmi(struct pmc_data *pmc, const char *name,
-		       struct clk *parent)
+static struct clk *at91_clk_register_utmi_internal(struct pmc_data *pmc,
+						   const char *name,
+						   const struct clk_ops *ops,
+						   struct clk *parent)
 {
 	struct clk_utmi *utmi = NULL;
 	struct clk *clk = NULL;
 
-	clk = clk_alloc(name, &utmi_ops, &parent, 1);
+	clk = clk_alloc(name, ops, &parent, 1);
 	if (!clk)
 		return NULL;
 
@@ -136,3 +137,57 @@ at91_clk_register_utmi(struct pmc_data *pmc, const char *name,
 
 	return clk;
 }
+
+struct clk *at91_clk_register_utmi(struct pmc_data *pmc,
+				   const char *name,
+				   struct clk *parent)
+{
+	return at91_clk_register_utmi_internal(pmc, name, &utmi_ops, parent);
+}
+
+static TEE_Result clk_utmi_sama7g5_prepare(struct clk *clk)
+{
+	struct clk *clk_parent = NULL;
+	struct clk_utmi *utmi = clk->priv;
+	unsigned long parent_rate = 0;
+	uint32_t val = 0;
+
+	clk_parent = clk_get_parent(clk);
+	parent_rate = clk_get_rate(clk_parent);
+
+	switch (parent_rate) {
+	case 16000000:
+		val = 0;
+		break;
+	case 20000000:
+		val = 2;
+		break;
+	case 24000000:
+		val = 3;
+		break;
+	case 32000000:
+		val = 5;
+		break;
+	default:
+		EMSG("UTMICK: unsupported main_xtal rate");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	io_clrsetbits32(utmi->pmc_base + AT91_PMC_XTALF, AT91_PMC_XTALF_XTALF,
+			val);
+
+	return TEE_SUCCESS;
+}
+
+static const struct clk_ops sama7g5_utmi_ops = {
+	.enable = clk_utmi_sama7g5_prepare,
+	.get_rate = clk_utmi_get_rate,
+};
+
+struct clk *at91_clk_sama7g5_register_utmi(struct pmc_data *pmc,
+					   const char *name,
+					   struct clk *parent)
+{
+	return at91_clk_register_utmi_internal(pmc, name, &sama7g5_utmi_ops,
+					       parent);
+}
diff --git a/core/drivers/clk/sam/clk-sam9x60-pll.c b/core/drivers/clk/sam/clk-sam9x60-pll.c
new file mode 100644
index 0000000000000000000000000000000000000000..e3e79ce209e8b6255f73563e5aee7390c267093a
--- /dev/null
+++ b/core/drivers/clk/sam/clk-sam9x60-pll.c
@@ -0,0 +1,520 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ *  Copyright (C) 2019 Microchip Technology Inc.
+ */
+
+#include <io.h>
+#include <kernel/misc.h>
+#include <mm/core_memprot.h>
+#include <types_ext.h>
+#include <util.h>
+#include "at91_clk.h"
+
+#define PMC_PLL_CTRL0_DIV_MASK 0xf
+#define PMC_PLL_CTRL0_DIV_POS 0
+#define PMC_PLL_CTRL1_MUL_MASK 0xff
+#define PMC_PLL_CTRL1_MUL_POS 24
+#define PMC_PLL_CTRL1_FRACR_MASK 0x3fffff
+#define PMC_PLL_CTRL1_FRACR_POS 0
+
+#define PLL_STATUS_MASK(id)	BIT(1 + (id))
+#define PLL_REG(id)		(AT91_CKGR_PLLAR + ((id) * 4))
+#define PLL_DIV_MASK		0xff
+#define PLL_DIV_MAX		PLL_DIV_MASK
+#define PLL_DIV(reg)		((reg) & PLL_DIV_MASK)
+#define PLL_MUL(reg, layout) \
+	({ \
+		typeof(layout) __layout = layout; \
+		\
+		(((reg) >> (__layout)->mul_shift) & (__layout)->mul_mask); \
+	})
+#define PLL_MUL_MIN		2
+#define PLL_MUL_MASK(layout)	((layout)->mul_mask)
+#define PLL_MUL_MAX(layout)	(PLL_MUL_MASK(layout) + 1)
+#define PLL_ICPR_SHIFT(id)	((id) * 16)
+#define PLL_ICPR_MASK(id)	SHIFT_U64(0xffff, PLL_ICPR_SHIFT(id))
+#define PLL_MAX_COUNT		0x3f
+#define PLL_COUNT_SHIFT		8
+#define PLL_OUT_SHIFT		14
+
+struct sam9x60_pll_core {
+	vaddr_t base;
+	const struct clk_pll_charac *charac;
+	const struct clk_pll_layout *layout;
+	struct clk *hw;
+	uint8_t id;
+};
+
+struct sam9x60_frac {
+	struct sam9x60_pll_core core;
+	uint32_t frac;
+	uint16_t mul;
+};
+
+struct sam9x60_div {
+	struct sam9x60_pll_core core;
+	uint8_t div;
+	uint8_t safe_div;
+};
+
+#define WAIT_PLL_READY_TIMEOUT(_base, _id) \
+	({ \
+		uint32_t __timeout = 0; \
+		uint32_t _c = 0; \
+		\
+		while (__timeout++ < 1000) { \
+			_c = io_read32((_base) + AT91_PMC_PLL_ISR0) & \
+				BIT(_id); \
+			if (_c) \
+				break; \
+			wait_cycles(100); \
+		} \
+		!(_c); \
+	})
+
+static bool sam9x60_pll_ready(vaddr_t base, int id)
+{
+	return io_read32(base + AT91_PMC_PLL_ISR0) & BIT(id);
+}
+
+static bool sam9x60_frac_pll_ready(vaddr_t regmap, uint8_t id)
+{
+	return sam9x60_pll_ready(regmap, id);
+}
+
+static unsigned long sam9x60_frac_pll_recalc_rate(struct clk *hw,
+						  unsigned long parent_rate)
+{
+	struct sam9x60_frac *frac = hw->priv;
+
+	return parent_rate * (frac->mul + 1) +
+		UDIV_ROUND_NEAREST((unsigned long long)parent_rate * frac->frac,
+				   1 << 22);
+}
+
+static TEE_Result sam9x60_frac_pll_set(struct sam9x60_frac *frac)
+{
+	struct sam9x60_pll_core *core = &frac->core;
+	vaddr_t regmap = frac->core.base;
+	unsigned int val = 0;
+	unsigned int cfrac = 0;
+	unsigned int cmul = 0;
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK, core->id);
+	val = io_read32(regmap + AT91_PMC_PLL_CTRL1);
+	cmul = (val & core->layout->mul_mask) >> core->layout->mul_shift;
+	cfrac = (val & core->layout->frac_mask) >> core->layout->frac_shift;
+
+	if (sam9x60_frac_pll_ready(regmap, core->id) &&
+	    cmul == frac->mul && cfrac == frac->frac)
+		return TEE_SUCCESS;
+
+	/* Recommended value for PMC_PLL_ACR */
+	if (core->charac->upll)
+		val = AT91_PMC_PLL_ACR_DEFAULT_UPLL;
+	else
+		val = AT91_PMC_PLL_ACR_DEFAULT_PLLA;
+	io_write32(regmap + AT91_PMC_PLL_ACR, val);
+
+	io_write32(regmap + AT91_PMC_PLL_CTRL1,
+		   SHIFT_U32(frac->mul, core->layout->mul_shift) |
+		   SHIFT_U32(frac->frac, core->layout->frac_shift));
+
+	if (core->charac->upll) {
+		/* Enable the UTMI internal bandgap */
+		val |= AT91_PMC_PLL_ACR_UTMIBG;
+		io_write32(regmap + AT91_PMC_PLL_ACR, val);
+
+		udelay(10);
+
+		/* Enable the UTMI internal regulator */
+		val |= AT91_PMC_PLL_ACR_UTMIVR;
+		io_write32(regmap + AT91_PMC_PLL_ACR, val);
+
+		udelay(10);
+	}
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK,
+			AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+	io_setbits32(regmap + AT91_PMC_PLL_CTRL0,
+		     AT91_PMC_PLL_CTRL0_ENLOCK | AT91_PMC_PLL_CTRL0_ENPLL);
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK,
+			AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+	if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) {
+		EMSG("PLL not ready");
+		return TEE_ERROR_BUSY;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sam9x60_frac_pll_prepare(struct clk *hw)
+{
+	struct sam9x60_frac *frac = hw->priv;
+
+	return sam9x60_frac_pll_set(frac);
+}
+
+static void sam9x60_frac_pll_unprepare(struct clk *hw)
+{
+	struct sam9x60_frac *frac = hw->priv;
+
+	io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK, frac->core.id);
+
+	io_clrbits32(frac->core.base + AT91_PMC_PLL_CTRL0,
+		     AT91_PMC_PLL_CTRL0_ENPLL);
+
+	if (frac->core.charac->upll)
+		io_clrbits32(frac->core.base + AT91_PMC_PLL_ACR,
+			     AT91_PMC_PLL_ACR_UTMIBG |
+			     AT91_PMC_PLL_ACR_UTMIVR);
+
+	io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK,
+			AT91_PMC_PLL_UPDT_UPDATE | frac->core.id);
+}
+
+static TEE_Result sam9x60_frac_pll_compute_mul_frac(struct sam9x60_frac *frac,
+						    unsigned long rate,
+						    unsigned long parent_rate,
+						    bool update)
+{
+	unsigned long tmprate = 0;
+	unsigned long remainder = 0;
+	unsigned long nmul = 0;
+	unsigned long nfrac = 0;
+
+	if (rate < frac->core.charac->output[0].min ||
+	    rate > frac->core.charac->output[0].max)
+		return TEE_ERROR_GENERIC;
+
+	/*
+	 * Calculate the multiplier associated with the current
+	 * divider that provide the closest rate to the requested one.
+	 */
+	nmul = rate / parent_rate;
+	tmprate = parent_rate * nmul;
+	remainder = rate - tmprate;
+
+	if (remainder) {
+		nfrac = UDIV_ROUND_NEAREST((uint64_t)remainder * (1 << 22),
+					   parent_rate);
+
+		tmprate += UDIV_ROUND_NEAREST((uint64_t)nfrac * parent_rate,
+					      1 << 22);
+	}
+
+	/* Check if resulted rate is a valid. */
+	if (tmprate < frac->core.charac->output[0].min ||
+	    tmprate > frac->core.charac->output[0].max)
+		return TEE_ERROR_GENERIC;
+
+	if (update) {
+		frac->mul = nmul - 1;
+		frac->frac = nfrac;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sam9x60_frac_pll_set_rate_chg(struct clk *hw,
+						unsigned long rate,
+						unsigned long parent_rate)
+{
+	TEE_Result ret = TEE_SUCCESS;
+	struct sam9x60_frac *frac = hw->priv;
+	struct sam9x60_pll_core *core = &frac->core;
+	vaddr_t regmap = core->base;
+
+	ret = sam9x60_frac_pll_compute_mul_frac(frac, rate, parent_rate, true);
+	if (ret == TEE_SUCCESS) {
+		io_write32(regmap + AT91_PMC_PLL_CTRL1,
+			   SHIFT_U32(frac->mul, core->layout->mul_shift) |
+			   SHIFT_U32(frac->frac, core->layout->frac_shift));
+
+		io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+				AT91_PMC_PLL_UPDT_UPDATE |
+				AT91_PMC_PLL_UPDT_ID_MASK,
+				AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+		io_setbits32(regmap + AT91_PMC_PLL_CTRL0,
+			     AT91_PMC_PLL_CTRL0_ENLOCK |
+			     AT91_PMC_PLL_CTRL0_ENPLL);
+
+		io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+				AT91_PMC_PLL_UPDT_UPDATE |
+				AT91_PMC_PLL_UPDT_ID_MASK,
+				AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+		if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) {
+			EMSG("PLL not ready");
+			return TEE_ERROR_BUSY;
+		}
+	}
+
+	return ret;
+}
+
+static const struct clk_ops sam9x60_frac_pll_ops_chg = {
+	.enable = sam9x60_frac_pll_prepare,
+	.disable = sam9x60_frac_pll_unprepare,
+	.get_rate = sam9x60_frac_pll_recalc_rate,
+	.set_rate = sam9x60_frac_pll_set_rate_chg,
+};
+
+static TEE_Result sam9x60_div_pll_set_div(struct sam9x60_pll_core *core,
+					  uint32_t div,
+					  bool enable)
+{
+	vaddr_t regmap = core->base;
+	uint32_t enable_mask = enable ? core->layout->endiv_mask : 0;
+	uint32_t ena_val = enable ? BIT(core->layout->endiv_shift) : 0;
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_CTRL0,
+			core->layout->div_mask | enable_mask,
+			SHIFT_U32(div, core->layout->div_shift) | ena_val);
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK,
+			AT91_PMC_PLL_UPDT_UPDATE | core->id);
+
+	if (WAIT_PLL_READY_TIMEOUT(regmap, core->id)) {
+		EMSG("PLL not ready");
+		return TEE_ERROR_BUSY;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sam9x60_div_pll_set(struct sam9x60_div *div)
+{
+	struct sam9x60_pll_core *core = &div->core;
+	vaddr_t regmap = core->base;
+	unsigned int val = 0;
+	unsigned int cdiv = 0;
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK, core->id);
+	val = io_read32(regmap + AT91_PMC_PLL_CTRL0);
+	cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
+
+	/* Stop if enabled an nothing changed. */
+	if ((val & core->layout->endiv_mask) && cdiv == div->div)
+		return TEE_SUCCESS;
+
+	return sam9x60_div_pll_set_div(core, div->div, 1);
+}
+
+static TEE_Result sam9x60_div_pll_prepare(struct clk *hw)
+{
+	struct sam9x60_div *div = hw->priv;
+
+	return sam9x60_div_pll_set(div);
+}
+
+static void sam9x60_div_pll_unprepare(struct clk *hw)
+{
+	struct sam9x60_div *div = hw->priv;
+	struct sam9x60_pll_core *core = &div->core;
+	vaddr_t regmap = core->base;
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK, core->id);
+
+	io_clrbits32(regmap + AT91_PMC_PLL_CTRL0, core->layout->endiv_mask);
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_UPDATE | AT91_PMC_PLL_UPDT_ID_MASK,
+			AT91_PMC_PLL_UPDT_UPDATE | core->id);
+}
+
+static unsigned long sam9x60_div_pll_recalc_rate(struct clk *hw,
+						 unsigned long parent_rate)
+{
+	struct sam9x60_div *div = hw->priv;
+
+	return UDIV_ROUND_NEAREST(parent_rate, div->div + 1);
+}
+
+static TEE_Result sam9x60_div_pll_set_rate(struct clk *hw,
+					   unsigned long rate,
+					   unsigned long parent_rate)
+{
+	struct sam9x60_div *div = hw->priv;
+
+	div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sam9x60_div_pll_set_rate_chg(struct clk *hw,
+					       unsigned long rate,
+					       unsigned long parent_rate)
+{
+	struct sam9x60_div *div = hw->priv;
+	struct sam9x60_pll_core *core = &div->core;
+	vaddr_t regmap = core->base;
+	unsigned int val = 0;
+	unsigned int cdiv = 0;
+
+	div->div = UDIV_ROUND_NEAREST(parent_rate, rate) - 1;
+
+	io_clrsetbits32(regmap + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK,
+			core->id);
+	val = io_read32(regmap + AT91_PMC_PLL_CTRL0);
+	cdiv = (val & core->layout->div_mask) >> core->layout->div_shift;
+
+	/* Stop if nothing changed. */
+	if (cdiv == div->div)
+		return TEE_SUCCESS;
+
+	return sam9x60_div_pll_set_div(core, div->div, 0);
+}
+
+static const struct clk_ops sam9x60_div_pll_ops = {
+	.enable = sam9x60_div_pll_prepare,
+	.disable = sam9x60_div_pll_unprepare,
+	.set_rate = sam9x60_div_pll_set_rate,
+	.get_rate = sam9x60_div_pll_recalc_rate,
+};
+
+static const struct clk_ops sam9x60_div_pll_ops_chg = {
+	.enable = sam9x60_div_pll_prepare,
+	.disable = sam9x60_div_pll_unprepare,
+	.set_rate = sam9x60_div_pll_set_rate_chg,
+	.get_rate = sam9x60_div_pll_recalc_rate,
+};
+
+struct clk *sam9x60_clk_register_frac_pll(struct pmc_data *pmc,
+					  const char *name,
+					  struct clk *parent,
+					  uint8_t id,
+					  const struct clk_pll_charac *charac,
+					  const struct clk_pll_layout *layout,
+					  uint32_t flags)
+{
+	struct sam9x60_frac *frac = NULL;
+	struct clk *hw = NULL;
+	unsigned long parent_rate = 0;
+	unsigned int val = 0;
+	TEE_Result ret = TEE_SUCCESS;
+
+	frac = calloc(1, sizeof(*frac));
+	if (!frac)
+		return NULL;
+
+	hw = clk_alloc(name, &sam9x60_frac_pll_ops_chg, &parent, 1);
+	if (!hw) {
+		free(frac);
+		return NULL;
+	}
+
+	hw->priv = frac;
+	hw->flags = flags;
+	frac->core.id = id;
+	frac->core.charac = charac;
+	frac->core.layout = layout;
+	frac->core.base = pmc->base;
+
+	if (sam9x60_pll_ready(pmc->base, id)) {
+		io_clrsetbits32(frac->core.base + AT91_PMC_PLL_UPDT,
+				AT91_PMC_PLL_UPDT_ID_MASK, id);
+		val = io_read32(pmc->base + AT91_PMC_PLL_CTRL1);
+		frac->mul = (val >> PMC_PLL_CTRL1_MUL_POS) &
+			PMC_PLL_CTRL1_MUL_MASK;
+		frac->frac = (val >> PMC_PLL_CTRL1_FRACR_POS) &
+			PMC_PLL_CTRL1_FRACR_MASK;
+	} else {
+		/*
+		 * This means the PLL is not setup by bootloaders. In this
+		 * case we need to set the minimum rate for it. Otherwise
+		 * a clock child of this PLL may be enabled before setting
+		 * its rate leading to enabling this PLL with unsupported
+		 * rate. This will lead to PLL not being locked at all.
+		 */
+		parent_rate = clk_get_rate(parent);
+		if (!parent_rate) {
+			clk_free(hw);
+			free(frac);
+			return NULL;
+		}
+
+		ret = sam9x60_frac_pll_compute_mul_frac(frac,
+							charac->output[0].min,
+							parent_rate, true);
+		if (ret != TEE_SUCCESS) {
+			clk_free(hw);
+			free(frac);
+			return NULL;
+		}
+	}
+
+	frac->core.hw = hw;
+	if (clk_register(hw)) {
+		clk_free(hw);
+		free(frac);
+		return NULL;
+	}
+
+	return hw;
+}
+
+struct clk *sam9x60_clk_register_div_pll(struct pmc_data *pmc,
+					 const char *name,
+					 struct clk *parent,
+					 uint8_t id,
+					 const struct clk_pll_charac *charac,
+					 const struct clk_pll_layout *layout,
+					 uint32_t flags,
+					 uint32_t safe_div)
+{
+	struct sam9x60_div *div = NULL;
+	struct clk *hw = NULL;
+	unsigned int val = 0;
+
+	if (safe_div >= PLL_DIV_MAX)
+		safe_div = PLL_DIV_MAX - 1;
+
+	div = calloc(1, sizeof(*div));
+	if (!div)
+		return NULL;
+
+	if (flags & CLK_SET_RATE_GATE)
+		hw = clk_alloc(name, &sam9x60_div_pll_ops, &parent, 1);
+	else
+		hw = clk_alloc(name, &sam9x60_div_pll_ops_chg, &parent, 1);
+	if (!hw) {
+		free(div);
+		return NULL;
+	}
+
+	hw->priv = div;
+	hw->flags = flags;
+	div->core.id = id;
+	div->core.charac = charac;
+	div->core.layout = layout;
+	div->core.base = pmc->base;
+	div->safe_div = safe_div;
+
+	io_clrsetbits32(pmc->base + AT91_PMC_PLL_UPDT,
+			AT91_PMC_PLL_UPDT_ID_MASK, id);
+	val = io_read32(pmc->base + AT91_PMC_PLL_CTRL0);
+	div->div = (val >> PMC_PLL_CTRL0_DIV_POS) & PMC_PLL_CTRL0_DIV_MASK;
+
+	div->core.hw = hw;
+	if (clk_register(hw)) {
+		clk_free(hw);
+		free(div);
+		return NULL;
+	}
+
+	return hw;
+}
diff --git a/core/drivers/clk/sam/phy-sama7-utmi-clk.c b/core/drivers/clk/sam/phy-sama7-utmi-clk.c
new file mode 100644
index 0000000000000000000000000000000000000000..772989310596af71fb511c891f4b3f2941b614cc
--- /dev/null
+++ b/core/drivers/clk/sam/phy-sama7-utmi-clk.c
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Driver for the Microchip SAMA7 USB 2.0 PHY Clock
+ *
+ * Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries
+ *
+ * Author: Tony Han <tony.han@microchip.com>
+ *
+ */
+
+#include <drivers/atmel_rstc.h>
+#include <io.h>
+#include <kernel/delay.h>
+#include <mm/core_memprot.h>
+#include <sam_sfr.h>
+#include "at91_clk.h"
+
+#define SAMA7_SFR_UTMI0R(x) (0x2040 + 4 * (x)) /* offset of SFR_UTMI0Rx */
+#define SAMA7_SFR_UTMI_COMMONON BIT(3) /* PLL Common ON bit */
+
+struct sama7_utmi_clk {
+	vaddr_t base;
+	uint8_t id;
+};
+
+static TEE_Result sama7_utmi_clk_enable(struct clk *hw)
+{
+	struct sama7_utmi_clk *utmi = hw->priv;
+	uint8_t id = utmi->id;
+
+	sam_rstc_usb_por(id, true);
+	io_clrbits32(utmi->base + SAMA7_SFR_UTMI0R(id),
+		     SAMA7_SFR_UTMI_COMMONON);
+	sam_rstc_usb_por(id, false);
+
+	/* Datasheet states a minimum of 45 us before any USB operation */
+	udelay(50);
+
+	return TEE_SUCCESS;
+}
+
+static void sama7_utmi_clk_disable(struct clk *hw)
+{
+	struct sama7_utmi_clk *utmi = hw->priv;
+	uint8_t id = utmi->id;
+
+	sam_rstc_usb_por(id, true);
+	io_setbits32(utmi->base + SAMA7_SFR_UTMI0R(id),
+		     SAMA7_SFR_UTMI_COMMONON);
+}
+
+static const struct clk_ops sama7_utmi_ops = {
+	.enable = sama7_utmi_clk_enable,
+	.disable = sama7_utmi_clk_disable,
+};
+
+struct clk *sama7_utmi_clk_register(const char *name,
+				    struct clk *parent,
+				    uint8_t id)
+{
+	struct clk *hw = NULL;
+	struct sama7_utmi_clk *utmi_clk = NULL;
+
+	hw = clk_alloc(name, &sama7_utmi_ops, &parent, 1);
+	if (!hw)
+		return NULL;
+
+	utmi_clk = calloc(1, sizeof(*utmi_clk));
+	if (!utmi_clk) {
+		clk_free(hw);
+		return NULL;
+	}
+
+	utmi_clk->base = sam_sfr_base();
+	utmi_clk->id = id;
+	hw->priv = utmi_clk;
+
+	if (clk_register(hw)) {
+		clk_free(hw);
+		free(utmi_clk);
+		return NULL;
+	}
+
+	return hw;
+}
diff --git a/core/drivers/clk/sam/sama5d2_clk.c b/core/drivers/clk/sam/sama5d2_clk.c
index 65f8f1bcfb4f93b1112da17698bda2a27e32b40d..3bc9ce61c2a91ea4a6f5a5ee6fcccf1f2d76b11b 100644
--- a/core/drivers/clk/sam/sama5d2_clk.c
+++ b/core/drivers/clk/sam/sama5d2_clk.c
@@ -572,7 +572,7 @@ static TEE_Result pmc_setup(const void *fdt, int nodeoffset,
 		clk = at91_clk_register_generated(pmc,
 						  &sama5d2_pcr_layout,
 						  sam_clk->n,
-						  parents, 6,
+						  parents, NULL, 6,
 						  sam_clk->id,
 						  &sama5d2_gck[i].r,
 						  sama5d2_gck[i].chg_pid);
diff --git a/core/drivers/clk/sam/sama7g5_clk.c b/core/drivers/clk/sam/sama7g5_clk.c
new file mode 100644
index 0000000000000000000000000000000000000000..67f702b5ec7637e335c00f1582db64762fc8ad2a
--- /dev/null
+++ b/core/drivers/clk/sam/sama7g5_clk.c
@@ -0,0 +1,1580 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Microchip
+ */
+
+#include <assert.h>
+#include <dt-bindings/clock/at91.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <matrix.h>
+#include <sama7g5.h>
+#include <stdint.h>
+#include <util.h>
+#include "at91_clk.h"
+
+#define CLK_IS_CRITICAL 0
+
+/* PLL clocks identifiers */
+enum pll_ids {
+	PLL_ID_CPU,
+	PLL_ID_SYS,
+	PLL_ID_DDR,
+	PLL_ID_IMG,
+	PLL_ID_BAUD,
+	PLL_ID_AUDIO,
+	PLL_ID_ETH,
+	PLL_ID_MAX,
+};
+
+/* PLL type identifiers */
+enum pll_type {
+	PLL_TYPE_FRAC,
+	PLL_TYPE_DIV,
+	PLL_TYPE_CNT,
+};
+
+/* Layout for fractional PLLs */
+static const struct clk_pll_layout pll_layout_frac = {
+	.mul_mask	= GENMASK_32(31, 24),
+	.frac_mask	= GENMASK_32(21, 0),
+	.mul_shift	= 24,
+	.frac_shift	= 0,
+};
+
+/* Layout for DIVPMC dividers */
+static const struct clk_pll_layout pll_layout_divpmc = {
+	.div_mask	= GENMASK_32(7, 0),
+	.endiv_mask	= BIT(29),
+	.div_shift	= 0,
+	.endiv_shift	= 29,
+};
+
+/* Layout for DIVIO dividers */
+static const struct clk_pll_layout pll_layout_divio = {
+	.div_mask	= GENMASK_32(19, 12),
+	.endiv_mask	= BIT(30),
+	.div_shift	= 12,
+	.endiv_shift	= 30,
+};
+
+/*
+ * CPU PLL output range
+ * Notice: The upper limit has been setup to 1000000002 due to hardware
+ * block which cannot output exactly 1GHz.
+ */
+static const struct clk_range cpu_pll_output[] = {
+	{ .min = 2343750, .max = 1000000002 },
+};
+
+/* PLL output range */
+static const struct clk_range pll_output[] = {
+	{ .min = 2343750, .max = 1200000000 },
+};
+
+/* CPU PLL characteristics */
+static const struct clk_pll_charac cpu_pll_characteristics = {
+	.input = { .min = 12000000, .max = 50000000 },
+	.num_output = ARRAY_SIZE(cpu_pll_output),
+	.output = cpu_pll_output,
+};
+
+/* PLL characteristics */
+static const struct clk_pll_charac pll_characteristics = {
+	.input = { .min = 12000000, .max = 50000000 },
+	.num_output = ARRAY_SIZE(pll_output),
+	.output = pll_output,
+};
+
+/* PLL clocks description */
+struct sama7g5_pll {
+	const char *name;
+	const char *parent;
+	const struct clk_pll_layout *layout;
+	const struct clk_pll_charac *charac;
+	unsigned long flags;
+	uint8_t type;
+	uint8_t eid; /* export index in sama7g5->chws[] array */
+	uint8_t safe_div; /* intermediate divider need to be set on
+			   * PRE_RATE_CHANGE notification
+			   */
+};
+
+static const struct sama7g5_pll sama7g5_plls[][PLL_ID_MAX] = {
+	[PLL_ID_CPU] = {
+		{
+			.name = "cpupll_fracck",
+			.parent = "mainck",
+			.layout = &pll_layout_frac,
+			.charac = &cpu_pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			/*
+			 * This feeds cpupll_divpmcck which feeds CPU. It
+			 * should not be disabled.
+			 */
+			.flags = CLK_IS_CRITICAL,
+		},
+		{
+			.name = "cpupll_divpmcck",
+			.parent = "cpupll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &cpu_pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			/* This feeds CPU. It should not be disabled. */
+			.flags = CLK_IS_CRITICAL,
+			.eid = PMC_CPUPLL,
+			/*
+			 * Safe div=15 should be safe even for switching b/w
+			 * 1GHz and 90MHz (frac pll might go up to 1.2GHz).
+			 */
+			.safe_div = 15,
+		},
+	},
+
+	[PLL_ID_SYS] = {
+		{
+			.name = "syspll_fracck",
+			.parent = "mainck",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			/*
+			 * This feeds syspll_divpmcck which may feed critical
+			 * parts of the systems like timers. Therefore it
+			 * should not be disabled.
+			 */
+			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "syspll_divpmcck",
+			.parent = "syspll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			/*
+			 * This may feed critical parts of the systems like
+			 * timers. Therefore it should not be disabled.
+			 */
+			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+			.eid = PMC_SYSPLL,
+		},
+	},
+
+	[PLL_ID_DDR] = {
+		{
+			.name = "ddrpll_fracck",
+			.parent = "mainck",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			/*
+			 * This feeds ddrpll_divpmcck which feeds DDR. It
+			 * should not be disabled.
+			 */
+			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "ddrpll_divpmcck",
+			.parent = "ddrpll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			/* This feeds DDR. It should not be disabled. */
+			.flags = CLK_IS_CRITICAL | CLK_SET_RATE_GATE,
+			.eid = PMC_DDRPLL,
+		},
+	},
+
+	[PLL_ID_IMG] = {
+		{
+			.name = "imgpll_fracck",
+			.parent = "mainck",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			.flags = CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "imgpll_divpmcck",
+			.parent = "imgpll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
+			.eid = PMC_IMGPLL,
+		},
+	},
+
+	[PLL_ID_BAUD] = {
+		{
+			.name = "baudpll_fracck",
+			.parent = "mainck",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			.flags = CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "baudpll_divpmcck",
+			.parent = "baudpll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
+			.eid = PMC_BAUDPLL,
+		},
+	},
+
+	[PLL_ID_AUDIO] = {
+		{
+			.name = "audiopll_fracck",
+			.parent = "main_xtal",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			.flags = CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "audiopll_divck",
+			.parent = "audiopll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
+			.eid = PMC_AUDIOPMCPLL,
+		},
+		{
+			.name = "audiopll_diviock",
+			.parent = "audiopll_fracck",
+			.layout = &pll_layout_divio,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
+			.eid = PMC_AUDIOIOPLL,
+		},
+	},
+
+	[PLL_ID_ETH] = {
+		{
+			.name = "ethpll_fracck",
+			.parent = "main_xtal",
+			.layout = &pll_layout_frac,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_FRAC,
+			.flags = CLK_SET_RATE_GATE,
+		},
+		{
+			.name = "ethpll_divpmcck",
+			.parent = "ethpll_fracck",
+			.layout = &pll_layout_divpmc,
+			.charac = &pll_characteristics,
+			.type = PLL_TYPE_DIV,
+			.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE,
+			.eid = PMC_ETHPLL,
+		},
+	},
+};
+
+/*
+ * Master clock (MCK[1..4]) description
+ * @eparents:		extra parents names array
+ * @eparents_chg_id:	index in parents array that specifies the changeable
+ *			parent
+ * @eparents_count:	extra parents count
+ * @eparents_mux_table:	mux table for extra parents
+ * @id:			clock id
+ * @eid:		export index in sama7g5->chws[] array
+ */
+struct sama7g5_mck {
+	const char *name;
+	const char *eparents[4];
+	int eparents_chg_id;
+	uint8_t eparents_count;
+	uint8_t eparents_mux_table[4];
+	uint8_t id;
+	uint8_t eid;
+};
+
+static const struct sama7g5_mck sama7g5_mckx[] = {
+	{
+		.name = "mck1",
+		.id = 1,
+		.eparents = { "syspll_divpmcck", },
+		.eparents_mux_table = { 5, },
+		.eparents_count = 1,
+		.eparents_chg_id = INT_MIN,
+		.eid = PMC_MCK1,
+	},
+	{
+		.name = "mck2",
+		.id = 2,
+		.eparents = { "ddrpll_divpmcck", },
+		.eparents_mux_table = { 6, },
+		.eparents_count = 1,
+		.eparents_chg_id = INT_MIN,
+	},
+	{
+		.name = "mck3",
+		.id = 3,
+		.eparents = { "syspll_divpmcck",
+			"ddrpll_divpmcck",
+			"imgpll_divpmcck", },
+		.eparents_mux_table = { 5, 6, 7, },
+		.eparents_count = 3,
+		.eparents_chg_id = 5,
+	},
+	{
+		.name = "mck4",
+		.id = 4,
+		.eparents = { "syspll_divpmcck", },
+		.eparents_mux_table = { 5, },
+		.eparents_count = 1,
+		.eparents_chg_id = INT_MIN,
+	},
+};
+
+/* System clock description */
+static const struct {
+	const char *name;
+	const char *parent;
+	uint8_t id;
+} sama7g5_systemck[] = {
+	{ .name = "pck0", .parent = "prog0", .id = 8, },
+	{ .name = "pck1", .parent = "prog1", .id = 9, },
+	{ .name = "pck2", .parent = "prog2", .id = 10, },
+	{ .name = "pck3", .parent = "prog3", .id = 11, },
+	{ .name = "pck4", .parent = "prog4", .id = 12, },
+	{ .name = "pck5", .parent = "prog5", .id = 13, },
+	{ .name = "pck6", .parent = "prog6", .id = 14, },
+	{ .name = "pck7", .parent = "prog7", .id = 15, },
+};
+
+/* Peripheral clock description */
+static const struct {
+	const char *name;
+	const char *parent;
+	struct clk_range output;
+	uint8_t id;
+} peri_clks[] = {
+	{
+		.name = "pioA_clk",
+		.parent = "mck0",
+		.id = 11,
+	},
+	{
+		.name = "securam_clk",
+		.parent = "mck0",
+		.id = 18,
+	},
+	{
+		.name = "sfr_clk",
+		.parent = "mck1",
+		.id = 19,
+	},
+	{
+		.name = "hsmc_clk",
+		.parent = "mck1",
+		.id = 21,
+	},
+	{
+		.name = "xdmac0_clk",
+		.parent = "mck1",
+		.id = 22,
+	},
+	{
+		.name = "xdmac1_clk",
+		.parent = "mck1",
+		.id = 23,
+	},
+	{
+		.name = "xdmac2_clk",
+		.parent = "mck1",
+		.id = 24,
+	},
+	{
+		.name = "acc_clk",
+		.parent = "mck1",
+		.id = 25,
+	},
+	{
+		.name = "aes_clk",
+		.parent = "mck1",
+		.id = 27,
+	},
+	{
+		.name = "tzaesbasc_clk",
+		.parent = "mck1",
+		.id = 28,
+	},
+	{
+		.name = "asrc_clk",
+		.parent = "mck1",
+		.id = 30,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "cpkcc_clk",
+		.parent = "mck0",
+		.id = 32,
+	},
+	{
+		.name = "csi_clk",
+		.parent = "mck3",
+		.id = 33,
+		.output = { .max = 266000000, },
+	},
+	{
+		.name = "csi2dc_clk",
+		.parent = "mck3",
+		.id = 34,
+		.output = { .max = 266000000, },
+	},
+	{
+		.name = "eic_clk",
+		.parent = "mck1",
+		.id = 37,
+	},
+	{
+		.name = "flex0_clk",
+		.parent = "mck1",
+		.id = 38,
+	},
+	{
+		.name = "flex1_clk",
+		.parent = "mck1",
+		.id = 39,
+	},
+	{
+		.name = "flex2_clk",
+		.parent = "mck1",
+		.id = 40,
+	},
+	{
+		.name = "flex3_clk",
+		.parent = "mck1",
+		.id = 41,
+	},
+	{
+		.name = "flex4_clk",
+		.parent = "mck1",
+		.id = 42,
+	},
+	{
+		.name = "flex5_clk",
+		.parent = "mck1",
+		.id = 43,
+	},
+	{
+		.name = "flex6_clk",
+		.parent = "mck1",
+		.id = 44,
+	},
+	{
+		.name = "flex7_clk",
+		.parent = "mck1",
+		.id = 45,
+	},
+	{
+		.name = "flex8_clk",
+		.parent = "mck1",
+		.id = 46,
+	},
+	{
+		.name = "flex9_clk",
+		.parent = "mck1",
+		.id = 47,
+	},
+	{
+		.name = "flex10_clk",
+		.parent = "mck1",
+		.id = 48,
+	},
+	{
+		.name = "flex11_clk",
+		.parent = "mck1",
+		.id = 49,
+	},
+	{
+		.name = "gmac0_clk",
+		.parent = "mck1",
+		.id = 51,
+	},
+	{
+		.name = "gmac1_clk",
+		.parent = "mck1",
+		.id = 52,
+	},
+	{
+		.name = "icm_clk",
+		.parent = "mck1",
+		.id = 55,
+	},
+	{
+		.name = "isc_clk",
+		.parent = "mck3",
+		.id = 56,
+		.output = { .max = 266000000, },
+	},
+	{
+		.name = "i2smcc0_clk",
+		.parent = "mck1",
+		.id = 57,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "i2smcc1_clk",
+		.parent = "mck1",
+		.id = 58,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "matrix_clk",
+		.parent = "mck1",
+		.id = 60, },
+	{
+		.name = "mcan0_clk",
+		.parent = "mck1",
+		.id = 61,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "mcan1_clk",
+		.parent = "mck1",
+		.id = 62,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "mcan2_clk",
+		.parent = "mck1",
+		.id = 63,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "mcan3_clk",
+		.parent = "mck1",
+		.id = 64,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "mcan4_clk",
+		.parent = "mck1",
+		.id = 65,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "mcan5_clk",
+		.parent = "mck1",
+		.id = 66,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "pdmc0_clk",
+		.parent = "mck1",
+		.id = 68,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "pdmc1_clk",
+		.parent = "mck1",
+		.id = 69,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "pit64b0_clk",
+		.parent = "mck1",
+		.id = 70,
+	},
+	{
+		.name = "pit64b1_clk",
+		.parent = "mck1",
+		.id = 71,
+	},
+	{
+		.name = "pit64b2_clk",
+		.parent = "mck1",
+		.id = 72,
+	},
+	{
+		.name = "pit64b3_clk",
+		.parent = "mck1",
+		.id = 73,
+	},
+	{
+		.name = "pit64b4_clk",
+		.parent = "mck1",
+		.id = 74,
+	},
+	{
+		.name = "pit64b5_clk",
+		.parent = "mck1",
+		.id = 75,
+	},
+	{
+		.name = "pwm_clk",
+		.parent = "mck1",
+		.id = 77,
+	},
+	{
+		.name = "qspi0_clk",
+		.parent = "mck1",
+		.id = 78,
+	},
+	{
+		.name = "qspi1_clk",
+		.parent = "mck1",
+		.id = 79,
+	},
+	{
+		.name = "sdmmc0_clk",
+		.parent = "mck1",
+		.id = 80,
+	},
+	{
+		.name = "sdmmc1_clk",
+		.parent = "mck1",
+		.id = 81,
+	},
+	{
+		.name = "sdmmc2_clk",
+		.parent = "mck1",
+		.id = 82,
+	},
+	{
+		.name = "sha_clk",
+		.parent = "mck1",
+		.id = 83,
+	},
+	{
+		.name = "spdifrx_clk",
+		.parent = "mck1",
+		.id = 84,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "spdiftx_clk",
+		.parent = "mck1",
+		.id = 85,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "ssc0_clk",
+		.parent = "mck1",
+		.id = 86,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "ssc1_clk",
+		.parent = "mck1",
+		.id = 87,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb0_ch0_clk",
+		.parent = "mck1",
+		.id = 88,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb0_ch1_clk",
+		.parent = "mck1",
+		.id = 89,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb0_ch2_clk",
+		.parent = "mck1",
+		.id = 90,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb1_ch0_clk",
+		.parent = "mck1",
+		.id = 91,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb1_ch1_clk",
+		.parent = "mck1",
+		.id = 92,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcb1_ch2_clk",
+		.parent = "mck1",
+		.id = 93,
+		.output = { .max = 200000000, },
+	},
+	{
+		.name = "tcpca_clk",
+		.parent = "mck1",
+		.id = 94,
+	},
+	{
+		.name = "tcpcb_clk",
+		.parent = "mck1",
+		.id = 95,
+	},
+	{
+		.name = "tdes_clk",
+		.parent = "mck1",
+		.id = 96,
+	},
+	{
+		.name = "trng_clk",
+		.parent = "mck1",
+		.id = 97,
+	},
+	{
+		.name = "udphsa_clk",
+		.parent = "mck1",
+		.id = 104,
+	},
+	{
+		.name = "udphsb_clk",
+		.parent = "mck1",
+		.id = 105,
+	},
+	{
+		.name = "uhphs_clk",
+		.parent = "mck1",
+		.id = 106,
+	},
+};
+
+/* UTMI clock description */
+static struct {
+	const char *name;
+	const char *parent;
+	uint8_t id;
+} sama7_utmick[] = {
+	{ .name = "utmi1ck", .parent = "utmick", .id = 0, },
+	{ .name = "utmi2ck", .parent = "utmi1ck", .id = 1, },
+	{ .name = "utmi3ck", .parent = "utmi1ck", .id = 2, },
+};
+
+/* Generic clock description */
+struct sama7g5_gck {
+	const char *name;
+	const char *parents[8];
+	const char parents_mux_table[8];
+	struct clk_range output;
+	int parents_chg_id; /* id in parent array of changeable PLL parent */
+	uint8_t parents_count;
+	uint8_t id;
+};
+
+static const struct sama7g5_gck sama7g5_gcks[] = {
+	{
+		.name  = "adc_gclk",
+		.id = 26,
+		.output = { .max = 100000000, },
+		.parents = { "syspll_divpmcck",
+			     "imgpll_divpmcck",
+			     "audiopll_divck", },
+		.parents_mux_table = { 5, 7, 9, },
+		.parents_count = 3,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "asrc_gclk",
+		.id = 30,
+		.output = { .max = 200000000 },
+		.parents = { "audiopll_divck", },
+		.parents_mux_table = { 9, },
+		.parents_count = 1,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "csi_gclk",
+		.id = 33,
+		.output = { .max = 27000000  },
+		.parents = { "ddrpll_divpmcck", "imgpll_divpmcck", },
+		.parents_mux_table = { 6, 7, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex0_gclk",
+		.id = 38,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex1_gclk",
+		.id = 39,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex2_gclk",
+		.id = 40,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex3_gclk",
+		.id = 41,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex4_gclk",
+		.id = 42,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex5_gclk",
+		.id = 43,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex6_gclk",
+		.id = 44,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex7_gclk",
+		.id = 45,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex8_gclk",
+		.id = 46,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex9_gclk",
+		.id = 47,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex10_gclk",
+		.id = 48,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "flex11_gclk",
+		.id = 49,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "gmac0_gclk",
+		.id = 51,
+		.output = { .max = 125000000 },
+		.parents = { "ethpll_divpmcck", },
+		.parents_mux_table = { 10, },
+		.parents_count = 1,
+		.parents_chg_id = 3,
+	},
+	{
+		.name  = "gmac1_gclk",
+		.id = 52,
+		.output = { .max = 50000000  },
+		.parents = { "ethpll_divpmcck", },
+		.parents_mux_table = { 10, },
+		.parents_count = 1,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "gmac0_tsu_gclk",
+		.id = 53,
+		.output = { .max = 300000000 },
+		.parents = { "audiopll_divck", "ethpll_divpmcck", },
+		.parents_mux_table = { 9, 10, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "gmac1_tsu_gclk",
+		.id = 54,
+		.output = { .max = 300000000 },
+		.parents = { "audiopll_divck", "ethpll_divpmcck", },
+		.parents_mux_table = { 9, 10, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "i2smcc0_gclk",
+		.id = 57,
+		.output = { .max = 100000000 },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "i2smcc1_gclk",
+		.id = 58,
+		.output = { .max = 100000000 },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan0_gclk",
+		.id = 61,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan1_gclk",
+		.id = 62,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan2_gclk",
+		.id = 63,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan3_gclk",
+		.id = 64,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan4_gclk",
+		.id = 65,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "mcan5_gclk",
+		.id = 66,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pdmc0_gclk",
+		.id = 68,
+		.output = { .max = 50000000  },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pdmc1_gclk",
+		.id = 69,
+		.output = { .max = 50000000, },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b0_gclk",
+		.id = 70,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b1_gclk",
+		.id = 71,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b2_gclk",
+		.id = 72,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b3_gclk",
+		.id = 73,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b4_gclk",
+		.id = 74,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "pit64b5_gclk",
+		.id = 75,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "qspi0_gclk",
+		.id = 78,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "qspi1_gclk",
+		.id = 79,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "sdmmc0_gclk",
+		.id = 80,
+		.output = { .max = 208000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = 4,
+	},
+	{
+		.name  = "sdmmc1_gclk",
+		.id = 81,
+		.output = { .max = 208000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = 4,
+	},
+	{
+		.name  = "sdmmc2_gclk",
+		.id = 82,
+		.output = { .max = 208000000 },
+		.parents = { "syspll_divpmcck", "baudpll_divpmcck", },
+		.parents_mux_table = { 5, 8, },
+		.parents_count = 2,
+		.parents_chg_id = 4,
+	},
+	{
+		.name  = "spdifrx_gclk",
+		.id = 84,
+		.output = { .max = 150000000 },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name = "spdiftx_gclk",
+		.id = 85,
+		.output = { .max = 25000000  },
+		.parents = { "syspll_divpmcck", "audiopll_divck", },
+		.parents_mux_table = { 5, 9, },
+		.parents_count = 2,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "tcb0_ch0_gclk",
+		.id = 88,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "tcb1_ch0_gclk",
+		.id = 91,
+		.output = { .max = 200000000 },
+		.parents = { "syspll_divpmcck", "imgpll_divpmcck",
+			     "baudpll_divpmcck", "audiopll_divck",
+			     "ethpll_divpmcck", },
+		.parents_mux_table = { 5, 7, 8, 9, 10, },
+		.parents_count = 5,
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "tcpca_gclk",
+		.id = 94,
+		.output = { .max = 32768, },
+		.parents_chg_id = INT_MIN,
+	},
+	{
+		.name  = "tcpcb_gclk",
+		.id = 95,
+		.output = { .max = 32768, },
+		.parents_chg_id = INT_MIN,
+	},
+};
+
+/* MCK0 characteristics */
+static const struct clk_master_charac mck0_characteristics = {
+	.output = { .min = 32768, .max = 200000000 },
+	.divisors = { 1, 2, 4, 3, 5 },
+	.have_div3_pres = 1,
+};
+
+/* MCK0 layout */
+static const struct clk_master_layout mck0_layout = {
+	.mask = 0x773,
+	.pres_shift = 4,
+	.offset = 0x28,
+};
+
+/* Peripheral clock layout */
+static const struct clk_pcr_layout sama7g5_pcr_layout = {
+	.offset = 0x88,
+	.cmd = BIT(31),
+	.div_mask = GENMASK_32(27, 20),
+	.gckcss_mask = GENMASK_32(12, 8),
+	.pid_mask = GENMASK_32(6, 0),
+};
+
+static const struct clk_programmable_layout sama7g5_prog_layout = {
+	.pres_mask = 0xff,
+	.pres_shift = 8,
+	.css_mask = GENMASK_32(4, 0),
+	.have_slck_mck = 0,
+	.is_pres_direct = 1,
+};
+
+static const struct {
+	const char *name;
+	uint8_t id;
+} sama7g5_progck[] = {
+	{ .name = "prog0", .id = 0 },
+	{ .name = "prog1", .id = 1 },
+	{ .name = "prog2", .id = 2 },
+	{ .name = "prog3", .id = 3 },
+	{ .name = "prog4", .id = 4 },
+	{ .name = "prog5", .id = 5 },
+	{ .name = "prog6", .id = 6 },
+	{ .name = "prog7", .id = 7 },
+};
+
+static struct pmc_data *sama7g5_pmc;
+
+vaddr_t at91_pmc_get_base(void)
+{
+	assert(sama7g5_pmc);
+
+	return sama7g5_pmc->base;
+}
+
+TEE_Result at91_pmc_clk_get(unsigned int type, unsigned int idx,
+			    struct clk **clk)
+{
+	return pmc_clk_get(sama7g5_pmc, type, idx, clk);
+}
+
+static TEE_Result pmc_setup_sama7g5(const void *fdt, int nodeoffset,
+				    const void *data __unused)
+{
+	struct clk *pll_frac_clk[PLL_ID_MAX] = { };
+	struct clk *pll_div_clk[PLL_ID_MAX] = { };
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const uint32_t *fdt_prop = NULL;
+	struct pmc_clk *pmc_clk = NULL;
+	struct clk *parents[11] = { };
+	struct clk *main_xtal_clk = NULL;
+	struct clk *main_rc_osc = NULL;
+	struct clk *main_osc = NULL;
+	struct clk *mck0_clk = NULL;
+	struct clk *main_clk = NULL;
+	struct clk *md_slck = NULL;
+	struct clk *td_slck = NULL;
+	struct clk *parent = NULL;
+	struct clk *clk = NULL;
+	unsigned int i = 0;
+	unsigned int j = 0;
+	vaddr_t base = 0;
+	size_t size = 0;
+	int bypass = 0;
+
+	if (dt_map_dev(fdt, nodeoffset, &base, &size, DT_MAP_AUTO) < 0)
+		panic();
+
+	if (fdt_get_status(fdt, nodeoffset) == DT_STATUS_OK_SEC)
+		matrix_configure_periph_secure(ID_PMC);
+
+	res = clk_dt_get_by_name(fdt, nodeoffset, "md_slck", &md_slck);
+	if (res)
+		return res;
+
+	res = clk_dt_get_by_name(fdt, nodeoffset, "td_slck", &td_slck);
+	if (res)
+		return res;
+
+	res = clk_dt_get_by_name(fdt, nodeoffset, "main_xtal", &main_xtal_clk);
+	if (res)
+		return res;
+
+	sama7g5_pmc = pmc_data_allocate(PMC_SAMA7G5_CORE_CLK_COUNT,
+					ARRAY_SIZE(sama7g5_systemck),
+					ARRAY_SIZE(peri_clks),
+					ARRAY_SIZE(sama7g5_gcks), 8);
+	if (!sama7g5_pmc)
+		panic();
+
+	sama7g5_pmc->base = base;
+
+	main_rc_osc = pmc_register_main_rc_osc(sama7g5_pmc, "main_rc_osc",
+					       12000000);
+	if (!main_rc_osc)
+		panic();
+
+	fdt_prop = fdt_getprop(fdt, nodeoffset, "atmel,osc-bypass", NULL);
+	if (fdt_prop)
+		bypass = fdt32_to_cpu(*fdt_prop);
+
+	main_osc = pmc_register_main_osc(sama7g5_pmc, "main_osc",
+					 main_xtal_clk, bypass);
+	if (!main_osc)
+		panic();
+
+	parents[0] = main_rc_osc;
+	parents[1] = main_osc;
+	main_clk = at91_clk_register_sam9x5_main(sama7g5_pmc, "mainck",
+						 parents, 2);
+	if (!main_clk)
+		panic();
+	pmc_clk = &sama7g5_pmc->chws[PMC_MAIN];
+	pmc_clk->clk = main_clk;
+	pmc_clk->id = PMC_MAIN;
+
+	for (i = 0; i < PLL_ID_MAX; i++) {
+		struct pmc_data *pmc = sama7g5_pmc;
+		const struct sama7g5_pll *p = NULL;
+
+		for (j = 0; j < 3; j++) {
+			p = &sama7g5_plls[i][j];
+			if (!p->name)
+				continue;
+
+			switch (p->type) {
+			case PLL_TYPE_FRAC:
+				if (!strcmp(p->parent, "mainck"))
+					parent = main_clk;
+				else if (!strcmp(p->parent, "main_xtal"))
+					parent = main_xtal_clk;
+				else
+					parent = pmc_clk_get_by_name(pmc->chws,
+								     pmc->ncore,
+								     p->parent);
+				assert(parent);
+
+				clk = sam9x60_clk_register_frac_pll(sama7g5_pmc,
+								    p->name,
+								    parent, i,
+								    p->charac,
+								    p->layout,
+								    p->flags);
+				pll_frac_clk[i] = clk;
+				break;
+
+			case PLL_TYPE_DIV:
+				parent = clk;
+				clk = sam9x60_clk_register_div_pll(sama7g5_pmc,
+								   p->name,
+								   parent, i,
+								   p->charac,
+								   p->layout,
+								   p->flags,
+								   p->safe_div);
+				break;
+
+			default:
+				continue;
+			}
+			if (!clk)
+				panic();
+
+			if (p->eid) {
+				sama7g5_pmc->chws[p->eid].clk = clk;
+				sama7g5_pmc->chws[p->eid].id = p->eid;
+			}
+		}
+		p = &sama7g5_plls[i][PLL_TYPE_DIV];
+		pll_div_clk[i] = sama7g5_pmc->chws[p->eid].clk;
+	}
+
+	parents[0] = md_slck;
+	parents[1] = main_clk;
+	parents[2] = pll_div_clk[PLL_ID_CPU];
+	parents[3] = pll_div_clk[PLL_ID_SYS];
+	clk = at91_clk_register_master_pres(sama7g5_pmc, "fclk", 4,
+					    parents,
+					    &mck0_layout,
+					    &mck0_characteristics, INT_MIN);
+	if (!clk)
+		panic();
+	pmc_clk = &sama7g5_pmc->chws[PMC_MCK_PRES];
+	pmc_clk->clk = clk;
+	pmc_clk->id = PMC_MCK_PRES;
+
+	mck0_clk = at91_clk_register_master_div(sama7g5_pmc, "mck0",
+						clk,
+						&mck0_layout,
+						&mck0_characteristics);
+	if (!mck0_clk)
+		panic();
+	pmc_clk = &sama7g5_pmc->chws[PMC_MCK];
+	pmc_clk->clk = mck0_clk;
+	pmc_clk->id = PMC_MCK;
+
+	parents[0] = md_slck;
+	parents[1] = td_slck;
+	parents[2] = main_clk;
+	parents[3] = mck0_clk;
+	for (i = 0; i < ARRAY_SIZE(sama7g5_mckx); i++) {
+		const struct sama7g5_mck *mck = &sama7g5_mckx[i];
+		uint8_t num_parents = 4 + mck->eparents_count;
+		uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table));
+
+		if (!mux_table)
+			panic();
+
+		mux_table[0] = 0;
+		mux_table[1] = 1;
+		mux_table[2] = 2;
+		mux_table[3] = 3;
+		for (j = 0; j < mck->eparents_count; j++) {
+			parents[4 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws,
+							     sama7g5_pmc->ncore,
+							     mck->eparents[j]);
+			assert(parents[4 + j]);
+			mux_table[4 + j] = mck->eparents_mux_table[j];
+		}
+
+		clk = at91_clk_sama7g5_register_master(sama7g5_pmc,
+						       mck->name,
+						       num_parents, parents,
+						       mux_table,
+						       mck->id,
+						       mck->eparents_chg_id);
+		if (!clk)
+			panic();
+
+		sama7g5_pmc->chws[PMC_MCK1 + i].clk = clk;
+	}
+
+	clk = at91_clk_sama7g5_register_utmi(sama7g5_pmc, "utmick", main_clk);
+	if (!clk)
+		panic();
+	sama7g5_pmc->chws[PMC_UTMI].clk = clk;
+	sama7g5_pmc->chws[PMC_UTMI].id = PMC_UTMI;
+
+	for (i = 0; i < ARRAY_SIZE(sama7_utmick); i++) {
+		if (strcmp("utmick", sama7_utmick[i].parent) == 0)
+			parent = clk;
+		else if (strcmp("utmi1ck", sama7_utmick[i].parent) == 0)
+			parent = sama7g5_pmc->chws[PMC_UTMI1].clk;
+		else
+			panic();
+		clk = sama7_utmi_clk_register(sama7_utmick[i].name, parent,
+					      sama7_utmick[i].id);
+		if (!clk)
+			panic();
+
+		pmc_clk = &sama7g5_pmc->chws[PMC_UTMI1 + i];
+		pmc_clk->clk = clk;
+		pmc_clk->id = PMC_UTMI1 + i;
+	}
+
+	parents[0] = md_slck;
+	parents[1] = td_slck;
+	parents[2] = main_clk;
+	parents[3] = pll_div_clk[PLL_ID_SYS];
+	parents[4] = pll_div_clk[PLL_ID_DDR];
+	parents[5] = pll_div_clk[PLL_ID_IMG];
+	parents[6] = pll_div_clk[PLL_ID_BAUD];
+	parents[7] = pll_div_clk[PLL_ID_AUDIO];
+	parents[8] = pll_div_clk[PLL_ID_ETH];
+	for (i = 0; i < ARRAY_SIZE(sama7g5_progck); i++) {
+		clk = at91_clk_register_programmable(sama7g5_pmc,
+						     sama7g5_progck[i].name,
+						     parents, 9, i,
+						     &sama7g5_prog_layout);
+		if (!clk)
+			panic();
+
+		pmc_clk = &sama7g5_pmc->pchws[i];
+		pmc_clk->clk = clk;
+		pmc_clk->id = sama7g5_progck[i].id;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sama7g5_systemck); i++) {
+		clk = at91_clk_register_system(sama7g5_pmc,
+					       sama7g5_systemck[i].name,
+					       sama7g5_pmc->pchws[i].clk,
+					       sama7g5_systemck[i].id);
+		if (!clk)
+			panic();
+
+		pmc_clk = &sama7g5_pmc->shws[i];
+		pmc_clk->clk = clk;
+		pmc_clk->id = sama7g5_systemck[i].id;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(peri_clks); i++) {
+		parent = pmc_clk_get_by_name(sama7g5_pmc->chws,
+					     sama7g5_pmc->ncore,
+					     peri_clks[i].parent);
+		clk = at91_clk_register_sam9x5_periph(sama7g5_pmc,
+						      &sama7g5_pcr_layout,
+						      peri_clks[i].name,
+						      parent,
+						      peri_clks[i].id,
+						      &peri_clks[i].output);
+		if (!clk)
+			panic();
+
+		pmc_clk = &sama7g5_pmc->phws[i];
+		pmc_clk->clk = clk;
+		pmc_clk->id = peri_clks[i].id;
+	}
+
+	parents[0] = md_slck;
+	parents[1] = td_slck;
+	parents[2] = main_clk;
+	for (i = 0; i < ARRAY_SIZE(sama7g5_gcks); i++) {
+		const struct sama7g5_gck *gck = sama7g5_gcks + i;
+		uint8_t num_parents = 3 + gck->parents_count;
+		uint32_t *mux_table = calloc(num_parents, sizeof(*mux_table));
+
+		if (!mux_table)
+			panic();
+
+		mux_table[0] = 0;
+		mux_table[1] = 1;
+		mux_table[2] = 2;
+		for (j = 0; j < gck->parents_count; j++) {
+			parents[3 + j] = pmc_clk_get_by_name(sama7g5_pmc->chws,
+							     sama7g5_pmc->ncore,
+							     gck->parents[j]);
+			assert(parents[3 + j]);
+			mux_table[3 + j] = gck->parents_mux_table[j];
+		}
+
+		clk = at91_clk_register_generated(sama7g5_pmc,
+						  &sama7g5_pcr_layout,
+						  gck->name, parents,
+						  mux_table,
+						  num_parents, gck->id,
+						  &gck->output,
+						  gck->parents_chg_id);
+		if (!clk)
+			panic();
+
+		pmc_clk = &sama7g5_pmc->ghws[i];
+		pmc_clk->clk = clk;
+		pmc_clk->id = gck->id;
+	}
+
+	res = clk_set_rate(pll_frac_clk[PLL_ID_ETH], 625000000);
+	if (res)
+		panic();
+
+	res = clk_set_rate(pll_div_clk[PLL_ID_ETH], 625000000);
+	if (res)
+		panic();
+
+	res = clk_dt_register_clk_provider(fdt, nodeoffset, clk_dt_pmc_get,
+					   sama7g5_pmc);
+	if (res)
+		panic();
+
+	pmc_register_pm();
+
+	return TEE_SUCCESS;
+}
+
+CLK_DT_DECLARE(sama7g5_clk, "microchip,sama7g5-pmc", pmc_setup_sama7g5);
diff --git a/core/drivers/clk/sam/sub.mk b/core/drivers/clk/sam/sub.mk
index eca5a707d49f604c2b2f4d776c33b090cb5b9c8b..242125774f93aa8fafc96090522fb91159b17189 100644
--- a/core/drivers/clk/sam/sub.mk
+++ b/core/drivers/clk/sam/sub.mk
@@ -1,8 +1,14 @@
 global-incdirs-y += .
 
-at91-common = at91_sckc.c at91_main.c at91_pmc.c at91_pll.c at91_plldiv.c
-at91-common += at91_utmi.c at91_master.c at91_h32mx.c at91_usb.c
-at91-common += at91_programmable.c at91_system.c at91_peripheral.c
-at91-common += at91_generated.c at91_i2s_mux.c at91_audio_pll.c
+srcs-y += at91_sckc.c at91_main.c at91_pmc.c
+srcs-y += at91_utmi.c at91_master.c
+srcs-y += at91_programmable.c at91_system.c at91_peripheral.c
+srcs-y += at91_generated.c
+srcs-y += at91_cpu_opp.c
 
-srcs-$(CFG_DRIVERS_SAMA5D2_CLK) += $(at91-common) sama5d2_clk.c
+srcs-$(CFG_SAMA5D2) += at91_pll.c at91_plldiv.c
+srcs-$(CFG_SAMA5D2) += at91_h32mx.c at91_usb.c
+srcs-$(CFG_SAMA5D2) += at91_i2s_mux.c at91_audio_pll.c
+srcs-$(CFG_SAMA5D2) += sama5d2_clk.c
+
+srcs-$(CFG_SAMA7G5) += clk-sam9x60-pll.c phy-sama7-utmi-clk.c sama7g5_clk.c
diff --git a/core/drivers/clk/sub.mk b/core/drivers/clk/sub.mk
index 6233483e4e4e279132b51823afa84eaac47e5c01..8038778ef4d5067c85f0b0afee1b1890b65d1f84 100644
--- a/core/drivers/clk/sub.mk
+++ b/core/drivers/clk/sub.mk
@@ -4,5 +4,6 @@ srcs-$(CFG_DRIVERS_CLK_FIXED) += fixed_clk.c
 srcs-$(CFG_STM32MP_CLK_CORE) += clk-stm32-core.c
 srcs-$(CFG_STM32MP13_CLK) += clk-stm32mp13.c
 srcs-$(CFG_STM32MP15_CLK) += clk-stm32mp15.c
+srcs-$(CFG_STM32MP25_CLK) += clk-stm32mp25.c
 
 subdirs-$(CFG_DRIVERS_SAM_CLK) += sam
\ No newline at end of file
diff --git a/core/drivers/crypto/caam/acipher/caam_dh.c b/core/drivers/crypto/caam/acipher/caam_dh.c
index 35fc44541644af74fccfbd75b1ef7472867cd48d..c6b352dc566dad548a91405bed239017db647aad 100644
--- a/core/drivers/crypto/caam/acipher/caam_dh.c
+++ b/core/drivers/crypto/caam/acipher/caam_dh.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2023 NXP
  *
  * Implementation of DH
  */
@@ -8,6 +8,7 @@
 #include <caam_common.h>
 #include <caam_hal_ctrl.h>
 #include <caam_jr.h>
+#include <caam_key.h>
 #include <caam_utils_mem.h>
 #include <caam_utils_status.h>
 #include <drvcrypt.h>
@@ -30,7 +31,7 @@
 struct caam_dh_keypair {
 	struct caambuf g; /* Generator */
 	struct caambuf p; /* Prime Number Modulus */
-	struct caambuf x; /* Private key */
+	struct caamkey x; /* Private key */
 	struct caambuf y; /* Public key */
 };
 
@@ -43,7 +44,7 @@ static void do_keypair_free(struct caam_dh_keypair *key)
 {
 	caam_free_buf(&key->g);
 	caam_free_buf(&key->p);
-	caam_free_buf(&key->x);
+	caam_key_free(&key->x);
 	caam_free_buf(&key->y);
 }
 
@@ -114,12 +115,11 @@ static enum caam_status do_keypriv_conv(struct caam_dh_keypair *outkey,
 	cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length);
 
 	/* Private Key X */
-	retstatus = caam_calloc_buf(&outkey->x, key_size);
+	retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, 0);
 	if (retstatus != CAAM_NO_ERROR)
 		return retstatus;
 
-	crypto_bignum_bn2bin(inkey->x, outkey->x.data);
-	cache_operation(TEE_CACHECLEAN, outkey->x.data, outkey->x.length);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->x);
 
 	return CAAM_NO_ERROR;
 }
@@ -176,7 +176,7 @@ static TEE_Result do_allocate_keypair(struct dh_keypair *key, size_t size_bits)
 		goto err;
 
 	/* Allocate Private key X */
-	key->x = crypto_bignum_allocate(size_bits);
+	key->x = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->x)
 		goto err;
 
@@ -226,6 +226,7 @@ static TEE_Result do_gen_keypair(struct dh_keypair *key,
 	uint32_t *desc = NULL;
 	uint32_t desclen = 0;
 	int counter = 0;
+	enum caam_key_type key_type = caam_key_default_key_gen_type();
 
 	l_bytes = crypto_bignum_num_bytes(key->p);
 	if (!l_bytes)
@@ -256,13 +257,17 @@ static TEE_Result do_gen_keypair(struct dh_keypair *key,
 	}
 
 	/* Allocate Private Key to be generated */
-	retstatus = caam_calloc_align_buf(&caam_dh_key.x, n_bytes);
+	caam_dh_key.x.key_type = key_type;
+	caam_dh_key.x.sec_size = n_bytes;
+	caam_dh_key.x.is_blob = false;
+
+	retstatus = caam_key_alloc(&caam_dh_key.x);
 	if (retstatus != CAAM_NO_ERROR) {
 		ret = caam_status_to_tee_result(retstatus);
 		goto out;
 	}
-	cache_operation(TEE_CACHEFLUSH, caam_dh_key.x.data,
-			caam_dh_key.x.length);
+
+	caam_key_cache_op(TEE_CACHEFLUSH, &caam_dh_key.x);
 
 	/* Allocate Public Key to be generated */
 	retstatus = caam_calloc_align_buf(&caam_dh_key.y, l_bytes);
@@ -301,9 +306,23 @@ static TEE_Result do_gen_keypair(struct dh_keypair *key,
 	caam_desc_add_ptr(desc, caam_dh_key.p.paddr);
 	caam_desc_add_ptr(desc, dh_r.paddr);
 	caam_desc_add_ptr(desc, caam_dh_key.g.paddr);
-	caam_desc_add_ptr(desc, caam_dh_key.x.paddr);
+	caam_desc_add_ptr(desc, caam_dh_key.x.buf.paddr);
 	caam_desc_add_ptr(desc, caam_dh_key.y.paddr);
-	caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL));
+
+	switch (key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
@@ -321,15 +340,12 @@ static TEE_Result do_gen_keypair(struct dh_keypair *key,
 		retstatus = caam_jr_enqueue(&jobctx, NULL);
 
 		if (retstatus == CAAM_NO_ERROR) {
-			cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.x.data,
-					caam_dh_key.x.length);
+			caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dh_key.x);
 			cache_operation(TEE_CACHEINVALIDATE, caam_dh_key.y.data,
 					caam_dh_key.y.length);
 
 			/* Copy Private and Public keypair */
-			ret = crypto_bignum_bin2bn(caam_dh_key.x.data,
-						   caam_dh_key.x.length,
-						   key->x);
+			ret = caam_key_serialize_to_bn(key->x, &caam_dh_key.x);
 			if (ret != TEE_SUCCESS)
 				goto out;
 
@@ -432,7 +448,7 @@ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
 	caam_desc_add_word(desc, DESC_HEADER(0));
 	caam_desc_add_word(desc, pdb_sgt_flags |
 				 PDB_DL_KEY_L_SIZE(caam_dh_key.y.length) |
-				 PDB_DL_KEY_N_SIZE(caam_dh_key.x.length));
+				 PDB_DL_KEY_N_SIZE(caam_dh_key.x.sec_size));
 	/* Prime */
 	caam_desc_add_ptr(desc, caam_dh_key.p.paddr);
 	/* Modulus - Not used */
@@ -440,11 +456,25 @@ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
 	/* Public key */
 	caam_desc_add_ptr(desc, caam_dh_key.y.paddr);
 	/* Private key */
-	caam_desc_add_ptr(desc, caam_dh_key.x.paddr);
+	caam_desc_add_ptr(desc, caam_dh_key.x.buf.paddr);
 	/* Output secret */
 	caam_desc_add_ptr(desc, secret.sgtbuf.paddr);
 
-	caam_desc_add_word(desc, SHARED_SECRET(DL));
+	switch (caam_dh_key.x.key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, SHARED_SECRET(DL, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, SHARED_SECRET(DL, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, SHARED_SECRET(DL, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
+
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
 
diff --git a/core/drivers/crypto/caam/acipher/caam_dsa.c b/core/drivers/crypto/caam/acipher/caam_dsa.c
index 8c0dbf055e213ac7da0c410b177c67db1533d069..d7264c5c4c4dc414196e623a46bd02cb742f878b 100644
--- a/core/drivers/crypto/caam/acipher/caam_dsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_dsa.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2019-2021 NXP
+ * Copyright 2019-2021, 2023 NXP
  *
  * Implementation of DSA functions
  */
@@ -8,6 +8,7 @@
 #include <caam_common.h>
 #include <caam_hal_ctrl.h>
 #include <caam_jr.h>
+#include <caam_key.h>
 #include <caam_utils_mem.h>
 #include <caam_utils_status.h>
 #include <drvcrypt.h>
@@ -17,6 +18,7 @@
 #include <string.h>
 
 #include "local.h"
+#include "utee_types.h"
 
 #ifdef CFG_CAAM_64BIT
 #define MAX_DESC_KEY_GEN 14
@@ -38,7 +40,7 @@ struct caam_dsa_keypair {
 	struct caambuf g; /* Generator */
 	struct caambuf p; /* Prime Number (L bits) */
 	struct caambuf q; /* Subprime Number (N bits) */
-	struct caambuf x; /* Private key */
+	struct caamkey x; /* Private key */
 	struct caambuf y; /* Public key */
 };
 
@@ -52,7 +54,7 @@ static void do_keypair_free(struct caam_dsa_keypair *key)
 	caam_free_buf(&key->g);
 	caam_free_buf(&key->p);
 	caam_free_buf(&key->q);
-	caam_free_buf(&key->x);
+	caam_key_free(&key->x);
 	caam_free_buf(&key->y);
 }
 
@@ -184,19 +186,14 @@ static enum caam_status do_keypriv_conv(struct caam_dsa_keypair *outkey,
 	field_size = crypto_bignum_num_bytes(inkey->q);
 	crypto_bignum_bn2bin(inkey->q, outkey->q.data + n_bytes - field_size);
 
-	/* Private key is only scalar x of n bytes */
-	retstatus = caam_calloc_buf(&outkey->x, n_bytes);
+	retstatus = caam_key_deserialize_from_bn(inkey->x, &outkey->x, n_bytes);
 	if (retstatus != CAAM_NO_ERROR)
 		return retstatus;
 
-	/* Get the number of bytes of x to pad with 0's */
-	field_size = crypto_bignum_num_bytes(inkey->x);
-	crypto_bignum_bn2bin(inkey->x, outkey->x.data + n_bytes - field_size);
-
 	cache_operation(TEE_CACHECLEAN, outkey->g.data, outkey->g.length);
 	cache_operation(TEE_CACHECLEAN, outkey->p.data, outkey->p.length);
 	cache_operation(TEE_CACHECLEAN, outkey->q.data, outkey->q.length);
-	cache_operation(TEE_CACHECLEAN, outkey->x.data, outkey->x.length);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->x);
 
 	return CAAM_NO_ERROR;
 }
@@ -295,7 +292,7 @@ static TEE_Result do_allocate_keypair(struct dsa_keypair *key, size_t l_bits,
 		goto err;
 
 	/* Allocate Private key X */
-	key->x = crypto_bignum_allocate(n_bits);
+	key->x = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->x)
 		goto err;
 
@@ -385,6 +382,7 @@ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
 	uint32_t desclen = 0;
 	size_t l_bytes = l_bits / 8;
 	size_t n_bytes = n_bits / 8;
+	enum caam_key_type key_type = caam_key_default_key_gen_type();
 
 	DSA_TRACE("Generate Key - Private (%zu bits) and Public (%zu bits)",
 		  n_bits, l_bits);
@@ -397,13 +395,17 @@ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
 	}
 
 	/* Allocate Private Key to be generated */
-	retstatus = caam_calloc_align_buf(&caam_dsa_key.x, n_bytes);
+	caam_dsa_key.x.key_type = caam_key_default_key_gen_type();
+	caam_dsa_key.x.sec_size = n_bytes;
+	caam_dsa_key.x.is_blob = false;
+
+	retstatus = caam_key_alloc(&caam_dsa_key.x);
 	if (retstatus != CAAM_NO_ERROR) {
 		ret = caam_status_to_tee_result(retstatus);
 		goto out;
 	}
-	cache_operation(TEE_CACHEFLUSH, caam_dsa_key.x.data,
-			caam_dsa_key.x.length);
+
+	caam_key_cache_op(TEE_CACHEFLUSH, &caam_dsa_key.x);
 
 	/* Allocate Public Key to be generated */
 	retstatus = caam_calloc_align_buf(&caam_dsa_key.y, l_bytes);
@@ -430,9 +432,23 @@ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
 	caam_desc_add_ptr(desc, caam_dsa_key.p.paddr);
 	caam_desc_add_ptr(desc, caam_dsa_key.q.paddr);
 	caam_desc_add_ptr(desc, caam_dsa_key.g.paddr);
-	caam_desc_add_ptr(desc, caam_dsa_key.x.paddr);
+	caam_desc_add_ptr(desc, caam_dsa_key.x.buf.paddr);
 	caam_desc_add_ptr(desc, caam_dsa_key.y.paddr);
-	caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL));
+
+	switch (key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(DL, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
@@ -443,14 +459,13 @@ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
 	retstatus = caam_jr_enqueue(&jobctx, NULL);
 
 	if (retstatus == CAAM_NO_ERROR) {
-		cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.x.data,
-				caam_dsa_key.x.length);
+		caam_key_cache_op(TEE_CACHEINVALIDATE, &caam_dsa_key.x);
+
 		cache_operation(TEE_CACHEINVALIDATE, caam_dsa_key.y.data,
 				caam_dsa_key.y.length);
 
 		/* Copy Private and Public keypair */
-		ret = crypto_bignum_bin2bn(caam_dsa_key.x.data,
-					   caam_dsa_key.x.length, key->x);
+		ret = caam_key_serialize_to_bn(key->x, &caam_dsa_key.x);
 		if (ret != TEE_SUCCESS)
 			goto out;
 
@@ -459,7 +474,8 @@ static TEE_Result do_gen_keypair(struct dsa_keypair *key, size_t l_bits,
 		if (ret != TEE_SUCCESS)
 			goto out;
 
-		DSA_DUMPBUF("X", caam_dsa_key.x.data, caam_dsa_key.x.length);
+		DSA_DUMPBUF("X", caam_dsa_key.x.buf.data,
+			    caam_dsa_key.x.buf.length);
 		DSA_DUMPBUF("Y", caam_dsa_key.y.data, caam_dsa_key.y.length);
 	} else {
 		DSA_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
@@ -569,7 +585,7 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes,
 	/* Generator */
 	caam_desc_add_ptr(desc, dsakey.g.paddr);
 	/* Secret key */
-	caam_desc_add_ptr(desc, dsakey.x.paddr);
+	caam_desc_add_ptr(desc, dsakey.x.buf.paddr);
 	/* Input message */
 	caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
 	/* Signature 1st part */
@@ -579,7 +595,20 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata, size_t l_bytes,
 	/* Message length */
 	caam_desc_add_word(desc, sdata->message.length);
 
-	caam_desc_add_word(desc, DSA_SIGN(DL, HASHED));
+	switch (dsakey.x.key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, DSA_SIGN(DL, HASHED, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
diff --git a/core/drivers/crypto/caam/acipher/caam_ecc.c b/core/drivers/crypto/caam/acipher/caam_ecc.c
index b9c2cde8817dc64f9ce667718c8dc7b32cf957f4..f609fee4c06babb92a2038202478fd76a9bf240d 100644
--- a/core/drivers/crypto/caam/acipher/caam_ecc.c
+++ b/core/drivers/crypto/caam/acipher/caam_ecc.c
@@ -8,13 +8,17 @@
 #include <caam_common.h>
 #include <caam_hal_ctrl.h>
 #include <caam_jr.h>
+#include <caam_key.h>
+#include <caam_trace.h>
 #include <caam_utils_mem.h>
 #include <caam_utils_status.h>
 #include <drvcrypt.h>
 #include <drvcrypt_acipher.h>
 #include <mm/core_memprot.h>
+#include <stdint.h>
 #include <string.h>
 #include <tee/cache.h>
+#include <utee_types.h>
 
 #ifdef CFG_CAAM_64BIT
 #define MAX_DESC_KEY_GEN 8
@@ -35,7 +39,7 @@
  */
 struct caam_ecc_keypair {
 	struct caambuf xy;
-	struct caambuf d;
+	struct caamkey d;
 };
 
 /*
@@ -46,7 +50,7 @@ struct caam_ecc_keypair {
 static void do_keypair_free(struct caam_ecc_keypair *key)
 {
 	caam_free_buf(&key->xy);
-	caam_free_buf(&key->d);
+	caam_key_free(&key->d);
 }
 
 /*
@@ -85,7 +89,7 @@ static enum caam_status do_keypub_conv(struct caam_ecc_keypair *outkey,
 
 /*
  * Convert Crypto ECC Key to local ECC Keypair Key
- * Don't convert the exponent e not used in decrytion
+ * Don't convert the exponent e not used in decryption
  *
  * @outkey    [out] Output keypair in local format
  * @inkey     Input key in TEE Crypto format
@@ -96,20 +100,18 @@ static enum caam_status do_keypair_conv(struct caam_ecc_keypair *outkey,
 					size_t size_sec)
 {
 	enum caam_status retstatus = CAAM_OUT_MEMORY;
-	size_t d_size = 0;
 
 	ECC_TRACE("ECC Convert Keypair size %zu bytes", size_sec);
 
 	/* Private key is only scalar d of sec_size bytes */
-	retstatus = caam_calloc_buf(&outkey->d, size_sec);
-	if (retstatus != CAAM_NO_ERROR)
+	retstatus = caam_key_deserialize_from_bn(inkey->d, &outkey->d,
+						 size_sec);
+	if (retstatus)
 		return retstatus;
 
-	/* Get the number of bytes of d to pad with 0's */
-	d_size = crypto_bignum_num_bytes(inkey->d);
-	crypto_bignum_bn2bin(inkey->d, outkey->d.data + size_sec - d_size);
+	caam_key_cache_op(TEE_CACHEFLUSH, &outkey->d);
 
-	cache_operation(TEE_CACHECLEAN, outkey->d.data, outkey->d.length);
+	ECC_DUMPBUF("Outkey", outkey->d.buf.data, outkey->d.buf.length);
 
 	return CAAM_NO_ERROR;
 }
@@ -140,19 +142,29 @@ static enum caam_ecc_curve get_caam_curve(uint32_t tee_curve)
  * Allocate a ECC keypair
  *
  * @key        Keypair
+ * @type       Type of ECC key
  * @size_bits  Key size in bits
  */
 static TEE_Result do_allocate_keypair(struct ecc_keypair *key,
-				      uint32_t type __unused,
+				      uint32_t type,
 				      size_t size_bits)
 {
 	ECC_TRACE("Allocate Keypair of %zu bits", size_bits);
 
+	switch (type) {
+	case TEE_TYPE_SM2_PKE_KEYPAIR:
+	case TEE_TYPE_SM2_DSA_KEYPAIR:
+		/* Software fallback */
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	default:
+		break;
+	}
+
 	/* Initialize the key fields to NULL */
 	memset(key, 0, sizeof(*key));
 
 	/* Allocate Secure Scalar */
-	key->d = crypto_bignum_allocate(size_bits);
+	key->d = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->d)
 		goto err;
 
@@ -181,14 +193,24 @@ err:
  * Allocate an ECC Public Key
  *
  * @key        Public Key
+ * @type       Type of ECC key
  * @size_bits  Key size in bits
  */
 static TEE_Result do_allocate_publickey(struct ecc_public_key *key,
-					uint32_t type __unused,
+					uint32_t type,
 					size_t size_bits)
 {
 	ECC_TRACE("Allocate Public Key of %zu bits", size_bits);
 
+	switch (type) {
+	case TEE_TYPE_SM2_PKE_PUBLIC_KEY:
+	case TEE_TYPE_SM2_DSA_PUBLIC_KEY:
+		/* Software fallback */
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	default:
+		break;
+	}
+
 	/* Initialize the key fields to NULL */
 	memset(key, 0, sizeof(*key));
 
@@ -234,11 +256,12 @@ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
 	TEE_Result ret = TEE_ERROR_GENERIC;
 	enum caam_status retstatus = CAAM_FAILURE;
 	enum caam_ecc_curve curve = CAAM_ECC_UNKNOWN;
-	struct caambuf d = { };
+	struct caamkey d = { };
 	struct caambuf xy = { };
 	struct caam_jobctx jobctx = { };
 	uint32_t *desc = NULL;
 	uint32_t desclen = 0;
+	enum caam_key_type key_type = caam_key_default_key_gen_type();
 
 	ECC_TRACE("Generate Keypair of %zu bits", key_size);
 
@@ -258,28 +281,47 @@ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
 	}
 
 	/*
-	 * Allocate secure and public keys in one buffer
+	 * Allocate secure and public keys in two buffers
 	 * Secure key size = key_size align in bytes
 	 * Public key size = (key_size * 2) align in bytes
 	 */
-	retstatus = caam_alloc_align_buf(&d, (key_size / 8) * 3);
+	d.key_type = key_type;
+	d.sec_size = ROUNDUP_DIV(key_size, 8);
+	d.is_blob = false;
+
+	retstatus = caam_key_alloc(&d);
 	if (retstatus != CAAM_NO_ERROR) {
 		ret = caam_status_to_tee_result(retstatus);
 		goto out;
 	}
 
-	/* Build the xy buffer to simplify the code */
-	xy.data = d.data + key_size / 8;
-	xy.length = 2 * (key_size / 8);
-	xy.paddr = d.paddr + key_size / 8;
+	retstatus = caam_alloc_align_buf(&xy, (key_size / 8) * 2);
+	if (retstatus != CAAM_NO_ERROR) {
+		ret = caam_status_to_tee_result(retstatus);
+		goto out;
+	}
 
-	/* Build the descriptor using Predifined ECC curve */
+	/* Build the descriptor using Predefined ECC curve */
 	caam_desc_init(desc);
 	caam_desc_add_word(desc, DESC_HEADER(0));
 	caam_desc_add_word(desc, PDB_PKGEN_PD1 | PDB_ECC_ECDSEL(curve));
-	caam_desc_add_ptr(desc, d.paddr);
+	caam_desc_add_ptr(desc, d.buf.paddr);
 	caam_desc_add_ptr(desc, xy.paddr);
-	caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC));
+
+	switch (key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, PK_KEYPAIR_GEN(ECC, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
 
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
@@ -287,16 +329,21 @@ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
 	ECC_DUMPDESC(desc);
 
 	jobctx.desc = desc;
-	cache_operation(TEE_CACHEFLUSH, d.data, d.length);
+	caam_key_cache_op(TEE_CACHEFLUSH, &d);
+	cache_operation(TEE_CACHEFLUSH, xy.data, xy.length);
+
 	retstatus = caam_jr_enqueue(&jobctx, NULL);
 
 	if (retstatus == CAAM_NO_ERROR) {
-		cache_operation(TEE_CACHEINVALIDATE, d.data, d.length);
+		caam_key_cache_op(TEE_CACHEINVALIDATE, &d);
+		cache_operation(TEE_CACHEINVALIDATE, xy.data, xy.length);
 
 		/* Copy all keypair parameters */
-		ret = crypto_bignum_bin2bn(d.data, key_size / 8, key->d);
-		if (ret != TEE_SUCCESS)
+		retstatus = caam_key_serialize_to_bn(key->d, &d);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
 			goto out;
+		}
 
 		ret = crypto_bignum_bin2bn(xy.data, xy.length / 2, key->x);
 		if (ret != TEE_SUCCESS)
@@ -307,7 +354,7 @@ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
 		if (ret != TEE_SUCCESS)
 			goto out;
 
-		ECC_DUMPBUF("D", d.data, key_size / 8);
+		ECC_DUMPBUF("D", d.buf.data, key_size / 8);
 		ECC_DUMPBUF("X", xy.data, xy.length / 2);
 		ECC_DUMPBUF("Y", xy.data + xy.length / 2, xy.length / 2);
 	} else {
@@ -317,7 +364,8 @@ static TEE_Result do_gen_keypair(struct ecc_keypair *key, size_t key_size)
 
 out:
 	caam_free_desc(&desc);
-	caam_free_buf(&d);
+	caam_key_free(&d);
+	caam_free_buf(&xy);
 
 	return ret;
 }
@@ -481,13 +529,13 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
 
 	caam_dmaobj_cache_push(&sign_c);
 
-	/* Build the descriptor using Predifined ECC curve */
+	/* Build the descriptor using Predefined ECC curve */
 	caam_desc_init(desc);
 	caam_desc_add_word(desc, DESC_HEADER(0));
 	caam_desc_add_word(desc, PDB_PKSIGN_PD1 | PDB_ECC_ECDSEL(curve) |
 				 pdb_sgt_flags);
 	/* Secret key */
-	caam_desc_add_ptr(desc, ecckey.d.paddr);
+	caam_desc_add_ptr(desc, ecckey.d.buf.paddr);
 	/* Input message */
 	caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
 	/* Signature 1st part */
@@ -496,12 +544,38 @@ static TEE_Result do_sign(struct drvcrypt_sign_data *sdata)
 	caam_desc_add_ptr(desc, sign_d.sgtbuf.paddr);
 
 	if (msg_mes_rep(sdata->message.length, sdata->size_sec)) {
-		caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP));
+		switch (ecckey.d.key_type) {
+		case CAAM_KEY_PLAIN_TEXT:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, NONE));
+			break;
+		case CAAM_KEY_BLACK_ECB:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, ECB));
+			break;
+		case CAAM_KEY_BLACK_CCM:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, MES_REP, CCM));
+			break;
+		default:
+			ret = TEE_ERROR_GENERIC;
+			goto out;
+		}
 	} else {
 		/* Message length */
 		caam_desc_add_word(desc, sdata->message.length);
 
-		caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED));
+		switch (ecckey.d.key_type) {
+		case CAAM_KEY_PLAIN_TEXT:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, NONE));
+			break;
+		case CAAM_KEY_BLACK_ECB:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, ECB));
+			break;
+		case CAAM_KEY_BLACK_CCM:
+			caam_desc_add_word(desc, DSA_SIGN(ECC, HASHED, CCM));
+			break;
+		default:
+			ret = TEE_ERROR_GENERIC;
+			goto out;
+		}
 	}
 
 	desclen = caam_desc_get_len(desc);
@@ -560,6 +634,9 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 	struct caambuf caambuf_msg = { };
 
 	ECC_TRACE("ECC Verify");
+	ECC_DUMPBUF("Message", sdata->message.data, sdata->message.length);
+	ECC_DUMPBUF("Signature", sdata->signature.data,
+		    sdata->signature.length);
 
 	/* Verify first if the curve is supported */
 	curve = get_caam_curve(inkey->curve);
@@ -635,7 +712,7 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 		goto out;
 	}
 
-	/* Build the descriptor using Predifined ECC curve */
+	/* Build the descriptor using Predefined ECC curve */
 	caam_desc_init(desc);
 	caam_desc_add_word(desc, DESC_HEADER(0));
 	caam_desc_add_word(desc, PDB_PKVERIFY_PD1 | PDB_ECC_ECDSEL(curve) |
@@ -668,6 +745,8 @@ static TEE_Result do_verify(struct drvcrypt_sign_data *sdata)
 	jobctx.desc = desc;
 
 	cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length);
+	cache_operation(TEE_CACHEFLUSH, ecckey.xy.data, ecckey.xy.length);
+
 	retstatus = caam_jr_enqueue(&jobctx, NULL);
 
 	if (retstatus == CAAM_JOB_STATUS && !jobctx.status) {
@@ -753,7 +832,7 @@ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
 
 	caam_dmaobj_cache_push(&secret);
 
-	/* Build the descriptor using Predifined ECC curve */
+	/* Build the descriptor using Predefined ECC curve */
 	caam_desc_init(desc);
 	caam_desc_add_word(desc, DESC_HEADER(0));
 	caam_desc_add_word(desc, PDB_SHARED_SECRET_PD1 | PDB_ECC_ECDSEL(curve) |
@@ -761,11 +840,25 @@ static TEE_Result do_shared_secret(struct drvcrypt_secret_data *sdata)
 	/* Public key */
 	caam_desc_add_ptr(desc, ecckey.xy.paddr);
 	/* Private key */
-	caam_desc_add_ptr(desc, ecckey.d.paddr);
+	caam_desc_add_ptr(desc, ecckey.d.buf.paddr);
 	/* Output secret */
 	caam_desc_add_ptr(desc, secret.sgtbuf.paddr);
 
-	caam_desc_add_word(desc, SHARED_SECRET(ECC));
+	switch (ecckey.d.key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		caam_desc_add_word(desc, SHARED_SECRET(ECC, NONE));
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, SHARED_SECRET(ECC, ECB));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, SHARED_SECRET(ECC, CCM));
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto out;
+	}
+
 	desclen = caam_desc_get_len(desc);
 	caam_desc_update_hdr(desc, DESC_HEADER_IDX(desclen, desclen - 1));
 
diff --git a/core/drivers/crypto/caam/acipher/caam_prime_dsa.c b/core/drivers/crypto/caam/acipher/caam_prime_dsa.c
index c02c1329cad03f8986cecbc0afeab76f15dd0877..3f02d618fb937a1bae34a264f9fbbbfe444b28ae 100644
--- a/core/drivers/crypto/caam/acipher/caam_prime_dsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_prime_dsa.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2020-2021 NXP
+ * Copyright 2020-2021, 2023 NXP
  *
  * CAAM DSA Prime Numbering.
  * Implementation of Prime Number functions
@@ -98,7 +98,7 @@ static void do_desc_prime_q(uint32_t *desc, struct caambuf *seed,
 	}
 
 	caam_desc_add_word(desc, MOVE(C1_ALIGN, OFIFO, 0, seed->length));
-	caam_desc_add_word(desc, FIFO_ST(MSG_DATA, seed->length));
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, MSG_DATA, seed->length));
 	caam_desc_add_ptr(desc, seed->paddr);
 
 	/*
@@ -143,7 +143,7 @@ static void do_desc_prime_q(uint32_t *desc, struct caambuf *seed,
 	caam_desc_add_word(desc, prime->q->length);
 
 	/* Store the Prime q here because Miller-Rabin test affect PKHA N */
-	caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->q->length));
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_N, prime->q->length));
 	caam_desc_add_ptr(desc, prime->q->paddr);
 
 	/*
@@ -265,7 +265,7 @@ static void do_desc_gen_x(uint32_t *desc, struct caambuf *x,
 			   FIFO_LD(CLASS_1, PKHA_A, NOACTION, seed->length));
 	caam_desc_add_ptr(desc, seed->paddr);
 	caam_desc_add_word(desc, PKHA_OP(MOD_ADD_A_B, A));
-	caam_desc_add_word(desc, FIFO_ST(PKHA_A, seed->length));
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_A, seed->length));
 	caam_desc_add_ptr(desc, seed->paddr);
 
 	caam_desc_add_word(desc, PKHA_CPY_NSIZE(A0, B1));
@@ -419,7 +419,7 @@ static void do_desc_prime_p(uint32_t *desc, struct prime_data_dsa *prime,
 	 * affected by the Miller-Rabin test
 	 */
 	caam_desc_add_word(desc, PKHA_CPY_SSIZE(A0, N0));
-	caam_desc_add_word(desc, FIFO_ST(PKHA_N, prime->p->length));
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_N, prime->p->length));
 	caam_desc_add_ptr(desc, prime->p->paddr);
 	caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0));
 
@@ -648,7 +648,7 @@ static enum caam_status do_generator(uint32_t *desc,
 					  retry_new_h - desclen));
 
 	/* g is good save it */
-	caam_desc_add_word(desc, FIFO_ST(PKHA_A, prime->g->length));
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_A, prime->g->length));
 	caam_desc_add_ptr(desc, prime->g->paddr);
 
 	DSA_DUMPDESC(desc);
diff --git a/core/drivers/crypto/caam/acipher/caam_prime_rsa.c b/core/drivers/crypto/caam/acipher/caam_prime_rsa.c
index d3b16ed08600b2e06c2f943778447fbd99a04636..53037a5adbd19cd700d9f5997c739c9221075234 100644
--- a/core/drivers/crypto/caam/acipher/caam_prime_rsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_prime_rsa.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2023 NXP
  *
  * CAAM Prime Numbering.
  * Implementation of Prime Number functions
@@ -373,6 +373,8 @@ static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data,
 			  const struct caambuf *small_prime,
 			  const paddr_t desc_prime)
 {
+	size_t key_size = data->key_size / 8;
+
 	/*
 	 * Referring to FIPS.186-4, B.3.3 (step 4.7)
 	 * Maximum tries = 5 * (nlen / 2)
@@ -390,7 +392,7 @@ static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data,
 	 * of the prime number size
 	 */
 	caam_desc_add_word(desc, MATH(ADD, IMM_DATA, ZERO, SIL, 4));
-	if (data->p->length > (MR_PRIME_SIZE / 8))
+	if ((key_size / 2) > (MR_PRIME_SIZE / 8))
 		caam_desc_add_word(desc, 0x4);
 	else
 		caam_desc_add_word(desc, 0x5);
@@ -400,7 +402,7 @@ static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data,
 	 * Do it once, not at each loop
 	 */
 	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_A2, NOACTION,
-					 data->p->length));
+					 key_size / 2));
 	caam_desc_add_ptr(desc, virt_to_phys((void *)sqrt_value));
 
 	if (data->era >= 8 && small_prime->paddr) {
@@ -422,7 +424,7 @@ static void do_desc_setup(uint32_t *desc, struct prime_data_rsa *data,
 
 	/* Load PKHA N Size with the prime size */
 	caam_desc_add_word(desc, LD_IMM(CLASS_1, REG_PKHA_N_SIZE, 4));
-	caam_desc_add_word(desc, data->p->length);
+	caam_desc_add_word(desc, key_size / 2);
 
 	/*
 	 * Set the number of maximum tries because of generated value
@@ -514,7 +516,7 @@ static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data,
 	 */
 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
 	caam_desc_add_word(desc, NFIFO_PAD(C1, 0, PKHA_N, RND, 0));
-	caam_desc_add_word(desc, data->p->length - 16);
+	caam_desc_add_word(desc, (data->key_size / 8 / 2) - 16);
 
 	/* And send the 8 LSB into PKHA N */
 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 4));
@@ -580,7 +582,7 @@ static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data,
 	retry_mr_test = caam_desc_get_len(desc);
 	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO, 8));
 	caam_desc_add_word(desc, NFIFO_PAD(C1, NFIFO_FC1, PKHA_A, RND, 0));
-	caam_desc_add_word(desc, data->p->length);
+	caam_desc_add_word(desc, (data->key_size / 8 / 2));
 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, PKHA_B, NOACTION, 1));
 	caam_desc_add_word(desc, 0x01);
 	caam_desc_add_word(desc, PKHA_OP(MR_PRIMER_TEST, B));
@@ -598,7 +600,8 @@ static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data,
 					  retry_mr_test - desclen));
 
 	/* Save prime generated */
-	caam_desc_add_word(desc, FIFO_ST(PKHA_N, data->p->length));
+	caam_desc_add_word(desc,
+			   FIFO_ST(CLASS_NO, PKHA_N, (data->key_size / 8 / 2)));
 
 	if (do_prime_q)
 		caam_desc_add_ptr(desc, data->q->paddr);
@@ -627,7 +630,8 @@ static void do_desc_prime(uint32_t *desc, struct prime_data_rsa *data,
  */
 static void do_checks_primes(uint32_t *desc, const struct caambuf *p,
 			     const struct caambuf *max_n,
-			     const paddr_t desc_new_q)
+			     const paddr_t desc_new_q,
+			     size_t key_size)
 {
 	const uint8_t check_len = 16; /* Check 128 bits */
 
@@ -635,7 +639,7 @@ static void do_checks_primes(uint32_t *desc, const struct caambuf *p,
 	caam_desc_add_word(desc, DESC_HEADER(0));
 
 	/* Load prime p */
-	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B, NOACTION, p->length));
+	caam_desc_add_word(desc, FIFO_LD(CLASS_1, PKHA_B, NOACTION, key_size));
 	caam_desc_add_ptr(desc, p->paddr);
 
 	/* Retrieve Q from PKHA N, previously computed */
@@ -661,13 +665,13 @@ static void do_checks_primes(uint32_t *desc, const struct caambuf *p,
 	 * We started with 128, 192, or 256 bytes in the OFIFO before we moved
 	 * check_len bytes into MATH registers.
 	 */
-	if (p->length > 128 + (size_t)check_len) {
+	if (key_size > 128 + (size_t)check_len) {
 		caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0, check_len));
 		caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0,
-					      (p->length - 128 - check_len)));
-	} else if (p->length > check_len) {
+					      (key_size - 128 - check_len)));
+	} else if (key_size > check_len) {
 		caam_desc_add_word(desc, MOVE(OFIFO, C1_CTX_REG, 0,
-					      (p->length - check_len)));
+					      (key_size - check_len)));
 	}
 
 	/*
@@ -779,6 +783,7 @@ enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data)
 	paddr_t paddr_desc_check_p_q = 0;
 	size_t size_all_descs = 0;
 	size_t nb_tries = RSA_MAX_TRIES_PRIMES;
+	size_t key_size = data->key_size / 8 / 2;
 
 	/* Allocate the job used to prepare the operation */
 	if (data->q) {
@@ -786,7 +791,7 @@ enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data)
 				 GEN_RSA_DESC_ENTRIES * 2 +
 				 CHECK_P_Q_DESC_ENTRIES;
 
-		retstatus = caam_calloc_buf(&max_n, data->p->length + 1);
+		retstatus = caam_calloc_buf(&max_n, key_size + 1);
 		if (retstatus != CAAM_NO_ERROR)
 			goto end_gen_prime;
 
@@ -816,11 +821,11 @@ enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data)
 	 * small prime is not found in the list, continue anyway
 	 * but prime will be probably not so strong
 	 */
-	search_smallprime(data->p->length, &small_prime);
+	search_smallprime(key_size, &small_prime);
 
 	RSA_TRACE("Do prime of %zu bytes (security len %zu bits) (ERA=%" PRId8
 		  ")",
-		  data->p->length, data->key_size, data->era);
+		  key_size, data->key_size, data->era);
 
 	do_desc_setup(all_descs, data, &small_prime, paddr_desc_p);
 
@@ -841,7 +846,8 @@ enum caam_status caam_prime_rsa_gen(struct prime_data_rsa *data)
 		do_desc_prime(desc_q, data, &small_prime, true,
 			      paddr_desc_check_p_q);
 
-		do_checks_primes(desc_check_p_q, data->p, &max_n, paddr_desc_q);
+		do_checks_primes(desc_check_p_q, data->p, &max_n, paddr_desc_q,
+				 key_size);
 	} else {
 		do_desc_prime(desc_p, data, &small_prime, false, 0);
 	}
diff --git a/core/drivers/crypto/caam/acipher/caam_rsa.c b/core/drivers/crypto/caam/acipher/caam_rsa.c
index 580048b8ea0200c004309a7e42a3974f4ce948f2..a776431bbc40bae7ea34bc337ceb9bc9f983303c 100644
--- a/core/drivers/crypto/caam/acipher/caam_rsa.c
+++ b/core/drivers/crypto/caam/acipher/caam_rsa.c
@@ -1,24 +1,31 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2023 NXP
  *
  * CAAM RSA manager.
  * Implementation of RSA functions
  */
 #include <caam_acipher.h>
 #include <caam_common.h>
+#include <caam_desc_helper.h>
 #include <caam_hal_ctrl.h>
 #include <caam_io.h>
 #include <caam_jr.h>
+#include <caam_key.h>
+#include <caam_status.h>
 #include <caam_utils_mem.h>
 #include <caam_utils_status.h>
 #include <drvcrypt.h>
 #include <drvcrypt_acipher.h>
 #include <drvcrypt_math.h>
 #include <mm/core_memprot.h>
+#include <stdint.h>
 #include <string.h>
 #include <tee/cache.h>
 #include <tee/tee_cryp_utl.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <utee_types.h>
 
 #include "local.h"
 
@@ -61,15 +68,15 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
  *   Private Key Format #3: (p, q, dp, dq, qp)
  */
 struct caam_rsa_keypair {
-	uint8_t format;	   /* Define the Private Key Format (1, 2 or 3) */
-	struct caambuf n;  /* Modulus [n = p * q] */
-	struct caambuf e;  /* Public Exponent 65537 <= e < 2^256 */
-	struct caambuf d;  /* Private Exponent [d = 1/e mod LCM(p-1, q-1)] */
-	struct caambuf p;  /* Private Prime p */
-	struct caambuf q;  /* Private Prime q */
-	struct caambuf dp; /* Private [dp = d mod (p-1)] */
-	struct caambuf dq; /* Private [dq = d mod (q-1)] */
-	struct caambuf qp; /* Private [qp = 1/q mod p] */
+	uint8_t format;	    /* Define the Private Key Format (1, 2 or 3) */
+	struct caambuf n;   /* Modulus [n = p * q] */
+	struct caambuf e;   /* Public Exponent 65537 <= e < 2^256 */
+	struct caamkey d;   /* Private Exponent [d = 1/e mod LCM(p-1, q-1)] */
+	struct caamkey p;   /* Private Prime p */
+	struct caamkey q;   /* Private Prime q */
+	struct caamkey dp;  /* Private [dp = d mod (p-1)] */
+	struct caamkey dq;  /* Private [dq = d mod (q-1)] */
+	struct caamkey qp;  /* Private [qp = 1/q mod p] */
 };
 
 #define RSA_PRIVATE_KEY_FORMAT_1 1
@@ -105,17 +112,13 @@ static void do_keypair_free(struct caam_rsa_keypair *key)
 {
 	caam_free_buf(&key->e);
 	caam_free_buf(&key->n);
-	caam_free_buf(&key->d);
 
-	if (key->format > RSA_PRIVATE_KEY_FORMAT_1 && key->p.data) {
-		key->p.length += key->q.length;
-		caam_free_buf(&key->p);
-	}
-
-	if (key->format > RSA_PRIVATE_KEY_FORMAT_2 && key->dp.data) {
-		key->dp.length += key->dq.length + key->qp.length;
-		caam_free_buf(&key->dp);
-	}
+	caam_key_free(&key->d);
+	caam_key_free(&key->p);
+	caam_key_free(&key->q);
+	caam_key_free(&key->dp);
+	caam_key_free(&key->dq);
+	caam_key_free(&key->qp);
 }
 
 /*
@@ -174,16 +177,12 @@ static enum caam_status do_keypair_conv_f3(struct caam_rsa_keypair *outkey,
 	size_t size_dq = 0;
 	size_t size_qp = 0;
 
-	size_p = outkey->p.length;
-	size_q = outkey->q.length;
+	size_p = outkey->p.sec_size;
+	size_q = outkey->q.sec_size;
 	size_dp = crypto_bignum_num_bytes(inkey->dp);
 	size_dq = crypto_bignum_num_bytes(inkey->dq);
 	size_qp = crypto_bignum_num_bytes(inkey->qp);
 
-	/* Check that dp, dq and qp size not exceed p and q size */
-	if (size_dp > size_p || size_dq > size_q || size_qp > size_p)
-		return CAAM_FAILURE;
-
 	/*
 	 * If one of the parameters dp, dq or qp are not filled,
 	 * returns immediately. This is not an error.
@@ -200,47 +199,27 @@ static enum caam_status do_keypair_conv_f3(struct caam_rsa_keypair *outkey,
 	 * than above assumption, force the dp, dq and qp
 	 * buffer size.
 	 */
-	/* Allocate one buffer for the 3 fields */
-	retstatus =
-		caam_calloc_align_buf(&outkey->dp, size_p + size_q + size_p);
-	if (retstatus != CAAM_NO_ERROR)
-		return CAAM_OUT_MEMORY;
-
-	/* Field dp */
-	outkey->dp.length = size_p;
-
-	/*
-	 * Ensure buffer is copied starting with 0's
-	 * if size_dp != size_p
-	 */
-	crypto_bignum_bn2bin(inkey->dp, outkey->dp.data + size_p - size_dp);
+	retstatus = caam_key_deserialize_from_bn(inkey->dp,
+						 &outkey->dp, size_p);
+	if (retstatus)
+		return retstatus;
 
 	/* Field dq */
-	outkey->dq.data = outkey->dp.data + size_p;
-	outkey->dq.length = size_q;
-	outkey->dq.paddr = outkey->dp.paddr + size_p;
-
-	/*
-	 * Ensure buffer is copied starting with 0's
-	 * if size_dq != size_q
-	 */
-	crypto_bignum_bn2bin(inkey->dq, outkey->dq.data + size_q - size_dq);
+	retstatus = caam_key_deserialize_from_bn(inkey->dq,
+						 &outkey->dq, size_p);
+	if (retstatus)
+		return retstatus;
 
 	/* Field qp */
-	outkey->qp.data = outkey->dq.data + size_q;
-	outkey->qp.length = size_p;
-	outkey->qp.paddr = outkey->dq.paddr + size_q;
-
-	/*
-	 * Ensure buffer is copied starting with 0's
-	 * if size_qp != size_p
-	 */
-	crypto_bignum_bn2bin(inkey->qp, outkey->qp.data + size_p - size_qp);
+	retstatus = caam_key_deserialize_from_bn(inkey->qp,
+						 &outkey->qp, size_q);
+	if (retstatus)
+		return retstatus;
 
 	/* Push fields value to the physical memory */
-	cache_operation(TEE_CACHECLEAN, outkey->dp.data,
-			outkey->dp.length + outkey->dq.length +
-				outkey->qp.length);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->dp);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->qp);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->dq);
 
 	outkey->format = RSA_PRIVATE_KEY_FORMAT_3;
 
@@ -271,24 +250,19 @@ static enum caam_status do_keypair_conv_f2(struct caam_rsa_keypair *outkey,
 	if (size_p || !size_q)
 		return CAAM_NO_ERROR;
 
-	/* Allocate one buffer for both */
-	retstatus = caam_calloc_align_buf(&outkey->p, size_p + size_q);
-	if (retstatus != CAAM_NO_ERROR)
-		return CAAM_OUT_MEMORY;
-
 	/* Field Prime p */
-	outkey->p.length = size_p;
-	crypto_bignum_bn2bin(inkey->p, outkey->p.data);
+	retstatus = caam_key_deserialize_from_bn(inkey->p, &outkey->p, 0);
+	if (retstatus)
+		return retstatus;
 
 	/* Field Prime q */
-	outkey->q.data = outkey->p.data + size_p;
-	outkey->q.length = size_q;
-	outkey->q.paddr = outkey->p.paddr + size_p;
-
-	crypto_bignum_bn2bin(inkey->q, outkey->q.data);
+	retstatus = caam_key_deserialize_from_bn(inkey->q, &outkey->q, 0);
+	if (retstatus)
+		return retstatus;
 
 	/* Push fields value to the physical memory */
-	cache_operation(TEE_CACHECLEAN, outkey->p.data, size_p + size_q);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->p);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->q);
 
 	outkey->format = RSA_PRIVATE_KEY_FORMAT_2;
 
@@ -325,13 +299,11 @@ static enum caam_status do_keypair_conv(struct caam_rsa_keypair *outkey,
 	crypto_bignum_bn2bin(inkey->n, outkey->n.data);
 	cache_operation(TEE_CACHECLEAN, outkey->n.data, outkey->n.length);
 
-	retstatus = caam_calloc_align_buf(&outkey->d,
-					  crypto_bignum_num_bytes(inkey->d));
-	if (retstatus != CAAM_NO_ERROR)
+	retstatus = caam_key_deserialize_from_bn(inkey->d, &outkey->d, 0);
+	if (retstatus)
 		return retstatus;
 
-	crypto_bignum_bn2bin(inkey->d, outkey->d.data);
-	cache_operation(TEE_CACHECLEAN, outkey->d.data, outkey->d.length);
+	caam_key_cache_op(TEE_CACHECLEAN, &outkey->d);
 
 	outkey->format = RSA_PRIVATE_KEY_FORMAT_1;
 
@@ -349,7 +321,8 @@ static enum caam_status do_keypair_conv(struct caam_rsa_keypair *outkey,
  * @key        Keypair
  * @size_bits  Key size in bits
  */
-static TEE_Result do_allocate_keypair(struct rsa_keypair *key, size_t size_bits)
+static TEE_Result do_allocate_keypair(struct rsa_keypair *key,
+				      size_t size_bits)
 {
 	RSA_TRACE("Allocate Keypair of %zu bits", size_bits);
 
@@ -362,7 +335,7 @@ static TEE_Result do_allocate_keypair(struct rsa_keypair *key, size_t size_bits)
 		goto err_alloc_keypair;
 
 	/* Allocate the Private Exponent [d = 1/e mod LCM(p-1, q-1)] */
-	key->d = crypto_bignum_allocate(size_bits);
+	key->d = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->d)
 		goto err_alloc_keypair;
 
@@ -371,28 +344,28 @@ static TEE_Result do_allocate_keypair(struct rsa_keypair *key, size_t size_bits)
 	if (!key->n)
 		goto err_alloc_keypair;
 
-	/* Allocate the prime number p of size (size_bits / 2) */
-	key->p = crypto_bignum_allocate(size_bits / 2);
+	/* Allocate the prime number p */
+	key->p = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->p)
 		goto err_alloc_keypair;
 
-	/* Allocate the prime number q of size (size_bits / 2) */
-	key->q = crypto_bignum_allocate(size_bits / 2);
+	/* Allocate the prime number q */
+	key->q = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->q)
 		goto err_alloc_keypair;
 
-	/* Allocate dp (size_bits / 2) [d mod (p-1)] */
-	key->dp = crypto_bignum_allocate(size_bits / 2);
+	/* Allocate dp [d mod (p-1)] */
+	key->dp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->dp)
 		goto err_alloc_keypair;
 
-	/* Allocate dq (size_bits / 2) [d mod (q-1)] */
-	key->dq = crypto_bignum_allocate(size_bits / 2);
+	/* Allocate dq [d mod (q-1)] */
+	key->dq = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->dq)
 		goto err_alloc_keypair;
 
-	/* Allocate qp (size_bits / 2) [1/q mod p] */
-	key->qp = crypto_bignum_allocate(size_bits / 2);
+	/* Allocate qp [1/q mod p] */
+	key->qp = crypto_bignum_allocate(CFG_CORE_BIGNUM_MAX_BITS);
 	if (!key->qp)
 		goto err_alloc_keypair;
 
@@ -456,57 +429,88 @@ static void do_free_publickey(struct rsa_public_key *key)
  * Output the RSA keypair format 3 additional fields in bignumber object
  *
  * @key        [out] Keypair
- * @key_size   Key size in bits
+ * @genkey     Key pair in local format
  */
 static TEE_Result gen_keypair_get_f3(struct rsa_keypair *key,
 				     struct caam_rsa_keypair *genkey)
 {
-	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status status = CAAM_FAILURE;
 
-	cache_operation(TEE_CACHEINVALIDATE, genkey->dp.data,
-			genkey->dp.length + genkey->dq.length +
-				genkey->qp.length);
+	caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dp);
+	caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->dq);
+	caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->qp);
 
-	RSA_DUMPBUF("dp", genkey->dp.data, genkey->dp.length);
-	RSA_DUMPBUF("dq", genkey->dq.data, genkey->dq.length);
-	RSA_DUMPBUF("qp", genkey->qp.data, genkey->qp.length);
+	RSA_DUMPBUF("dp", genkey->dp.buf.data, genkey->dp.buf.length);
+	RSA_DUMPBUF("dq", genkey->dq.buf.data, genkey->dq.buf.length);
+	RSA_DUMPBUF("qp", genkey->qp.buf.data, genkey->qp.buf.length);
 
-	ret = crypto_bignum_bin2bn(genkey->dp.data, genkey->dp.length, key->dp);
-	if (ret != TEE_SUCCESS)
-		return ret;
+	status = caam_key_serialize_to_bn(key->dp, &genkey->dp);
+	if (status)
+		return caam_status_to_tee_result(status);
 
-	ret = crypto_bignum_bin2bn(genkey->dq.data, genkey->dq.length, key->dq);
-	if (ret != TEE_SUCCESS)
-		return ret;
+	status = caam_key_serialize_to_bn(key->dq, &genkey->dq);
+	if (status)
+		return caam_status_to_tee_result(status);
 
-	ret = crypto_bignum_bin2bn(genkey->qp.data, genkey->qp.length, key->qp);
-	return ret;
+	status = caam_key_serialize_to_bn(key->qp, &genkey->qp);
+	if (status)
+		return caam_status_to_tee_result(status);
+
+	return TEE_SUCCESS;
 }
 
 /*
  * Output the RSA keypair format 2 additional fields in big number object
  *
  * @key        [out] Keypair
- * @key_size   Key size in bits
+ * @genkey     Key pair in local format
  */
 static TEE_Result gen_keypair_get_f2(struct rsa_keypair *key,
 				     struct caam_rsa_keypair *genkey)
 {
-	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status status = CAAM_FAILURE;
 
-	cache_operation(TEE_CACHEINVALIDATE, genkey->p.data,
-			genkey->p.length + genkey->q.length);
+	caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->q);
+	caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey->p);
 
-	ret = crypto_bignum_bin2bn(genkey->p.data, genkey->p.length, key->p);
-	if (ret != TEE_SUCCESS)
+	RSA_DUMPBUF("p", genkey->p.buf.data, genkey->p.buf.length);
+	RSA_DUMPBUF("q", genkey->q.buf.data, genkey->q.buf.length);
+
+	status = caam_key_serialize_to_bn(key->p, &genkey->p);
+	if (status)
+		return caam_status_to_tee_result(status);
+
+	status = caam_key_serialize_to_bn(key->q, &genkey->q);
+	if (status)
+		return caam_status_to_tee_result(status);
+
+	if (genkey->format > RSA_PRIVATE_KEY_FORMAT_2)
+		return gen_keypair_get_f3(key, genkey);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+do_black_key_encapsulation(struct caam_rsa_keypair *rsa_keypair)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_key_type key_type = caam_key_default_key_gen_type();
+
+	ret = caam_key_black_encapsulation(&rsa_keypair->p, key_type);
+	if (ret) {
+		RSA_TRACE("RSA Key p component encapsulation failed");
 		return ret;
+	}
 
-	ret = crypto_bignum_bin2bn(genkey->q.data, genkey->q.length, key->q);
+	ret = caam_key_black_encapsulation(&rsa_keypair->q, key_type);
+	if (ret) {
+		RSA_TRACE("RSA Key q component encapsulation failed");
+		return ret;
+	}
 
-	if (ret == TEE_SUCCESS && genkey->format > RSA_PRIVATE_KEY_FORMAT_2)
-		ret = gen_keypair_get_f3(key, genkey);
+	RSA_TRACE("Black key encapsulation done");
 
-	return ret;
+	return TEE_SUCCESS;
 }
 
 /*
@@ -520,13 +524,14 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 	TEE_Result ret = TEE_ERROR_GENERIC;
 	enum caam_status retstatus = CAAM_FAILURE;
 	struct caam_rsa_keypair genkey = { };
-	size_t size_d = 0;
-	size_t size_n = 0;
-	size_t size_d_gen = 0;
+	size_t size_d_gen __maybe_unused = 0;
+	uint32_t *size_d_gen_val_ptr = NULL;
 	struct caam_jobctx jobctx = { };
 	uint32_t *desc = 0;
 	uint32_t desclen = 0;
 	struct prime_data_rsa prime = { };
+	enum caam_key_type key_type = caam_key_default_key_gen_type();
+	size_t key_size_bytes = key_size / 8;
 
 	RSA_TRACE("Generate Keypair of %zu bits", key_size);
 
@@ -539,18 +544,32 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 		goto exit_gen_keypair;
 	}
 
-	/* First allocate primes p and q in one buffer */
-	retstatus = caam_calloc_align_buf(&genkey.p, key_size / 8);
+	size_d_gen_val_ptr = caam_calloc_align(sizeof(uint32_t));
+	if (!size_d_gen_val_ptr) {
+		ret = TEE_ERROR_OUT_OF_MEMORY;
+		goto exit_gen_keypair;
+	}
+
+	/* First allocate primes p and q */
+	genkey.p.key_type = CAAM_KEY_PLAIN_TEXT;
+	genkey.p.sec_size = key_size_bytes / 2;
+	genkey.p.is_blob = false;
+
+	retstatus = caam_key_alloc(&genkey.p);
 	if (retstatus != CAAM_NO_ERROR) {
 		ret = caam_status_to_tee_result(retstatus);
 		goto exit_gen_keypair;
 	}
 
-	/* Prepare q */
-	genkey.p.length /= 2;
-	genkey.q.data = genkey.p.data + genkey.p.length;
-	genkey.q.length = genkey.p.length;
-	genkey.q.paddr = genkey.p.paddr + genkey.p.length;
+	genkey.q.key_type = CAAM_KEY_PLAIN_TEXT;
+	genkey.q.sec_size = key_size_bytes / 2;
+	genkey.q.is_blob = false;
+
+	retstatus = caam_key_alloc(&genkey.q);
+	if (retstatus != CAAM_NO_ERROR) {
+		ret = caam_status_to_tee_result(retstatus);
+		goto exit_gen_keypair;
+	}
 
 	/* Allocate Public exponent to a caam buffer */
 	retstatus = caam_calloc_buf(&genkey.e, crypto_bignum_num_bytes(key->e));
@@ -559,43 +578,52 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 		goto exit_gen_keypair;
 	}
 
-	/*
-	 * Allocate d and n in one buffer.
-	 * Size of d is (key_size + 1) bits - Add a 32 bits word to
-	 * retrieve the length of d generated by CAAM RSA Finalize Key
-	 */
-	size_d = sizeof(uint32_t) + key_size / 8 + 1;
-	size_n = key_size / 8;
+	genkey.d.key_type = key_type;
+	genkey.d.sec_size = key_size_bytes;
+	genkey.d.is_blob = false;
 
-	retstatus = caam_calloc_align_buf(&genkey.d, size_d + size_n);
+	retstatus = caam_key_alloc(&genkey.d);
 	if (retstatus != CAAM_NO_ERROR) {
 		ret = caam_status_to_tee_result(retstatus);
 		goto exit_gen_keypair;
 	}
 
-	genkey.d.length = size_d;
-	genkey.n.data = genkey.d.data + size_d;
-	genkey.n.length = size_n;
-	genkey.n.paddr = genkey.d.paddr + size_d;
+	retstatus = caam_calloc_align_buf(&genkey.n, key_size_bytes);
+	if (retstatus != CAAM_NO_ERROR) {
+		ret = caam_status_to_tee_result(retstatus);
+		goto exit_gen_keypair;
+	}
 
 	if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) {
-		/* Allocate dp, dq and qp in one buffer */
-		retstatus = caam_calloc_align_buf(&genkey.dp,
-						  ((key_size / 8) / 2) * 3);
+		genkey.dp.key_type = key_type;
+		genkey.dp.sec_size = key_size_bytes / 2;
+		genkey.dp.is_blob = false;
+
+		retstatus = caam_key_alloc(&genkey.dp);
+		if (retstatus != CAAM_NO_ERROR) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto exit_gen_keypair;
+		}
+
+		genkey.dq.key_type = key_type;
+		genkey.dq.sec_size = key_size_bytes / 2;
+		genkey.dq.is_blob = false;
+
+		retstatus = caam_key_alloc(&genkey.dq);
 		if (retstatus != CAAM_NO_ERROR) {
 			ret = caam_status_to_tee_result(retstatus);
 			goto exit_gen_keypair;
 		}
 
-		genkey.dp.length /= 3;
-		/* Prepare dq and qp */
-		genkey.dq.data = genkey.dp.data + genkey.dp.length;
-		genkey.dq.length = genkey.dp.length;
-		genkey.dq.paddr = genkey.dp.paddr + genkey.dp.length;
+		genkey.qp.key_type = key_type;
+		genkey.qp.sec_size = key_size_bytes / 2;
+		genkey.qp.is_blob = false;
 
-		genkey.qp.data = genkey.dq.data + genkey.dq.length;
-		genkey.qp.length = genkey.dq.length;
-		genkey.qp.paddr = genkey.dq.paddr + genkey.dq.length;
+		retstatus = caam_key_alloc(&genkey.qp);
+		if (retstatus != CAAM_NO_ERROR) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto exit_gen_keypair;
+		}
 	}
 
 	crypto_bignum_bn2bin(key->e, genkey.e.data);
@@ -603,8 +631,8 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 	prime.era = caam_era;
 	prime.key_size = key_size;
 	prime.e = &genkey.e;
-	prime.p = &genkey.p;
-	prime.q = &genkey.q;
+	prime.p = &genkey.p.buf;
+	prime.q = &genkey.q.buf;
 
 	/* Generate prime p and q */
 	retstatus = caam_prime_rsa_gen(&prime);
@@ -618,29 +646,55 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 	caam_desc_add_word(desc, DESC_HEADER(0));
 
 	caam_desc_add_word(desc, 0);
-	caam_desc_add_word(desc, PDB_RSA_KEY_P_SIZE(genkey.p.length));
+	caam_desc_add_word(desc, PDB_RSA_KEY_P_SIZE(genkey.p.sec_size));
 	caam_desc_add_word(desc, PDB_RSA_KEY_N_SIZE(genkey.n.length) |
 					 PDB_RSA_KEY_E_SIZE(genkey.e.length));
 
-	caam_desc_add_ptr(desc, genkey.p.paddr);
-	caam_desc_add_ptr(desc, genkey.q.paddr);
+	caam_desc_add_ptr(desc, genkey.p.buf.paddr);
+	caam_desc_add_ptr(desc, genkey.q.buf.paddr);
 	caam_desc_add_ptr(desc, genkey.e.paddr);
 	caam_desc_add_ptr(desc, genkey.n.paddr);
-	caam_desc_add_ptr(desc, genkey.d.paddr + sizeof(uint32_t));
-	caam_desc_add_ptr(desc, genkey.d.paddr);
+	caam_desc_add_ptr(desc, genkey.d.buf.paddr);
+	caam_desc_add_ptr(desc, virt_to_phys(size_d_gen_val_ptr));
 
 	if (genkey.format > RSA_PRIVATE_KEY_FORMAT_2) {
-		caam_desc_add_ptr(desc, genkey.dp.paddr);
-		caam_desc_add_ptr(desc, genkey.dq.paddr);
-		caam_desc_add_ptr(desc, genkey.qp.paddr);
-		caam_desc_add_word(desc, RSA_FINAL_KEY(ALL));
-
-		cache_operation(TEE_CACHEFLUSH, genkey.dp.data,
-				genkey.dp.length + genkey.dq.length +
-					genkey.qp.length);
+		caam_desc_add_ptr(desc, genkey.dp.buf.paddr);
+		caam_desc_add_ptr(desc, genkey.dq.buf.paddr);
+		caam_desc_add_ptr(desc, genkey.qp.buf.paddr);
+
+		switch (key_type) {
+		case CAAM_KEY_PLAIN_TEXT:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, NONE));
+			break;
+		case CAAM_KEY_BLACK_ECB:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, ECB));
+			break;
+		case CAAM_KEY_BLACK_CCM:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(ALL, CCM));
+			break;
+		default:
+			ret = TEE_ERROR_GENERIC;
+			goto exit_gen_keypair;
+		}
 
+		caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dp);
+		caam_key_cache_op(TEE_CACHEFLUSH, &genkey.dq);
+		caam_key_cache_op(TEE_CACHEFLUSH, &genkey.qp);
 	} else {
-		caam_desc_add_word(desc, RSA_FINAL_KEY(N_D));
+		switch (key_type) {
+		case CAAM_KEY_PLAIN_TEXT:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, NONE));
+			break;
+		case CAAM_KEY_BLACK_ECB:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, ECB));
+			break;
+		case CAAM_KEY_BLACK_CCM:
+			caam_desc_add_word(desc, RSA_FINAL_KEY(N_D, CCM));
+			break;
+		default:
+			ret = TEE_ERROR_GENERIC;
+			goto exit_gen_keypair;
+		}
 	}
 
 	desclen = caam_desc_get_len(desc);
@@ -650,31 +704,46 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 	RSA_DUMPDESC(desc);
 
 	cache_operation(TEE_CACHECLEAN, genkey.e.data, genkey.e.length);
-	cache_operation(TEE_CACHEFLUSH, genkey.p.data,
-			genkey.p.length + genkey.q.length);
-	cache_operation(TEE_CACHEFLUSH, genkey.d.data,
-			genkey.d.length + genkey.n.length);
+	caam_key_cache_op(TEE_CACHEFLUSH, &genkey.p);
+	caam_key_cache_op(TEE_CACHEFLUSH, &genkey.q);
+	caam_key_cache_op(TEE_CACHEFLUSH, &genkey.d);
+	cache_operation(TEE_CACHEFLUSH, genkey.n.data, genkey.n.length);
+	cache_operation(TEE_CACHEFLUSH, size_d_gen_val_ptr, sizeof(uint32_t));
 
 	retstatus = caam_jr_enqueue(&jobctx, NULL);
 
 	if (retstatus == CAAM_NO_ERROR) {
-		cache_operation(TEE_CACHEINVALIDATE, genkey.d.data,
-				genkey.d.length + genkey.n.length);
+		caam_key_cache_op(TEE_CACHEINVALIDATE, &genkey.d);
+		cache_operation(TEE_CACHEINVALIDATE, &genkey.n,
+				genkey.n.length);
+
+		cache_operation(TEE_CACHEINVALIDATE, size_d_gen_val_ptr,
+				sizeof(uint32_t));
+
+		size_d_gen = caam_read_val32(size_d_gen_val_ptr);
 
-		size_d_gen = caam_read_val32(genkey.d.data);
 		RSA_TRACE("D size %zu", size_d_gen);
+		RSA_DUMPBUF("D", genkey.d.buf.data, genkey.d.buf.length);
 		RSA_DUMPBUF("N", genkey.n.data, genkey.n.length);
-		RSA_DUMPBUF("D", genkey.d.data + sizeof(uint32_t), size_d_gen);
+
+		genkey.d.sec_size = size_d_gen;
+
+		if (key_type != CAAM_KEY_PLAIN_TEXT) {
+			ret = do_black_key_encapsulation(&genkey);
+			if (ret != TEE_SUCCESS)
+				goto exit_gen_keypair;
+		}
 
 		ret = crypto_bignum_bin2bn(genkey.n.data, genkey.n.length,
 					   key->n);
 		if (ret != TEE_SUCCESS)
 			goto exit_gen_keypair;
 
-		ret = crypto_bignum_bin2bn(genkey.d.data + sizeof(uint32_t),
-					   size_d_gen, key->d);
-		if (ret != TEE_SUCCESS)
+		retstatus = caam_key_serialize_to_bn(key->d, &genkey.d);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
 			goto exit_gen_keypair;
+		}
 
 		if (genkey.format > RSA_PRIVATE_KEY_FORMAT_1)
 			ret = gen_keypair_get_f2(key, &genkey);
@@ -684,10 +753,8 @@ static TEE_Result do_gen_keypair(struct rsa_keypair *key, size_t key_size)
 	}
 
 exit_gen_keypair:
-	genkey.d.length += genkey.n.length;
-	genkey.n.data = NULL;
 	do_keypair_free(&genkey);
-
+	caam_free(size_d_gen_val_ptr);
 	caam_free_desc(&desc);
 
 	return ret;
@@ -823,8 +890,8 @@ static TEE_Result do_oaep_decoding(struct drvcrypt_rsa_ed *rsa_data)
 	 *
 	 * Note: Use same buffer for seed and seedMask
 	 */
-	mgf_data.hash_algo = rsa_data->hash_algo;
-	mgf_data.digest_size = rsa_data->digest_size;
+	mgf_data.hash_algo = rsa_data->mgf_algo;
+	mgf_data.digest_size = rsa_data->mgf_size;
 	mgf_data.seed.data = maskedDB.data;
 	mgf_data.seed.length = maskedDB.length;
 	mgf_data.mask.data = seed.data;
@@ -1056,8 +1123,8 @@ static TEE_Result do_oaep_encoding(struct drvcrypt_rsa_ed *rsa_data)
 	 * Generate a Mask of the seed value
 	 * dbMask = MGF(seed, k - hLen - 1)
 	 */
-	mgf_data.hash_algo = rsa_data->hash_algo;
-	mgf_data.digest_size = rsa_data->digest_size;
+	mgf_data.hash_algo = rsa_data->mgf_algo;
+	mgf_data.digest_size = rsa_data->mgf_size;
 	mgf_data.seed.data = seed.data;
 	mgf_data.seed.length = seed.length;
 	mgf_data.mask.data = dbMask.data;
@@ -1252,6 +1319,35 @@ exit_encrypt:
 	return ret;
 }
 
+/*
+ * Get RSA key pair key type
+ *
+ * @kp RSA key pair
+ */
+static enum caam_key_type get_caam_key_type(const struct caam_rsa_keypair kp)
+{
+	switch (kp.format) {
+	case RSA_PRIVATE_KEY_FORMAT_1:
+		return kp.d.key_type;
+	case RSA_PRIVATE_KEY_FORMAT_2:
+		if (kp.p.key_type == kp.q.key_type &&
+		    kp.q.key_type == kp.d.key_type)
+			return kp.p.key_type;
+		else
+			return CAAM_KEY_MAX_VALUE;
+	case RSA_PRIVATE_KEY_FORMAT_3:
+		if (kp.p.key_type == kp.q.key_type &&
+		    kp.q.key_type == kp.dp.key_type &&
+		    kp.dp.key_type == kp.dq.key_type &&
+		    kp.dq.key_type == kp.qp.key_type)
+			return kp.p.key_type;
+		else
+			return CAAM_KEY_MAX_VALUE;
+	default:
+		return CAAM_KEY_MAX_VALUE;
+	}
+}
+
 /*
  * CAAM RSA Decryption of the input cipher to a message
  *
@@ -1271,7 +1367,9 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 	uint32_t desclen = 0;
 	uint32_t pdb_sgt_flags = 0;
 	struct caambuf size_msg = { };
-	struct caambuf tmp = { };
+	struct caamkey tmp_1 = { };
+	struct caamkey tmp_2 = { };
+	enum caam_key_type g_key_type = CAAM_KEY_MAX_VALUE;
 
 	RSA_TRACE("RSA Decrypt mode %d", rsa_data->rsa_id);
 
@@ -1302,7 +1400,7 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 	caam_dmaobj_cache_push(&msg);
 
 	/* Allocate the returned computed size when PKCS V1.5 */
-	if (operation == RSA_DECRYPT(PKCS_V1_5)) {
+	if ((operation & PROT_RSA_FMT_MASK) == PROT_RSA_FMT(PKCS_V1_5)) {
 		retstatus = caam_alloc_align_buf(&size_msg, 4);
 		if (retstatus != CAAM_NO_ERROR)
 			goto exit_decrypt;
@@ -1340,15 +1438,29 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 			ret = TEE_ERROR_OUT_OF_MEMORY;
 			goto exit_decrypt;
 		}
-		/* Allocate temporary buffers used by the CAAM */
-		retstatus =
-			caam_alloc_align_buf(&tmp, key.p.length + key.q.length);
+		/* Allocate two temporary buffers used by the CAAM */
+		tmp_1.key_type = CAAM_KEY_PLAIN_TEXT;
+		tmp_1.sec_size = key.p.sec_size;
+		tmp_1.is_blob = false;
+
+		retstatus = caam_key_alloc(&tmp_1);
+		if (retstatus != CAAM_NO_ERROR) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto exit_decrypt;
+		}
+
+		tmp_2.key_type = CAAM_KEY_PLAIN_TEXT;
+		tmp_2.sec_size = key.q.sec_size;
+		tmp_2.is_blob = false;
+
+		retstatus = caam_key_alloc(&tmp_2);
 		if (retstatus != CAAM_NO_ERROR) {
 			ret = caam_status_to_tee_result(retstatus);
 			goto exit_decrypt;
 		}
 
-		cache_operation(TEE_CACHEFLUSH, tmp.data, tmp.length);
+		caam_key_cache_op(TEE_CACHEFLUSH, &tmp_1);
+		caam_key_cache_op(TEE_CACHEFLUSH, &tmp_2);
 		break;
 
 	default:
@@ -1363,31 +1475,31 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 	switch (key.format) {
 	case RSA_PRIVATE_KEY_FORMAT_1:
 		caam_desc_add_word(desc,
-				   PDB_RSA_DEC_D_SIZE(key.d.length) |
+				   PDB_RSA_DEC_D_SIZE(key.d.sec_size) |
 					   PDB_RSA_DEC_N_SIZE(key.n.length) |
 					   pdb_sgt_flags);
 		caam_desc_add_ptr(desc, cipher.sgtbuf.paddr);
 		caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
 		caam_desc_add_ptr(desc, key.n.paddr);
-		caam_desc_add_ptr(desc, key.d.paddr);
+		caam_desc_add_ptr(desc, key.d.buf.paddr);
 
 		break;
 
 	case RSA_PRIVATE_KEY_FORMAT_2:
 		caam_desc_add_word(desc,
-				   PDB_RSA_DEC_D_SIZE(key.d.length) |
+				   PDB_RSA_DEC_D_SIZE(key.d.sec_size) |
 					   PDB_RSA_DEC_N_SIZE(key.n.length) |
 					   pdb_sgt_flags);
 		caam_desc_add_ptr(desc, cipher.sgtbuf.paddr);
 		caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
-		caam_desc_add_ptr(desc, key.d.paddr);
-		caam_desc_add_ptr(desc, key.p.paddr);
-		caam_desc_add_ptr(desc, key.q.paddr);
-		caam_desc_add_ptr(desc, tmp.paddr);
-		caam_desc_add_ptr(desc, tmp.paddr + key.p.length);
+		caam_desc_add_ptr(desc, key.d.buf.paddr);
+		caam_desc_add_ptr(desc, key.p.buf.paddr);
+		caam_desc_add_ptr(desc, key.q.buf.paddr);
+		caam_desc_add_ptr(desc, tmp_1.buf.paddr);
+		caam_desc_add_ptr(desc, tmp_2.buf.paddr);
 		caam_desc_add_word(desc,
-				   PDB_RSA_DEC_Q_SIZE(key.q.length) |
-					   PDB_RSA_DEC_P_SIZE(key.p.length));
+				   PDB_RSA_DEC_Q_SIZE(key.q.sec_size) |
+					   PDB_RSA_DEC_P_SIZE(key.p.sec_size));
 		break;
 
 	case RSA_PRIVATE_KEY_FORMAT_3:
@@ -1395,16 +1507,16 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 						 pdb_sgt_flags);
 		caam_desc_add_ptr(desc, cipher.sgtbuf.paddr);
 		caam_desc_add_ptr(desc, msg.sgtbuf.paddr);
-		caam_desc_add_ptr(desc, key.qp.paddr);
-		caam_desc_add_ptr(desc, key.p.paddr);
-		caam_desc_add_ptr(desc, key.q.paddr);
-		caam_desc_add_ptr(desc, key.dp.paddr);
-		caam_desc_add_ptr(desc, key.dq.paddr);
-		caam_desc_add_ptr(desc, tmp.paddr);
-		caam_desc_add_ptr(desc, tmp.paddr + key.p.length);
+		caam_desc_add_ptr(desc, key.qp.buf.paddr);
+		caam_desc_add_ptr(desc, key.p.buf.paddr);
+		caam_desc_add_ptr(desc, key.q.buf.paddr);
+		caam_desc_add_ptr(desc, key.dp.buf.paddr);
+		caam_desc_add_ptr(desc, key.dq.buf.paddr);
+		caam_desc_add_ptr(desc, tmp_1.buf.paddr);
+		caam_desc_add_ptr(desc, tmp_2.buf.paddr);
 		caam_desc_add_word(desc,
-				   PDB_RSA_DEC_Q_SIZE(key.q.length) |
-					   PDB_RSA_DEC_P_SIZE(key.p.length));
+				   PDB_RSA_DEC_Q_SIZE(key.q.sec_size) |
+					   PDB_RSA_DEC_P_SIZE(key.p.sec_size));
 		break;
 
 	default:
@@ -1413,10 +1525,29 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 	}
 
 	/* Set the Decryption operation type */
-	caam_desc_add_word(desc, operation | PROT_RSA_DEC_KEYFORM(key.format));
+	operation |= PROT_RSA_DEC_KEYFORM(key.format);
+
+	/* Get key type */
+	g_key_type = get_caam_key_type(key);
+	switch (g_key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		operation |= PROT_RSA_KEY_ENC(NONE);
+		break;
+	case CAAM_KEY_BLACK_ECB:
+		operation |= PROT_RSA_KEY_ENC(ECB);
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		operation |= PROT_RSA_KEY_ENC(CCM);
+		break;
+	default:
+		ret = TEE_ERROR_GENERIC;
+		goto exit_decrypt;
+	}
+
+	caam_desc_add_word(desc, operation);
 
-	if (operation == RSA_DECRYPT(PKCS_V1_5)) {
-		/* Get the PPKCS1 v1.5 Message length generated */
+	if ((operation & PROT_RSA_FMT_MASK) == PROT_RSA_FMT(PKCS_V1_5)) {
+		/* Get the PKCS1 v1.5 Message length generated */
 		caam_desc_add_word(desc,
 				   ST_NOIMM_OFF(CLASS_DECO, REG_MATH0, 4, 4));
 		caam_desc_add_ptr(desc, size_msg.paddr);
@@ -1447,11 +1578,12 @@ static TEE_Result do_caam_decrypt(struct drvcrypt_rsa_ed *rsa_data,
 		goto exit_decrypt;
 	}
 
-	if (operation == RSA_DECRYPT(NO) &&
+	if ((operation & PROT_RSA_FMT_MASK) == PROT_RSA_FMT(NO) &&
 	    rsa_data->rsa_id == DRVCRYPT_RSA_NOPAD) {
 		rsa_data->message.length = caam_dmaobj_copy_ltrim_to_orig(&msg);
 	} else {
-		if (operation == RSA_DECRYPT(PKCS_V1_5)) {
+		if ((operation & PROT_RSA_FMT_MASK) ==
+		    PROT_RSA_FMT(PKCS_V1_5)) {
 			/* PKCS 1 v1.5 */
 			cache_operation(TEE_CACHEINVALIDATE, size_msg.data,
 					size_msg.length);
@@ -1481,7 +1613,8 @@ exit_decrypt:
 	caam_dmaobj_free(&msg);
 	caam_dmaobj_free(&cipher);
 
-	caam_free_buf(&tmp);
+	caam_key_free(&tmp_1);
+	caam_key_free(&tmp_2);
 
 	return ret;
 }
diff --git a/core/drivers/crypto/caam/ae/caam_ae.c b/core/drivers/crypto/caam/ae/caam_ae.c
new file mode 100644
index 0000000000000000000000000000000000000000..dda47711af82b948b97d87ef0dbbc47eca67d83a
--- /dev/null
+++ b/core/drivers/crypto/caam/ae/caam_ae.c
@@ -0,0 +1,1054 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 NXP
+ */
+#include <caam_ae.h>
+#include <caam_common.h>
+#include <caam_io.h>
+#include <caam_jr.h>
+#include <caam_status.h>
+#include <caam_utils_mem.h>
+#include <caam_utils_status.h>
+#include <drvcrypt.h>
+#include <drvcrypt_authenc.h>
+#include <mm/core_memprot.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <tee/cache.h>
+#include <utee_defines.h>
+#include <utee_types.h>
+
+#include "local.h"
+
+#define MAX_DESC_ENTRIES 64
+
+/*
+ * Constants definition of the AES algorithm
+ */
+static const struct cipheralg aes_alg[] = {
+#if defined(CFG_NXP_CAAM_AE_CCM_DRV)
+	[TEE_CHAIN_MODE_CCM] = {
+		.type = OP_ALGO(AES) | ALGO_AAI(AES_CCM),
+		.size_block = TEE_AES_BLOCK_SIZE,
+		.size_ctx = 7 * sizeof(uint64_t),
+		.ctx_offset = 0,
+		.def_key = { .min = 16, .max = 32, .mod = 8 },
+		.initialize = caam_ae_initialize_ccm,
+		.final = caam_ae_final_ccm,
+	},
+#endif
+#if defined(CFG_NXP_CAAM_AE_GCM_DRV)
+	[TEE_CHAIN_MODE_GCM] = {
+		.type = OP_ALGO(AES) | ALGO_AAI(AES_GCM),
+		.size_block = TEE_AES_BLOCK_SIZE,
+		.size_ctx = 8 * sizeof(uint64_t),
+		.ctx_offset = 0,
+		.def_key = { .min = 16, .max = 32, .mod = 8 },
+		.initialize = caam_ae_initialize_gcm,
+		.final = caam_ae_final_gcm,
+	},
+#endif
+};
+
+/*
+ * Checks if the algorithm @algo is supported and returns the
+ * local algorithm entry in the corresponding cipher array
+ */
+static const struct cipheralg *get_cipheralgo(uint32_t algo)
+{
+	unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo);
+	unsigned int algo_md = TEE_ALG_GET_CHAIN_MODE(algo);
+	const struct cipheralg *ca = NULL;
+
+	AE_TRACE("Algo id:%u md:%u", algo_id, algo_md);
+
+	switch (algo_id) {
+	case TEE_MAIN_ALGO_AES:
+		if (algo_md < ARRAY_SIZE(aes_alg))
+			ca = &aes_alg[algo_md];
+		break;
+
+	default:
+		break;
+	}
+
+	if (ca && ca->type)
+		return ca;
+
+	return NULL;
+}
+
+/*
+ * Allocate the SW cipher data context
+ *
+ * @ctx   [out] Caller context variable
+ * @algo  Algorithm ID of the context
+ */
+static TEE_Result caam_ae_allocate(void **ctx, uint32_t algo)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	struct caam_ae_ctx *caam_ctx = NULL;
+	const struct cipheralg *alg = NULL;
+
+	assert(ctx);
+
+	alg = get_cipheralgo(algo);
+	if (!alg) {
+		AE_TRACE("Algorithm not implemented");
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	caam_ctx = caam_calloc(sizeof(*caam_ctx));
+	if (!caam_ctx)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	caam_ctx->descriptor = caam_calloc_desc(MAX_DESC_ENTRIES);
+	if (!caam_ctx->descriptor) {
+		ret = TEE_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+
+	/* Setup the Algorithm pointer */
+	caam_ctx->alg = alg;
+	/* Initialize the block buffer */
+	caam_ctx->blockbuf.max = caam_ctx->alg->size_block;
+
+	*ctx = caam_ctx;
+
+	return TEE_SUCCESS;
+err:
+	caam_free_desc(&caam_ctx->descriptor);
+	caam_free(caam_ctx);
+
+	return ret;
+}
+
+/*
+ * Free the internal cipher data context
+ *
+ * @ctx    Caller context variable or NULL
+ */
+static void caam_ae_free(void *ctx)
+{
+	struct caam_ae_ctx *caam_ctx = ctx;
+
+	assert(ctx);
+
+	caam_free_desc(&caam_ctx->descriptor);
+	caam_free_buf(&caam_ctx->key);
+	caam_free_buf(&caam_ctx->nonce);
+	caam_free_buf(&caam_ctx->ctx);
+	caam_free_buf(&caam_ctx->initial_ctx);
+	caam_free_buf(&caam_ctx->buf_aad.buf);
+	caam_free_buf(&caam_ctx->blockbuf.buf);
+	caam_free(caam_ctx);
+}
+
+/*
+ * Initialization of the cipher operation
+ *
+ * @dinit  Data initialization object
+ */
+static TEE_Result caam_ae_initialize(struct drvcrypt_authenc_init *dinit)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_ae_ctx *caam_ctx = NULL;
+
+	assert(dinit);
+
+	if (dinit->aad_len >= AAD_LENGTH_OVERFLOW)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	caam_ctx = dinit->ctx;
+	if (!caam_ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	caam_ctx->encrypt = dinit->encrypt;
+	caam_ctx->aad_length = dinit->aad_len;
+	caam_ctx->payload_length = dinit->payload_len;
+	caam_ctx->tag_length = dinit->tag_len;
+
+	if (dinit->key.data && dinit->key.length) {
+		retstatus = caam_cpy_buf(&caam_ctx->key, dinit->key.data,
+					 dinit->key.length);
+		AE_TRACE("Copy key returned %d", retstatus);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto err;
+		}
+	}
+
+	caam_ctx->blockbuf.filled = 0;
+	caam_ctx->buf_aad.filled = 0;
+
+	ret = caam_ctx->alg->initialize(dinit);
+	if (ret)
+		goto err;
+
+	return TEE_SUCCESS;
+err:
+	caam_free_buf(&caam_ctx->key);
+
+	return ret;
+}
+
+/*
+ * Update Additional Authenticated Data part of the authenc operation
+ *
+ * @dupdate  Additional Authenticated Data update object
+ */
+static TEE_Result
+caam_ae_update_aad(struct drvcrypt_authenc_update_aad *dupdate)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_ae_ctx *caam_ctx = NULL;
+	struct caambuf aad = { };
+
+	assert(dupdate);
+
+	caam_ctx = dupdate->ctx;
+	if (!caam_ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (dupdate->aad.data) {
+		retstatus = caam_cpy_buf(&aad, dupdate->aad.data,
+					 dupdate->aad.length);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto out;
+		}
+
+		/* Initialize the AAD buffer if not already done */
+		if (!caam_ctx->buf_aad.max)
+			caam_ctx->buf_aad.max = dupdate->aad.length;
+
+		retstatus = caam_cpy_block_src(&caam_ctx->buf_aad, &aad, 0);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto out;
+		}
+	}
+
+	ret = TEE_SUCCESS;
+out:
+	caam_free_buf(&aad);
+	return ret;
+}
+
+/*
+ * Update of the cipher operation. Call the algorithm update
+ * function associated.
+ *
+ * @dupdate  Data update object
+ */
+static TEE_Result
+caam_ae_update_payload(struct drvcrypt_authenc_update_payload *dupdate)
+{
+	struct caam_ae_ctx *caam_ctx = NULL;
+
+	assert(dupdate);
+
+	caam_ctx = dupdate->ctx;
+	if (!caam_ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return caam_ae_do_update(caam_ctx, &dupdate->src, &dupdate->dst, false);
+}
+
+/*
+ * Last cipher update operation. Call the algorithm final
+ * function associated.
+ *
+ * @dfinal  Data final object
+ */
+static TEE_Result caam_ae_final(struct drvcrypt_authenc_final *dfinal)
+{
+	struct caam_ae_ctx *caam_ctx = NULL;
+	TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
+
+	assert(dfinal);
+
+	caam_ctx = dfinal->ctx;
+	if (!caam_ctx)
+		return ret;
+
+	ret = caam_ctx->alg->final(dfinal);
+
+	caam_free_buf(&caam_ctx->nonce);
+	caam_free_buf(&caam_ctx->ctx);
+	caam_free_buf(&caam_ctx->initial_ctx);
+	caam_free_buf(&caam_ctx->buf_aad.buf);
+	caam_free_buf(&caam_ctx->blockbuf.buf);
+
+	return ret;
+}
+
+/*
+ * Finalize of the cipher operation
+ *
+ * @ctx    Caller context variable or NULL
+ */
+static void caam_ae_finalize(void *ctx __unused)
+{
+}
+
+/*
+ * Copy software Context
+ *
+ * @dst_ctx  [out] Reference the context destination
+ * @src_ctx  Reference the context source
+ */
+static void caam_ae_copy_state(void *dst_ctx, void *src_ctx)
+{
+	struct caam_ae_ctx *dst = dst_ctx;
+	struct caam_ae_ctx *src = src_ctx;
+
+	if (!dst || !src)
+		return;
+
+	AE_TRACE("Copy State context (%p) to (%p)", src_ctx, dst_ctx);
+
+	dst->alg = src->alg;
+	dst->encrypt = src->encrypt;
+	dst->aad_length = src->aad_length;
+	dst->tag_length = src->tag_length;
+	dst->payload_length = src->payload_length;
+	dst->buf_aad.max = src->buf_aad.max;
+	dst->do_block = src->do_block;
+
+	caam_free_buf(&dst->key);
+	caam_free_buf(&dst->nonce);
+	caam_free_buf(&dst->ctx);
+	caam_free_buf(&dst->initial_ctx);
+	caam_free_buf(&dst->buf_aad.buf);
+	caam_free_buf(&dst->blockbuf.buf);
+	dst->buf_aad.filled = 0;
+	dst->blockbuf.filled = 0;
+
+	if (src->blockbuf.filled) {
+		struct caambuf srcdata = {
+			.data = src->blockbuf.buf.data,
+			.length = src->blockbuf.filled
+		};
+
+		caam_cpy_block_src(&dst->blockbuf, &srcdata, 0);
+	}
+
+	if (src->buf_aad.filled) {
+		struct caambuf srcdata = {
+			.data = src->buf_aad.buf.data,
+			.length = src->buf_aad.filled
+		};
+
+		caam_cpy_block_src(&dst->buf_aad, &srcdata, 0);
+	}
+
+	if (src->key.length)
+		caam_cpy_buf(&dst->key, src->key.data, src->key.length);
+
+	if (src->ctx.length)
+		caam_cpy_buf(&dst->ctx, src->ctx.data, src->ctx.length);
+
+	if (src->initial_ctx.length)
+		caam_cpy_buf(&dst->initial_ctx, src->initial_ctx.data,
+			     src->initial_ctx.length);
+
+	if (src->nonce.length)
+		caam_cpy_buf(&dst->nonce, src->nonce.data,
+			     src->nonce.length);
+}
+
+/*
+ * Registration of the Authentication Encryption Driver
+ */
+static struct drvcrypt_authenc driver_ae = {
+	.alloc_ctx = &caam_ae_allocate,
+	.free_ctx = &caam_ae_free,
+	.init = &caam_ae_initialize,
+	.update_aad = &caam_ae_update_aad,
+	.update_payload = &caam_ae_update_payload,
+	.enc_final = &caam_ae_final,
+	.dec_final = &caam_ae_final,
+	.final = &caam_ae_finalize,
+	.copy_state = &caam_ae_copy_state,
+};
+
+/*
+ * Init descriptor with a cipher key
+ *
+ * @caam_ctx  Reference the AE cipher context
+ */
+static void init_descriptor(struct caam_ae_ctx *caam_ctx)
+{
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	caam_desc_init(desc);
+	caam_desc_add_word(desc, DESC_HEADER(0));
+
+	/* Build the descriptor */
+	caam_desc_add_word(desc,
+			   LD_KEY_PLAIN(CLASS_1, REG, caam_ctx->key.length));
+	caam_desc_add_ptr(desc, caam_ctx->key.paddr);
+}
+
+/*
+ * Init descriptor with an initial context
+ *
+ * @caam_ctx  Reference the AE cipher context
+ */
+static void add_initial_context(struct caam_ae_ctx *caam_ctx)
+{
+	uint32_t *desc = NULL;
+	size_t length = 0;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+	length = caam_ctx->initial_ctx.length;
+
+	if (length) {
+		caam_desc_add_word(desc,
+				   LD_NOIMM_OFF(CLASS_1, REG_CTX, length, 0));
+		caam_desc_add_ptr(desc, caam_ctx->initial_ctx.paddr);
+
+		/* Ensure Context register data are not in cache */
+		cache_operation(TEE_CACHECLEAN, caam_ctx->initial_ctx.data,
+				length);
+	}
+}
+
+/*
+ * Set descriptor with a saved CAAM context
+ *
+ * @caam_ctx  Reference the AE cipher context
+ */
+static void load_context(struct caam_ae_ctx *caam_ctx)
+{
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	caam_desc_add_word(desc,
+			   LD_NOIMM_OFF(CLASS_1, REG_CTX, caam_ctx->ctx.length,
+					caam_ctx->alg->ctx_offset));
+	caam_desc_add_ptr(desc, caam_ctx->ctx.paddr);
+}
+
+/*
+ * Set descriptor to saved CAAM context
+ *
+ * @caam_ctx  Reference the AE cipher context
+ */
+static void store_context(struct caam_ae_ctx *caam_ctx)
+{
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	/* Store the context */
+	caam_desc_add_word(desc,
+			   ST_NOIMM_OFF(CLASS_1, REG_CTX, caam_ctx->ctx.length,
+					caam_ctx->alg->ctx_offset));
+	caam_desc_add_ptr(desc, caam_ctx->ctx.paddr);
+
+	/* Ensure Context register data are not in cache */
+	cache_operation(TEE_CACHECLEAN, caam_ctx->ctx.data,
+			caam_ctx->ctx.length);
+}
+
+/*
+ * Cipher operation and generates a message authentication
+ *
+ * @caam_ctx AE Cipher context
+ * @encrypt  Encrypt or decrypt direction
+ * @src      Source data to encrypt/decrypt
+ * @dst      [out] Destination data encrypted/decrypted
+ * @aad      Additional Authenticated data
+ */
+static enum caam_status caam_ae_do_oneshot(struct caam_ae_ctx *caam_ctx,
+					   bool encrypt, struct caamdmaobj *src,
+					   struct caamdmaobj *dst,
+					   struct caamdmaobj *aad)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_jobctx jobctx = { };
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	init_descriptor(caam_ctx);
+
+	add_initial_context(caam_ctx);
+
+	AE_TRACE("Init/Final operation");
+
+	/* Operation with the direction */
+	caam_desc_add_word(desc,
+			   CIPHER_INITFINAL(caam_ctx->alg->type, encrypt));
+
+	if (!caam_ctx->ctx.data) {
+		retstatus = caam_alloc_align_buf(&caam_ctx->ctx,
+						 caam_ctx->alg->size_ctx);
+		if (retstatus)
+			return retstatus;
+	}
+
+	if (caam_ctx->nonce.data) {
+		if (!src && !aad)
+			caam_desc_add_word(desc,
+					   FIFO_LD(CLASS_1, IV, LAST_C1,
+						   caam_ctx->nonce.length));
+		else
+			caam_desc_add_word(desc,
+					   FIFO_LD(CLASS_1, IV, FLUSH,
+						   caam_ctx->nonce.length));
+		caam_desc_add_ptr(desc, caam_ctx->nonce.paddr);
+
+		/* Ensure Nonce data are not in cache */
+		cache_operation(TEE_CACHECLEAN, caam_ctx->nonce.data,
+				caam_ctx->nonce.length);
+	}
+
+	if (aad) {
+		if (!src)
+			caam_desc_fifo_load(desc, aad, CLASS_1, AAD, LAST_C1);
+		else
+			caam_desc_fifo_load(desc, aad, CLASS_1, AAD, FLUSH);
+		caam_dmaobj_cache_push(aad);
+	}
+
+	/* Load the source data if any */
+	if (src) {
+		caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1);
+		caam_dmaobj_cache_push(src);
+	}
+
+	/* Store the output data if any */
+	if (dst) {
+		caam_desc_fifo_store(desc, dst, MSG_DATA);
+		caam_dmaobj_cache_push(dst);
+	}
+
+	store_context(caam_ctx);
+
+	AE_DUMPDESC(desc);
+
+	jobctx.desc = desc;
+	retstatus = caam_jr_enqueue(&jobctx, NULL);
+	if (retstatus) {
+		AE_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32,
+			 retstatus, jobctx.status);
+		retstatus = CAAM_FAILURE;
+	}
+
+	/* Ensure Context register data are not in cache */
+	cache_operation(TEE_CACHEINVALIDATE, caam_ctx->ctx.data,
+			caam_ctx->ctx.length);
+
+	return retstatus;
+}
+
+/*
+ * Init cipher operation
+ *
+ * @caam_ctx AE Cipher context
+ * @encrypt  Encrypt or decrypt direction
+ * @aad      Additional Authenticated data
+ */
+static enum caam_status caam_ae_do_init(struct caam_ae_ctx *caam_ctx,
+					bool encrypt, struct caamdmaobj *aad)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_jobctx jobctx = { };
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	init_descriptor(caam_ctx);
+
+	add_initial_context(caam_ctx);
+
+	AE_TRACE("Init operation");
+
+	/* Operation with the direction */
+	caam_desc_add_word(desc, CIPHER_INIT(caam_ctx->alg->type, encrypt));
+
+	if (!caam_ctx->ctx.data) {
+		retstatus = caam_alloc_align_buf(&caam_ctx->ctx,
+						 caam_ctx->alg->size_ctx);
+		if (retstatus)
+			return retstatus;
+	}
+
+	if (caam_ctx->nonce.data) {
+		if (!aad)
+			caam_desc_add_word(desc,
+					   FIFO_LD(CLASS_1, IV, LAST_C1,
+						   caam_ctx->nonce.length));
+		else
+			caam_desc_add_word(desc,
+					   FIFO_LD(CLASS_1, IV, FLUSH,
+						   caam_ctx->nonce.length));
+		caam_desc_add_ptr(desc, caam_ctx->nonce.paddr);
+
+		/* Ensure Nonce data are not in cache */
+		cache_operation(TEE_CACHECLEAN, caam_ctx->nonce.data,
+				caam_ctx->nonce.length);
+	}
+
+	if (aad) {
+		caam_desc_fifo_load(desc, aad, CLASS_1, AAD, LAST_C1);
+		caam_dmaobj_cache_push(aad);
+	} else if (!caam_ctx->nonce.data) {
+		/* Required for null aad (initialize nonce only) */
+		caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_1, AAD, LAST_C1, 0));
+	}
+
+	store_context(caam_ctx);
+
+	AE_DUMPDESC(desc);
+
+	jobctx.desc = desc;
+	retstatus = caam_jr_enqueue(&jobctx, NULL);
+	if (retstatus) {
+		AE_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32,
+			 retstatus, jobctx.status);
+		retstatus = CAAM_FAILURE;
+	}
+
+	/* Ensure Context register data are not in cache */
+	cache_operation(TEE_CACHEINVALIDATE, caam_ctx->ctx.data,
+			caam_ctx->ctx.length);
+
+	return retstatus;
+}
+
+/*
+ * Update cipher operation and generates a message authentication
+ * on the last update
+ *
+ * @caam_ctx AE Cipher context
+ * @savectx  Save or not the context
+ * @encrypt  Encrypt or decrypt direction
+ * @src      Source data to encrypt/decrypt
+ * @dst      [out] Destination data encrypted/decrypted
+ * @final    Final AES block flag
+ */
+static enum caam_status caam_ae_do_block(struct caam_ae_ctx *caam_ctx,
+					 bool savectx, bool encrypt,
+					 struct caamdmaobj *src,
+					 struct caamdmaobj *dst, bool final)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_jobctx jobctx = { };
+	uint32_t *desc = NULL;
+
+	assert(caam_ctx);
+
+	desc = caam_ctx->descriptor;
+
+	if (!caam_ctx->ctx.length)
+		return CAAM_NOT_INIT;
+
+	init_descriptor(caam_ctx);
+
+	load_context(caam_ctx);
+
+	if (!caam_ctx->do_block ||
+	    !caam_ctx->do_block(caam_ctx, encrypt, src, dst, final)) {
+		if (final)
+			caam_desc_add_word(desc,
+					   CIPHER_FINAL(caam_ctx->alg->type,
+							encrypt));
+		else
+			caam_desc_add_word(desc,
+					   CIPHER_UPDATE(caam_ctx->alg->type,
+							 encrypt));
+
+		/* Load the source data if any */
+		if (src) {
+			caam_desc_fifo_load(desc, src, CLASS_1, MSG, LAST_C1);
+			caam_dmaobj_cache_push(src);
+		} else {
+			/*
+			 * Add the input data of 0 bytes to start
+			 * algorithm by setting the input data size
+			 */
+			caam_desc_add_word(desc,
+					   FIFO_LD(CLASS_1, MSG, LAST_C1, 0));
+			caam_desc_add_ptr(desc, 0);
+		}
+
+		/* Store the output data if any */
+		if (dst) {
+			caam_desc_fifo_store(desc, dst, MSG_DATA);
+			caam_dmaobj_cache_push(dst);
+		}
+	}
+
+	if (savectx)
+		store_context(caam_ctx);
+
+	AE_DUMPDESC(desc);
+
+	jobctx.desc = desc;
+	retstatus = caam_jr_enqueue(&jobctx, NULL);
+	if (retstatus) {
+		AE_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32,
+			 retstatus, jobctx.status);
+		retstatus = CAAM_FAILURE;
+	}
+
+	/* Ensure Context register data are not in cache */
+	if (savectx)
+		cache_operation(TEE_CACHEINVALIDATE, caam_ctx->ctx.data,
+				caam_ctx->ctx.length);
+
+	return retstatus;
+}
+
+TEE_Result caam_ae_do_update(struct caam_ae_ctx *caam_ctx,
+			     struct drvcrypt_buf *src, struct drvcrypt_buf *dst,
+			     bool last)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caamdmaobj caam_src = { };
+	struct caamdmaobj caam_dst = { };
+	struct caamdmaobj caam_aad = { };
+	struct caamdmaobj *caam_aad_ptr = NULL;
+	struct caamblock trash_bck = { };
+	size_t full_size = 0;
+	size_t size_topost = 0;
+	size_t size_todo = 0;
+	size_t size_done = 0;
+	size_t size_inmade = 0;
+	size_t offset = 0;
+	bool do_init = false;
+
+	if (!caam_ctx || !src || !dst)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	AE_TRACE("Length=%zu - %s", src->length,
+		 caam_ctx->encrypt ? "Encrypt" : "Decrypt");
+
+	do_init = (caam_ctx->ctx.length == 0);
+
+	/*
+	 * According to the TEE API function TEE_AEUpdateAAD
+	 * Additional Authenticated data buffer could only be loaded
+	 * at Init state
+	 */
+	if (do_init && caam_ctx->buf_aad.filled) {
+		size_t aad_length = caam_ctx->buf_aad.filled;
+
+		ret = caam_dmaobj_init_input(&caam_aad,
+					     caam_ctx->buf_aad.buf.data,
+					     aad_length);
+		if (ret)
+			goto end_cipher;
+
+		ret = caam_dmaobj_prepare(&caam_aad, NULL, aad_length);
+		if (ret)
+			goto end_cipher;
+
+		ret = caam_dmaobj_sgtbuf_build(&caam_aad, &aad_length, 0,
+					       aad_length);
+		if (ret)
+			goto end_cipher;
+
+		if (aad_length != caam_ctx->buf_aad.filled) {
+			ret = TEE_ERROR_GENERIC;
+			goto end_cipher;
+		}
+
+		caam_aad_ptr = &caam_aad;
+	}
+
+	/*
+	 * Calculate the total data to be handled
+	 * which is data saved to complete the previous buffer
+	 * plus actual buffer length
+	 */
+	full_size = caam_ctx->blockbuf.filled + src->length;
+	if (!last) {
+		if (full_size < caam_ctx->alg->size_block) {
+			size_topost = src->length;
+			dst->length = 0;
+			goto end_cipher_post;
+		} else {
+			size_topost = full_size % caam_ctx->alg->size_block;
+			size_inmade = src->length - size_topost;
+			/* Total size that is a cipher block multiple */
+			size_todo = full_size - size_topost;
+		}
+	} else {
+		/* Last total size that is the remaining data */
+		size_todo = full_size;
+	}
+
+	AE_TRACE("FullSize %zu - posted %zu - todo %zu", full_size,
+		 size_topost, size_todo);
+
+	if (!size_todo) {
+		if (!last) {
+			ret = TEE_SUCCESS;
+			goto end_cipher_post;
+		} else if (do_init) {
+			retstatus = caam_ae_do_oneshot(caam_ctx,
+						       caam_ctx->encrypt, NULL,
+						       NULL, caam_aad_ptr);
+
+			ret = caam_status_to_tee_result(retstatus);
+
+			/* Nothing to post on last update operation */
+			goto end_cipher;
+		} else {
+			retstatus = caam_ae_do_block(caam_ctx, true,
+						     caam_ctx->encrypt, NULL,
+						     NULL, true);
+
+			ret = caam_status_to_tee_result(retstatus);
+
+			/* Nothing to post on last update operation */
+			goto end_cipher;
+		}
+	}
+
+	if (src->length) {
+		ret = caam_dmaobj_init_input(&caam_src, src->data, src->length);
+		if (ret)
+			goto end_cipher;
+	} else {
+		/* Init the buffer with saved data */
+		ret = caam_dmaobj_init_input(&caam_src,
+					     caam_ctx->blockbuf.buf.data,
+					     caam_ctx->blockbuf.filled);
+		if (ret)
+			goto end_cipher;
+
+		caam_ctx->blockbuf.filled = 0;
+	}
+
+	ret = caam_dmaobj_init_output(&caam_dst, dst->data, dst->length,
+				      size_todo);
+	if (ret)
+		goto end_cipher;
+
+	ret = caam_dmaobj_prepare(&caam_src, &caam_dst, size_todo);
+	if (ret)
+		goto end_cipher;
+
+	/* Check if there is some data saved to complete the buffer */
+	if (caam_ctx->blockbuf.filled) {
+		ret = caam_dmaobj_add_first_block(&caam_src,
+						  &caam_ctx->blockbuf);
+		if (ret)
+			goto end_cipher;
+
+		ret = caam_dmaobj_add_first_block(&caam_dst,
+						  &caam_ctx->blockbuf);
+		if (ret)
+			goto end_cipher;
+
+		caam_ctx->blockbuf.filled = 0;
+	}
+
+	if (do_init) {
+		retstatus = caam_ae_do_init(caam_ctx, caam_ctx->encrypt,
+					    caam_aad_ptr);
+
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto end_cipher;
+		}
+		do_init = false;
+	}
+
+	size_done = size_todo;
+	dst->length = 0;
+	for (offset = 0; size_todo;
+	     offset += size_done, size_todo -= size_done) {
+		AE_TRACE("Do input %zu bytes, offset %zu", size_done, offset);
+
+		ret = caam_dmaobj_sgtbuf_inout_build(&caam_src, &caam_dst,
+						     &size_done, offset,
+						     size_todo);
+		if (ret)
+			goto end_cipher;
+
+		/* is it last update and last block ? */
+		if (last && size_todo == size_done)
+			retstatus = caam_ae_do_block(caam_ctx, true,
+						     caam_ctx->encrypt,
+						     &caam_src, &caam_dst,
+						     true);
+		else
+			retstatus = caam_ae_do_block(caam_ctx, true,
+						     caam_ctx->encrypt,
+						     &caam_src, &caam_dst,
+						     false);
+
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto end_cipher;
+		}
+
+		dst->length += caam_dmaobj_copy_to_orig(&caam_dst);
+	}
+
+end_cipher_post:
+	if (size_topost) {
+		/*
+		 * Save the input data in the block buffer for next operation
+		 * and prepare the source DMA Object with the overall saved
+		 * data to generate destination bytes.
+		 */
+		struct caambuf cpysrc = { .data = src->data,
+					  .length = src->length };
+
+		caam_dmaobj_free(&caam_src);
+		caam_dmaobj_free(&caam_dst);
+		AE_TRACE("Save input data %zu bytes (done %zu) - off %zu",
+			 size_topost, size_inmade, offset);
+
+		size_todo = size_topost + caam_ctx->blockbuf.filled;
+
+		/*
+		 * Prepare the destination DMA Object:
+		 *  - Use given destination parameter bytes to return
+		 *  - If the previous operation saved data, use a trash
+		 *    buffer to do the operation but don't use unneeded data.
+		 */
+		ret = caam_dmaobj_init_output(&caam_dst,
+					      dst->data + size_inmade,
+					      size_topost, size_topost);
+		if (ret)
+			goto end_cipher;
+
+		ret = caam_dmaobj_prepare(NULL, &caam_dst,
+					  caam_ctx->alg->size_block);
+		if (ret)
+			goto end_cipher;
+
+		if (caam_ctx->blockbuf.filled) {
+			/*
+			 * Because there are some bytes to trash, use
+			 * a block buffer that will be added to the
+			 * destination SGT/Buffer structure to do the
+			 * cipher operation.
+			 */
+			ret = caam_alloc_align_buf(&trash_bck.buf,
+						   caam_ctx->blockbuf.filled);
+			if (ret != CAAM_NO_ERROR) {
+				AE_TRACE("Allocation Trash Block error");
+				goto end_cipher;
+			}
+			trash_bck.filled = caam_ctx->blockbuf.filled;
+
+			ret = caam_dmaobj_add_first_block(&caam_dst,
+							  &trash_bck);
+			if (ret)
+				goto end_cipher;
+		}
+
+		retstatus = caam_cpy_block_src(&caam_ctx->blockbuf, &cpysrc,
+					       size_inmade);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto end_cipher;
+		}
+
+		ret = caam_dmaobj_init_input(&caam_src,
+					     caam_ctx->blockbuf.buf.data,
+					     caam_ctx->blockbuf.filled);
+		if (ret)
+			goto end_cipher;
+
+		ret = caam_dmaobj_prepare(&caam_src, NULL,
+					  caam_ctx->alg->size_block);
+		if (ret)
+			goto end_cipher;
+
+		/*
+		 * Build input and output DMA Object with the same size.
+		 */
+		size_done = size_todo;
+		ret = caam_dmaobj_sgtbuf_inout_build(&caam_src, &caam_dst,
+						     &size_done, 0, size_todo);
+		if (ret)
+			goto end_cipher;
+
+		if (size_todo != size_done) {
+			AE_TRACE("Invalid end streaming size %zu vs %zu",
+				 size_done, size_todo);
+			ret = TEE_ERROR_GENERIC;
+			goto end_cipher;
+		}
+
+		if (do_init) {
+			retstatus = caam_ae_do_init(caam_ctx, caam_ctx->encrypt,
+						    caam_aad_ptr);
+
+			if (retstatus) {
+				ret = caam_status_to_tee_result(retstatus);
+				goto end_cipher;
+			}
+		}
+
+		retstatus = caam_ae_do_block(caam_ctx, false, caam_ctx->encrypt,
+					     &caam_src, &caam_dst, false);
+
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto end_cipher;
+		}
+
+		dst->length += caam_dmaobj_copy_to_orig(&caam_dst);
+
+		AE_DUMPBUF("Source", caam_ctx->blockbuf.buf.data,
+			   caam_ctx->blockbuf.filled);
+		AE_DUMPBUF("Result", dst->data + size_inmade, size_topost);
+	}
+
+	ret = TEE_SUCCESS;
+
+end_cipher:
+	caam_dmaobj_free(&caam_src);
+	caam_dmaobj_free(&caam_dst);
+	caam_dmaobj_free(&caam_aad);
+
+	/* Free Trash block buffer */
+	caam_free_buf(&trash_bck.buf);
+
+	return ret;
+}
+
+/*
+ * Initialize the authenticated encryption cipher module
+ *
+ * @ctrl_addr   Controller base address
+ */
+enum caam_status caam_ae_init(vaddr_t ctrl_addr __unused)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+
+	if (drvcrypt_register_authenc(&driver_ae) == TEE_SUCCESS)
+		retstatus = CAAM_NO_ERROR;
+
+	return retstatus;
+}
diff --git a/core/drivers/crypto/caam/ae/caam_ae_ccm.c b/core/drivers/crypto/caam/ae/caam_ae_ccm.c
new file mode 100644
index 0000000000000000000000000000000000000000..5c2bfbd0253d954a7233279e04a930b6c89d4dab
--- /dev/null
+++ b/core/drivers/crypto/caam/ae/caam_ae_ccm.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 NXP
+ *
+ * Implementation of Cipher CCM functions
+ */
+#include <caam_common.h>
+#include <caam_utils_mem.h>
+#include <caam_utils_status.h>
+#include <drvcrypt_math.h>
+#include <string.h>
+#include <string_ext.h>
+#include <utee_defines.h>
+
+#include "local.h"
+
+/* Length of AAD buffer size, as in SP800-38C */
+#define AAD_SIZE_LEN 2
+
+/* Nonce length */
+#define AES_CCM_MAX_NONCE_LEN 15
+
+/* Tag length */
+#define AES_CCM_MIN_TAG_LEN 4
+#define AES_CCM_MAX_TAG_LEN 16
+
+/* Adata Flag */
+#define BM_B0_ADATA_PRESENCE BIT32(6)
+
+/* B0 Tag length */
+#define BS_B0_TAG_LENGTH 3
+#define BM_B0_TAG_LENGTH SHIFT_U32(0x7, BS_B0_TAG_LENGTH)
+#define B0_TAG_LENGTH(x) \
+	(SHIFT_U32(((x) - 2) / 2, BS_B0_TAG_LENGTH) & BM_B0_TAG_LENGTH)
+
+/* B0 Payload size length */
+#define BS_B0_Q_LENGTH 0
+#define BM_B0_Q_LENGTH SHIFT_U32(0x7, BS_B0_Q_LENGTH)
+#define B0_Q_LENGTH(x) (SHIFT_U32((x) - 1, BS_B0_Q_LENGTH) & BM_B0_Q_LENGTH)
+
+/*
+ * Initialize AES CCM operation context
+ *
+ * @caam_ctx AE Cipher context
+ * @dinit    Data initialization object
+ */
+static TEE_Result caam_ae_ccm_init_ctx(struct caam_ae_ctx *caam_ctx,
+				       struct drvcrypt_authenc_init *dinit)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caambuf aad = { };
+	uint8_t *b0 = NULL;
+	uint8_t *ctr0 = NULL;
+	size_t q = 0;
+	size_t payload_len = 0;
+	size_t i = 0;
+
+	assert(caam_ctx && dinit);
+
+	if (dinit->nonce.length > AES_CCM_MAX_NONCE_LEN)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/* The tag_len should be 4, 6, 8, 10, 12, 14 or 16 */
+	if (caam_ctx->tag_length < 4 || caam_ctx->tag_length > 16 ||
+	    caam_ctx->tag_length % 2 != 0)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	payload_len = caam_ctx->payload_length;
+
+	/*
+	 * Before AE operations CAAM ctx register
+	 * must be filled with B0 and Ctr0.
+	 */
+	b0 = caam_ctx->initial_ctx.data;
+	ctr0 = caam_ctx->initial_ctx.data + TEE_AES_BLOCK_SIZE;
+
+	/*
+	 * Set B0 initial value
+	 * B0 initial value (specification SP 800-38C) contains flags,
+	 * data length (Whole operation length in case of init update final)
+	 * and nonce
+	 */
+	memset(b0, 0, TEE_AES_BLOCK_SIZE);
+
+	/* Available length for the data size length field */
+	q = AES_CCM_MAX_NONCE_LEN - dinit->nonce.length;
+
+	/* Flags value in b0[0] */
+	b0[0] = B0_TAG_LENGTH(caam_ctx->tag_length) | B0_Q_LENGTH(q);
+	if (caam_ctx->aad_length)
+		b0[0] |= BM_B0_ADATA_PRESENCE;
+
+	/* Nonce value in b0[1..AES_CCM_MAX_NONCE_LEN] */
+	memcpy(&b0[1], dinit->nonce.data, dinit->nonce.length);
+
+	/*
+	 * Payload length as defined in SP800-38C,
+	 * A.2.1 Formatting of the Control Information and the Nonce
+	 * Payload length (i.e. Q) is store in big-endian fashion.
+	 */
+	for (i = AES_CCM_MAX_NONCE_LEN; i >= dinit->nonce.length + 1; i--) {
+		b0[i] = payload_len & 0xFF;
+		payload_len >>= 8;
+	}
+
+	/* Add AAD size to Adata */
+	if (caam_ctx->aad_length > 0) {
+		if (caam_ctx->aad_length >= AAD_LENGTH_OVERFLOW)
+			return TEE_ERROR_NOT_SUPPORTED;
+
+		retstatus = caam_calloc_align_buf(&aad, AAD_SIZE_LEN);
+		if (retstatus)
+			return caam_status_to_tee_result(retstatus);
+
+		aad.data[0] = (caam_ctx->aad_length & GENMASK_32(15, 8)) >> 8;
+		aad.data[1] = caam_ctx->aad_length & GENMASK_32(7, 0);
+		retstatus = caam_cpy_block_src(&caam_ctx->buf_aad, &aad, 0);
+		if (retstatus) {
+			ret = caam_status_to_tee_result(retstatus);
+			goto out;
+		}
+	}
+
+	/*
+	 * Set CTR0 initial value
+	 * Ctr0 initial value (specification SP 800-38C) contains flags
+	 * and nonce
+	 */
+	memset(ctr0, 0, TEE_AES_BLOCK_SIZE);
+
+	/* Flags value in ctr0[0] */
+	ctr0[0] = B0_Q_LENGTH(q);
+
+	/* Nonce value in ctr0[1..AES_CCM_MAX_NONCE_LEN] */
+	memcpy(&ctr0[1], &b0[1], dinit->nonce.length);
+
+	ret = TEE_SUCCESS;
+out:
+	caam_free_buf(&aad);
+	return ret;
+}
+
+TEE_Result caam_ae_initialize_ccm(struct drvcrypt_authenc_init *dinit)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_ae_ctx *caam_ctx = NULL;
+
+	if (!dinit || !dinit->ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	caam_ctx = dinit->ctx;
+
+	if (caam_ctx->tag_length < AES_CCM_MIN_TAG_LEN ||
+	    caam_ctx->tag_length > AES_CCM_MAX_TAG_LEN)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	/* Allocate initial B0 and CTR0 input */
+	retstatus = caam_alloc_align_buf(&caam_ctx->initial_ctx,
+					 caam_ctx->alg->size_ctx);
+	if (retstatus)
+		return caam_status_to_tee_result(retstatus);
+
+	/* Initialize the AAD buffer */
+	caam_ctx->buf_aad.max = dinit->aad_len + AAD_SIZE_LEN;
+
+	ret = caam_ae_ccm_init_ctx(caam_ctx, dinit);
+	if (ret)
+		goto err;
+
+	return TEE_SUCCESS;
+err:
+	caam_free_buf(&caam_ctx->initial_ctx);
+
+	return ret;
+}
+
+TEE_Result caam_ae_final_ccm(struct drvcrypt_authenc_final *dfinal)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	struct caam_ae_ctx *caam_ctx = NULL;
+	uint8_t *encrypted_tag = NULL;
+	struct drvcrypt_mod_op mod_op = { };
+
+	if (!dfinal || !dfinal->ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	caam_ctx = dfinal->ctx;
+
+	ret = caam_ae_do_update(caam_ctx, &dfinal->src, &dfinal->dst, true);
+	if (ret)
+		return ret;
+
+	if (caam_ctx->tag_length) {
+		if (dfinal->tag.length < caam_ctx->tag_length)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		if (caam_ctx->encrypt) {
+			encrypted_tag = caam_ctx->ctx.data +
+					(2 * AES_CCM_MAX_TAG_LEN);
+
+			memcpy(dfinal->tag.data, encrypted_tag,
+			       caam_ctx->tag_length);
+			dfinal->tag.length = caam_ctx->tag_length;
+		} else {
+			encrypted_tag = caam_ctx->ctx.data;
+
+			mod_op.n.length = caam_ctx->tag_length;
+			mod_op.a.data = encrypted_tag;
+			mod_op.a.length = caam_ctx->tag_length;
+			mod_op.b.data = encrypted_tag +
+					2 * AES_CCM_MAX_TAG_LEN;
+			mod_op.b.length = caam_ctx->tag_length;
+			mod_op.result.data = encrypted_tag;
+			mod_op.result.length = caam_ctx->tag_length;
+
+			ret = drvcrypt_xor_mod_n(&mod_op);
+			if (ret)
+				return ret;
+
+			if (consttime_memcmp(dfinal->tag.data, encrypted_tag,
+					     caam_ctx->tag_length))
+				return TEE_ERROR_MAC_INVALID;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
diff --git a/core/drivers/crypto/caam/ae/caam_ae_gcm.c b/core/drivers/crypto/caam/ae/caam_ae_gcm.c
new file mode 100644
index 0000000000000000000000000000000000000000..78171aaf0d1559c06f9a25bb18c4f6a3028111e0
--- /dev/null
+++ b/core/drivers/crypto/caam/ae/caam_ae_gcm.c
@@ -0,0 +1,354 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 NXP
+ *
+ * Implementation of Cipher GCM functions
+ */
+#include <caam_common.h>
+#include <caam_desc_ccb_defines.h>
+#include <caam_utils_mem.h>
+#include <caam_utils_status.h>
+#include <stdint.h>
+#include <string.h>
+#include <string_ext.h>
+#include <utee_defines.h>
+
+#include "local.h"
+
+/*
+ * Default GCM nonce length
+ * CAAM Errata fix is used if nonce size is not the default one
+ */
+#define AES_GCM_DEFAULT_NONCE_LEN 12
+
+/*
+ * Context format in GCM mode
+ */
+struct gcm_caam_ctx_layout {
+	/*
+	 * 128 bits MAC value
+	 */
+	uint32_t mac[4];
+	/*
+	 * 128 bits Ctri value
+	 */
+	uint32_t yi[4];
+	/*
+	 * 128 bits Ctr0 value
+	 */
+	uint32_t y0[4];
+};
+
+/*
+ * Update of the cipher operation of complete block except
+ * last block. Last block can be partial block.
+ *
+ * @caam_ctx AE Cipher context
+ * @encrypt  Encrypt or decrypt direction
+ * @src      Source data to encrypt/decrypt
+ * @dst      [out] Destination data encrypted/decrypted
+ * @final    Last block flag
+ */
+static bool caam_ae_do_block_gcm(struct caam_ae_ctx *caam_ctx, bool encrypt,
+				 struct caamdmaobj *src, struct caamdmaobj *dst,
+				 bool final)
+{
+	/*
+	 * CAAM Errata:
+	 * When running GCM when the IV is not 12 bytes (96 bits),
+	 * it is possible to "roll over" the 32-bit counter value.
+	 * When this occurs (unless counter starts at -1),
+	 * the AES operation will generate an incorrect MAC.
+	 * This occurs even when -1 is used as the counter for the last block.
+	 * The problem is that the 32-bit counter will overflow into the h
+	 *  value, thus corrupting the MAC.
+	 * In order to reliably work around this issue,
+	 * the AES operation must be stopped after initialization to
+	 * determine the counter value to see whether/when it will roll over.
+	 * Then, before the offending block is processed,
+	 * the context needs to be saved. The one block gets processed twice :
+	 * GCM, restore MAC, GMAC over its ciphertext,
+	 * then patch up the message and AAD lengths, and carry on as normal.
+	 */
+	uint32_t *desc = NULL;
+	struct gcm_caam_ctx_layout ctx = { };
+	size_t input_length = 0;
+	uint32_t processed_blocks = 0;
+	uint32_t counter_value = 0;
+	uint32_t corrupted_block_size = 0;
+	uint32_t yi_1s_complement = 0;
+	uint32_t remaining_len = 0;
+
+	if (!caam_ctx)
+		return false;
+
+	desc = caam_ctx->descriptor;
+
+	/*
+	 *  for encrypt:
+	 *  1) Run GCM until we get to the block which will
+	 *     roll over the counter.
+	 *  2) Save the current ghash value
+	 *  3) Encrypt that one block (creating a bad hash value)
+	 *  4) Restore the hash value
+	 *  5) Save current AAD len
+	 *  6) Run ciphertext of the block in as AAD
+	 *  7) Restore the AAD len
+	 *  8) Run GCM on the rest of the message
+	 *  9) Compute and store the MAC/tag
+	 *
+	 *  for decrypt:
+	 *  1) Run GCM until we get to the block which will
+	 *     roll over the counter.
+	 *  2) Save the current ghash value
+	 *  3) Decrypt that one block (creating a bad hash value)
+	 *  4) Restore the hash value
+	 *  5) Save current AAD len
+	 *  6) Run ciphertext of the block in as AAD
+	 *  7) Restore the AAD len
+	 *  8) Run GCM on the rest of the message
+	 *  9) Compute and store the MAC/tag
+	 */
+
+	if (!src || src->orig.length == 0 ||
+	    caam_ctx->nonce.length == AES_GCM_DEFAULT_NONCE_LEN)
+		return false;
+
+	memcpy(&ctx, caam_ctx->ctx.data, sizeof(struct gcm_caam_ctx_layout));
+	processed_blocks = TEE_U32_FROM_BIG_ENDIAN(ctx.yi[3]);
+	input_length = src->orig.length;
+	counter_value = processed_blocks + ROUNDUP_DIV(input_length, 16);
+
+	/* check for overflow */
+	if (counter_value >= processed_blocks)
+		return false;
+
+	assert(dst);
+
+	yi_1s_complement = SHIFT_U32(UINT32_MAX - processed_blocks, 4);
+	if ((yi_1s_complement + TEE_AES_BLOCK_SIZE) > input_length)
+		corrupted_block_size = input_length - yi_1s_complement;
+	else
+		corrupted_block_size = TEE_AES_BLOCK_SIZE;
+	remaining_len = input_length - (yi_1s_complement +
+			corrupted_block_size);
+
+	caam_desc_seq_out(desc, dst);
+	caam_dmaobj_cache_push(dst);
+
+	caam_desc_seq_in(desc, src);
+	caam_dmaobj_cache_push(src);
+
+	/* operation: cls1-op aes gcm update enc/dec */
+	caam_desc_add_word(desc, CIPHER_UPDATE(caam_ctx->alg->type, encrypt));
+
+	caam_desc_add_word(desc, FIFO_LD_SEQ(MSG, 0) | FIFO_STORE_EXT |
+			   CMD_CLASS(CLASS_1) |
+			   FIFO_LOAD_ACTION(LAST_C1));
+	caam_desc_add_word(desc, yi_1s_complement);
+
+	caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0) | FIFO_STORE_EXT);
+	caam_desc_add_word(desc, yi_1s_complement);
+
+	/* jump: class1-done all-match[] always-jump offset=[01] local->[15] */
+	caam_desc_add_word(desc,
+			   JUMP_C1_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 1));
+
+	/*
+	 * move: class1-ctx+0 -> math2, len=TEE_AES_BLOCK_SIZE wait
+	 * Save the current ghash value
+	 */
+	caam_desc_add_word(desc, MOVE_WAIT(C1_CTX_REG, MATH_REG2, 0,
+					   TEE_AES_BLOCK_SIZE));
+
+	/*
+	 * ld: ind-clrw len=4 offs=0 imm
+	 *     clrw: clr_c1mode clr_c1datas reset_cls1_done reset_cls1_cha
+	 *	     clr_c2_ctx
+	 */
+	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4));
+	caam_desc_add_word(desc, CLR_WR_RST_C1_MDE | CLR_WR_RST_C1_DSZ |
+				 CLR_WR_RST_C1_CHA | CLR_WR_RST_C1_DNE |
+				 CLR_WR_RST_C2_CTX);
+
+	/*
+	 * Encrypt that one block (creating a bad hash value)
+	 * operation: cls1-op aes gcm update enc/dec
+	 */
+	caam_desc_add_word(desc, CIPHER_UPDATE(caam_ctx->alg->type, encrypt));
+
+	if (encrypt) {
+		/* seqfifold: class1 msg-last1 len=corrupted_Block_Size */
+		caam_desc_add_word(desc,
+				   FIFO_LD_SEQ(MSG, corrupted_block_size) |
+				   CMD_CLASS(CLASS_1) |
+				   FIFO_LOAD_ACTION(LAST_C1));
+
+		/* move: ofifo -> class2-ctx+0, len=corrupted_Block_Size wait */
+		caam_desc_add_word(desc, MOVE_WAIT(OFIFO, C2_CTX_REG, 0,
+						   corrupted_block_size));
+
+		/* seqstr: ccb2 ctx len=vseqoutsz offs=0 */
+		caam_desc_add_word(desc, ST_NOIMM_SEQ(CLASS_2, REG_CTX,
+						      corrupted_block_size));
+	} else {
+		/* seqfifold: both msg-last2-last1 len=corrupted_Block_Size */
+		caam_desc_add_word(desc,
+				   FIFO_LD_SEQ(MSG, corrupted_block_size) |
+				   CMD_CLASS(CLASS_DECO) |
+				   FIFO_LOAD_ACTION(LAST_C1) |
+				   FIFO_LOAD_ACTION(LAST_C2));
+
+		/*
+		 * move: class2-alnblk -> class2-ctx+0,
+		 *	 len=corrupted_Block_Size (aux_ms)
+		 */
+		caam_desc_add_word(desc, MOVE(DECO_ALIGN, C2_CTX_REG, 0,
+					      corrupted_block_size) |
+					 MOVE_AUX(0x2));
+
+		/* seqfifostr: msg len=vseqoutsz */
+		caam_desc_add_word(desc,
+				   FIFO_ST_SEQ(MSG_DATA, corrupted_block_size));
+	}
+
+	/* jump: class1-done all-match[] always-jump offset=[01] local->[23] */
+	caam_desc_add_word(desc,
+			   JUMP_C1_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 1));
+
+	/*
+	 * Restore the hash value
+	 * move: math2 -> class1-ctx+0, len=TEE_AES_BLOCK_SIZE wait
+	 */
+	caam_desc_add_word(desc, MOVE_WAIT(MATH_REG2, C1_CTX_REG, 0,
+					   TEE_AES_BLOCK_SIZE));
+
+	/*
+	 * ld: ind-clrw len=4 offs=0 imm
+	 *     clrw: clr_c1mode clr_c1datas reset_cls1_done reset_cls1_cha
+	 */
+	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4));
+	caam_desc_add_word(desc, CLR_WR_RST_C1_MDE | CLR_WR_RST_C1_DSZ |
+				 CLR_WR_RST_C1_CHA | CLR_WR_RST_C1_DNE);
+
+	/*
+	 * Save current AAD len
+	 * move: class1-ctx+48 -> math2, len=8 wait
+	 */
+	caam_desc_add_word(desc, MOVE_WAIT(C1_CTX_REG, MATH_REG2, 48, 8));
+
+	/*
+	 * Run ciphertext of the block in as AAD
+	 * move: class2-ctx+0 -> ififo, len=corrupted_Block_Size
+	 */
+	caam_desc_add_word(desc,
+			   MOVE(C2_CTX_REG, IFIFO, 0, corrupted_block_size));
+
+	/*
+	 * ld: ind-nfsl len=4 offs=0 imm
+	 * <nfifo_entry: ififo->class1 type=aad/pka1 lc1 len=16>
+	 */
+	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_NFIFO_n_SIZE,
+					sizeof(uint32_t)));
+	caam_desc_add_word(desc, NFIFO_NOPAD(C1, NFIFO_LC1, IFIFO, AAD,
+					     corrupted_block_size));
+
+	/* operation: cls1-op aes gcm update enc/dec */
+	caam_desc_add_word(desc, CIPHER_UPDATE(caam_ctx->alg->type, encrypt));
+
+	/* jump: class1-done all-match[] always-jump offset=[01] local->[32] */
+	caam_desc_add_word(desc,
+			   JUMP_C1_LOCAL(ALL_COND_TRUE, JMP_COND(NONE), 1));
+
+	/*
+	 * Restore the AAD len
+	 * move: math2 -> class1-ctx+48, len=8 wait
+	 */
+	caam_desc_add_word(desc, MOVE_WAIT(MATH_REG2, C1_CTX_REG, 48, 8));
+
+	/*
+	 * Run GCM on the rest of the message
+	 * ld: ind-clrw len=4 offs=0 imm
+	 *     clrw: clr_c1mode clr_c1datas reset_cls1_done reset_cls1_cha
+	 */
+	caam_desc_add_word(desc, LD_IMM(CLASS_NO, REG_CLEAR_WRITTEN, 4));
+	caam_desc_add_word(desc, CLR_WR_RST_C1_MDE | CLR_WR_RST_C1_DSZ |
+				 CLR_WR_RST_C1_CHA | CLR_WR_RST_C1_DNE);
+
+	if (final)
+		caam_desc_add_word(desc,
+				   CIPHER_FINAL(caam_ctx->alg->type, encrypt));
+	else
+		caam_desc_add_word(desc,
+				   CIPHER_UPDATE(caam_ctx->alg->type, encrypt));
+
+	/* ptr incremented by max. 7 */
+	caam_desc_add_word(desc, FIFO_LD_SEQ(MSG, 0) | FIFO_STORE_EXT |
+				 CMD_CLASS(CLASS_1) |
+				 FIFO_LOAD_ACTION(LAST_C1));
+	caam_desc_add_word(desc, remaining_len);
+
+	caam_desc_add_word(desc, FIFO_ST_SEQ(MSG_DATA, 0) | FIFO_STORE_EXT);
+	caam_desc_add_word(desc, remaining_len);
+
+	return true;
+}
+
+TEE_Result caam_ae_initialize_gcm(struct drvcrypt_authenc_init *dinit)
+{
+	enum caam_status retstatus = CAAM_FAILURE;
+	struct caam_ae_ctx *caam_ctx = NULL;
+
+	if (!dinit || !dinit->ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	caam_ctx = dinit->ctx;
+
+	if (dinit->nonce.data && dinit->nonce.length) {
+		retstatus = caam_cpy_buf(&caam_ctx->nonce, dinit->nonce.data,
+					 dinit->nonce.length);
+		AE_TRACE("Copy Nonce returned 0x%" PRIx32, retstatus);
+		if (retstatus)
+			return caam_status_to_tee_result(retstatus);
+	}
+
+	caam_ctx->do_block = caam_ae_do_block_gcm;
+
+	/* Initialize the AAD buffer */
+	caam_ctx->buf_aad.max = dinit->aad_len;
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result caam_ae_final_gcm(struct drvcrypt_authenc_final *dfinal)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	struct caam_ae_ctx *caam_ctx = NULL;
+
+	if (!dfinal)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	caam_ctx = dfinal->ctx;
+
+	ret = caam_ae_do_update(caam_ctx, &dfinal->src, &dfinal->dst, true);
+	if (ret)
+		return ret;
+
+	if (caam_ctx->tag_length) {
+		if (dfinal->tag.length < caam_ctx->tag_length)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		if (caam_ctx->encrypt) {
+			memcpy(dfinal->tag.data, caam_ctx->ctx.data,
+			       caam_ctx->tag_length);
+			dfinal->tag.length = caam_ctx->tag_length;
+		} else {
+			if (consttime_memcmp(dfinal->tag.data,
+					     caam_ctx->ctx.data,
+					     caam_ctx->tag_length))
+				return TEE_ERROR_MAC_INVALID;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
diff --git a/core/drivers/crypto/caam/ae/local.h b/core/drivers/crypto/caam/ae/local.h
new file mode 100644
index 0000000000000000000000000000000000000000..fced6bf0e91bab1baa9f7d8184a976a31a7c41f9
--- /dev/null
+++ b/core/drivers/crypto/caam/ae/local.h
@@ -0,0 +1,116 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2024 NXP
+ */
+#ifndef __LOCAL_H__
+#define __LOCAL_H__
+
+#include <caam_utils_dmaobj.h>
+#include <drvcrypt.h>
+#include <drvcrypt_authenc.h>
+
+/* Maximum AAD size */
+#define AAD_LENGTH_OVERFLOW 0xFF00
+
+/*
+ * Cipher Algorithm definition
+ * @type:		Algo type for operation
+ * @size_block:		Computing block size
+ * @size_ctx:		CAAM Context Register size
+ * @ctx_offset:		CAAM Context Register offset
+ * @def_key:		Define accepted key size
+ * @initialize:		Initialize function
+ * @final:		Final function
+ */
+struct cipheralg {
+	uint32_t type;
+	uint8_t size_block;
+	uint8_t size_ctx;
+	uint8_t ctx_offset;
+	struct caamdefkey def_key;
+
+	TEE_Result (*initialize)(struct drvcrypt_authenc_init *dinit);
+	TEE_Result (*final)(struct drvcrypt_authenc_final *dfinal);
+};
+
+/*
+ * CAAM Authenticated Encryption Context
+ *
+ * @descriptor:		Job descriptor
+ * @tag_length:		Hash tag length
+ * @aad_length:		Additional data length
+ * @payload_length:	Data length
+ * @encrypt:		Encrypt direction
+ * @key:		Cipher key
+ * @initial_ctx:	Initial CCM context
+ * @ctx:		Saved context for multi-part update
+ * @nonce:		Initial GCM Nonce value
+ * @buf_add:		Additional Data buffer if needed
+ * @blockbuf:		Temporary Block buffer
+ * @do_block:		Block Encryption operation function
+ * @alg:		Reference to the algo constants
+ */
+struct caam_ae_ctx {
+	uint32_t *descriptor;
+
+	size_t tag_length;
+	size_t aad_length;
+	size_t payload_length;
+
+	bool encrypt;
+
+	struct caambuf key;
+	struct caambuf initial_ctx;
+	struct caambuf ctx;
+	struct caambuf nonce;
+
+	struct caamblock buf_aad;
+	struct caamblock blockbuf;
+
+	bool (*do_block)(struct caam_ae_ctx *caam_ctx, bool encrypt,
+			 struct caamdmaobj *src, struct caamdmaobj *dst,
+			 bool final);
+
+	const struct cipheralg *alg;
+};
+
+/*
+ * Update of the Authenticated Encryption Operation.
+ *
+ * @ctx      AE Cipher context
+ * @src      Source data to encrypt/decrypt
+ * @dst      [out] Destination data encrypted/decrypted
+ * @last     Last update flag
+ */
+TEE_Result caam_ae_do_update(struct caam_ae_ctx *ctx, struct drvcrypt_buf *src,
+			     struct drvcrypt_buf *dst, bool last);
+
+/*
+ * Initialization of the AES GCM operation
+ *
+ * @dinit  Data initialization object
+ */
+TEE_Result caam_ae_initialize_gcm(struct drvcrypt_authenc_init *dinit);
+
+/*
+ * Finalize the AES GCM operation
+ *
+ * @dfinal  Last data object
+ */
+TEE_Result caam_ae_final_gcm(struct drvcrypt_authenc_final *dfinal);
+
+/*
+ * Initialization of the AES CCM operation
+ *
+ * @dinit  Data initialization object
+ */
+TEE_Result caam_ae_initialize_ccm(struct drvcrypt_authenc_init *dinit);
+
+/*
+ * Finalize the AES CCM operation
+ *
+ * @dfinal  Last data object
+ */
+TEE_Result caam_ae_final_ccm(struct drvcrypt_authenc_final *dfinal);
+
+#endif /* __LOCAL_H__ */
diff --git a/core/drivers/crypto/caam/ae/sub.mk b/core/drivers/crypto/caam/ae/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..4e505191afc79a86fd8bb7edfd1f60f9692e07c4
--- /dev/null
+++ b/core/drivers/crypto/caam/ae/sub.mk
@@ -0,0 +1,5 @@
+incdirs-y += ../include
+
+srcs-y += caam_ae.c
+srcs-$(CFG_NXP_CAAM_AE_GCM_DRV) += caam_ae_gcm.c
+srcs-$(CFG_NXP_CAAM_AE_CCM_DRV) += caam_ae_ccm.c
diff --git a/core/drivers/crypto/caam/caam_ctrl.c b/core/drivers/crypto/caam/caam_ctrl.c
index 4dc07f6c73de99244815498639e014345d14a03a..51df78b24d8346c5c8b60fc2df3d95e243729f9b 100644
--- a/core/drivers/crypto/caam/caam_ctrl.c
+++ b/core/drivers/crypto/caam/caam_ctrl.c
@@ -1,18 +1,20 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2017-2021 NXP
+ * Copyright 2017-2021, 2023 NXP
  *
  * Brief   CAAM Global Controller.
  */
 #include <assert.h>
 #include <caam_acipher.h>
 #include <caam_cipher.h>
+#include <caam_ae.h>
 #include <caam_common.h>
 #include <caam_hal_cfg.h>
 #include <caam_hal_clk.h>
 #include <caam_hal_ctrl.h>
 #include <caam_hash.h>
 #include <caam_jr.h>
+#include <caam_key.h>
 #include <caam_blob.h>
 #include <caam_mp.h>
 #include <caam_pwr.h>
@@ -99,6 +101,13 @@ static TEE_Result crypto_driver_init(void)
 		goto exit_init;
 	}
 
+	/* Initialize the Authenticated Encryption Module */
+	retstatus = caam_ae_init(jrcfg.base);
+	if (retstatus != CAAM_NO_ERROR) {
+		retresult = TEE_ERROR_GENERIC;
+		goto exit_init;
+	}
+
 	/* Initialize the HMAC Module */
 	retstatus = caam_hmac_init(&jrcfg);
 	if (retstatus != CAAM_NO_ERROR) {
@@ -155,6 +164,13 @@ static TEE_Result crypto_driver_init(void)
 		goto exit_init;
 	}
 
+	/* Initialize the KEY Module */
+	retstatus = caam_key_init();
+	if (retstatus != CAAM_NO_ERROR) {
+		retresult = TEE_ERROR_GENERIC;
+		goto exit_init;
+	}
+
 	/* Everything is OK, register the Power Management handler */
 	caam_pwr_init();
 
diff --git a/core/drivers/crypto/caam/caam_desc.c b/core/drivers/crypto/caam/caam_desc.c
index 361e1aa10ff05e298c54fb51deae241a152a22dd..43f070a179d6340484e655cbdaf85f23fb336e3a 100644
--- a/core/drivers/crypto/caam/caam_desc.c
+++ b/core/drivers/crypto/caam/caam_desc.c
@@ -142,6 +142,7 @@ void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data,
 		op_length = KEY_LENGTH(data->sgtbuf.length);
 		break;
 
+	case CMD_SEQ_IN_TYPE:
 	case CMD_SEQ_OUT_TYPE:
 		op_length = SEQ_LENGTH(data->sgtbuf.length);
 		op_ext_length = SEQ_EXT;
diff --git a/core/drivers/crypto/caam/caam_key.c b/core/drivers/crypto/caam/caam_key.c
new file mode 100644
index 0000000000000000000000000000000000000000..835ad32e1b1c9eee430a2a746c2f704afa7d7e54
--- /dev/null
+++ b/core/drivers/crypto/caam/caam_key.c
@@ -0,0 +1,761 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2023-2024 NXP
+ */
+#include <assert.h>
+#include <caam_desc_helper.h>
+#include <caam_key.h>
+#include <caam_status.h>
+#include <caam_trace.h>
+#include <caam_utils_mem.h>
+#include <crypto/crypto.h>
+#include <kernel/panic.h>
+#include <mm/core_memprot.h>
+#include <stdint.h>
+#include <string.h>
+#include <tee/cache.h>
+#include <tee_api_defines.h>
+#include <trace.h>
+#include <utee_types.h>
+
+/*
+ * CAAM Key magic number.
+ * When the first 32 bits of a key buffer are equal to this value, the buffer
+ * is a serialized CAAM key structure.
+ */
+#define MAGIC_NUMBER 0xCAAFBFFB
+
+/*
+ * Because the CAAM driver relies on this magic number to determine if the key
+ * is plain text or black, collision can happen. A randomly generated plain text
+ * key could feature the magic number. That's unlikely but still possible.
+ *
+ * Regarding the possibility of collision or forging attack, there are no
+ * security concerns. Forging and trying to make a plain text key look like a
+ * black key, won't do much. If the key is forged to look like an ECB Black
+ * key, the singing operation will output a corrupted result. If the key is
+ * forged to look like a CCM Black key, the import key will fail (because the
+ * MAC verification) and no signing operation will be done.
+ */
+
+#define BLOB_BKEK_SIZE	     32 /* Blob key encryption key size */
+#define BLOB_MAC_SIZE	     16 /* Blob MAC size */
+#define BLOB_PAD_SIZE	     (BLOB_BKEK_SIZE + BLOB_MAC_SIZE)
+
+/*
+ * CAAM Blob key modifier
+ * Key modifier used to derive Blob-key encryption key (BKEK) from the CAAM
+ * master key.
+ *
+ * A CAAM black key is encrypted using a volatile Job Descriptor key encryption
+ * key or JDKEK. Black keys are not intended for storage of keys across SoC
+ * power cycles. The JDKEK is re-generated upon every power cycle (reset,
+ * suspend/resume ...) or CAAM RNG re-seed.
+ *
+ * To retain key across power cycles, the black key must be encapsulated as a
+ * blob. The blob key encryption key is derived from the CAAM master key which
+ * makes it non-volatile and can be re-created when the chip powers up again.
+ */
+#define KEY_BLOB_MODIFIER_SIZE 16
+#define KEY_BLOB_MODIFIER "NXP_KEY_MODIFIER"
+static_assert(sizeof(KEY_BLOB_MODIFIER) >= KEY_BLOB_MODIFIER_SIZE);
+static uint8_t *key_blob_modifier;
+
+/*
+ * Serialized CAAM key structure format.
+ *
+ * If the incoming key buffer is the following:
+ *	| Magic number | key type | key size | key blob buffer |
+ * The CAAM Key structure will be populated as following:
+ * struct caamkey {
+ *	.key_type = key type,
+ *	.key_size = key size,
+ *	.is_blob = true,
+ *	.buf = key blob buffer
+ * }
+ *
+ * If the incoming key buffer is the following:
+ *	| Key buffer |
+ * The CAAM Key structure will be populated as following:
+ * struct caamkey {
+ *	.key_type = CAAM_KEY_PLAIN_TEXT,
+ *	.key_size = sizeof(Key buffer),
+ *	.is_blob = false,
+ *	.buf = key buffer
+ * }
+ */
+struct caam_key_serialized {
+	uint32_t magic_number; /* Magic number */
+	uint32_t key_type; /* Black key type */
+	uint32_t sec_size; /* The original plain text key size */
+	uint8_t key[];
+};
+
+/*
+ * CAAM key type enumeration to string
+ */
+static const char *const caam_key_type_to_str[] __maybe_unused = {
+	[CAAM_KEY_PLAIN_TEXT] = "Plain Text",
+	[CAAM_KEY_BLACK_ECB] = "Black ECB",
+	[CAAM_KEY_BLACK_CCM] = "Black CCM",
+};
+
+static struct caam_key_serialized *data_to_serialized_key(const uint8_t *data,
+							  size_t size)
+{
+	assert(data && size);
+	assert(size > sizeof(struct caam_key_serialized));
+
+	/*
+	 * It's important to make sure uint8_t and caam_key_serialized{} are
+	 * actually aligned for performance purpose.
+	 *
+	 * A __packed attribute to caam_key_serialized{} could solve the
+	 * alignment issue but at the cost of un-optimize memory access.
+	 * To avoid using the __packed attribute, caam_key_serialized{} is
+	 * defined to be aligned on uint8_t. The following assert checks
+	 * for this alignment.
+	 */
+	assert(IS_ALIGNED_WITH_TYPE(data, struct caam_key_serialized));
+
+	/*
+	 * The cast to void* instead of struct caam_key_serialized* is needed
+	 * to avoid the cast alignment compilation warning.
+	 */
+	return (void *)data;
+}
+
+/*
+ * Return the CAAM key type of the given key buffer
+ *
+ * @data	Input buffer
+ * @size	Input buffer size
+ */
+static enum caam_key_type get_key_type(const uint8_t *data, size_t size)
+{
+	struct caam_key_serialized *key = data_to_serialized_key(data, size);
+
+	if (key->magic_number != MAGIC_NUMBER)
+		return CAAM_KEY_PLAIN_TEXT;
+
+	return key->key_type;
+}
+
+/*
+ * Return the CAAM key size of the given key buffer
+ *
+ * @data	Input buffer
+ * @size	Input buffer size
+ */
+static size_t get_key_sec_size(const uint8_t *data, size_t size)
+{
+	struct caam_key_serialized *key = data_to_serialized_key(data, size);
+
+	if (key->magic_number != MAGIC_NUMBER)
+		return size;
+
+	return key->sec_size;
+}
+
+/*
+ * Return the CAAM key buffer pointer of the given key buffer
+ *
+ * @data	Input buffer
+ * @size	Input buffer size
+ */
+static unsigned long get_key_buf_offset(const uint8_t *data, size_t size)
+{
+	struct caam_key_serialized *key = data_to_serialized_key(data, size);
+
+	if (key->magic_number != MAGIC_NUMBER)
+		return 0;
+	else
+		return offsetof(struct caam_key_serialized, key);
+}
+
+/*
+ * Return the CAAM key buffer size of the given key buffer
+ *
+ * @data	Input buffer
+ * @size	Input buffer size
+ */
+static size_t get_key_buf_size(const uint8_t *data, size_t size)
+{
+	struct caam_key_serialized *key = data_to_serialized_key(data, size);
+
+	/*
+	 * In the caam_key_serialized{}, the last element of the structure is
+	 * a variable-sized buffer.
+	 */
+	return size - sizeof(*key);
+}
+
+size_t caam_key_get_alloc_size(const struct caamkey *key)
+{
+	if (!key)
+		return 0;
+
+	/* A blob size is independent from the key encryption algorithm */
+	if (key->is_blob)
+		return key->sec_size + BLOB_PAD_SIZE;
+
+	switch (key->key_type) {
+	case CAAM_KEY_PLAIN_TEXT:
+		/*
+		 * If the key is plain text, the allocation size is equal to the
+		 * key size and no blob operation on this key is possible.
+		 */
+		return key->sec_size;
+	case CAAM_KEY_BLACK_ECB:
+		/* ECB-black key must be a multiple of 16 bytes */
+		return ROUNDUP(key->sec_size, 16);
+	case CAAM_KEY_BLACK_CCM:
+		/*
+		 * CCM-black key must be a multiple of 8 bytes. The nonce and
+		 * ICV add another 12 bytes to the allocation size
+		 */
+		return ROUNDUP(key->sec_size, 8) + BLACK_KEY_NONCE_SIZE +
+		       BLACK_KEY_ICV_SIZE;
+	default:
+		return 0;
+	}
+}
+
+void caam_key_dump(const char *trace, const struct caamkey *key)
+{
+	if (!key || !trace)
+		return;
+
+	if (key->key_type >= CAAM_KEY_MAX_VALUE)
+		return;
+
+	KEY_TRACE("%s key_type:%s key_size:%zu is_blob:%s addr:%p",
+		  caam_key_type_to_str[key->key_type], trace, key->sec_size,
+		  key->is_blob ? "yes" : "no", key->buf.data);
+
+	if (key->buf.data)
+		KEY_DUMPBUF("Key data", key->buf.data, key->buf.length);
+}
+
+enum caam_status caam_key_alloc(struct caamkey *key)
+{
+	size_t alloc_size = 0;
+
+	if (!key)
+		return CAAM_BAD_PARAM;
+
+	if (key->buf.data) {
+		KEY_TRACE("Key already allocated");
+		return CAAM_BAD_PARAM;
+	}
+
+	alloc_size = caam_key_get_alloc_size(key);
+	if (!alloc_size)
+		return CAAM_FAILURE;
+
+	return caam_calloc_align_buf(&key->buf, alloc_size);
+}
+
+void caam_key_free(struct caamkey *key)
+{
+	if (!key)
+		return;
+
+	caam_free_buf(&key->buf);
+}
+
+void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key)
+{
+	if (!key)
+		return;
+
+	if (!key->buf.nocache)
+		cache_operation(op, key->buf.data, key->buf.length);
+}
+
+#define BLOB_OP_DESC_ENTRIES 12
+enum caam_status caam_key_operation_blob(const struct caamkey *in_key,
+					 struct caamkey *out_key)
+{
+	enum caam_status status = CAAM_FAILURE;
+	struct caam_jobctx jobctx = { };
+	uint32_t opflag = PROT_BLOB_TYPE(BLACK_KEY);
+	uint32_t *desc = NULL;
+	size_t output_buffer_size = 0;
+	size_t input_buffer_size = 0;
+
+	assert(in_key && out_key);
+
+	KEY_TRACE("Blob %scapsulation of the following key",
+		  in_key->is_blob ? "de" : "en");
+
+	caam_key_dump("Blob input key", in_key);
+
+	/* This function blobs or un-blobs */
+	if (in_key->is_blob == out_key->is_blob) {
+		KEY_TRACE("Only one key must be defined as a blob");
+		return CAAM_BAD_PARAM;
+	}
+
+	/* A black blob cannot take a plain test key as input */
+	if (out_key->key_type == CAAM_KEY_PLAIN_TEXT ||
+	    in_key->key_type == CAAM_KEY_PLAIN_TEXT) {
+		KEY_TRACE("A blob in/out operation cannot be plain text");
+		return CAAM_BAD_PARAM;
+	}
+
+	/* The key type must remain the same */
+	if (out_key->key_type != in_key->key_type) {
+		KEY_TRACE("The in/out keys must have the same key type");
+		return CAAM_BAD_PARAM;
+	}
+
+	/* Define blob operation direction */
+	if (out_key->is_blob)
+		opflag |= BLOB_ENCAPS;
+	else
+		opflag |= BLOB_DECAPS;
+
+	/* Build OP flags depending on the blob type */
+	switch (out_key->key_type) {
+	case CAAM_KEY_BLACK_ECB:
+		opflag |= PROT_BLOB_INFO(ECB);
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		opflag |= PROT_BLOB_INFO(CCM);
+		break;
+	default:
+		return CAAM_BAD_PARAM;
+	}
+
+	/* Allocate the descriptor */
+	desc = caam_calloc_desc(BLOB_OP_DESC_ENTRIES);
+	if (!desc) {
+		KEY_TRACE("CAAM Context Descriptor Allocation error");
+		return CAAM_OUT_MEMORY;
+	}
+
+	status = caam_key_alloc(out_key);
+	if (status) {
+		KEY_TRACE("Key output allocation error");
+		goto err;
+	}
+
+	/* Define input and output buffer size */
+	if (out_key->is_blob) {
+		/*
+		 * For a blob operation, the input key size is the original key
+		 * size of the black key.
+		 * The output key size is the final blob size.
+		 */
+		input_buffer_size = in_key->sec_size;
+		output_buffer_size = out_key->buf.length;
+	} else {
+		/*
+		 * For an non-blob operation, the input key size is the original
+		 * key size of the black key.
+		 * The output key size is the key security size.
+		 */
+		input_buffer_size = in_key->buf.length;
+		output_buffer_size = out_key->sec_size;
+	}
+
+	/* Create the blob encapsulation/decapsulation descriptor */
+	caam_desc_init(desc);
+	caam_desc_add_word(desc, DESC_HEADER(0));
+
+	/* Load the key modifier */
+	caam_desc_add_word(desc,
+			   LD_NOIMM(CLASS_2, REG_KEY, KEY_BLOB_MODIFIER_SIZE));
+	caam_desc_add_ptr(desc, virt_to_phys((void *)key_blob_modifier));
+
+	/* Define the Input data sequence */
+	caam_desc_add_word(desc, SEQ_IN_PTR(input_buffer_size));
+	caam_desc_add_ptr(desc, in_key->buf.paddr);
+
+	/* Define the Output data sequence */
+	caam_desc_add_word(desc, SEQ_OUT_PTR(output_buffer_size));
+	caam_desc_add_ptr(desc, out_key->buf.paddr);
+	caam_desc_add_word(desc, opflag);
+
+	KEY_DUMPDESC(desc);
+
+	cache_operation(TEE_CACHECLEAN, key_blob_modifier,
+			KEY_BLOB_MODIFIER_SIZE);
+	caam_key_cache_op(TEE_CACHECLEAN, in_key);
+	caam_key_cache_op(TEE_CACHECLEAN, out_key);
+
+	jobctx.desc = desc;
+	status = caam_jr_enqueue(&jobctx, NULL);
+
+	if (status == CAAM_NO_ERROR) {
+		KEY_TRACE("CAAM Blob %scapsulation Done",
+			  out_key->is_blob ? "En" : "De");
+
+		caam_key_cache_op(TEE_CACHEINVALIDATE, out_key);
+		caam_key_dump("Blob output key", out_key);
+
+		goto out;
+	} else {
+		KEY_TRACE("CAAM Blob Status 0x%08" PRIx32 "", jobctx.status);
+	}
+
+err:
+	caam_key_free(out_key);
+out:
+	caam_free_desc(&desc);
+	return status;
+}
+
+enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size,
+					       struct caamkey *key,
+					       size_t sec_size)
+{
+	enum caam_status status = CAAM_FAILURE;
+	struct caamkey blob = { };
+
+	assert(data && size && key);
+
+	KEY_TRACE("Deserialization binary buffer");
+	KEY_DUMPBUF("Deserialize key buffer input", data, size);
+
+	/*
+	 * If a security key size is given, use it. Otherwise, rely on
+	 * the buffer size.
+	 * In some case, like ECC keys, the bignum size is less than the
+	 * security size and it requires the key to be padded with 0's.
+	 */
+	if (sec_size == 0)
+		sec_size = get_key_sec_size(data, size);
+
+	blob.key_type = get_key_type(data, size);
+	blob.sec_size = sec_size;
+	blob.is_blob = true;
+
+	if (blob.key_type == CAAM_KEY_PLAIN_TEXT) {
+		key->sec_size = blob.sec_size;
+		key->key_type = blob.key_type;
+		key->is_blob = false;
+
+		status = caam_key_alloc(key);
+		if (status) {
+			KEY_TRACE("Key allocation error");
+			return status;
+		}
+
+		/* Some asymmetric keys have leading zeros we must preserve */
+		memcpy(key->buf.data + key->buf.length - size, data, size);
+
+		return CAAM_NO_ERROR;
+	}
+
+	status = caam_key_alloc(&blob);
+	if (status) {
+		KEY_TRACE("Key allocation error");
+		return status;
+	}
+
+	memcpy(blob.buf.data, data + get_key_buf_offset(data, size),
+	       get_key_buf_size(data, size));
+
+	/* Set destination key */
+	key->key_type = blob.key_type;
+	key->sec_size = blob.sec_size;
+	key->is_blob = false;
+
+	/* De-blob operation */
+	status = caam_key_operation_blob(&blob, key);
+	if (status) {
+		KEY_TRACE("De-blob operation fail");
+		goto out;
+	}
+
+	KEY_TRACE("Deserialization binary buffer done");
+	caam_key_dump("Deserialization output key", key);
+out:
+	caam_key_free(&blob);
+	return status;
+}
+
+enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size,
+					   const struct caamkey *key)
+{
+	struct caam_key_serialized key_ser = { };
+	struct caamkey blob = { };
+	enum caam_status status = CAAM_FAILURE;
+	size_t serialized_size = 0;
+
+	assert(data && size && key);
+
+	caam_key_dump("Serialization input key", key);
+
+	/* If the key is plain text, just copy key to buffer */
+	if (key->key_type == CAAM_KEY_PLAIN_TEXT) {
+		if (size < key->buf.length) {
+			KEY_TRACE("Buffer is too short");
+			return CAAM_SHORT_BUFFER;
+		}
+
+		memcpy(data, key->buf.data, key->buf.length);
+
+		return CAAM_NO_ERROR;
+	}
+
+	/* The input key must not be a blob */
+	assert(!key->is_blob);
+
+	/* Blob the given key for serialization and export */
+	blob.is_blob = true;
+	blob.sec_size = key->sec_size;
+	blob.key_type = key->key_type;
+
+	/*
+	 * Check if the destination is big enough for the black blob buffer and
+	 * header.
+	 */
+	status = caam_key_serialized_size(&blob, &serialized_size);
+	if (status)
+		return status;
+
+	if (size < serialized_size) {
+		KEY_TRACE("Destination buffer is too short %zu < %zu", size,
+			  serialized_size);
+		return CAAM_OUT_MEMORY;
+	}
+
+	/* Blob the given key */
+	status = caam_key_operation_blob(key, &blob);
+	if (status) {
+		KEY_TRACE("Blob operation fail");
+		return status;
+	}
+
+	/* Copy the header to destination */
+	key_ser.magic_number = MAGIC_NUMBER;
+	key_ser.key_type = blob.key_type;
+	key_ser.sec_size = blob.sec_size;
+	memcpy(data, &key_ser, sizeof(key_ser));
+
+	/* Copy the key buffer */
+	memcpy(data + sizeof(key_ser), blob.buf.data, blob.buf.length);
+
+	KEY_DUMPBUF("Key data", data, size);
+
+	caam_key_free(&blob);
+
+	return status;
+}
+
+enum caam_status caam_key_serialized_size(const struct caamkey *key,
+					  size_t *size)
+{
+	assert(key && size);
+
+	/* For a plain text key, the serialized key is identical to the key */
+	*size = key->buf.length;
+
+	/*
+	 * For black keys, the serialized key includes the header and must be
+	 * in a blob format
+	 */
+	if (key->key_type != CAAM_KEY_PLAIN_TEXT) {
+		size_t alloc = 0;
+		const struct caamkey tmp = {
+			.key_type = key->key_type,
+			.sec_size = key->sec_size,
+			.is_blob = true,
+		};
+
+		alloc = caam_key_get_alloc_size(&tmp);
+		if (!alloc)
+			return CAAM_FAILURE;
+
+		*size = alloc + sizeof(struct caam_key_serialized);
+	}
+
+	return CAAM_NO_ERROR;
+}
+
+enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey,
+					      struct caamkey *outkey,
+					      size_t size_sec)
+{
+	enum caam_status status = CAAM_FAILURE;
+	uint8_t *buf = NULL;
+	size_t size = 0;
+
+	assert(inkey && outkey);
+
+	KEY_TRACE("Deserialization bignum");
+
+	/* Get bignum size */
+	size = crypto_bignum_num_bytes((struct bignum *)inkey);
+
+	/* Allocate temporary buffer */
+	buf = caam_calloc(size);
+	if (!buf)
+		return CAAM_OUT_MEMORY;
+
+	/* Convert bignum to binary */
+	crypto_bignum_bn2bin(inkey, buf);
+
+	status = caam_key_deserialize_from_bin(buf, size, outkey, size_sec);
+
+	caam_key_dump("Output key", outkey);
+
+	caam_free(buf);
+
+	return status;
+}
+
+enum caam_status caam_key_serialize_to_bn(struct bignum *outkey,
+					  const struct caamkey *inkey)
+{
+	enum caam_status status = CAAM_FAILURE;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *buf = NULL;
+	size_t size = 0;
+
+	assert(inkey && outkey);
+
+	KEY_TRACE("Serialization bignum");
+	caam_key_dump("Input key", inkey);
+
+	status = caam_key_serialized_size(inkey, &size);
+	if (status)
+		return status;
+
+	buf = caam_calloc(size);
+	if (!buf)
+		return CAAM_OUT_MEMORY;
+
+	status = caam_key_serialize_to_bin(buf, size, inkey);
+	if (status)
+		goto out;
+
+	res = crypto_bignum_bin2bn(buf, size, outkey);
+	if (res)
+		status = CAAM_FAILURE;
+out:
+	caam_free(buf);
+
+	return status;
+}
+
+#define MAX_DESC_ENTRIES 22
+enum caam_status caam_key_black_encapsulation(struct caamkey *key,
+					      enum caam_key_type key_type)
+{
+	enum caam_status status = CAAM_FAILURE;
+	struct caambuf input_buf = { };
+	struct caam_jobctx jobctx = { };
+	uint32_t *desc = NULL;
+
+	assert(key);
+	assert(!key->is_blob && key->key_type == CAAM_KEY_PLAIN_TEXT);
+	assert(key_type != CAAM_KEY_PLAIN_TEXT);
+
+	KEY_TRACE("Black key encapsulation");
+
+	/* Copy input plain text key to temp buffer */
+	status = caam_calloc_align_buf(&input_buf, key->buf.length);
+	if (status)
+		return status;
+
+	memcpy(input_buf.data, key->buf.data, key->buf.length);
+	cache_operation(TEE_CACHEFLUSH, input_buf.data, input_buf.length);
+
+	/* Re-allocate the output key for black format */
+	caam_key_free(key);
+	key->key_type = key_type;
+
+	status = caam_key_alloc(key);
+	if (status)
+		goto out;
+
+	/* Allocate the descriptor */
+	desc = caam_calloc_desc(MAX_DESC_ENTRIES);
+	if (!desc) {
+		KEY_TRACE("Allocation descriptor error");
+		status = CAAM_OUT_MEMORY;
+		goto out;
+	}
+
+	caam_key_dump("Input key", key);
+
+	caam_desc_init(desc);
+	caam_desc_add_word(desc, DESC_HEADER(0));
+	caam_desc_add_word(desc, LD_KEY(CLASS_1, PKHA_E, key->sec_size));
+	caam_desc_add_ptr(desc, input_buf.paddr);
+
+	switch (key->key_type) {
+	case CAAM_KEY_BLACK_ECB:
+		caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_ECB_JKEK,
+						 key->sec_size));
+		break;
+	case CAAM_KEY_BLACK_CCM:
+		caam_desc_add_word(desc, FIFO_ST(CLASS_NO, PKHA_E_AES_CCM_JKEK,
+						 key->sec_size));
+		break;
+	default:
+		status = CAAM_FAILURE;
+		goto out;
+	}
+
+	caam_desc_add_ptr(desc, key->buf.paddr);
+
+	KEY_DUMPDESC(desc);
+
+	caam_key_cache_op(TEE_CACHEFLUSH, key);
+
+	jobctx.desc = desc;
+	status = caam_jr_enqueue(&jobctx, NULL);
+	if (status != CAAM_NO_ERROR) {
+		KEY_TRACE("CAAM return 0x%08x Status 0x%08" PRIx32, status,
+			  jobctx.status);
+		status = CAAM_FAILURE;
+		goto out;
+	}
+
+	caam_key_cache_op(TEE_CACHEINVALIDATE, key);
+
+	caam_key_dump("Output Key", key);
+
+out:
+	caam_free_buf(&input_buf);
+	caam_free_desc(&desc);
+
+	return status;
+}
+
+enum caam_status caam_key_init(void)
+{
+	size_t alloc_size = 0;
+	const struct caamkey key = {
+		.key_type = caam_key_default_key_gen_type(),
+		.sec_size = 4096, /* Max RSA key size */
+		.is_blob = true,
+	};
+
+	/*
+	 * Ensure bignum format maximum size is enough to store a black key
+	 * blob. The largest key is a 4096 bits RSA key pair.
+	 */
+	if (caam_key_serialized_size(&key, &alloc_size))
+		return CAAM_FAILURE;
+
+	assert(alloc_size <= CFG_CORE_BIGNUM_MAX_BITS);
+
+	key_blob_modifier = caam_calloc_align(KEY_BLOB_MODIFIER_SIZE);
+	if (!key_blob_modifier)
+		return CAAM_FAILURE;
+
+	memcpy(key_blob_modifier, KEY_BLOB_MODIFIER, KEY_BLOB_MODIFIER_SIZE);
+
+	KEY_TRACE("Max serialized key size %zu", alloc_size);
+
+	KEY_TRACE("Default CAAM key generation type %s",
+		  caam_key_type_to_str[caam_key_default_key_gen_type()]);
+
+	return CAAM_NO_ERROR;
+}
diff --git a/core/drivers/crypto/caam/caam_rng.c b/core/drivers/crypto/caam/caam_rng.c
index a2a8fdd71e945001bc5c00beb31c7a680ccb6eb9..879740029561b137d6a1ed68fc56c4730b857585 100644
--- a/core/drivers/crypto/caam/caam_rng.c
+++ b/core/drivers/crypto/caam/caam_rng.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /**
- * Copyright 2017-2021 NXP
+ * Copyright 2017-2021, 2024 NXP
  *
  * Brief   CAAM Random Number Generator manager.
  *         Implementation of RNG functions.
@@ -11,6 +11,7 @@
 #include <caam_jr.h>
 #include <caam_rng.h>
 #include <caam_utils_mem.h>
+#include <caam_utils_status.h>
 #include <crypto/crypto.h>
 #include <kernel/panic.h>
 #include <mm/core_memprot.h>
@@ -19,41 +20,11 @@
 #include <tee/tee_cryp_utl.h>
 #include <string.h>
 
-/*
- * Define the RNG Data buffer size and number
- */
-#define RNG_DATABUF_SIZE	1024
-#define RNG_DATABUF_NB		2
-
 /*
  * Define the number of descriptor entry to generate random data
  */
 #define RNG_GEN_DESC_ENTRIES	5
 
-/*
- * Status of the data generation
- */
-enum rngsta {
-	DATA_EMPTY = 0, /* Data bufer empty */
-	DATA_ONGOING,   /* Data generation on going */
-	DATA_FAILURE,   /* Error during data generation */
-	DATA_OK,        /* Data generation complete with success */
-};
-
-/*
- * RNG Data generation
- */
-struct rngdata {
-	struct caam_jobctx jobctx; /* Job Ring Context */
-	uint32_t job_id;           /* Job Id enqueued */
-
-	uint8_t *data;           /* Random Data buffer */
-	size_t size;             /* Size in bytes of the Random data buffer */
-	size_t rdindex;          /* Current data index in the buffer */
-
-	enum rngsta status;      /* Status of the data generation */
-};
-
 /*
  * RNG module private data
  */
@@ -61,8 +32,6 @@ struct rng_privdata {
 	vaddr_t baseaddr;                       /* RNG base address */
 	bool instantiated;                      /* RNG instantiated */
 	bool pr_enabled;			/* RNG prediction resistance */
-	struct rngdata databuf[RNG_DATABUF_NB]; /* RNG Data generation */
-	uint8_t dataidx;                        /* Current RNG Data buffer */
 };
 
 static struct rng_privdata *rng_privdata;
@@ -70,9 +39,6 @@ static struct rng_privdata *rng_privdata;
 /* Allocate and initialize module private data */
 static enum caam_status do_allocate(void)
 {
-	struct rngdata *rngdata = NULL;
-	unsigned int idx = 0;
-
 	/* Allocate the Module resources */
 	rng_privdata = caam_calloc(sizeof(*rng_privdata));
 	if (!rng_privdata) {
@@ -82,201 +48,17 @@ static enum caam_status do_allocate(void)
 
 	rng_privdata->instantiated = false;
 
-	/* Allocates the RNG Data Buffers */
-	for (idx = 0; idx < RNG_DATABUF_NB; idx++) {
-		rngdata = &rng_privdata->databuf[idx];
-		rngdata->data = caam_calloc_align(RNG_DATABUF_SIZE);
-		if (!rngdata->data)
-			return CAAM_OUT_MEMORY;
-
-		rngdata->size = RNG_DATABUF_SIZE;
-		rngdata->jobctx.desc = caam_calloc_desc(RNG_GEN_DESC_ENTRIES);
-		if (!rngdata->jobctx.desc)
-			return CAAM_OUT_MEMORY;
-	}
-
 	return CAAM_NO_ERROR;
 }
 
 /* Free module private data */
 static void do_free(void)
 {
-	struct rngdata *rng = NULL;
-	unsigned int idx = 0;
-
-	if (rng_privdata) {
-		for (idx = 0; idx < RNG_DATABUF_NB; idx++) {
-			rng = &rng_privdata->databuf[idx];
-
-			/* Check if there is a Job ongoing to cancel it */
-			if (atomic_load_u32(&rng->status) == DATA_ONGOING)
-				caam_jr_cancel(rng->job_id);
-
-			caam_free_desc(&rng->jobctx.desc);
-			caam_free(rng->data);
-			rng->data = NULL;
-		}
-
-		caam_free(rng_privdata);
-		rng_privdata = NULL;
-	}
+	caam_free(rng_privdata);
+	rng_privdata = NULL;
 }
 
 #ifdef CFG_NXP_CAAM_RNG_DRV
-/*
- * RNG data generation job ring callback completion
- *
- * @jobctx      RNG data JR Job Context
- */
-static void rng_data_done(struct caam_jobctx *jobctx)
-{
-	struct rngdata *rng = jobctx->context;
-
-	RNG_TRACE("RNG Data id 0x%08" PRIx32 " done with status 0x%" PRIx32,
-		  rng->job_id, jobctx->status);
-
-	if (JRSTA_SRC_GET(jobctx->status) == JRSTA_SRC(NONE)) {
-		atomic_store_u32(&rng->status, DATA_OK);
-
-		/* Invalidate the data buffer to ensure software gets it */
-		cache_operation(TEE_CACHEINVALIDATE, rng->data, rng->size);
-	} else {
-		RNG_TRACE("RNG Data completion in error 0x%" PRIx32,
-			  jobctx->status);
-		atomic_store_u32(&rng->status, DATA_FAILURE);
-	}
-
-	rng->job_id = 0;
-	rng->rdindex = 0;
-}
-
-/*
- * Prepares the data generation descriptors
- *
- * @rng       Reference to the RNG Data object
- */
-static enum caam_status prepare_gen_desc(struct rngdata *rng)
-{
-	paddr_t paddr = 0;
-	uint32_t *desc = NULL;
-	uint32_t op = RNG_GEN_DATA;
-
-	if (rng_privdata->pr_enabled)
-		op |= ALGO_RNG_PR;
-
-	/* Convert the buffer virtual address to physical address */
-	paddr = virt_to_phys(rng->data);
-	if (!paddr)
-		return CAAM_FAILURE;
-
-	desc = rng->jobctx.desc;
-
-	caam_desc_init(desc);
-	caam_desc_add_word(desc, DESC_HEADER(0));
-	caam_desc_add_word(desc, op);
-	caam_desc_add_word(desc, FIFO_ST(RNG_TO_MEM, rng->size));
-	caam_desc_add_ptr(desc, paddr);
-
-	RNG_DUMPDESC(desc);
-
-	/* Prepare the job context */
-	rng->jobctx.context = rng;
-	rng->jobctx.callback = rng_data_done;
-	return CAAM_NO_ERROR;
-}
-
-/*
- * Launches a RNG Data generation
- *
- * @rng      RNG Data context
- */
-static enum caam_status do_rng_start(struct rngdata *rng)
-{
-	enum caam_status ret = CAAM_FAILURE;
-
-	/* Ensure that data buffer is visible from the HW */
-	cache_operation(TEE_CACHEFLUSH, rng->data, rng->size);
-
-	rng->job_id = 0;
-	atomic_store_u32(&rng->status, DATA_EMPTY);
-
-	ret = caam_jr_enqueue(&rng->jobctx, &rng->job_id);
-
-	if (ret == CAAM_PENDING) {
-		atomic_store_u32(&rng->status, DATA_ONGOING);
-		ret = CAAM_NO_ERROR;
-	} else {
-		RNG_TRACE("RNG Job Ring Error 0x%08x", ret);
-		atomic_store_u32(&rng->status, DATA_FAILURE);
-		ret = CAAM_FAILURE;
-	}
-
-	return ret;
-}
-
-/* Checks if there are random data available */
-static enum caam_status do_check_data(void)
-{
-	enum caam_status ret = CAAM_FAILURE;
-	struct rngdata *rng = NULL;
-	uint32_t wait_jobs = 0;
-	unsigned int idx = 0;
-	unsigned int loop = 4;
-
-	/* Check if there is a RNG Job to be run */
-	for (idx = 0; idx < RNG_DATABUF_NB; idx++) {
-		rng = &rng_privdata->databuf[idx];
-		if (atomic_load_u32(&rng->status) == DATA_EMPTY) {
-			RNG_TRACE("Start RNG #%" PRIu32 " data generation",
-				  idx);
-			ret = do_rng_start(rng);
-			if (ret != CAAM_NO_ERROR)
-				return CAAM_FAILURE;
-		}
-	}
-
-	/* Check if the current data buffer contains data */
-	rng = &rng_privdata->databuf[rng_privdata->dataidx];
-
-	switch (atomic_load_u32(&rng->status)) {
-	case DATA_OK:
-		return CAAM_NO_ERROR;
-
-	case DATA_FAILURE:
-		return CAAM_FAILURE;
-
-	default:
-		/* Wait until one of the data buffer completes */
-		do {
-			wait_jobs = 0;
-			for (idx = 0; idx < RNG_DATABUF_NB; idx++) {
-				rng = &rng_privdata->databuf[idx];
-				wait_jobs |= rng->job_id;
-
-				if (atomic_load_u32(&rng->status) == DATA_OK) {
-					RNG_TRACE("RNG Data buffer #%" PRIu32
-						  " ready",
-						  idx);
-					rng_privdata->dataidx = idx;
-					return CAAM_NO_ERROR;
-				}
-			}
-
-			if (!wait_jobs) {
-				RNG_TRACE("There are no Data Buffers ongoing");
-				return CAAM_FAILURE;
-			}
-
-			/* Need to wait until one of the jobs completes */
-			(void)caam_jr_dequeue(wait_jobs, 100);
-		} while (loop--);
-
-		break;
-	}
-
-	return CAAM_FAILURE;
-}
-
 /*
  * Return the requested random data
  *
@@ -285,9 +67,12 @@ static enum caam_status do_check_data(void)
  */
 static TEE_Result do_rng_read(uint8_t *buf, size_t len)
 {
-	struct rngdata *rng = NULL;
-	size_t remlen = len;
-	uint8_t *rngbuf = buf;
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	uint32_t *desc = NULL;
+	uint32_t op = RNG_GEN_DATA;
+	void *rng_data = NULL;
+	paddr_t paddr = 0;
+	struct caam_jobctx jobctx = { };
 
 	if (!rng_privdata) {
 		RNG_TRACE("RNG Driver not initialized");
@@ -299,60 +84,54 @@ static TEE_Result do_rng_read(uint8_t *buf, size_t len)
 		return TEE_ERROR_BAD_STATE;
 	}
 
-	do {
-		if (do_check_data() != CAAM_NO_ERROR) {
-			RNG_TRACE("No Data available or Error");
-			return TEE_ERROR_BAD_STATE;
-		}
+	rng_data = caam_calloc_align(len);
+	if (!rng_data) {
+		RNG_TRACE("RNG buffer allocation failed");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
 
-		rng = &rng_privdata->databuf[rng_privdata->dataidx];
-		RNG_TRACE("Context #%" PRIu8
-			  " contains %zu data asked %zu (%zu)",
-			  rng_privdata->dataidx, rng->size - rng->rdindex,
-			  remlen, len);
+	/* Ensure that data buffer is visible from the HW */
+	cache_operation(TEE_CACHEFLUSH, rng_data, len);
 
-		/* Check that current context data are available */
-		if ((rng->size - rng->rdindex) <= remlen) {
-			/*
-			 * There is no or just enough data available,
-			 * copy all data
-			 */
-			RNG_TRACE("Copy all available data");
-			memcpy(rngbuf, &rng->data[rng->rdindex],
-			       rng->size - rng->rdindex);
-
-			remlen -= rng->size - rng->rdindex;
-			rngbuf += rng->size - rng->rdindex;
-			/* Set the RNG data status as empty */
-			atomic_store_u32(&rng->status, DATA_EMPTY);
-		} else {
-			/* There is enough data in the current context */
-			RNG_TRACE("Copy %zu data", remlen);
-			memcpy(rngbuf, &rng->data[rng->rdindex], remlen);
-			rng->rdindex += remlen;
-			remlen = 0;
-		}
-	} while (remlen);
+	/* Convert the buffer virtual address to physical address */
+	paddr = virt_to_phys(rng_data);
+	if (!paddr) {
+		RNG_TRACE("Virtual/Physical conversion failed");
+		goto exit;
+	}
 
-	return TEE_SUCCESS;
-}
+	desc = caam_calloc_desc(RNG_GEN_DESC_ENTRIES);
+	if (!desc) {
+		RNG_TRACE("Descriptor allocation failed");
+		ret = TEE_ERROR_OUT_OF_MEMORY;
+		goto exit;
+	}
 
-/* Initialize the RNG module to generate data */
-static enum caam_status caam_rng_init_data(void)
-{
-	enum caam_status retstatus = CAAM_FAILURE;
-	struct rngdata *rng = NULL;
-	unsigned int idx = 0;
+	if (IS_ENABLED(CFG_CAAM_RNG_RUNTIME_PR) && rng_privdata->pr_enabled)
+		op |= ALGO_RNG_PR;
 
-	for (idx = 0; idx < RNG_DATABUF_NB; idx++) {
-		rng = &rng_privdata->databuf[idx];
-		retstatus = prepare_gen_desc(rng);
+	caam_desc_init(desc);
+	caam_desc_add_word(desc, DESC_HEADER(0));
+	caam_desc_add_word(desc, op);
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO, RNG_TO_MEM, len));
+	caam_desc_add_ptr(desc, paddr);
+
+	jobctx.desc = desc;
+	RNG_DUMPDESC(desc);
 
-		if (retstatus != CAAM_NO_ERROR)
-			break;
+	if (!caam_jr_enqueue(&jobctx, NULL)) {
+		cache_operation(TEE_CACHEINVALIDATE, rng_data, len);
+		memcpy(buf, rng_data, len);
+		ret = TEE_SUCCESS;
+	} else {
+		RNG_TRACE("CAAM Status 0x%08" PRIx32, jobctx.status);
+		ret = job_status_to_tee_result(jobctx.status);
 	}
 
-	return retstatus;
+exit:
+	caam_free(rng_data);
+	caam_free_desc(&desc);
+	return ret;
 }
 #endif /* CFG_NXP_CAAM_RNG_DRV */
 
@@ -531,7 +310,8 @@ end_inst:
 	if (retstatus == CAAM_NO_ERROR) {
 		rng_privdata->instantiated = true;
 		rng_privdata->pr_enabled =
-			caam_hal_rng_pr_enabled(rng_privdata->baseaddr);
+			caam_hal_rng_pr_enabled(rng_privdata->baseaddr) &
+			IS_ENABLED(CFG_CAAM_RNG_RUNTIME_PR);
 
 		RNG_TRACE("RNG prediction resistance is %sabled",
 			  rng_privdata->pr_enabled ? "en" : "dis");
@@ -555,11 +335,6 @@ enum caam_status caam_rng_init(vaddr_t ctrl_addr)
 		retstatus = caam_rng_instantiation();
 	}
 
-#ifdef CFG_NXP_CAAM_RNG_DRV
-	if (retstatus == CAAM_NO_ERROR)
-		retstatus = caam_rng_init_data();
-#endif
-
 	if (retstatus != CAAM_NO_ERROR)
 		do_free();
 
diff --git a/core/drivers/crypto/caam/caam_sm.c b/core/drivers/crypto/caam/caam_sm.c
index 231df870e6e18e63e9d3419df61df0d1de3d4731..0fe8fc2791bbffb75845de1365788d306fd0f876 100644
--- a/core/drivers/crypto/caam/caam_sm.c
+++ b/core/drivers/crypto/caam/caam_sm.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2019, 2023 NXP
+ * Copyright 2019, 2023-2024 NXP
  */
 #include <caam_common.h>
 #include <caam_hal_ctrl.h>
@@ -124,8 +124,8 @@ enum caam_status
 caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc,
 			unsigned int grp1_perm, unsigned int grp2_perm)
 {
-	uint32_t grp1 = UINT32_MAX;
-	uint32_t grp2 = UINT32_MAX;
+	uint32_t grp1 = 0;
+	uint32_t grp2 = 0;
 
 	if (!page_desc)
 		return CAAM_BAD_PARAM;
@@ -144,12 +144,18 @@ caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc,
 	 *
 	 * The Access Group is related to the Job Ring owner setting without
 	 * the Secure Bit setting already managed by the Job Ring.
+	 *
+	 * If any group permissions are set, need to enable Secure World MID
+	 * access in SMAG1/2 registers.
+	 * Since both Non-Secure/Secure world has same MID, using JROWN_ARM_NS
+	 * and if any grp1_perm/grp2_perm is set, need to enable permission
+	 * for Secure World for partition in SMAG1/2 Registers.
 	 */
 	if (grp1_perm)
-		grp1 = JROWN_ARM_NS;
+		grp1 = SHIFT_U32(1, JROWN_ARM_NS);
 
 	if (grp2_perm)
-		grp2 = JROWN_ARM_NS;
+		grp2 = SHIFT_U32(1, JROWN_ARM_NS);
 
 	caam_hal_sm_set_access_group(sm_privdata.jr_addr, page_desc->partition,
 				     grp1, grp2);
diff --git a/core/drivers/crypto/caam/cipher/caam_cipher.c b/core/drivers/crypto/caam/cipher/caam_cipher.c
index 29cb8f41946e934b6e98c743c03fc40c1bda769c..59e4c7beb1d94f30b532734a74c3a94333f27bf3 100644
--- a/core/drivers/crypto/caam/cipher/caam_cipher.c
+++ b/core/drivers/crypto/caam/cipher/caam_cipher.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2024 NXP
  *
  * Implementation of Cipher functions
  */
@@ -116,33 +116,6 @@ static const struct cipheralg des3_alg[] = {
 	},
 };
 
-/*
- * Allocate context data and copy input data into
- *
- * @dst  [out] Destination data to allocate and fill
- * @src  Source of data to copy
- */
-static enum caam_status copy_ctx_data(struct caambuf *dst,
-				      struct drvcrypt_buf *src)
-{
-	enum caam_status ret = CAAM_OUT_MEMORY;
-
-	if (!dst->data) {
-		/* Allocate the destination buffer */
-		ret = caam_alloc_align_buf(dst, src->length);
-		if (ret != CAAM_NO_ERROR)
-			return CAAM_OUT_MEMORY;
-	}
-
-	/* Do the copy */
-	memcpy(dst->data, src->data, dst->length);
-
-	/* Push data to physical memory */
-	cache_operation(TEE_CACHEFLUSH, dst->data, dst->length);
-
-	return CAAM_NO_ERROR;
-}
-
 /*
  * Verify the input key size with the requirements
  *
@@ -384,38 +357,20 @@ void caam_cipher_copy_state(void *dst_ctx, void *src_ctx)
 		caam_cpy_block_src(&dst->blockbuf, &srcdata, 0);
 	}
 
-	if (src->key1.length) {
-		struct drvcrypt_buf key1 = {
-			.data = src->key1.data,
-			.length = src->key1.length
-		};
-		copy_ctx_data(&dst->key1, &key1);
-	}
+	if (src->key1.length)
+		caam_cpy_buf(&dst->key1, src->key1.data, src->key1.length);
 
-	if (src->key2.length) {
-		struct drvcrypt_buf key2 = {
-			.data = src->key2.data,
-			.length = src->key2.length
-		};
-		copy_ctx_data(&dst->key2, &key2);
-	}
+	if (src->key2.length)
+		caam_cpy_buf(&dst->key2, src->key2.data, src->key2.length);
 
 	if (src->ctx.length) {
-		struct drvcrypt_buf ctx = {
-			.data = src->ctx.data,
-			.length = src->ctx.length
-		};
-		cache_operation(TEE_CACHEINVALIDATE, ctx.data, ctx.length);
-		copy_ctx_data(&dst->ctx, &ctx);
+		cache_operation(TEE_CACHEINVALIDATE, src->ctx.data,
+				src->ctx.length);
+		caam_cpy_buf(&dst->ctx, src->ctx.data, src->ctx.length);
 	}
 
-	if (src->tweak.length) {
-		struct drvcrypt_buf tweak = {
-			.data = src->tweak.data,
-			.length = src->tweak.length
-		};
-		copy_ctx_data(&dst->tweak, &tweak);
-	}
+	if (src->tweak.length)
+		caam_cpy_buf(&dst->tweak, src->tweak.data, src->tweak.length);
 }
 
 TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit)
@@ -444,7 +399,8 @@ TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit)
 		}
 
 		/* Copy the key 1 */
-		retstatus = copy_ctx_data(&cipherdata->key1, &dinit->key1);
+		retstatus = caam_cpy_buf(&cipherdata->key1, dinit->key1.data,
+					 dinit->key1.length);
 		CIPHER_TRACE("Copy Key 1 returned 0x%" PRIx32, retstatus);
 
 		if (retstatus != CAAM_NO_ERROR) {
@@ -464,7 +420,8 @@ TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit)
 		}
 
 		/* Copy the key 2 */
-		retstatus = copy_ctx_data(&cipherdata->key2, &dinit->key2);
+		retstatus = caam_cpy_buf(&cipherdata->key2, dinit->key2.data,
+					 dinit->key2.length);
 		CIPHER_TRACE("Copy Key 2 returned 0x%" PRIx32, retstatus);
 
 		if (retstatus != CAAM_NO_ERROR) {
@@ -488,7 +445,8 @@ TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit)
 			     alg->size_ctx);
 
 		/* Copy the IV into the context register */
-		retstatus = copy_ctx_data(&cipherdata->ctx, &dinit->iv);
+		retstatus = caam_cpy_buf(&cipherdata->ctx, dinit->iv.data,
+					 dinit->iv.length);
 		CIPHER_TRACE("Copy IV returned 0x%" PRIx32, retstatus);
 
 		if (retstatus != CAAM_NO_ERROR) {
@@ -506,8 +464,9 @@ TEE_Result caam_cipher_initialize(struct drvcrypt_cipher_init *dinit)
 			}
 
 			/* Copy the tweak */
-			retstatus = copy_ctx_data(&cipherdata->tweak,
-						  &dinit->iv);
+			retstatus = caam_cpy_buf(&cipherdata->tweak,
+						 dinit->iv.data,
+						 dinit->iv.length);
 			CIPHER_TRACE("Copy Tweak returned 0x%" PRIx32,
 				     retstatus);
 
diff --git a/core/drivers/crypto/caam/crypto.mk b/core/drivers/crypto/caam/crypto.mk
index 13f8e4cc070e93b079829dd799f3e4e60a8d5770..e2233b71697afddd04f359c1752e94e27b6d4a76 100644
--- a/core/drivers/crypto/caam/crypto.mk
+++ b/core/drivers/crypto/caam/crypto.mk
@@ -20,6 +20,7 @@ ifeq ($(CFG_NXP_CAAM),y)
 # DBG_DH     BIT32(13) // DH Trace
 # DBG_DSA    BIT32(14) // DSA trace
 # DBG_MP     BIT32(15) // MP trace
+# DBG_AE     BIT32(17) // AE trace
 CFG_DBG_CAAM_TRACE ?= 0x2
 CFG_DBG_CAAM_DESC ?= 0x0
 CFG_DBG_CAAM_BUF ?= 0x0
@@ -28,7 +29,7 @@ CFG_DBG_CAAM_BUF ?= 0x0
 caam-drivers = RNG BLOB
 
 # CAAM default drivers connected to the HW crypto API
-caam-crypto-drivers = CIPHER HASH HMAC CMAC
+caam-crypto-drivers = CIPHER HASH HMAC CMAC AE_CCM
 
 ifneq (,$(filter $(PLATFORM_FLAVOR),ls1012ardb ls1043ardb ls1046ardb))
 $(call force, CFG_CAAM_BIG_ENDIAN,y)
@@ -39,7 +40,7 @@ $(call force, CFG_CAAM_SGT_ALIGN,4)
 $(call force, CFG_CAAM_64BIT,y)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_CAAM_ITR,n)
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),ls1088ardb ls2088ardb ls1028ardb))
 $(call force, CFG_CAAM_LITTLE_ENDIAN,y)
 $(call force, CFG_JR_BLOCK_SIZE,0x10000)
@@ -49,7 +50,7 @@ $(call force, CFG_NXP_CAAM_SGT_V2,y)
 $(call force, CFG_CAAM_SGT_ALIGN,4)
 $(call force, CFG_CAAM_64BIT,y)
 $(call force, CFG_CAAM_ITR,n)
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),lx2160aqds lx2160ardb))
 $(call force, CFG_CAAM_LITTLE_ENDIAN,y)
 $(call force, CFG_JR_BLOCK_SIZE,0x10000)
@@ -60,14 +61,14 @@ $(call force, CFG_NXP_CAAM_SGT_V2,y)
 $(call force, CFG_CAAM_SGT_ALIGN,4)
 $(call force, CFG_CAAM_64BIT,y)
 $(call force, CFG_CAAM_ITR,n)
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8qm-flavorlist) $(mx8qx-flavorlist)))
 $(call force, CFG_CAAM_SIZE_ALIGN,4)
 $(call force, CFG_JR_BLOCK_SIZE,0x10000)
 $(call force, CFG_JR_INDEX,3)
 $(call force, CFG_JR_INT,486)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8dxl-flavorlist)))
 $(call force, CFG_CAAM_SIZE_ALIGN,4)
 $(call force, CFG_JR_BLOCK_SIZE,0x10000)
@@ -75,7 +76,7 @@ $(call force, CFG_JR_INDEX,3)
 $(call force, CFG_JR_INT,356)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_CAAM_JR_DISABLE_NODE,n)
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8mm-flavorlist) $(mx8mn-flavorlist) \
 	$(mx8mp-flavorlist) $(mx8mq-flavorlist)))
 $(call force, CFG_JR_BLOCK_SIZE,0x1000)
@@ -89,19 +90,21 @@ $(call force, CFG_JR_HAB_INDEX,0)
 # this issue, controlled by CFG_NXP_CAAM_C2_CTX_REG_WA flag.
 $(call force, CFG_NXP_CAAM_C2_CTX_REG_WA,y)
 caam-drivers += MP DEK
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx8ulp-flavorlist)))
 $(call force, CFG_JR_BLOCK_SIZE,0x1000)
 $(call force, CFG_JR_INDEX,2)
 $(call force, CFG_JR_INT,114)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_CAAM_ITR,n)
+caam-crypto-drivers += AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx7ulp-flavorlist)))
 $(call force, CFG_JR_BLOCK_SIZE,0x1000)
 $(call force, CFG_JR_INDEX,0)
 $(call force, CFG_JR_INT,137)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 $(call force, CFG_CAAM_ITR,n)
+caam-crypto-drivers += AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6ul-flavorlist) $(mx7d-flavorlist) \
 	$(mx7s-flavorlist)))
 $(call force, CFG_JR_BLOCK_SIZE,0x1000)
@@ -109,10 +112,10 @@ $(call force, CFG_JR_INDEX,0)
 $(call force, CFG_JR_INT,137)
 $(call force, CFG_NXP_CAAM_SGT_V1,y)
 caam-drivers += MP
-caam-crypto-drivers += RSA DSA ECC DH MATH
+caam-crypto-drivers += RSA DSA ECC DH MATH AE_GCM
 else ifneq (,$(filter $(PLATFORM_FLAVOR),$(mx6q-flavorlist) $(mx6qp-flavorlist) \
 	$(mx6sx-flavorlist) $(mx6d-flavorlist) $(mx6dl-flavorlist) \
-        $(mx6s-flavorlist) $(mx8ulp-flavorlist)))
+	$(mx6s-flavorlist) $(mx8ulp-flavorlist)))
 $(call force, CFG_JR_BLOCK_SIZE,0x1000)
 $(call force, CFG_JR_INDEX,0)
 $(call force, CFG_JR_INT,137)
@@ -145,6 +148,19 @@ CFG_NXP_CAAM_RSA_KEY_FORMAT ?= 3
 # Disable device tree status of the secure job ring
 CFG_CAAM_JR_DISABLE_NODE ?= y
 
+# Define the default CAAM private key encryption generation and the bignum
+# maximum size needed.
+# CAAM_KEY_PLAIN_TEXT    -> 4096 bits
+# CAAM_KEY_BLACK_ECB|CCM -> 4576 bits
+# 4096 (RSA Max key size) +  12 * 8 (Header serialization) +
+# 48 * 8 (Black blob overhead in bytes) = 4576 bits
+CFG_CORE_BIGNUM_MAX_BITS ?= 4576
+
+# CAAM RNG Prediction Resistance
+# When this flag is y, the CAAM RNG is reseeded on every random number request.
+# In this case the performance is drastically reduced.
+CFG_CAAM_RNG_RUNTIME_PR ?= n
+
 # Enable CAAM non-crypto drivers
 $(foreach drv, $(caam-drivers), $(eval CFG_NXP_CAAM_$(drv)_DRV ?= y))
 
@@ -174,6 +190,11 @@ ifeq ($(CFG_NXP_CAAM_CIPHER_DRV), y)
 $(call force, CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_NXP_CAAM_CIPHER_DRV)
 endif
 
+# Enable AE crypto driver
+ifeq ($(call cfg-one-enabled,CFG_NXP_CAAM_AE_CCM_DRV CFG_NXP_CAAM_AE_GCM_DRV),y)
+$(call force, CFG_CRYPTO_DRV_AUTHENC,y,Mandated by CFG_NXP_CAAM_AE_CCM/GCM_DRV)
+endif
+
 # Enable HASH crypto driver
 ifeq ($(CFG_NXP_CAAM_HASH_DRV), y)
 $(call force, CFG_CRYPTO_DRV_HASH,y,Mandated by CFG_NXP_CAAM_HASH_DRV)
@@ -205,12 +226,5 @@ ifeq ($(call cfg-one-enabled,CFG_CRYPTO_DRV_RSA CFG_CRYPTO_DRV_ECC \
 $(call force, CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_CRYPTO_DRV_{RSA|ECC|DSA|DH})
 endif
 
-# Disable SM2 as it is not supported by the CAAM driver
-ifeq ($(CFG_NXP_CAAM_ECC_DRV),y)
-$(call force,CFG_CRYPTO_SM2_PKE,n)
-$(call force,CFG_CRYPTO_SM2_KEP,n)
-$(call force,CFG_CRYPTO_SM2_DSA,n)
-endif
-
 endif # CFG_CRYPTO_DRIVER
 endif # CFG_NXP_CAAM
diff --git a/core/drivers/crypto/caam/hal/common/hal_cfg.c b/core/drivers/crypto/caam/hal/common/hal_cfg.c
index 2bdf9e6554632159025478ffcc9045d405204100..e1ba8d67842f761340ff318fff59bf8104269d82 100644
--- a/core/drivers/crypto/caam/hal/common/hal_cfg.c
+++ b/core/drivers/crypto/caam/hal/common/hal_cfg.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2017-2019, 2021 NXP
+ * Copyright 2017-2019, 2021, 2024 NXP
  *
  * Brief   CAAM Configuration.
  */
@@ -66,6 +66,12 @@ enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg)
 
 	retstatus = CAAM_NO_ERROR;
 
+	if (IS_ENABLED(CFG_NXP_CAAM_RUNTIME_JR))
+		caam_hal_jr_prepare_backup(jrcfg->base, jrcfg->offset);
+
+	if (IS_ENABLED(CFG_MX8M))
+		caam_hal_cfg_hab_jr_mgmt(jrcfg);
+
 exit_get_conf:
 	HAL_TRACE("HAL CFG Get CAAM config ret (0x%x)\n", retstatus);
 	return retstatus;
@@ -80,6 +86,14 @@ void __weak caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg)
 	for (jrnum = caam_hal_ctrl_jrnum(jrcfg->base); jrnum; jrnum--) {
 		jr_offset = jrnum * JRX_BLOCK_SIZE;
 
+		/*
+		 * Skip configuration for the JR used by the HAB
+		 */
+		if (IS_ENABLED(CFG_MX8M)) {
+			if (caam_hal_cfg_is_hab_jr(jr_offset))
+				continue;
+		}
+
 #ifdef CFG_NXP_CAAM_RUNTIME_JR
 		/*
 		 * When the Cryptographic driver is enabled, keep the
diff --git a/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c b/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
index 9a84b2c083882becdf918a602740e6ade063a776..5bd4c51cb283973bc98a416b08a5d43baec3237d 100644
--- a/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
+++ b/core/drivers/crypto/caam/hal/common/hal_cfg_dt.c
@@ -69,15 +69,8 @@ void caam_hal_cfg_get_ctrl_dt(void *fdt, vaddr_t *ctrl_base)
 	 * already present in the MMU table.
 	 * Then get the virtual address of the CAAM controller
 	 */
-	pctrl_base = fdt_reg_base_address(fdt, node);
-	if (pctrl_base == DT_INFO_INVALID_REG) {
-		HAL_TRACE("CAAM control base address not defined");
-		return;
-	}
-
-	size = fdt_reg_size(fdt, node);
-	if (size == DT_INFO_INVALID_REG_SIZE) {
-		HAL_TRACE("CAAM control base address size not defined");
+	if (fdt_reg_info(fdt, node, &pctrl_base, &size)) {
+		HAL_TRACE("CAAM control base address or size not defined");
 		return;
 	}
 
diff --git a/core/drivers/crypto/caam/hal/common/hal_rng.c b/core/drivers/crypto/caam/hal/common/hal_rng.c
index 5f8f0afc2910bc8e51f136c68169e1d1b60c8a0d..aba8cbcd4b0a82cffaddfd76d9b20b0500d41001 100644
--- a/core/drivers/crypto/caam/hal/common/hal_rng.c
+++ b/core/drivers/crypto/caam/hal/common/hal_rng.c
@@ -62,7 +62,10 @@ bool caam_hal_rng_key_loaded(vaddr_t baseaddr)
 	return io_caam_read32(baseaddr + RNG_STA) & RNG_STA_SKVN;
 }
 
-bool caam_hal_rng_pr_enabled(vaddr_t baseaddr)
+/*
+ * This function will be overridden for i.MX8QX and i.MX8DX platforms.
+ */
+bool __weak caam_hal_rng_pr_enabled(vaddr_t baseaddr)
 {
 	uint32_t bitmask = RNG_STA_PR0;
 
diff --git a/core/drivers/crypto/caam/hal/common/hal_sm.c b/core/drivers/crypto/caam/hal/common/hal_sm.c
index 04552c26ae791f62181953b1af18b0c13524d385..87e1651e05a34269d031818cd6629f4b8407d091 100644
--- a/core/drivers/crypto/caam/hal/common/hal_sm.c
+++ b/core/drivers/crypto/caam/hal/common/hal_sm.c
@@ -101,13 +101,8 @@ void caam_hal_sm_set_access_group(vaddr_t jr_base, unsigned int partition,
 	if (!jr_base)
 		return;
 
-	if (grp1 != UINT32_MAX)
-		io_caam_write32(jr_base + SM_SMAG1(partition),
-				SHIFT_U32(1, grp1));
-
-	if (grp2 != UINT32_MAX)
-		io_caam_write32(jr_base + SM_SMAG2(partition),
-				SHIFT_U32(1, grp2));
+	io_caam_write32(jr_base + SM_SMAG1(partition), grp1);
+	io_caam_write32(jr_base + SM_SMAG2(partition), grp2);
 }
 
 void caam_hal_sm_open_access_perm(vaddr_t jr_base, unsigned int partition)
diff --git a/core/drivers/crypto/caam/hal/common/hal_sm_dt.c b/core/drivers/crypto/caam/hal/common/hal_sm_dt.c
new file mode 100644
index 0000000000000000000000000000000000000000..a3138e7cfcbe9bdd0d1efbcc58b0e8d192d54098
--- /dev/null
+++ b/core/drivers/crypto/caam/hal/common/hal_sm_dt.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 NXP
+ *
+ * Brief   CAAM Secure Memory Hardware Abstraction Layer.
+ */
+
+#include <caam_common.h>
+#include <caam_hal_sm.h>
+#include <kernel/dt.h>
+#include <libfdt.h>
+
+static const char *dt_sm_match_table = {
+	"fsl,imx6q-caam-sm",
+};
+
+void caam_hal_sm_get_base_dt(void *fdt, vaddr_t *sm_base)
+{
+	int node = 0;
+	int ret = 0;
+	size_t size = 0;
+
+	*sm_base = 0;
+
+	node = fdt_node_offset_by_compatible(fdt, 0, dt_sm_match_table);
+
+	if (node < 0) {
+		HAL_TRACE("CAAM Node not found err = 0x%X", node);
+		return;
+	}
+
+	/* Map the device in the system if not already present */
+	ret = dt_map_dev(fdt, node, sm_base, &size, DT_MAP_AUTO);
+	if (ret < 0) {
+		HAL_TRACE("Cannot map node 0x%X", node);
+		return;
+	}
+}
diff --git a/core/drivers/crypto/caam/hal/common/sub.mk b/core/drivers/crypto/caam/hal/common/sub.mk
index dbab332a7ffb4c9dfe8623e51a11f7eaa6b05f7d..0b6c4d3f2a1b256b0039495aff077dff81032797 100644
--- a/core/drivers/crypto/caam/hal/common/sub.mk
+++ b/core/drivers/crypto/caam/hal/common/sub.mk
@@ -2,7 +2,7 @@ incdirs-y += ../../include
 incdirs-y += ../$(CAAM_HAL_DIR)
 incdirs-y += .
 
-srcs-$(CFG_DT) += hal_cfg_dt.c
+srcs-$(CFG_DT) += hal_cfg_dt.c hal_sm_dt.c
 srcs-y += hal_cfg.c
 srcs-y += hal_rng.c
 srcs-y += hal_jr.c
diff --git a/core/drivers/crypto/caam/hal/imx_8m/hal_cfg.c b/core/drivers/crypto/caam/hal/imx_8m/hal_cfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..1129e775c2732237fe15417f100b2f78042bf220
--- /dev/null
+++ b/core/drivers/crypto/caam/hal/imx_8m/hal_cfg.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 NXP
+ *
+ * Brief   CAAM Configuration.
+ */
+#include <caam_hal_cfg.h>
+#include <caam_hal_jr.h>
+#include <kernel/dt.h>
+#include <registers/jr_regs.h>
+
+void caam_hal_cfg_hab_jr_mgmt(struct caam_jrcfg *jrcfg)
+{
+	void *fdt = NULL;
+	struct caam_jrcfg tmp_jrcfg = {
+		.offset = (CFG_JR_HAB_INDEX + 1) * JRX_BLOCK_SIZE,
+	};
+
+	fdt = get_dt();
+	if (fdt) {
+		/* Ensure Secure Job Ring is secure only into DTB */
+		caam_hal_cfg_disable_jobring_dt(fdt, &tmp_jrcfg);
+	}
+
+	caam_hal_jr_prepare_backup(jrcfg->base, tmp_jrcfg.offset);
+}
+
+bool caam_hal_cfg_is_hab_jr(paddr_t jr_offset)
+{
+	unsigned int jr_idx = JRX_IDX(jr_offset);
+
+	return jr_idx == CFG_JR_HAB_INDEX;
+}
diff --git a/core/drivers/crypto/caam/hal/imx_8m/sub.mk b/core/drivers/crypto/caam/hal/imx_8m/sub.mk
index 5231cce665261ba48835a84832b07f0766836558..d8c98585a5a5a18442695f8c39f37387abd18ec6 100644
--- a/core/drivers/crypto/caam/hal/imx_8m/sub.mk
+++ b/core/drivers/crypto/caam/hal/imx_8m/sub.mk
@@ -5,3 +5,4 @@ incdirs-y += .
 srcs-y += hal_clk.c
 srcs-y += hal_ctrl.c
 srcs-y += hal_jr.c
+srcs-y += hal_cfg.c
diff --git a/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c b/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c
index a561ab1235b33f9f94fb1b5f218de79a86830779..40d9a6b22427064102ff291fbaa91d747aaaaf96 100644
--- a/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c
+++ b/core/drivers/crypto/caam/hal/imx_8q/hal_rng.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2020-2021 NXP
+ * Copyright 2020-2021, 2024 NXP
  */
 #include <caam_hal_rng.h>
 #include <caam_status.h>
@@ -18,3 +18,12 @@ enum caam_status caam_hal_rng_instantiated(vaddr_t baseaddr __unused)
 	else
 		return CAAM_NO_ERROR;
 }
+
+bool caam_hal_rng_pr_enabled(vaddr_t baseaddr __unused)
+{
+	/*
+	 * On platforms i.MX8Q and i.MX8DXL CAAM RNG Prediction
+	 * resistance is enabled by default. So returning true.
+	 */
+	return true;
+}
diff --git a/core/drivers/crypto/caam/hash/caam_hash_mac.c b/core/drivers/crypto/caam/hash/caam_hash_mac.c
index 423e90fd1a32eb75837a70e547261e4830fc1c14..3bc5b31045d3de83bba2695de8599dfceabbaff6 100644
--- a/core/drivers/crypto/caam/hash/caam_hash_mac.c
+++ b/core/drivers/crypto/caam/hash/caam_hash_mac.c
@@ -176,7 +176,8 @@ static TEE_Result do_hmac_init(struct crypto_mac_ctx *ctx, const uint8_t *inkey,
 	caam_desc_add_word(desc, HMAC_INIT_DECRYPT(alg->type));
 	caam_desc_add_word(desc, FIFO_LD_IMM(CLASS_2, MSG, LAST_C2, 0));
 	/* Store the split key */
-	caam_desc_add_word(desc, FIFO_ST(C2_MDHA_SPLIT_KEY_AES_ECB_JKEK,
+	caam_desc_add_word(desc, FIFO_ST(CLASS_NO,
+					 C2_MDHA_SPLIT_KEY_AES_ECB_JKEK,
 					 hmac_ctx->key.length));
 	caam_desc_add_ptr(desc, hmac_ctx->key.paddr);
 	HASH_DUMPDESC(desc);
diff --git a/core/drivers/crypto/caam/include/caam_ae.h b/core/drivers/crypto/caam/include/caam_ae.h
new file mode 100644
index 0000000000000000000000000000000000000000..e02fcc9d04e2016aa867bba339a33b0cccca674f
--- /dev/null
+++ b/core/drivers/crypto/caam/include/caam_ae.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2024 NXP
+ */
+#ifndef __CAAM_AE_H__
+#define __CAAM_AE_H__
+
+#include <caam_common.h>
+
+/*
+ * Initialize the Authentication Encryption module
+ *
+ * @ctrl_addr   Controller base address
+ */
+enum caam_status caam_ae_init(vaddr_t ctrl_addr __unused);
+
+#endif /* __CAAM_AE_H__ */
diff --git a/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h b/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h
index 8bfd512ce7902db21130a491b1d80daf999827ff..c6970278acf9f32e0506224c6477bfaad61129ad 100644
--- a/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h
+++ b/core/drivers/crypto/caam/include/caam_desc_ccb_defines.h
@@ -13,8 +13,13 @@
 
 /* CCB Clear Written Register */
 #define CLR_WR_IFIFO_NFIFO BIT32(31)
+#define CLR_WR_RST_C1_CHA  BIT32(29)
 #define CLR_WR_RST_C2_CHA  BIT32(28)
+#define CLR_WR_RST_C1_DNE  BIT32(27)
+#define CLR_WR_RST_C2_CTX  BIT32(21)
 #define CLR_WR_RST_C2_DSZ  BIT32(18)
+#define CLR_WR_RST_C1_DSZ  BIT32(2)
+#define CLR_WR_RST_C1_MDE  BIT32(0)
 
 /* CCB NFIFO */
 #define NFIFO_CLASS(cla)       SHIFT_U32(NFIFO_CLASS_##cla & 0x3, 30)
@@ -31,6 +36,7 @@
 #define NFIFO_STYPE_PAD        0x2
 
 #define NFIFO_DTYPE(data)      SHIFT_U32(NFIFO_DTYPE_##data & 0xF, 20)
+#define NFIFO_DTYPE_AAD        0x1
 #define NFIFO_DTYPE_MSG        0xF
 #define NFIFO_DTYPE_PKHA_N     0x8
 #define NFIFO_DTYPE_PKHA_A     0xC
diff --git a/core/drivers/crypto/caam/include/caam_desc_defines.h b/core/drivers/crypto/caam/include/caam_desc_defines.h
index f9b6349fdfcd2c26004cc96c47737b729749fbc2..a75182702d9707ed6b2c799716ea918d8770f221 100644
--- a/core/drivers/crypto/caam/include/caam_desc_defines.h
+++ b/core/drivers/crypto/caam/include/caam_desc_defines.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2023 NXP
  *
  * Brief   CAAM Descriptor defines.
  */
@@ -136,6 +136,7 @@
  * FIFO LOAD Command fields
  */
 #define CMD_FIFO_LOAD_TYPE	CMD_TYPE(0x04)
+#define CMD_SEQ_FIFO_LOAD_TYPE  CMD_TYPE(0x05)
 
 /* Extended Length */
 #define FIFO_LOAD_EXT		BIT32(22)
@@ -317,6 +318,7 @@
 #define PROT_RSA_FMT(format)	SHIFT_U32((PROT_RSA_FMT_##format) & 0x1, 12)
 #define PROT_RSA_FMT_NO		0
 #define PROT_RSA_FMT_PKCS_V1_5	1
+#define PROT_RSA_FMT_MASK	SHIFT_U32(0x1, 12)
 
 #define PROT_RSA_DEC_KEYFORM(format)	SHIFT_U32(((format) - 1) & 0x3, 0)
 
@@ -325,6 +327,26 @@
 #define PROT_RSA_KEY_ALL	0
 #define PROT_RSA_KEY_N_D	2
 
+#define PROT_RSA_FINISH_KEY_ENC_OUT(alg) PROT_RSA_FINISH_KEY_ENC_OUT_##alg
+#define PROT_RSA_FINISH_KEY_ENC_OUT_ECB	 BIT32(6)
+#define PROT_RSA_FINISH_KEY_ENC_OUT_CCM	 BIT32(6)
+
+#define PROT_RSA_FINISH_KEY_ENC(alg) PROT_RSA_FINISH_KEY_ENC_##alg
+#define PROT_RSA_FINISH_KEY_ENC_ECB  0
+#define PROT_RSA_FINISH_KEY_ENC_CCM  BIT32(4)
+
+#define PROT_RSA_FINISH_KEY(alg) PROT_RSA_FINISH_KEY_##alg
+#define PROT_RSA_FINISH_KEY_NONE 0
+#define PROT_RSA_FINISH_KEY_ECB (PROT_RSA_FINISH_KEY_ENC_OUT_ECB | \
+				 PROT_RSA_FINISH_KEY_ENC_ECB)
+#define PROT_RSA_FINISH_KEY_CCM (PROT_RSA_FINISH_KEY_ENC_OUT_CCM | \
+				 PROT_RSA_FINISH_KEY_ENC_CCM)
+
+#define PROT_RSA_KEY_ENC(format) SHIFT_U32((PROT_RSA_KEY_ENC_##format) & 0x3, 8)
+#define PROT_RSA_KEY_ENC_NONE	 0
+#define PROT_RSA_KEY_ENC_ECB	 1
+#define PROT_RSA_KEY_ENC_CCM	 3
+
 /*
  * ECC Protocol Information
  */
@@ -334,6 +356,16 @@
 #define PROT_PK_TYPE(type)	SHIFT_U32(PROT_PK_##type, 1)
 #define PROT_PK_DL		0
 #define PROT_PK_ECC		1
+#define PROT_PRI_ENC(alg)	PROT_PRI_ENC_##alg
+#define PROT_PRI_ENC_ECB	BIT32(2)
+#define PROT_PRI_ENC_CCM	BIT32(2)
+#define PROT_PRI_EXT(type)	PROT_PRI_EXT_##type
+#define PROT_PRI_EXT_ECB	0
+#define PROT_PRI_EXT_CCM	BIT32(4)
+#define PROT_PRI(alg)		PROT_PRI_##alg
+#define PROT_PRI_NONE		0
+#define PROT_PRI_ECB		(PROT_PRI_ENC(ECB) | PROT_PRI_EXT(ECB))
+#define PROT_PRI_CCM		(PROT_PRI_ENC(CCM) | PROT_PRI_EXT(CCM))
 
 /*
  * BLOB Protocol Information
diff --git a/core/drivers/crypto/caam/include/caam_desc_helper.h b/core/drivers/crypto/caam/include/caam_desc_helper.h
index ca71cdcf3ddcd8d53a81a4f231210a5ee8b2b7b0..854487c82e04c45c11c3585699a4f0d961048052 100644
--- a/core/drivers/crypto/caam/include/caam_desc_helper.h
+++ b/core/drivers/crypto/caam/include/caam_desc_helper.h
@@ -32,7 +32,9 @@ void caam_desc_add_dmaobj(uint32_t *desc, struct caamdmaobj *data,
 #define caam_desc_store(desc, data, cla, src)                                  \
 	caam_desc_add_dmaobj(desc, data, ST_NOIMM(cla, src, 0))
 #define caam_desc_fifo_store(desc, data, src)                                  \
-	caam_desc_add_dmaobj(desc, data, FIFO_ST(src, 0))
+	caam_desc_add_dmaobj(desc, data, FIFO_ST(CLASS_NO, src, 0))
+#define caam_desc_seq_in(desc, data)                                           \
+	caam_desc_add_dmaobj(desc, data, SEQ_IN_PTR(0))
 #define caam_desc_seq_out(desc, data)                                          \
 	caam_desc_add_dmaobj(desc, data, SEQ_OUT_PTR(0))
 
@@ -202,6 +204,13 @@ static inline void dump_desc(uint32_t *desc)
 	(CMD_FIFO_LOAD_TYPE | CMD_IMM | CMD_CLASS(cla) |                       \
 	 FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len))
 
+/*
+ * SEQ FIFO Load from register src of length len
+ */
+#define FIFO_LD_SEQ(src, len)                                                  \
+	(CMD_SEQ_FIFO_LOAD_TYPE | FIFO_LOAD_INPUT(src) |                       \
+	 FIFO_LOAD_LENGTH(len))
+
 /*
  * Store value of length len from register src of class cla
  */
@@ -234,8 +243,9 @@ static inline void dump_desc(uint32_t *desc)
 /*
  * FIFO Store from register src of length len
  */
-#define FIFO_ST(src, len)                                                      \
-	(CMD_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | FIFO_STORE_LENGTH(len))
+#define FIFO_ST(cla, src, len)                                                 \
+	(CMD_FIFO_STORE_TYPE | CMD_CLASS(cla) | FIFO_STORE_OUTPUT(src) |       \
+	 FIFO_STORE_LENGTH(len))
 
 /*
  * FIFO Store from register src.
@@ -394,6 +404,12 @@ static inline void dump_desc(uint32_t *desc)
 	(CMD_KEY_TYPE | CMD_CLASS(CLASS_2) | KEY_DEST(MDHA_SPLIT) |            \
 	 KEY_LENGTH(len))
 
+/*
+ * Load a class cla key of length len to register dst.
+ */
+#define LD_KEY(cla, dst, len)                                                  \
+	(CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_DEST(dst) | KEY_LENGTH(len))
+
 /*
  * MPPRIVK generation function.
  */
@@ -484,21 +500,23 @@ static inline void dump_desc(uint32_t *desc)
 /*
  * RSA Finalize Key in format
  */
-#define RSA_FINAL_KEY(format)                                                  \
-	(CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format))
+#define RSA_FINAL_KEY(format, alg)                                             \
+	(CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format) |         \
+	 PROT_RSA_FINISH_KEY(alg))
 
 /*
  * Public Keypair generation
  */
-#define PK_KEYPAIR_GEN(type)                                                   \
-	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type))
+#define PK_KEYPAIR_GEN(type, alg)                                              \
+	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type) |     \
+	 PROT_PRI(alg))
 
 /*
  * DSA/ECDSA signature of message of msg_type
  */
-#define DSA_SIGN(type, msg_type)                        \
+#define DSA_SIGN(type, msg_type, alg) \
 	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | \
-	 PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type))
+	 PROT_PK_MSG(msg_type) | PROT_PK_TYPE(type) | PROT_PRI(alg))
 
 /*
  * DSA/ECDSA signature verify message of msg_type
@@ -510,9 +528,9 @@ static inline void dump_desc(uint32_t *desc)
 /*
  * DH/ECC Shared Secret
  */
-#define SHARED_SECRET(type)                                                    \
+#define SHARED_SECRET(type, alg)                                               \
 	(CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(SHARED_SECRET) |                  \
-	 PROT_PK_TYPE(type))
+	 PROT_PK_TYPE(type) | PROT_PRI(alg))
 
 /*
  * Blob Master Key Verification
diff --git a/core/drivers/crypto/caam/include/caam_hal_cfg.h b/core/drivers/crypto/caam/include/caam_hal_cfg.h
index 2d805620a40351e141175452b88ca30b321eb4c5..c9dfe62e18ad05cdc2e9f0952f93238543638952 100644
--- a/core/drivers/crypto/caam/include/caam_hal_cfg.h
+++ b/core/drivers/crypto/caam/include/caam_hal_cfg.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright 2018-2019 NXP
+ * Copyright 2018-2019, 2024 NXP
  *
  * Brief   CAAM Configuration header.
  */
@@ -27,6 +27,20 @@ enum caam_status caam_hal_cfg_get_conf(struct caam_jrcfg *jrcfg);
  */
 void caam_hal_cfg_setup_nsjobring(struct caam_jrcfg *jrcfg);
 
+/*
+ * Removes the JR used by HAB from dtb and backup its DID
+ *
+ * @jrcfg   Job Ring configuration of HAB JR
+ */
+void caam_hal_cfg_hab_jr_mgmt(struct caam_jrcfg *jrcfg);
+
+/*
+ * Indicate if the job ring is used by the HAB
+ *
+ * @jr_offset   Job Ring offset
+ */
+bool caam_hal_cfg_is_hab_jr(paddr_t jr_offset);
+
 #ifdef CFG_DT
 /*
  * Returns the Job Ring configuration to be used by the TEE
diff --git a/core/drivers/crypto/caam/include/caam_key.h b/core/drivers/crypto/caam/include/caam_key.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0a98a2a3fd88081a7a7872c4ff17219fba99933
--- /dev/null
+++ b/core/drivers/crypto/caam/include/caam_key.h
@@ -0,0 +1,155 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2023 NXP
+ */
+#ifndef __CAAM_KEY_H__
+#define __CAAM_KEY_H__
+
+#include <caam_types.h>
+#include <crypto/crypto.h>
+#include <types_ext.h>
+
+/*
+ * CAAM Key types
+ */
+enum caam_key_type {
+	CAAM_KEY_PLAIN_TEXT = 0, /* Plain text key or red key */
+	CAAM_KEY_BLACK_ECB, /* Black key AES-ECB encrypted */
+	CAAM_KEY_BLACK_CCM, /* Black key AES-CCM encrypted */
+	CAAM_KEY_MAX_VALUE, /* Max value - not valid */
+};
+
+/*
+ * CAAM key structure
+ */
+struct caamkey {
+	struct caambuf buf; /* Key buffer */
+	enum caam_key_type key_type; /* CAAM Key type */
+	size_t sec_size; /* Security key size */
+	bool is_blob; /* Shows if the key is in blob format */
+};
+
+/*
+ * Returns the default key type for CAAM key generation.
+ * The CAAM can only generate one key type.
+ */
+static inline enum caam_key_type caam_key_default_key_gen_type(void)
+{
+	return CAAM_KEY_BLACK_CCM;
+}
+
+/*
+ * Print CAAM Key structure
+ *
+ * @trace Additional log string
+ * @key Key to print
+ */
+void caam_key_dump(const char *trace, const struct caamkey *key);
+
+/*
+ * Allocate CAAM key buffer based on the CAAM key type, key security size, and
+ * whether it is in a blob format or not.
+ *
+ * @key CAAM key to allocate
+ */
+enum caam_status caam_key_alloc(struct caamkey *key);
+
+/*
+ * Free the CAAM key buffer
+ *
+ * @key CAAM key to free
+ */
+void caam_key_free(struct caamkey *key);
+
+/*
+ * Perform a cache operation on CAAM key buffer.
+ *
+ * @op Cache operation type
+ * @key CAAM key buffer to operate
+ */
+void caam_key_cache_op(enum utee_cache_operation op, const struct caamkey *key);
+
+/*
+ * Encapsulate or decapsulate the given CAAM key
+ *
+ * @in_key CAAM Key to encapsulate or decapsulate
+ * @out_key CAAM Key operation result. The out_key is allocated by the function.
+ */
+enum caam_status caam_key_operation_blob(const struct caamkey *in_key,
+					 struct caamkey *out_key);
+
+/*
+ * Deserialize CAAM key structure from binary buffer
+ *
+ * @data	Buffer input
+ * @size	Buffer input size
+ * @key		CAAM key structure to populate
+ * @sec_size	Security key size to deserialize, optional. If not needed,
+ *		set it to 0.
+ */
+enum caam_status caam_key_deserialize_from_bin(uint8_t *data, size_t size,
+					       struct caamkey *key,
+					       size_t sec_size);
+
+/*
+ * Serialize CAAM key structure to binary buffer
+ *
+ * @data	Buffer output
+ * @size	Buffer output size
+ * @key		CAAM key structure to serialize
+ */
+enum caam_status caam_key_serialize_to_bin(uint8_t *data, size_t size,
+					   const struct caamkey *key);
+
+/*
+ * Deserialize CAAM key structure from bignum
+ *
+ * @inkey	Bignum input
+ * @outkey	CAAM key structure to populate
+ * @size_sec	Security key size to deserialize, optional. If not needed,
+ *		set it to zero.
+ */
+enum caam_status caam_key_deserialize_from_bn(const struct bignum *inkey,
+					      struct caamkey *outkey,
+					      size_t size_sec);
+
+/*
+ * Serialize CAAM key structure to bignum
+ *
+ * @outkey	Bignum output
+ * @inkey	CAAM key structure to serialize
+ */
+enum caam_status caam_key_serialize_to_bn(struct bignum *outkey,
+					  const struct caamkey *inkey);
+
+/*
+ * Return the key buffer size needed given the CAAM key type, key security size,
+ * and whether it is in a blob format or not
+ *
+ * @key	CAAM key structure input
+ */
+size_t caam_key_get_alloc_size(const struct caamkey *key);
+
+/*
+ * Return the buffer size needed to serialize the given CAAM key structure
+ *
+ * @key		CAAM Key structure to serialize
+ * @size	returned buffer size
+ */
+enum caam_status caam_key_serialized_size(const struct caamkey *key,
+					  size_t *size);
+
+/*
+ * Encapsulate a plain text key to CAAM black key.
+ *
+ * @key		CAAM key to encapsulate
+ * @key_type	CAAM key encapsulation type
+ */
+enum caam_status caam_key_black_encapsulation(struct caamkey *key,
+					      enum caam_key_type key_type);
+
+/*
+ * CAAM Key initialization
+ */
+enum caam_status caam_key_init(void);
+#endif /* __CAAM_KEY_H__ */
diff --git a/core/drivers/crypto/caam/include/caam_trace.h b/core/drivers/crypto/caam/include/caam_trace.h
index 77772c613c4c373cb9dd5ca3ce4f1b57d5c9d138..d9a36ef274f8714aec65792a9569e1f226ff5183 100644
--- a/core/drivers/crypto/caam/include/caam_trace.h
+++ b/core/drivers/crypto/caam/include/caam_trace.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright 2019-2021 NXP
+ * Copyright 2019-2021, 2023-2024 NXP
  *
  * Brief   CAAM driver trace include file.
  *         Definition of the internal driver trace macros.
@@ -42,6 +42,8 @@
 #define DBG_TRACE_DSA	 BIT32(14) /* DSA trace */
 #define DBG_TRACE_MP	 BIT32(15) /* MP trace */
 #define DBG_TRACE_SM	 BIT32(16) /* Secure Memory trace */
+#define DBG_TRACE_KEY	 BIT32(17) /* KEY trace */
+#define DBG_TRACE_AE	 BIT32(18) /* AE trace */
 
 /* HAL */
 #if CAAM_DBG_TRACE(HAL)
@@ -240,7 +242,7 @@
 #if CAAM_DBG_DESC(DSA)
 #define DSA_DUMPDESC(desc)                                                     \
 	do {                                                                   \
-		MP_TRACE("DSA Descriptor");                                    \
+		DSA_TRACE("DSA Descriptor");                                   \
 		DRV_DUMPDESC(desc);                                            \
 	} while (0)
 #else
@@ -280,6 +282,29 @@
 #define MP_DUMPBUF(...)
 #endif
 
+/* KEY */
+#if CAAM_DBG_TRACE(KEY)
+#define KEY_TRACE DRV_TRACE
+#if CAAM_DBG_DESC(KEY)
+#define KEY_DUMPDESC(desc)			\
+	do {					\
+		KEY_TRACE("KEY Descriptor");	\
+		DRV_DUMPDESC(desc);		\
+	} while (0)
+#else
+#define KEY_DUMPDESC(desc)
+#endif
+#if CAAM_DBG_BUF(KEY)
+#define KEY_DUMPBUF DRV_DUMPBUF
+#else
+#define KEY_DUMPBUF(...)
+#endif
+#else
+#define KEY_TRACE(...) do { } while (0)
+#define KEY_DUMPDESC(desc) do { } while (0)
+#define KEY_DUMPBUF(...) do { } while (0)
+#endif
+
 #if (TRACE_LEVEL >= TRACE_DEBUG)
 #define DRV_TRACE(...)                                                         \
 	trace_printf(__func__, __LINE__, TRACE_DEBUG, true, __VA_ARGS__)
@@ -330,4 +355,27 @@
 #define SM_TRACE(...)
 #endif
 
+/* Cipher AE */
+#if CAAM_DBG_TRACE(AE)
+#define AE_TRACE DRV_TRACE
+#if CAAM_DBG_DESC(AE)
+#define AE_DUMPDESC(desc)                                              \
+	do {                                                           \
+		AE_TRACE("AE Descriptor");                             \
+		DRV_DUMPDESC(desc);                                    \
+	} while (0)
+#else
+#define AE_DUMPDESC(...)
+#endif
+#if CAAM_DBG_BUF(AE)
+#define AE_DUMPBUF DRV_DUMPBUF
+#else
+#define AE_DUMPBUF(...)
+#endif
+#else
+#define AE_TRACE(...)
+#define AE_DUMPDESC(...)
+#define AE_DUMPBUF(...)
+#endif
+
 #endif /* CAAM_TRACE_H__ */
diff --git a/core/drivers/crypto/caam/include/caam_utils_mem.h b/core/drivers/crypto/caam/include/caam_utils_mem.h
index cb7ce2c77da9ad47a83d605ab0dffcd66fe8d4e8..fb8adb8352a215a838f1597b0627051c97b14f5b 100644
--- a/core/drivers/crypto/caam/include/caam_utils_mem.h
+++ b/core/drivers/crypto/caam/include/caam_utils_mem.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2024 NXP
  *
  * Brief   Memory management utilities.
  *         Primitive to allocate, free memory.
@@ -95,7 +95,7 @@ void caam_free_buf(struct caambuf *buf);
 
 /*
  * Copy source data into the block buffer. Allocate block buffer if
- * it's not defined.
+ * it's not already allocated.
  *
  * @block  [in/out] Block buffer information. Return buffer filled.
  * @src    Source to copy
@@ -104,6 +104,16 @@ void caam_free_buf(struct caambuf *buf);
 enum caam_status caam_cpy_block_src(struct caamblock *block,
 				    struct caambuf *src, size_t offset);
 
+/*
+ * Copy data into the buffer. Allocate buffer if it's not already allocated.
+ *
+ * @dst         [out] Destination data to allocate and fill
+ * @src_data    Source to copy
+ * @src_length  Length to copy
+ */
+enum caam_status caam_cpy_buf(struct caambuf *dst, uint8_t *src_data,
+			      size_t src_length);
+
 /*
  * Return the number of Physical Areas used by the buffer @buf.
  * If @pabufs is not NULL, function fills it with the Physical Areas used
diff --git a/core/drivers/crypto/caam/include/caam_utils_status.h b/core/drivers/crypto/caam/include/caam_utils_status.h
index 8da32dc5da17569b8a554d38741342f0760a37ef..886de0ebfde7230c046349d20c0b0c6af18111ef 100644
--- a/core/drivers/crypto/caam/include/caam_utils_status.h
+++ b/core/drivers/crypto/caam/include/caam_utils_status.h
@@ -7,6 +7,7 @@
 #ifndef __CAAM_UTILS_STATUS_H__
 #define __CAAM_UTILS_STATUS_H__
 
+#include <caam_status.h>
 #include <stdint.h>
 #include <tee_api_types.h>
 
diff --git a/core/drivers/crypto/caam/sub.mk b/core/drivers/crypto/caam/sub.mk
index 8124501074250bbe57097b1c322b0764ab68a115..7ca62774c7bdc64e56807f3b89310834af0db87c 100644
--- a/core/drivers/crypto/caam/sub.mk
+++ b/core/drivers/crypto/caam/sub.mk
@@ -9,8 +9,10 @@ srcs-y += caam_jr.c
 srcs-y += caam_rng.c
 srcs-y += caam_desc.c
 srcs-$(CFG_NXP_CAAM_SM_DRV) += caam_sm.c
+srcs-y += caam_key.c
 subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_HASH_DRV CFG_NXP_CAAM_HMAC_DRV) += hash
 subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_CIPHER_DRV CFG_NXP_CAAM_CMAC_DRV) += cipher
+subdirs-$(call cfg-one-enabled, CFG_NXP_CAAM_AE_CCM_DRV CFG_NXP_CAAM_AE_GCM_DRV) += ae
 subdirs-y += acipher
 subdirs-y += blob
 subdirs-$(CFG_NXP_CAAM_MP_DRV) += mp
diff --git a/core/drivers/crypto/caam/utils/utils_dmaobj.c b/core/drivers/crypto/caam/utils/utils_dmaobj.c
index 424757c1479666a923c69869e18cb8758441e73c..ce2ab34fdd38c45900340382b818ade14d7c5657 100644
--- a/core/drivers/crypto/caam/utils/utils_dmaobj.c
+++ b/core/drivers/crypto/caam/utils/utils_dmaobj.c
@@ -386,7 +386,7 @@ static TEE_Result check_buffer_alignment(struct priv_dmaobj *priv,
 		}
 
 		va_start = (vaddr_t)entry->origbuf.data;
-		va_start_align = ROUNDUP(va_start, cacheline_size);
+		va_start_align = ROUNDUP2(va_start, cacheline_size);
 
 		if (va_start_align != va_start) {
 			DMAOBJ_TRACE("Start 0x%" PRIxVA " vs align 0x%" PRIxVA,
@@ -443,13 +443,13 @@ static TEE_Result check_buffer_alignment(struct priv_dmaobj *priv,
 		}
 
 		va_end = (vaddr_t)entry->origbuf.data + entry->origbuf.length;
-		va_end_align = ROUNDUP(va_end, cacheline_size);
+		va_end_align = ROUNDUP2(va_end, cacheline_size);
 
 		if (va_end != va_end_align) {
 			DMAOBJ_TRACE("End 0x%" PRIxVA " vs align 0x%" PRIxVA,
 				     va_end, va_end_align);
 
-			va_end_align = ROUNDDOWN(va_end, cacheline_size);
+			va_end_align = ROUNDDOWN2(va_end, cacheline_size);
 			remlen = entry->origbuf.length - va_end_align;
 
 			if (remlen <= cacheline_size) {
@@ -1296,7 +1296,7 @@ TEE_Result caam_dmaobj_sgtbuf_build(struct caamdmaobj *obj, size_t *length,
 	max_length = *length;
 	if (priv->dmabuf.allocated && max_length > priv->dmabuf.allocated &&
 	    priv->dmabuf.allocated > align)
-		max_length = ROUNDDOWN(priv->dmabuf.allocated, align);
+		max_length = ROUNDDOWN2(priv->dmabuf.allocated, align);
 
 	DMAOBJ_TRACE("Prepare SGT/Buffer to do %zu of %zu", max_length,
 		     *length);
diff --git a/core/drivers/crypto/caam/utils/utils_mem.c b/core/drivers/crypto/caam/utils/utils_mem.c
index e7c23cdee43d42d3e81f219aa0bcf97c88ae42e4..1f187e527e3dde1f90e0d56a6662adb9ddfe7a82 100644
--- a/core/drivers/crypto/caam/utils/utils_mem.c
+++ b/core/drivers/crypto/caam/utils/utils_mem.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2021, 2024 NXP
  *
  * Brief   Memory management utilities.
  *         Primitive to allocate, free memory.
@@ -12,6 +12,7 @@
 #include <io.h>
 #include <kernel/cache_helpers.h>
 #include <mm/core_memprot.h>
+#include <tee/cache.h>
 #include <string.h>
 
 #define MEM_TYPE_NORMAL 0      /* Normal allocation */
@@ -50,7 +51,7 @@ static void *mem_alloc(size_t size, uint8_t type)
 				     &alloc_size))
 			return NULL;
 
-		if (ROUNDUP_OVERFLOW(alloc_size, cacheline_size, &alloc_size))
+		if (ROUNDUP2_OVERFLOW(alloc_size, cacheline_size, &alloc_size))
 			return NULL;
 
 		ptr = memalign(cacheline_size, alloc_size);
@@ -230,6 +231,37 @@ end_cpy:
 	return ret;
 }
 
+enum caam_status caam_cpy_buf(struct caambuf *dst, uint8_t *src_data,
+			      size_t src_length)
+{
+	enum caam_status ret = CAAM_FAILURE;
+
+	if (!src_data || !dst)
+		return CAAM_FAILURE;
+
+	if (!src_length)
+		return CAAM_NO_ERROR;
+
+	if (!dst->data) {
+		/* Allocate the destination buffer */
+		ret = caam_alloc_align_buf(dst, src_length);
+		if (ret != CAAM_NO_ERROR) {
+			MEM_TRACE("Allocation buffer error");
+			return ret;
+		}
+	}
+
+	assert(dst->length == src_length);
+
+	/* Do the copy */
+	memcpy(dst->data, src_data, dst->length);
+
+	/* Push data to physical memory */
+	cache_operation(TEE_CACHECLEAN, dst->data, dst->length);
+
+	return CAAM_NO_ERROR;
+}
+
 int caam_mem_get_pa_area(struct caambuf *buf, struct caambuf **out_pabufs)
 {
 	int nb_pa_area = 0;
diff --git a/core/drivers/crypto/crypto_api/acipher/rsa.c b/core/drivers/crypto/crypto_api/acipher/rsa.c
index 24b26c219aa38f2015f1651b1ca0176e6debbf51..ca3ea3acf0bee52dc7db13ee645e377098327dae 100644
--- a/core/drivers/crypto/crypto_api/acipher/rsa.c
+++ b/core/drivers/crypto/crypto_api/acipher/rsa.c
@@ -199,6 +199,7 @@ TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
 
 TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
 					const uint8_t *label, size_t label_len,
+					uint32_t mgf_algo,
 					const uint8_t *cipher,
 					size_t cipher_len, uint8_t *msg,
 					size_t *msg_len)
@@ -231,6 +232,12 @@ TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
 			if (ret != TEE_SUCCESS)
 				return ret;
 
+			rsa_data.mgf_algo = mgf_algo;
+			ret = tee_alg_get_digest_size(rsa_data.mgf_algo,
+						      &rsa_data.mgf_size);
+			if (ret != TEE_SUCCESS)
+				return ret;
+
 			rsa_data.mgf = &drvcrypt_rsa_mgf1;
 		}
 
@@ -261,6 +268,7 @@ TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
 TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
 					struct rsa_public_key *key,
 					const uint8_t *label, size_t label_len,
+					uint32_t mgf_algo,
 					const uint8_t *msg, size_t msg_len,
 					uint8_t *cipher, size_t *cipher_len)
 {
@@ -322,6 +330,12 @@ TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
 			    rsa_data.key.n_size - 2 * rsa_data.digest_size - 2)
 				return TEE_ERROR_BAD_PARAMETERS;
 
+			rsa_data.mgf_algo = mgf_algo;
+			ret = tee_alg_get_digest_size(rsa_data.mgf_algo,
+						      &rsa_data.mgf_size);
+			if (ret != TEE_SUCCESS)
+				return ret;
+
 			rsa_data.mgf = &drvcrypt_rsa_mgf1;
 		}
 
diff --git a/core/drivers/crypto/crypto_api/acipher/rsassa.c b/core/drivers/crypto/crypto_api/acipher/rsassa.c
index c37670c8af895cc7b66266c69250f135c60581b6..0f71b84cc51c697daefb2fd23a3ee172c2ee86bc 100644
--- a/core/drivers/crypto/crypto_api/acipher/rsassa.c
+++ b/core/drivers/crypto/crypto_api/acipher/rsassa.c
@@ -748,7 +748,7 @@ static TEE_Result rsassa_pss_sign(struct drvcrypt_rsa_ssa *ssa_data)
 	 * if (modBits - 1) is not divisible by 8, one more byte is needed
 	 */
 	modBits--;
-	EM.length = ROUNDUP(modBits, 8) / 8;
+	EM.length = ROUNDUP_DIV(modBits, 8);
 
 	if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2)
 		return TEE_ERROR_BAD_PARAMETERS;
@@ -823,7 +823,7 @@ static TEE_Result rsassa_pss_verify(struct drvcrypt_rsa_ssa *ssa_data)
 	 * if (modBits - 1) is not divisible by 8, one more byte is needed
 	 */
 	modBits--;
-	EM.length = ROUNDUP(modBits, 8) / 8;
+	EM.length = ROUNDUP_DIV(modBits, 8);
 
 	if (EM.length < ssa_data->digest_size + ssa_data->salt_len + 2)
 		return TEE_ERROR_BAD_PARAMETERS;
diff --git a/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h b/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h
index 2a009c9816f7f4d5ee17bcc073a1e8a0b3e420bc..26c0bebb5d9a470fa532fa1772de6b4edbd972d1 100644
--- a/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h
+++ b/core/drivers/crypto/crypto_api/include/drvcrypt_acipher.h
@@ -68,6 +68,8 @@ struct drvcrypt_rsa_ed {
 	struct drvcrypt_buf message; /* Message to encrypt or decrypted */
 	struct drvcrypt_buf cipher;  /* Cipher encrypted or to decrypt */
 	struct drvcrypt_buf label;   /* Additional Label (RSAES) */
+	uint32_t mgf_algo;           /* MGF1 hash algorithm (RSAES) */
+	size_t mgf_size;             /* MGF1 hash digest size (RSAES) */
 
 	/* RSA Mask Generation function */
 	TEE_Result (*mgf)(struct drvcrypt_rsa_mgf *mgf_data);
diff --git a/core/drivers/crypto/hisilicon/crypto.mk b/core/drivers/crypto/hisilicon/crypto.mk
new file mode 100644
index 0000000000000000000000000000000000000000..bc2561ceaa462c2d322de64661200f90ecade658
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/crypto.mk
@@ -0,0 +1,19 @@
+ifeq ($(CFG_HISILICON_CRYPTO_DRIVER), y)
+$(call force,CFG_CRYPTO_DRIVER,y)
+CFG_CRYPTO_DRIVER_DEBUG ?= 0
+
+$(call force, CFG_CRYPTO_DRV_ACIPHER,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force, CFG_CRYPTO_DRV_HASH,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force, CFG_CRYPTO_DRV_MAC,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force, CFG_CRYPTO_DRV_CIPHER,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force,CFG_CRYPTO_DRV_AUTHENC,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force,CFG_CRYPTO_PBKDF2,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+$(call force,CFG_CRYPTO_HW_PBKDF2,y,Mandated by CFG_HISILICON_CRYPTO_DRIVER)
+
+ifeq ($(CFG_HISILICON_ACC_V3), y)
+$(call force, CFG_CRYPTO_DRV_DH,y,Mandated by CFG_HISILICON_ACC_V3)
+$(call force,CFG_CRYPTO_DRV_ECC,y,Mandated by CFG_HISILICON_ACC_V3)
+$(call force,CFG_CRYPTO_DRV_RSA,y,Mandated by CFG_HISILICON_ACC_V3)
+endif
+
+endif
diff --git a/core/drivers/crypto/hisilicon/hisi_qm.c b/core/drivers/crypto/hisilicon/hisi_qm.c
index daf7901a857fd67433258ca14c9c5f42d99eecda..a7f1bf343021df068aef01fc8c8f351ba77d8e1d 100644
--- a/core/drivers/crypto/hisilicon/hisi_qm.c
+++ b/core/drivers/crypto/hisilicon/hisi_qm.c
@@ -67,6 +67,10 @@
 #define QM_CACHE_CFG		0x4893
 #define QM_CACHE_WB_START	0x204
 #define QM_CACHE_WB_DONE	0x208
+#define QM_PM_CTRL0		0x100148
+#define QM_IDLE_DISABLE		BIT(9)
+#define QM_DB_TIMEOUT_CFG	0x100074
+#define QM_DB_TIMEOUT_SET	0x1fffff
 /* XQC shift */
 #define QM_SQ_SQE_SIZE_SHIFT	12
 #define QM_SQ_ORDER_SHIFT	4
@@ -318,11 +322,6 @@ static enum hisi_drv_status qm_set_xqc_vft(struct hisi_qm *qm,
 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
 	int i = 0;
 
-	if (!num) {
-		EMSG("Invalid sq num");
-		return HISI_QM_DRVCRYPT_EINVAL;
-	}
-
 	for (i = QM_SQC_VFT; i <= QM_CQC_VFT; i++) {
 		ret = qm_set_vft_common(qm, i, function, base, num);
 		if (ret) {
@@ -617,11 +616,22 @@ enum hisi_drv_status hisi_qm_start(struct hisi_qm *qm)
 	return HISI_QM_DRVCRYPT_NO_ERR;
 }
 
+static void qm_disable_clock_gate(struct hisi_qm *qm)
+
+{
+	if (qm->version == HISI_QM_HW_V2)
+		return;
+
+	io_setbits32(qm->io_base + QM_PM_CTRL0, QM_IDLE_DISABLE);
+}
+
 void hisi_qm_dev_init(struct hisi_qm *qm)
 {
 	if (qm->fun_type == HISI_QM_HW_VF)
 		return;
 
+	qm_disable_clock_gate(qm);
+
 	/* QM user domain */
 	io_write32(qm->io_base + QM_ARUSER_M_CFG_1, QM_AXUSER_CFG);
 	io_write32(qm->io_base + QM_ARUSER_M_CFG_ENABLE, AXUSER_M_CFG_ENABLE);
@@ -639,6 +649,8 @@ void hisi_qm_dev_init(struct hisi_qm *qm)
 	/* Disable QM ras */
 	io_write32(qm->io_base + HISI_QM_ABNML_INT_MASK,
 		   HISI_QM_ABNML_INT_MASK_CFG);
+	/* Set doorbell timeout to QM_DB_TIMEOUT_SET ns */
+	io_write32(qm->io_base + QM_DB_TIMEOUT_CFG, QM_DB_TIMEOUT_SET);
 }
 
 static enum hisi_drv_status qm_sqc_cfg(struct hisi_qp *qp)
@@ -719,18 +731,20 @@ struct hisi_qp *hisi_qm_create_qp(struct hisi_qm *qm, uint8_t sq_type)
 
 	if (qm_sqc_cfg(qp)) {
 		EMSG("Fail to set qp[%"PRIu32"] sqc", qp->qp_id);
-		goto err_proc;
+		goto err_qp_release;
 	}
 
 	if (qm_cqc_cfg(qp)) {
 		EMSG("Fail to set qp[%"PRIu32"] cqc", qp->qp_id);
-		goto err_proc;
+		goto err_qp_release;
 	}
 
 	qm->qp_in_used++;
 	mutex_unlock(&qm->qp_lock);
 	return qp;
 
+err_qp_release:
+	qp->used = false;
 err_proc:
 	qp->sq_type = 0;
 	qp->cqc_phase = false;
@@ -858,8 +872,8 @@ enum hisi_drv_status hisi_qp_recv_sync(struct hisi_qp *qp, void *msg)
 	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
 	uint32_t timeout = 0;
 
-	if (!qp) {
-		EMSG("QP is NULL");
+	if (!qp || !qp->qm || !msg) {
+		EMSG("Invalid qp recv sync parameters");
 		return HISI_QM_DRVCRYPT_EINVAL;
 	}
 
diff --git a/core/drivers/crypto/hisilicon/include/hisi_qm.h b/core/drivers/crypto/hisilicon/hisi_qm.h
similarity index 100%
rename from core/drivers/crypto/hisilicon/include/hisi_qm.h
rename to core/drivers/crypto/hisilicon/hisi_qm.h
diff --git a/core/drivers/crypto/hisilicon/hpre_dh.c b/core/drivers/crypto/hisilicon/hpre_dh.c
new file mode 100644
index 0000000000000000000000000000000000000000..82d7c8f33181954b4aaa40292943585dae733f99
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_dh.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
+ * Kunpeng hardware accelerator hpre dh algorithm implementation.
+ */
+
+#include <drvcrypt.h>
+#include <drvcrypt_acipher.h>
+#include <initcall.h>
+#include <malloc.h>
+#include <rng_support.h>
+#include <stdlib_ext.h>
+#include <string.h>
+#include <string_ext.h>
+#include <trace.h>
+
+#include "hpre_dh.h"
+#include "hpre_main.h"
+
+static TEE_Result hpre_dh_alloc_keypair(struct dh_keypair *key,
+					size_t size_bits)
+{
+	if (!key || !size_bits) {
+		EMSG("Invalid input parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	memset(key, 0, sizeof(*key));
+	key->g = crypto_bignum_allocate(size_bits);
+	if (!key->g)
+		goto g_err;
+
+	key->p = crypto_bignum_allocate(size_bits);
+	if (!key->p)
+		goto p_err;
+
+	key->x = crypto_bignum_allocate(size_bits);
+	if (!key->x)
+		goto x_err;
+
+	key->y = crypto_bignum_allocate(size_bits);
+	if (!key->y)
+		goto y_err;
+
+	/* Allocate subprime even if not used */
+	key->q = crypto_bignum_allocate(size_bits);
+	if (!key->q)
+		goto q_err;
+
+	return TEE_SUCCESS;
+q_err:
+	crypto_bignum_free(&key->y);
+y_err:
+	crypto_bignum_free(&key->x);
+x_err:
+	crypto_bignum_free(&key->p);
+p_err:
+	crypto_bignum_free(&key->g);
+g_err:
+	EMSG("HPRE dh alloc key pair fail.");
+
+	return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static enum hisi_drv_status hpre_dh_fill_sqe(void *bd, void *info)
+{
+	struct hpre_dh_msg *msg = info;
+	struct hpre_sqe *sqe = bd;
+
+	sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT);
+	sqe->task_len1 = TASK_LENGTH(msg->key_bytes);
+	sqe->key = msg->x_p_dma;
+	sqe->in = msg->g_dma;
+	sqe->out = msg->out_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status hpre_dh_parse_sqe(void *bd, void *info)
+{
+	struct hpre_dh_msg *msg = info;
+	struct hpre_sqe *sqe = bd;
+	uint16_t err = 0;
+	uint16_t done = 0;
+
+	err = HPRE_TASK_ETYPE(sqe->w0);
+	done = HPRE_TASK_DONE(sqe->w0);
+	if (done != HPRE_HW_TASK_DONE || err) {
+		EMSG("HPRE do dh fail! done=0x%"PRIx16", etype=0x%"PRIx16,
+		     done, err);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	if (hpre_bin_to_crypto_bin(msg->out, msg->out, msg->key_bytes,
+				   msg->out_bytes)) {
+		EMSG("Fail to transfer dh_y from hpre_bin to crypto_bin");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result hpre_dh_do_task(void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	TEE_Result res = TEE_SUCCESS;
+	struct hisi_qp *qp = NULL;
+
+	qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE0);
+	if (!qp) {
+		EMSG("Fail to create dh qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	qp->fill_sqe = hpre_dh_fill_sqe;
+	qp->parse_sqe = hpre_dh_parse_sqe;
+	ret = hisi_qp_send(qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+	ret = hisi_qp_recv_sync(qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+done_proc:
+	hisi_qm_release_qp(qp);
+
+	return res;
+}
+
+static size_t round_key_size_to_hw_size(size_t key_bytes)
+{
+	size_t size = 0;
+
+	if (key_bytes <= 96)
+		size = 96;
+	else if (key_bytes <= 128)
+		size = 128;
+	else if (key_bytes <= 192)
+		size = 192;
+	else if (key_bytes <= 256)
+		size = 256;
+	else if (key_bytes <= 384)
+		size = 384;
+	else if (key_bytes <= 512)
+		size = 512;
+	else
+		EMSG("Invalid key_bytes[%zu]", key_bytes);
+
+	return size;
+}
+
+static TEE_Result hpre_dh_gen_privkey(struct bignum *x, size_t key_bits)
+{
+	size_t key_bytes = BITS_TO_BYTES(key_bits);
+	uint8_t buf[HPRE_DH_MAX_KEY_BYTES] = { };
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (hw_get_random_bytes(buf, key_bytes)) {
+		EMSG("Fail to fill privkey");
+		return TEE_ERROR_NO_DATA;
+	}
+
+	ret = crypto_bignum_bin2bn(buf, key_bytes, x);
+	memzero_explicit(buf, key_bytes);
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_dh_params_alloc(struct hpre_dh_msg *msg)
+{
+	uint32_t size = HPRE_DH_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc dh total buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->x_p = data;
+	msg->x_p_dma = virt_to_phys(msg->x_p);
+
+	msg->g = msg->x_p + (msg->key_bytes << 1);
+	msg->g_dma = msg->x_p_dma + (msg->key_bytes << 1);
+	msg->out = msg->g + msg->key_bytes;
+	msg->out_dma = msg->g_dma + msg->key_bytes;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_dh_params_free(struct hpre_dh_msg *msg)
+{
+	if (msg->x_p) {
+		free_wipe(msg->x_p);
+		msg->x_p = NULL;
+	}
+}
+
+static enum hisi_drv_status hpre_dh_params_bn2bin(struct hpre_dh_msg *msg,
+						  struct dh_keypair *key,
+						  struct bignum *pubkey)
+{
+	uint8_t *p = msg->x_p + msg->key_bytes;
+	uint8_t *x = msg->x_p;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->xbytes = BITS_TO_BYTES(key->xbits);
+	msg->out_bytes = msg->pbytes;
+	crypto_bignum_bn2bin(key->x, x);
+	crypto_bignum_bn2bin(key->p, p);
+
+	if (!pubkey) {
+		msg->gbytes = crypto_bignum_num_bytes(key->g);
+		crypto_bignum_bn2bin(key->g, msg->g);
+	} else {
+		msg->gbytes = crypto_bignum_num_bytes(pubkey);
+		if (msg->gbytes != msg->pbytes)
+			return HISI_QM_DRVCRYPT_EINVAL;
+		crypto_bignum_bn2bin(pubkey, msg->g);
+	}
+
+	ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes, msg->xbytes);
+	if (ret) {
+		EMSG("Fail to transfer dh_x from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(p, p, msg->key_bytes, msg->pbytes);
+	if (ret) {
+		EMSG("Fail to transfer dh_p from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(msg->g, msg->g, msg->key_bytes,
+				       msg->gbytes);
+	if (ret)
+		EMSG("Fail to transfer dh_g from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static TEE_Result hpre_dh_request_init(struct hpre_dh_msg *msg,
+				       struct dh_keypair *key,
+				       struct bignum *pubkey)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->alg_type = HPRE_ALG_DH;
+	msg->key_bytes = round_key_size_to_hw_size(msg->pbytes);
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_dh_params_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_dh_params_bn2bin(msg, key, pubkey);
+	if (ret) {
+		hpre_dh_params_free(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void hpre_dh_request_deinit(struct hpre_dh_msg *msg)
+{
+	hpre_dh_params_free(msg);
+}
+
+static TEE_Result hpre_dh_gen_keypair(struct dh_keypair *key,
+				      struct bignum *q __unused,
+				      size_t key_size)
+{
+	struct hpre_dh_msg msg = { };
+	TEE_Result ret = TEE_SUCCESS;
+	size_t p_bits = 0;
+
+	if (!key || !key->g || !key->p || !key->x || !key->y) {
+		EMSG("Invalid dh_gen_keypair input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	p_bits = crypto_bignum_num_bits(key->p);
+	if (!p_bits) {
+		EMSG("p_bits can not be zero");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+	msg.pbytes = BITS_TO_BYTES(p_bits);
+
+	if (!key_size) {
+		/* xbits */
+		key->xbits = p_bits;
+		ret = hpre_dh_gen_privkey(key->x, key->xbits);
+		if (ret) {
+			EMSG("Fail to gen dh privkey");
+			return ret;
+		}
+	} else {
+		key->xbits = key_size;
+	}
+
+	ret = hpre_dh_request_init(&msg, key, NULL);
+	if (ret) {
+		EMSG("Fail to init dh msg");
+		return ret;
+	}
+
+	ret = hpre_dh_do_task(&msg);
+	if (ret)
+		goto req_deinit;
+
+	ret = crypto_bignum_bin2bn(msg.out, msg.out_bytes, key->y);
+	if (ret)
+		EMSG("Fail to bin2bn msg out");
+
+req_deinit:
+	hpre_dh_request_deinit(&msg);
+
+	return ret;
+}
+
+static TEE_Result hpre_dh_do_shared_secret(struct drvcrypt_secret_data *sdata)
+{
+	struct hpre_dh_msg msg = { };
+	struct dh_keypair *key = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!sdata || !sdata->key_priv || !sdata->key_pub) {
+		EMSG("Invalid dh_do_shared_secret input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	key = sdata->key_priv;
+	key->xbits = crypto_bignum_num_bits(key->x);
+	if (!key->xbits) {
+		EMSG("xbits can not be zero");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+	msg.pbytes = crypto_bignum_num_bytes(key->p);
+
+	ret = hpre_dh_request_init(&msg, key, (struct bignum *)sdata->key_pub);
+	if (ret) {
+		EMSG("Fail to init dh msg");
+		return ret;
+	}
+
+	ret = hpre_dh_do_task(&msg);
+	if (ret)
+		goto req_deinit;
+
+	sdata->secret.length = msg.out_bytes;
+	memcpy(sdata->secret.data, msg.out, msg.out_bytes);
+	memzero_explicit(msg.out, msg.out_bytes);
+
+req_deinit:
+	hpre_dh_request_deinit(&msg);
+
+	return ret;
+}
+
+static struct drvcrypt_dh driver_dh = {
+	.alloc_keypair = hpre_dh_alloc_keypair,
+	.gen_keypair = hpre_dh_gen_keypair,
+	.shared_secret = hpre_dh_do_shared_secret,
+};
+
+TEE_Result hpre_dh_init(void)
+{
+	TEE_Result ret = drvcrypt_register_dh(&driver_dh);
+
+	if (ret != TEE_SUCCESS)
+		EMSG("hpre dh register to crypto fail.");
+
+	return ret;
+}
+
+driver_init(hpre_dh_init);
diff --git a/core/drivers/crypto/hisilicon/hpre_dh.h b/core/drivers/crypto/hisilicon/hpre_dh.h
new file mode 100644
index 0000000000000000000000000000000000000000..3123314b89c955b56225774a401e7e1188c2837c
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_dh.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
+ */
+
+#ifndef __HPRE_DH_H__
+#define __HPRE_DH_H__
+
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+#define HPRE_DH_MAX_KEY_BYTES 512
+#define HPRE_DH_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 4)
+
+struct hpre_dh_msg {
+	uint8_t *x_p; /* X and p data in order */
+	paddr_t x_p_dma;
+	uint8_t *g;
+	paddr_t g_dma;
+	uint8_t *out;
+	paddr_t out_dma;
+	uint32_t alg_type;
+	uint32_t key_bytes;
+	uint32_t xbytes;
+	uint32_t pbytes;
+	uint32_t gbytes;
+	uint32_t out_bytes;
+};
+
+TEE_Result hpre_dh_init(void);
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/hpre_ecc.c b/core/drivers/crypto/hisilicon/hpre_ecc.c
new file mode 100644
index 0000000000000000000000000000000000000000..04d7f935e3e701a717634b1bba42b533b637fe19
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_ecc.c
@@ -0,0 +1,1475 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022, HiSilicon Technologies Co., Ltd.
+ * Kunpeng hardware accelerator hpre ecc algorithm implementation.
+ */
+#include <drvcrypt.h>
+#include <drvcrypt_acipher.h>
+#include <initcall.h>
+#include <malloc.h>
+#include <rng_support.h>
+#include <stdlib_ext.h>
+#include <string.h>
+#include <string_ext.h>
+#include <trace.h>
+
+#include "hpre_main.h"
+#include "hpre_ecc.h"
+
+#define ECC_DH_IN_PARAM_NUM	2
+#define ECC_DH_KEY_PARAM_NUM	4
+#define ECC_DH_OUT_PARAM_NUM	2
+#define ECC_DH_IN_SIZE(hsz)	((hsz) * ECC_DH_IN_PARAM_NUM)
+#define ECC_DH_KEY_SIZE(hsz)	((hsz) * ECC_DH_KEY_PARAM_NUM)
+#define ECC_DH_OUT_SIZE(hsz)	((hsz) * ECC_DH_OUT_PARAM_NUM)
+
+#define ECC_SIGN_IN_PARAM_NUM	2
+#define ECC_SIGN_KEY_PARAM_NUM	7
+#define SM2_DEC_KEY_PARAM_NUM	4
+#define SM2_DEC_IN_PARAM_NUM	4
+#define ECC_SIGN_OUT_PARAM_NUM	2
+#define ECC_SIGN_IN_SIZE(hsz)	((hsz) * ECC_SIGN_IN_PARAM_NUM)
+#define ECC_SIGN_KEY_SIZE(hsz)	((hsz) * ECC_SIGN_KEY_PARAM_NUM)
+#define ECC_SIGN_OUT_SIZE(hsz)	((hsz) * ECC_SIGN_OUT_PARAM_NUM)
+
+#define ECC_VERIF_IN_PARAM_NUM	3
+#define ECC_VERIF_KEY_PARAM_NUM	8
+#define SM2_ENC_KEY_PARAM_NUM	8
+#define ECC_VERIF_IN_SIZE(hsz)	((hsz) * ECC_VERIF_IN_PARAM_NUM)
+#define ECC_VERIF_KEY_SIZE(hsz)	((hsz) * ECC_VERIF_KEY_PARAM_NUM)
+#define SM2_ENC_KEY_SIZE(hsz)	((hsz) * SM2_ENC_KEY_PARAM_NUM)
+#define SM2_DEC_KEY_SIZE(hsz)	((hsz) * SM2_DEC_KEY_PARAM_NUM)
+#define ECC_POINT_PARAM_NUM		2
+#define MAX_SM2_MLEN			512
+
+#define HPRE_ECC_DH_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 8)
+#define HPRE_ECC_SIGN_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 11)
+#define HPRE_ECC_VERIFY_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 11)
+#define HPRE_SM2_ENC_TOTAL_BUF_SIZE(key_bytes, sm2_mlen) \
+	((key_bytes) * 12 + (sm2_mlen) * 2)
+#define HPRE_SM2_DEC_TOTAL_BUF_SIZE(key_bytes, sm2_mlen) \
+	((key_bytes) * 7 + (sm2_mlen) * 2)
+
+#define SM2_X2Y2_LEN 64
+
+struct hpre_ecc_curve {
+	const uint32_t id;
+	const uint32_t key_bits;
+	const uint8_t *p;
+	const uint8_t *a;
+	const uint8_t *b;
+	const uint8_t *x;
+	const uint8_t *y;
+	const uint8_t *n;
+};
+
+/* NID_X9_62_prime192v1 */
+static const uint8_t g_prime192v1_p[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t g_prime192v1_a[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+
+static const uint8_t g_prime192v1_b[] = {
+	0x64, 0x21, 0x05, 0x19, 0xE5, 0x9C, 0x80, 0xE7, 0x0F, 0xA7, 0xE9, 0xAB,
+	0x72, 0x24, 0x30, 0x49, 0xFE, 0xB8, 0xDE, 0xEC, 0xC1, 0x46, 0xB9, 0xB1
+};
+
+static const uint8_t g_prime192v1_gx[] = {
+	0x18, 0x8D, 0xA8, 0x0E, 0xB0, 0x30, 0x90, 0xF6, 0x7C, 0xBF, 0x20, 0xEB,
+	0x43, 0xA1, 0x88, 0x00, 0xF4, 0xFF, 0x0A, 0xFD, 0x82, 0xFF, 0x10, 0x12
+};
+
+static const uint8_t g_prime192v1_gy[] = {
+	0x07, 0x19, 0x2b, 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed,
+	0x6b, 0x24, 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11
+};
+
+static const uint8_t g_prime192v1_n[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x99, 0xDE, 0xF8, 0x36, 0x14, 0x6B, 0xC9, 0xB1, 0xB4, 0xD2, 0x28, 0x31
+};
+
+/* NID_secp224r1 */
+static const uint8_t g_secp224r1_p[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x01
+};
+
+static const uint8_t g_secp224r1_a[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFE
+};
+
+static const uint8_t g_secp224r1_b[] = {
+	0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
+	0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
+	0x23, 0x55, 0xFF, 0xB4
+};
+
+static const uint8_t g_secp224r1_gx[] = {
+	0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
+	0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
+	0x11, 0x5C, 0x1D, 0x21
+};
+
+static const uint8_t g_secp224r1_gy[] = {
+	0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
+	0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
+	0x85, 0x00, 0x7e, 0x34
+};
+
+static const uint8_t g_secp224r1_n[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
+	0x5C, 0x5C, 0x2A, 0x3D
+};
+
+/* NID_X9_62_prime256v1 */
+static const uint8_t g_prime256v1_p[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t g_prime256v1_a[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+
+static const uint8_t g_prime256v1_b[] = {
+	0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
+	0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
+	0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B
+};
+
+static const uint8_t g_prime256v1_gx[] = {
+	0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+	0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+	0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96
+};
+
+static const uint8_t g_prime256v1_gy[] = {
+	0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
+	0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+	0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5
+};
+
+static const uint8_t g_prime256v1_n[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+	0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
+};
+
+/* NID_secp384r1 */
+static const uint8_t g_secp384r1_p[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t g_secp384r1_a[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC
+};
+
+static const uint8_t g_secp384r1_b[] = {
+	0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
+	0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
+	0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
+	0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF
+};
+
+static const uint8_t g_secp384r1_gx[] = {
+	0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+	0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+	0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+	0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7
+};
+
+static const uint8_t g_secp384r1_gy[] = {
+	0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+	0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+	0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+	0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f
+};
+
+static const uint8_t g_secp384r1_n[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
+	0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
+};
+
+/* NID_secp521r1 */
+static const uint8_t g_secp521r1_p[] = {
+	0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+static const uint8_t g_secp521r1_a[] = {
+	0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
+};
+
+static const uint8_t g_secp521r1_b[] = {
+	0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
+	0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
+	0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
+	0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
+	0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
+	0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00
+};
+
+static const uint8_t g_secp521r1_gx[] = {
+	0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+	0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+	0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+	0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+	0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+	0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66
+};
+
+static const uint8_t g_secp521r1_gy[] = {
+	0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
+	0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+	0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
+	0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+	0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+	0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50
+};
+
+static const uint8_t g_secp521r1_n[] = {
+	0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
+	0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+	0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
+	0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
+};
+
+/* NID_SM2 */
+static const uint8_t g_sm2_p[] = {
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static const uint8_t g_sm2_a[] = {
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc
+};
+
+static const uint8_t g_sm2_b[] = {
+	0x28, 0xe9, 0xfa, 0x9e, 0x9d, 0x9f, 0x5e, 0x34, 0x4d, 0x5a, 0x9e, 0x4b,
+	0xcf, 0x65, 0x09, 0xa7, 0xf3, 0x97, 0x89, 0xf5, 0x15, 0xab, 0x8f, 0x92,
+	0xdd, 0xbc, 0xbd, 0x41, 0x4d, 0x94, 0x0e, 0x93
+};
+
+static const uint8_t g_sm2_gx[] = {
+	0x32, 0xc4, 0xae, 0x2c, 0x1f, 0x19, 0x81, 0x19, 0x5f, 0x99, 0x04, 0x46,
+	0x6a, 0x39, 0xc9, 0x94, 0x8f, 0xe3, 0x0b, 0xbf, 0xf2, 0x66, 0x0b, 0xe1,
+	0x71, 0x5a, 0x45, 0x89, 0x33, 0x4c, 0x74, 0xc7
+};
+
+static const uint8_t g_sm2_gy[] = {
+	0xbc, 0x37, 0x36, 0xa2, 0xf4, 0xf6, 0x77, 0x9c, 0x59, 0xbd, 0xce, 0xe3,
+	0x6b, 0x69, 0x21, 0x53, 0xd0, 0xa9, 0x87, 0x7c, 0xc6, 0x2a, 0x47, 0x40,
+	0x02, 0xdf, 0x32, 0xe5, 0x21, 0x39, 0xf0, 0xa0
+};
+
+static const uint8_t g_sm2_n[] = {
+	0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x72, 0x03, 0xdf, 0x6b, 0x21, 0xc6, 0x05, 0x2b,
+	0x53, 0xbb, 0xf4, 0x09, 0x39, 0xd5, 0x41, 0x23
+};
+
+static const struct hpre_ecc_curve g_curve_list[] = {
+	{
+		.id = TEE_ECC_CURVE_NIST_P192,
+		.key_bits = 192,
+		.p = g_prime192v1_p,
+		.a = g_prime192v1_a,
+		.b = g_prime192v1_b,
+		.x = g_prime192v1_gx,
+		.y = g_prime192v1_gy,
+		.n = g_prime192v1_n,
+	},
+	{
+		.id = TEE_ECC_CURVE_NIST_P224,
+		.key_bits = 224,
+		.p = g_secp224r1_p,
+		.a = g_secp224r1_a,
+		.b = g_secp224r1_b,
+		.x = g_secp224r1_gx,
+		.y = g_secp224r1_gy,
+		.n = g_secp224r1_n,
+	},
+	{
+		.id = TEE_ECC_CURVE_NIST_P256,
+		.key_bits = 256,
+		.p = g_prime256v1_p,
+		.a = g_prime256v1_a,
+		.b = g_prime256v1_b,
+		.x = g_prime256v1_gx,
+		.y = g_prime256v1_gy,
+		.n = g_prime256v1_n,
+	},
+	{
+		.id = TEE_ECC_CURVE_NIST_P384,
+		.key_bits = 384,
+		.p = g_secp384r1_p,
+		.a = g_secp384r1_a,
+		.b = g_secp384r1_b,
+		.x = g_secp384r1_gx,
+		.y = g_secp384r1_gy,
+		.n = g_secp384r1_n,
+	},
+	{
+		.id = TEE_ECC_CURVE_NIST_P521,
+		.key_bits = 521,
+		.p = g_secp521r1_p,
+		.a = g_secp521r1_a,
+		.b = g_secp521r1_b,
+		.x = g_secp521r1_gx,
+		.y = g_secp521r1_gy,
+		.n = g_secp521r1_n,
+	},
+	{
+		.id = TEE_ECC_CURVE_SM2,
+		.key_bits = 256,
+		.p = g_sm2_p,
+		.a = g_sm2_a,
+		.b = g_sm2_b,
+		.x = g_sm2_gx,
+		.y = g_sm2_gy,
+		.n = g_sm2_n,
+	}
+};
+
+static bool is_all_zero(uint8_t *data, uint32_t size, const char *p_name)
+{
+	uint32_t i = 0;
+
+	for (i = 0; i < size; i++) {
+		if (data[i])
+			return false;
+	}
+
+	EMSG("Error: %s all zero", p_name);
+
+	return true;
+}
+
+static enum hisi_drv_status hpre_ecc_curve_to_hpre_bin(uint8_t *p, uint8_t *a,
+						       uint8_t *b, uint8_t *n,
+						       uint8_t *gx, uint8_t *gy,
+						       uint32_t curve_bytes,
+						       uint32_t key_bytes)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_bin_from_crypto_bin(p, p, key_bytes, curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer p from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(a, a, key_bytes, curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer a from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(b, b, key_bytes, curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer b from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	if (n) {
+		ret = hpre_bin_from_crypto_bin(n, n, key_bytes, curve_bytes);
+		if (ret) {
+			EMSG("Fail to transfer n from crypto_bin to hpre_bin");
+			return ret;
+		}
+	}
+
+	if (gx) {
+		ret = hpre_bin_from_crypto_bin(gx, gx, key_bytes, curve_bytes);
+		if (ret) {
+			EMSG("Fail to transfer gx from crypto_bin to hpre_bin");
+			return ret;
+		}
+	}
+
+	if (gy) {
+		ret = hpre_bin_from_crypto_bin(gy, gy, key_bytes, curve_bytes);
+		if (ret)
+			EMSG("Fail to transfer gy from crypto_bin to hpre_bin");
+	}
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_ecc_fill_sqe(void *bd, void *info)
+{
+	struct hpre_ecc_msg *msg = (struct hpre_ecc_msg *)info;
+	struct hpre_sqe *sqe = (struct hpre_sqe *)bd;
+
+	sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT);
+	sqe->task_len1 = TASK_LENGTH(msg->key_bytes);
+	sqe->ext1 = msg->sm2_sp << HPRE_SQE_BD_RSV2_SHIFT;
+
+	if (msg->alg_type == HPRE_ALG_SM2_ENC ||
+	    msg->alg_type == HPRE_ALG_SM2_DEC)
+		sqe->sm2enc_klen = msg->sm2_mlen - 1;
+
+	if (msg->alg_type == HPRE_ALG_SM2_SIGN ||
+	    msg->alg_type == HPRE_ALG_SM2_ENC)
+		sqe->ext1 |= SHIFT_U32(0x1, HPRE_SQE_SM2_KSEL_SHIFT);
+
+	sqe->key = msg->key_dma;
+	sqe->in = msg->in_dma;
+	if (msg->alg_type != HPRE_ALG_ECDSA_VERF &&
+	    msg->alg_type != HPRE_ALG_SM2_VERF)
+		sqe->out = msg->out_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status ecc_dh_out_to_crypto_bin(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_dh *ecc_dh = &msg->param_size.ecc_dh;
+	uint8_t *rx = msg->out;
+	uint8_t *ry = rx + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_bin_to_crypto_bin(rx, rx, msg->key_bytes,
+				     ecc_dh->rx_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecc dh rx from hpre_bin to crypto_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_to_crypto_bin(ry, ry, msg->key_bytes,
+				     ecc_dh->ry_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecc dh ry from hpre_bin to crypto_bin");
+
+	return ret;
+}
+
+static enum hisi_drv_status ecc_sign_out_to_crypto_bin(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_sign *ecc_sign = &msg->param_size.ecc_sign;
+	uint8_t *r = msg->out;
+	uint8_t *s = r + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_bin_to_crypto_bin(r, r, msg->key_bytes,
+				     ecc_sign->r_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecc sign r from hpre_bin to crypto_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_to_crypto_bin(s, s, msg->key_bytes,
+				     ecc_sign->s_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecc sign s from hpre_bin to crypto_bin");
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_ecc_verify_get_result(struct hpre_ecc_msg *msg,
+						       struct hpre_sqe *sqe)
+{
+	if (sqe->out & BIT64(1)) {
+		msg->result = ECC_VERIFY_SUCCESS;
+		return HISI_QM_DRVCRYPT_NO_ERR;
+	}
+
+	msg->result = ECC_VERIFY_ERR;
+	return HISI_QM_DRVCRYPT_VERIFY_ERR;
+}
+
+static enum hisi_drv_status
+hpre_ecc_out_to_crypto_bin(struct hpre_ecc_msg *msg, struct hpre_sqe *sqe)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	switch (msg->alg_type) {
+	case HPRE_ALG_ECDH_MULTIPLY:
+		ret = ecc_dh_out_to_crypto_bin(msg);
+		break;
+	case HPRE_ALG_ECDSA_SIGN:
+	case HPRE_ALG_SM2_SIGN:
+		ret = ecc_sign_out_to_crypto_bin(msg);
+		break;
+	case HPRE_ALG_ECDSA_VERF:
+	case HPRE_ALG_SM2_VERF:
+		ret = hpre_ecc_verify_get_result(msg, sqe);
+		break;
+	default:
+		EMSG("Invalid alg type.");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_ecc_parse_sqe(void *bd, void *info)
+{
+	struct hpre_ecc_msg *msg = (struct hpre_ecc_msg *)info;
+	struct hpre_sqe *sqe = (struct hpre_sqe *)bd;
+	uint16_t err = 0;
+	uint16_t err1 = 0;
+	uint16_t done = 0;
+
+	err = HPRE_TASK_ETYPE(sqe->w0);
+	err1 = HPRE_TASK_ETYPE1(sqe->w0);
+	done = HPRE_TASK_DONE(sqe->w0);
+	if (done != HPRE_HW_TASK_DONE || err || err1) {
+		EMSG("HPRE do ecc fail! done=0x%"PRIX16", etype=0x%"PRIX16
+		     ",etype1=0x%"PRIX16, done, err, err1);
+
+		if (done == HPRE_HW_TASK_INIT)
+			return HISI_QM_DRVCRYPT_ENOPROC;
+
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	if (hpre_ecc_out_to_crypto_bin(msg, sqe)) {
+		EMSG("HPRE qm transfer ecc out fail.");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result hpre_do_ecc_task(void *msg)
+{
+	struct hisi_qp *ecc_qp = NULL;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ecc_qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE1);
+	if (!ecc_qp) {
+		EMSG("Fail to create ecc qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	ecc_qp->fill_sqe = hpre_ecc_fill_sqe;
+	ecc_qp->parse_sqe = hpre_ecc_parse_sqe;
+	ret = hisi_qp_send(ecc_qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		hisi_qm_release_qp(ecc_qp);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	ret = hisi_qp_recv_sync(ecc_qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		hisi_qm_release_qp(ecc_qp);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	hisi_qm_release_qp(ecc_qp);
+
+	return TEE_SUCCESS;
+}
+
+static bool key_size_is_supported(size_t key_bits)
+{
+	return (key_bits == 192 || key_bits == 224 || key_bits == 256 ||
+		key_bits == 384 || key_bits == 448 || key_bits == 512 ||
+		BITS_TO_BYTES(key_bits) == BITS_TO_BYTES(521) ||
+		BITS_TO_BYTES(key_bits) == BITS_TO_BYTES(225));
+}
+
+static TEE_Result hpre_ecc_alloc_keypair(struct ecc_keypair *key,
+					 uint32_t type __unused,
+					 size_t size_bits)
+{
+	if (!key || !key_size_is_supported(size_bits)) {
+		EMSG("Invalid input params.");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	memset(key, 0, sizeof(*key));
+
+	key->d = crypto_bignum_allocate(size_bits);
+	if (!key->d)
+		goto d_err;
+
+	key->x = crypto_bignum_allocate(size_bits);
+	if (!key->x)
+		goto x_err;
+
+	key->y = crypto_bignum_allocate(size_bits);
+	if (!key->y)
+		goto y_err;
+
+	return TEE_SUCCESS;
+
+y_err:
+	crypto_bignum_free(&key->x);
+x_err:
+	crypto_bignum_free(&key->d);
+d_err:
+	EMSG("Hpre ecc alloc key pair fail.");
+
+	return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result hpre_ecc_alloc_publickey(struct ecc_public_key *key,
+					   uint32_t type __unused,
+					   size_t size_bits)
+{
+	if (!key || !key_size_is_supported(size_bits)) {
+		EMSG("Invalid input params.");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	memset(key, 0, sizeof(*key));
+
+	key->x = crypto_bignum_allocate(size_bits);
+	if (!key->x)
+		goto x_err;
+
+	key->y = crypto_bignum_allocate(size_bits);
+	if (!key->y)
+		goto y_err;
+
+	return TEE_SUCCESS;
+
+y_err:
+	crypto_bignum_free(&key->x);
+x_err:
+	EMSG("Hpre ecc alloc publickey fail.");
+
+	return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static void hpre_ecc_free_publickey(struct ecc_public_key *key)
+{
+	if (key) {
+		crypto_bignum_free(&key->x);
+		crypto_bignum_free(&key->y);
+	}
+}
+
+static const struct hpre_ecc_curve *get_curve_from_list(uint32_t curve_id)
+{
+	size_t i = 0;
+
+	for (i = 0; i < ARRAY_SIZE(g_curve_list); i++) {
+		if (g_curve_list[i].id == curve_id)
+			return &g_curve_list[i];
+	}
+
+	return NULL;
+}
+
+static size_t hpre_ecc_get_hw_kbytes(size_t key_bits)
+{
+	size_t size = 0;
+
+	if (BITS_TO_BYTES(key_bits) <= BITS_TO_BYTES(256))
+		size = BITS_TO_BYTES(256);
+	else if (BITS_TO_BYTES(key_bits) <= BITS_TO_BYTES(384))
+		size = BITS_TO_BYTES(384);
+	else if (BITS_TO_BYTES(key_bits) <= BITS_TO_BYTES(576))
+		size = BITS_TO_BYTES(576);
+	else
+		EMSG("Fail to get key buffer size.");
+
+	return size;
+}
+
+static enum hisi_drv_status hpre_ecc_dh_transfer_key(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_dh *ecc_dh = &msg->param_size.ecc_dh;
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *d = a + msg->key_bytes;
+	uint8_t *b = d + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_ecc_curve_to_hpre_bin(p, a, b, NULL, NULL, NULL,
+					 msg->curve_bytes, msg->key_bytes);
+	if (ret)
+		return ret;
+
+	ret = hpre_bin_from_crypto_bin(d, d, msg->key_bytes, ecc_dh->d_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecc dh d from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_ecc_dh_transfer_in(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_dh *ecc_dh = &msg->param_size.ecc_dh;
+	uint8_t *x = msg->in;
+	uint8_t *y = x + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes,
+				       ecc_dh->x_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdh gx from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(y, y, msg->key_bytes,
+				       ecc_dh->y_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecdh gy from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_ecc_dh_params_fill(const struct hpre_ecc_curve *curve,
+			struct hpre_ecc_msg *msg, struct bignum *privkey,
+			struct ecc_public_key *pubkey)
+{
+	struct hpre_ecc_dh *ecc_dh = &msg->param_size.ecc_dh;
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *d = a + msg->key_bytes;
+	uint8_t *b = d + msg->key_bytes;
+	uint8_t *x = msg->in;
+	uint8_t *y = x + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	memcpy(p, curve->p, msg->curve_bytes);
+	memcpy(a, curve->a, msg->curve_bytes);
+	crypto_bignum_bn2bin(privkey, d);
+	ecc_dh->d_bytes = crypto_bignum_num_bytes(privkey);
+	if (is_all_zero(d, ecc_dh->d_bytes, "ecc dh d"))
+		return HISI_QM_DRVCRYPT_EINVAL;
+
+	memcpy(b, curve->b, msg->curve_bytes);
+
+	ecc_dh->x_bytes = msg->curve_bytes;
+	ecc_dh->y_bytes = msg->curve_bytes;
+	if (!pubkey) {
+		/* gen key pair */
+		memcpy(x, curve->x, ecc_dh->x_bytes);
+		memcpy(y, curve->y, ecc_dh->y_bytes);
+	} else {
+		/* do shared secret */
+		crypto_bignum_bn2bin(pubkey->x, x);
+		ecc_dh->x_bytes = crypto_bignum_num_bytes(pubkey->x);
+		crypto_bignum_bn2bin(pubkey->y, y);
+		ecc_dh->y_bytes = crypto_bignum_num_bytes(pubkey->y);
+	}
+
+	ret = hpre_ecc_dh_transfer_key(msg);
+	if (ret)
+		return ret;
+
+	return hpre_ecc_dh_transfer_in(msg);
+}
+
+static enum hisi_drv_status hpre_ecc_dh_params_alloc(struct hpre_ecc_msg *msg)
+{
+	uint32_t size = HPRE_ECC_DH_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc ecc dh total buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->key = data;
+	msg->key_dma = virt_to_phys(msg->key);
+
+	msg->in = msg->key + ECC_DH_KEY_SIZE(msg->key_bytes);
+	msg->in_dma = msg->key_dma + ECC_DH_KEY_SIZE(msg->key_bytes);
+	msg->out = msg->in + ECC_DH_IN_SIZE(msg->key_bytes);
+	msg->out_dma = msg->in_dma + ECC_DH_IN_SIZE(msg->key_bytes);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_ecc_request_deinit(struct hpre_ecc_msg *msg)
+{
+	if (msg->key) {
+		free_wipe(msg->key);
+		msg->key = NULL;
+	}
+}
+
+static TEE_Result hpre_ecc_request_init(const struct hpre_ecc_curve *curve,
+					struct hpre_ecc_msg *msg,
+					struct bignum *d,
+					struct ecc_public_key *pubkey)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->alg_type = HPRE_ALG_ECDH_MULTIPLY;
+
+	if (curve->id == TEE_ECC_CURVE_SM2)
+		msg->sm2_sp = true;
+
+	msg->curve_bytes = BITS_TO_BYTES(curve->key_bits);
+	msg->key_bytes = hpre_ecc_get_hw_kbytes(curve->key_bits);
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_ecc_dh_params_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_ecc_dh_params_fill(curve, msg, d, pubkey);
+	if (ret) {
+		hpre_ecc_request_deinit(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	msg->param_size.ecc_dh.rx_bytes = msg->curve_bytes;
+	msg->param_size.ecc_dh.ry_bytes = msg->curve_bytes;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result gen_random_k(struct bignum *d, size_t key_bits,
+			       const uint8_t *n)
+{
+	size_t size = BITS_TO_BYTES(key_bits);
+	uint8_t *rand_k = NULL;
+	size_t i = 0;
+	size_t j = 0;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!d || !n) {
+		EMSG("Input param is NULL.");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	rand_k = malloc(size);
+	if (!rand_k) {
+		EMSG("Fail to malloc rand_k buf.");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	for (i = 0; i < size; i++) {
+		if (n[i] > 1) {
+			rand_k[i] = n[i] - 1;
+			break;
+		}
+		rand_k[i] = n[i];
+	}
+
+	j = i + 1;
+	if (hw_get_random_bytes(rand_k + j, size - j)) {
+		EMSG("Fail to fill rand_k buf.");
+		free(rand_k);
+		return TEE_ERROR_NO_DATA;
+	}
+
+	ret = crypto_bignum_bin2bn(rand_k, size, d);
+	if (ret)
+		EMSG("Rand_k bin2bn fail.");
+
+	free(rand_k);
+
+	return ret;
+}
+
+static TEE_Result hpre_ecc_gen_keypair(struct ecc_keypair *key,
+				       size_t size_bits)
+{
+	struct hpre_ecc_msg msg = { };
+	const struct hpre_ecc_curve *curve = NULL;
+	struct hpre_ecc_dh *ecc_dh = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!key || !key->d || !key->x || !key->y) {
+		EMSG("Invalid ecc_gen_keypair input parameters.");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	curve = get_curve_from_list(key->curve);
+	if (!curve) {
+		EMSG("Fail to get valid curve, id %"PRIu32, key->curve);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (BITS_TO_BYTES(size_bits) != BITS_TO_BYTES(curve->key_bits)) {
+		EMSG("Invalid size_bits %zu.", size_bits);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = gen_random_k(key->d, curve->key_bits, curve->n);
+	if (ret)
+		return ret;
+
+	ret = hpre_ecc_request_init(curve, &msg, key->d, NULL);
+	if (ret) {
+		EMSG("Ecc key pair request init fail.");
+		return ret;
+	}
+
+	ret = hpre_do_ecc_task(&msg);
+	if (ret) {
+		EMSG("Fail to do ecc key pair task! ret = 0x%"PRIX16, ret);
+		goto done;
+	}
+
+	ecc_dh = &msg.param_size.ecc_dh;
+	ret = crypto_bignum_bin2bn(msg.out, ecc_dh->rx_bytes, key->x);
+	if (ret) {
+		EMSG("Fail to trans res x to bn.");
+		goto done;
+	}
+
+	ret = crypto_bignum_bin2bn(msg.out + msg.key_bytes,
+				   ecc_dh->ry_bytes, key->y);
+	if (ret)
+		EMSG("Fail to trans res y to bn.");
+done:
+	hpre_ecc_request_deinit(&msg);
+	return ret;
+}
+
+static TEE_Result hpre_ecc_do_shared_secret(struct drvcrypt_secret_data *sdata)
+{
+	struct hpre_ecc_msg msg = { };
+	const struct hpre_ecc_curve *curve = NULL;
+	struct ecc_public_key *pubkey = NULL;
+	struct ecc_keypair *ecc_key = NULL;
+	struct hpre_ecc_dh *ecc_dh = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!sdata || !sdata->key_priv || !sdata->key_pub) {
+		EMSG("Invalid ecc_do_shared_secret input parameters.");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ecc_key = sdata->key_priv;
+	pubkey = sdata->key_pub;
+
+	curve = get_curve_from_list(ecc_key->curve);
+	if (!curve) {
+		EMSG("Fail to get valid curve, id %"PRIu32, ecc_key->curve);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (sdata->size_sec != BITS_TO_BYTES(curve->key_bits)) {
+		EMSG("Invalid sdata size_sec %zu.", sdata->size_sec);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = hpre_ecc_request_init(curve, &msg, ecc_key->d, pubkey);
+	if (ret) {
+		EMSG("Ecc shared secret request init fail.");
+		return ret;
+	}
+
+	ret = hpre_do_ecc_task(&msg);
+	if (ret) {
+		EMSG("Fail to do ecc shared secret task! ret = 0x%"PRIX32,
+		     ret);
+		goto done;
+	}
+
+	ecc_dh = &msg.param_size.ecc_dh;
+	/*
+	 * Only take the x coordinate as the output result, according to
+	 * soft computing implementation.
+	 */
+	memcpy(sdata->secret.data, msg.out, ecc_dh->rx_bytes);
+	sdata->secret.length = ecc_dh->rx_bytes;
+	memzero_explicit(msg.out, ECC_DH_OUT_SIZE(msg.key_bytes));
+
+done:
+	hpre_ecc_request_deinit(&msg);
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_ecc_sign_params_fill(const struct hpre_ecc_curve *curve,
+			  struct hpre_ecc_msg *msg,
+			  struct drvcrypt_sign_data *sdata,
+			  struct bignum *rand_k)
+{
+	struct ecc_keypair *ecc_key = sdata->key;
+	struct hpre_ecc_sign *ecc_sign = &msg->param_size.ecc_sign;
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *d = a + msg->key_bytes;
+	uint8_t *b = d + msg->key_bytes;
+	uint8_t *n = b + msg->key_bytes;
+	uint8_t *gx = n + msg->key_bytes;
+	uint8_t *gy = gx + msg->key_bytes;
+	uint8_t *e = msg->in;
+	uint8_t *k = e + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	memcpy(p, curve->p, msg->curve_bytes);
+	memcpy(a, curve->a, msg->curve_bytes);
+	crypto_bignum_bn2bin(ecc_key->d, d);
+	ecc_sign->d_bytes = crypto_bignum_num_bytes(ecc_key->d);
+	memcpy(b, curve->b, msg->curve_bytes);
+	memcpy(n, curve->n, msg->curve_bytes);
+	memcpy(gx, curve->x, msg->curve_bytes);
+	memcpy(gy, curve->y, msg->curve_bytes);
+	crypto_bignum_bn2bin(rand_k, k);
+	ecc_sign->k_bytes = crypto_bignum_num_bytes(rand_k);
+
+	ecc_sign->e_bytes = MIN(sdata->message.length, msg->curve_bytes);
+	memcpy(e, sdata->message.data, ecc_sign->e_bytes);
+	if (is_all_zero(e, ecc_sign->e_bytes, "ecc sign msg_e"))
+		return HISI_QM_DRVCRYPT_EINVAL;
+
+	ret = hpre_ecc_curve_to_hpre_bin(p, a, b, n, gx, gy, msg->curve_bytes,
+					 msg->key_bytes);
+	if (ret)
+		return ret;
+
+	ret = hpre_bin_from_crypto_bin(d, d, msg->key_bytes,
+				       ecc_sign->d_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdsa sign d");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(e, e, msg->key_bytes,
+				       ecc_sign->e_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdsa sign e");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(k, k, msg->key_bytes,
+				       ecc_sign->k_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecdsa sign k");
+
+	return ret;
+}
+
+static enum hisi_drv_status hpre_ecc_sign_params_alloc(struct hpre_ecc_msg *msg)
+{
+	uint32_t size = HPRE_ECC_SIGN_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc ecc sign total buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->key = data;
+	msg->key_dma = virt_to_phys(msg->key);
+	if (!msg->key_dma) {
+		EMSG("Fail to get key dma addr");
+		free(data);
+		return HISI_QM_DRVCRYPT_EFAULT;
+	}
+
+	msg->in = msg->key + ECC_SIGN_KEY_SIZE(msg->key_bytes);
+	msg->in_dma = msg->key_dma + ECC_SIGN_KEY_SIZE(msg->key_bytes);
+	msg->out = msg->in + ECC_SIGN_IN_SIZE(msg->key_bytes);
+	msg->out_dma = msg->in_dma + ECC_SIGN_IN_SIZE(msg->key_bytes);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_ecc_sign_request_deinit(struct hpre_ecc_msg *msg)
+{
+	if (msg->key) {
+		free_wipe(msg->key);
+		msg->key = NULL;
+	}
+}
+
+static TEE_Result
+hpre_ecc_sign_request_init(const struct hpre_ecc_curve *curve,
+			   struct hpre_ecc_msg *msg,
+			   struct drvcrypt_sign_data *sdata,
+			   struct bignum *rand_k)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	if (curve->id == TEE_ECC_CURVE_SM2)
+		msg->alg_type = HPRE_ALG_SM2_SIGN;
+	else
+		msg->alg_type = HPRE_ALG_ECDSA_SIGN;
+	msg->curve_bytes = BITS_TO_BYTES(curve->key_bits);
+	msg->key_bytes = hpre_ecc_get_hw_kbytes(curve->key_bits);
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_ecc_sign_params_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_ecc_sign_params_fill(curve, msg, sdata, rand_k);
+	if (ret) {
+		hpre_ecc_sign_request_deinit(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	msg->param_size.ecc_sign.r_bytes = msg->curve_bytes;
+	msg->param_size.ecc_sign.s_bytes = msg->curve_bytes;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result hpre_ecdsa_param_check(struct drvcrypt_sign_data *sdata,
+					 const struct hpre_ecc_curve *curve)
+{
+	if (sdata->size_sec != BITS_TO_BYTES(curve->key_bits)) {
+		EMSG("Invalid sdata size_sec %zu", sdata->size_sec);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void hpre_ecc_sign_get_data_out(struct hpre_ecc_msg *msg,
+				       struct drvcrypt_sign_data *sdata)
+{
+	struct hpre_ecc_sign *ecc_sign;
+
+	ecc_sign = &msg->param_size.ecc_sign;
+	sdata->signature.length = ecc_sign->r_bytes + ecc_sign->s_bytes;
+	memcpy(sdata->signature.data, msg->out, ecc_sign->r_bytes);
+	memcpy(sdata->signature.data + ecc_sign->r_bytes, msg->out +
+	       msg->key_bytes, ecc_sign->s_bytes);
+}
+
+static TEE_Result hpre_ecc_sign(struct drvcrypt_sign_data *sdata)
+{
+	struct hpre_ecc_msg msg = { };
+	const struct hpre_ecc_curve *curve = NULL;
+	struct ecc_keypair *ecc_key = NULL;
+	struct bignum *rand_k = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!sdata || !sdata->key) {
+		EMSG("Invalid ecc_sign input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ecc_key = sdata->key;
+
+	curve = get_curve_from_list(ecc_key->curve);
+	if (!curve) {
+		EMSG("Fail to get valid curve, id %"PRIu32, ecc_key->curve);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	ret = hpre_ecdsa_param_check(sdata, curve);
+	if (ret)
+		return ret;
+
+	rand_k = crypto_bignum_allocate(curve->key_bits);
+	if (!rand_k) {
+		EMSG("Fail to alloc private k");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	ret = gen_random_k(rand_k, curve->key_bits, curve->n);
+	if (ret)
+		goto free_key;
+
+	ret = hpre_ecc_sign_request_init(curve, &msg, sdata, rand_k);
+	if (ret) {
+		EMSG("Ecc sign request init fail");
+		goto free_key;
+	}
+
+	ret = hpre_do_ecc_task(&msg);
+	if (ret) {
+		EMSG("Fail to do ecc sign task! ret = 0x%"PRIX16, ret);
+		goto done;
+	}
+
+	hpre_ecc_sign_get_data_out(&msg, sdata);
+
+done:
+	hpre_ecc_sign_request_deinit(&msg);
+free_key:
+	crypto_bignum_free(&rand_k);
+
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_ecc_verify_transfer_key(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_verify *ecc_verify = &msg->param_size.ecc_verify;
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *b = a + msg->key_bytes;
+	uint8_t *n = b + msg->key_bytes;
+	uint8_t *gx = n + msg->key_bytes;
+	uint8_t *gy = gx + msg->key_bytes;
+	uint8_t *pubx = gy + msg->key_bytes;
+	uint8_t *puby = pubx + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_ecc_curve_to_hpre_bin(p, a, b, n, gx, gy, msg->curve_bytes,
+					 msg->key_bytes);
+	if (ret)
+		return ret;
+
+	ret = hpre_bin_from_crypto_bin(pubx, pubx, msg->key_bytes,
+				       ecc_verify->pubx_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdsa verify pub_x");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(puby, puby, msg->key_bytes,
+				       ecc_verify->puby_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecdsa verify pub_y");
+
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_ecc_verify_transfer_in(struct hpre_ecc_msg *msg)
+{
+	struct hpre_ecc_verify *ecc_verify = &msg->param_size.ecc_verify;
+	uint8_t *e = msg->in;
+	uint8_t *s = e + msg->key_bytes;
+	uint8_t *r = s + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hpre_bin_from_crypto_bin(e, e, msg->key_bytes,
+				       ecc_verify->e_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdsa verify e");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(s, s, msg->key_bytes,
+				       ecc_verify->s_bytes);
+	if (ret) {
+		EMSG("Fail to transfer ecdsa verify s");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(r, r, msg->key_bytes,
+				       ecc_verify->r_bytes);
+	if (ret)
+		EMSG("Fail to transfer ecdsa verify r");
+
+	return ret;
+}
+
+static TEE_Result
+hpre_ecc_verify_params_fill(const struct hpre_ecc_curve *curve,
+			    struct hpre_ecc_msg *msg,
+			    struct drvcrypt_sign_data *sdata)
+{
+	struct ecc_public_key *ecc_key = sdata->key;
+	struct hpre_ecc_verify *ecc_verify = &msg->param_size.ecc_verify;
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *b = a + msg->key_bytes;
+	uint8_t *n = b + msg->key_bytes;
+	uint8_t *gx = n + msg->key_bytes;
+	uint8_t *gy = gx + msg->key_bytes;
+	uint8_t *pubx = gy + msg->key_bytes;
+	uint8_t *puby = pubx + msg->key_bytes;
+	uint8_t *e = msg->in;
+	uint8_t *s = e + msg->key_bytes;
+	uint8_t *r = s + msg->key_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	memcpy(p, curve->p, msg->curve_bytes);
+	memcpy(a, curve->a, msg->curve_bytes);
+	memcpy(b, curve->b, msg->curve_bytes);
+	memcpy(n, curve->n, msg->curve_bytes);
+	memcpy(gx, curve->x, msg->curve_bytes);
+	memcpy(gy, curve->y, msg->curve_bytes);
+	crypto_bignum_bn2bin(ecc_key->x, pubx);
+	ecc_verify->pubx_bytes = crypto_bignum_num_bytes(ecc_key->x);
+	crypto_bignum_bn2bin(ecc_key->y, puby);
+	ecc_verify->puby_bytes = crypto_bignum_num_bytes(ecc_key->y);
+
+	ecc_verify->e_bytes = MIN(sdata->message.length, msg->curve_bytes);
+	memcpy(e, sdata->message.data, ecc_verify->e_bytes);
+	if (is_all_zero(e, ecc_verify->e_bytes, "ecc verify msg_e"))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/* user should make param r and s be full width */
+	ecc_verify->r_bytes = sdata->signature.length >> 1;
+	memcpy(r, sdata->signature.data, ecc_verify->r_bytes);
+	ecc_verify->s_bytes = ecc_verify->r_bytes;
+	memcpy(s, sdata->signature.data + ecc_verify->r_bytes,
+	       ecc_verify->s_bytes);
+
+	ret = hpre_ecc_verify_transfer_key(msg);
+	if (ret)
+		return TEE_ERROR_BAD_STATE;
+
+	ret = hpre_ecc_verify_transfer_in(msg);
+	if (ret)
+		return TEE_ERROR_BAD_STATE;
+
+	return TEE_SUCCESS;
+}
+
+static enum hisi_drv_status
+hpre_ecc_verify_params_alloc(struct hpre_ecc_msg *msg)
+{
+	uint32_t size = HPRE_ECC_VERIFY_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc ecc verify total buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->key = data;
+	msg->key_dma = virt_to_phys(msg->key);
+	if (!msg->key_dma) {
+		EMSG("Fail to get key dma addr");
+		free(data);
+		return HISI_QM_DRVCRYPT_EFAULT;
+	}
+
+	msg->in = msg->key + ECC_VERIF_KEY_SIZE(msg->key_bytes);
+	msg->in_dma = msg->key_dma + ECC_VERIF_KEY_SIZE(msg->key_bytes);
+	msg->out = msg->in + ECC_VERIF_IN_SIZE(msg->key_bytes);
+	msg->out_dma = msg->in_dma + ECC_VERIF_IN_SIZE(msg->key_bytes);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_ecc_verify_request_deinit(struct hpre_ecc_msg *msg)
+{
+	if (msg->key) {
+		free_wipe(msg->key);
+		msg->key = NULL;
+	}
+}
+
+static TEE_Result
+hpre_ecc_verify_request_init(const struct hpre_ecc_curve *curve,
+			     struct hpre_ecc_msg *msg,
+			     struct drvcrypt_sign_data *sdata)
+{
+	int32_t ret = 0;
+
+	if (curve->id == TEE_ECC_CURVE_SM2)
+		msg->alg_type = HPRE_ALG_SM2_VERF;
+	else
+		msg->alg_type = HPRE_ALG_ECDSA_VERF;
+	msg->curve_bytes = BITS_TO_BYTES(curve->key_bits);
+	msg->key_bytes = hpre_ecc_get_hw_kbytes(curve->key_bits);
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_ecc_verify_params_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_ecc_verify_params_fill(curve, msg, sdata);
+	if (ret) {
+		hpre_ecc_verify_request_deinit(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result hpre_ecc_verify(struct drvcrypt_sign_data *sdata)
+{
+	struct hpre_ecc_msg msg = { };
+	const struct hpre_ecc_curve *curve = NULL;
+	struct ecc_public_key *pub_key = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!sdata || !sdata->key) {
+		EMSG("Invalid ecc_verify input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	pub_key = sdata->key;
+
+	curve = get_curve_from_list(pub_key->curve);
+	if (!curve) {
+		EMSG("Fail to get valid curve, id %"PRIu32, pub_key->curve);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	ret = hpre_ecdsa_param_check(sdata, curve);
+	if (ret)
+		return ret;
+
+	ret = hpre_ecc_verify_request_init(curve, &msg, sdata);
+	if (ret) {
+		EMSG("Ecc verify request init fail");
+		return ret;
+	}
+
+	ret = hpre_do_ecc_task(&msg);
+	if (ret) {
+		EMSG("Fail to do ecc verify task! ret = 0x%"PRIX16, ret);
+		goto done;
+	}
+
+	if (msg.result == ECC_VERIFY_ERR) {
+		EMSG("Hpre ecc verify fail");
+		ret = TEE_ERROR_SIGNATURE_INVALID;
+	}
+
+done:
+	hpre_ecc_verify_request_deinit(&msg);
+	return ret;
+}
+
+static struct drvcrypt_ecc driver_ecc = {
+	.alloc_keypair = hpre_ecc_alloc_keypair,
+	.alloc_publickey = hpre_ecc_alloc_publickey,
+	.free_publickey = hpre_ecc_free_publickey,
+	.gen_keypair = hpre_ecc_gen_keypair,
+	.shared_secret = hpre_ecc_do_shared_secret,
+	.sign = hpre_ecc_sign,
+	.verify = hpre_ecc_verify,
+};
+
+static TEE_Result hpre_ecc_init(void)
+{
+	TEE_Result ret = drvcrypt_register_ecc(&driver_ecc);
+
+	if (ret != TEE_SUCCESS)
+		EMSG("Hpre ecc register to crypto fail");
+
+	return ret;
+}
+
+driver_init(hpre_ecc_init);
diff --git a/core/drivers/crypto/hisilicon/hpre_ecc.h b/core/drivers/crypto/hisilicon/hpre_ecc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f7395321e55cf70d68b21b7cc961aea5bce12a8b
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_ecc.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
+ */
+
+#ifndef __HPRE_ECC_H__
+#define __HPRE_ECC_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+enum ecc_verify_status {
+	ECC_VERIFY_ERR = 0,
+	ECC_VERIFY_SUCCESS = 1,
+};
+
+struct hpre_ecc_dh {
+	uint32_t d_bytes;
+	uint32_t x_bytes;
+	uint32_t y_bytes;
+	uint32_t rx_bytes;
+	uint32_t ry_bytes;
+};
+
+struct hpre_ecc_sign {
+	uint32_t d_bytes;
+	uint32_t e_bytes;
+	uint32_t k_bytes;
+	uint32_t r_bytes;
+	uint32_t s_bytes;
+};
+
+struct hpre_ecc_verify {
+	uint32_t pubx_bytes;
+	uint32_t puby_bytes;
+	uint32_t e_bytes;
+	uint32_t s_bytes;
+	uint32_t r_bytes;
+};
+
+struct hpre_sm2_enc {
+	uint32_t pubx_bytes;
+	uint32_t puby_bytes;
+	uint32_t k_bytes;
+	uint32_t m_bytes;
+	uint32_t c1x_bytes;
+	uint32_t c1y_bytes;
+	uint32_t c2_bytes;
+	uint32_t c3_bytes;
+};
+
+struct hpre_sm2_dec {
+	uint32_t d_bytes;
+	uint32_t c1x_bytes;
+	uint32_t c1y_bytes;
+	uint32_t c2_bytes;
+	uint32_t c3_bytes;
+	uint32_t m_bytes;
+};
+
+struct hpre_ecc_msg {
+	uint8_t *key;
+	paddr_t key_dma;
+	uint8_t *in;
+	paddr_t in_dma;
+	uint8_t *out;
+	paddr_t out_dma;
+	uint8_t alg_type;
+	uint32_t key_bytes;
+	uint32_t curve_bytes;
+	uint32_t result;
+	uint32_t sm2_mlen;
+	bool sm2_sp;
+	union {
+		struct hpre_ecc_dh ecc_dh;
+		struct hpre_ecc_sign ecc_sign;
+		struct hpre_ecc_verify ecc_verify;
+		struct hpre_sm2_enc sm2_enc;
+		struct hpre_sm2_dec sm2_dec;
+	} param_size;
+};
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/hpre_main.c b/core/drivers/crypto/hisilicon/hpre_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..060592db20f2402cd8f0dd9fb26b40b25fe2a1c0
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_main.c
@@ -0,0 +1,329 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator HPRE module init.
+ */
+
+#include <initcall.h>
+
+#include "hpre_main.h"
+
+/* base config */
+#define HPRE_COMMON_CNT_CLR_CE		0x301000
+#define HPRE_CFG_AXCACHE		0x301010
+#define HPRE_RDCHN_INI_CFG		0x301014
+#define HPRE_BD_ENDIAN			0x301020
+#define HPRE_ECC_BYPASS			0x301024
+#define HPRE_POISON_BYPASS		0x30102c
+#define HPRE_BD_ARUSR_CFG		0x301030
+#define HPRE_BD_AWUSR_CFG		0x301034
+#define HPRE_TYPES_ENB			0x301038
+#define HPRE_DATA_RUSER_CFG		0x30103c
+#define HPRE_DATA_WUSER_CFG		0x301040
+#define HPRE_HAC_INT_MASK		0x301400
+#define HPRE_RAS_ECC_1BIT_TH		0x30140c
+#define HPRE_RAS_CE_ENB			0x301410
+#define HPRE_RAS_NFE_ENB		0x301414
+#define HPRE_RAS_FE_ENB			0x301418
+#define HPRE_HAC_INT_SRC		0x301600
+#define HPRE_RDCHN_INI_ST		0x301a00
+#define HPRE_OOO_SHUTDOWN_SEL		0x301a3c
+#define HPRE_CORE_ENB			0x302004
+#define HPRE_CORE_INI_CFG		0x302020
+#define HPRE_CORE_INI_STATUS		0x302080
+/* clock gate */
+#define HPRE_CLKGATE_CTL		0x301a10
+#define HPRE_PEH_CFG_AUTO_GATE		0x301a2c
+#define HPRE_CLUSTER_DYN_CTL		0x302010
+#define HPRE_CORE_SHB_CFG		0x302088
+#define HPRE_CORE_GATE_ENABLE		GENMASK_32(31, 30)
+
+#define HPRE_AXCACHE_MASK		0xff
+#define HPRE_HAC_INT_DISABLE		0x1ffffff
+#define HPRE_RAS_CE_MASK		0x1
+#define HPRE_RAS_NFE_MASK		0x1fffffe
+#define HPRE_RAS_FE_MASK		0
+#define HPRE_BD_LITTLE_ENDIAN		0
+#define HPRE_RSA_ENB			BIT(0)
+#define HPRE_ECC_ENB			BIT(1)
+#define HPRE_BD_ARUSR_MASK		0x2
+#define HPRE_BD_AWUSR_MASK		0x102
+#define HPRE_DATA_USR_MASK		0x32
+#define HPRE_CLUSTER_CORE_MASK		GENMASK_32(9, 0)
+
+static SLIST_HEAD(, acc_device) hpre_list = SLIST_HEAD_INITIALIZER(hpre_list);
+
+struct hisi_qp *hpre_create_qp(uint8_t sq_type)
+{
+	struct acc_device *hpre_dev = NULL;
+	struct acc_device *cur_dev = NULL;
+	struct hisi_qm *qm = NULL;
+	uint32_t free_qp_num = 0;
+	uint32_t max_qp_num = 0;
+
+	/* Find the HPRE device with the most remaining qp numbers */
+	SLIST_FOREACH(cur_dev, &hpre_list, link) {
+		qm = &cur_dev->qm;
+		if (qm->fun_type == HISI_QM_HW_PF)
+			free_qp_num = HISI_QM_PF_Q_NUM - qm->qp_in_used;
+		else
+			free_qp_num = HISI_QM_VF_Q_NUM - qm->qp_in_used;
+		if (free_qp_num > max_qp_num) {
+			max_qp_num = free_qp_num;
+			hpre_dev = cur_dev;
+		}
+	}
+
+	if (!hpre_dev) {
+		EMSG("No available hpre device");
+		return NULL;
+	}
+
+	return hisi_qm_create_qp(&hpre_dev->qm, sq_type);
+}
+
+enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src,
+					      uint32_t bsize, uint32_t dsize)
+{
+	if (!src || !dst || !dsize || !bsize) {
+		EMSG("parameter error");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	if (bsize < dsize) {
+		EMSG("dsize is too long");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	if (src == dst && bsize == dsize)
+		return HISI_QM_DRVCRYPT_NO_ERR;
+
+	/*
+	 * Copying non-zero data and padding with zeroes in high-bits
+	 * (eg: 1 2 3 0 0 -> 0 0 1 2 3)
+	 */
+	memmove(dst + bsize - dsize, src, dsize);
+	memset(dst, 0, bsize - dsize);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src,
+					    uint32_t bsize, uint32_t dsize)
+{
+	if (!dst || !src || !bsize || !dsize) {
+		EMSG("parameter error");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	if (bsize < dsize) {
+		EMSG("dsize is too long");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	if (src == dst && bsize == dsize)
+		return HISI_QM_DRVCRYPT_NO_ERR;
+	/*
+	 * Copying non-zero data and padding with zeroes in low-bits
+	 * (eg: 0 0 1 2 3 -> 1 2 3 0 0)
+	 */
+	memmove(dst, src + bsize - dsize, dsize);
+	memset(dst + dsize, 0, bsize - dsize);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status hpre_set_cluster(struct hisi_qm *qm)
+{
+	uint32_t val = 0;
+
+	io_write32(qm->io_base + HPRE_CORE_ENB, HPRE_CLUSTER_CORE_MASK);
+	io_write32(qm->io_base + HPRE_CORE_INI_CFG, 0x1);
+
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_CORE_INI_STATUS, val,
+				   (val & HPRE_CLUSTER_CORE_MASK) ==
+				   HPRE_CLUSTER_CORE_MASK, POLL_PERIOD,
+				   POLL_TIMEOUT))
+		return HISI_QM_DRVCRYPT_EBUSY;
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_disable_clock_gate(struct hisi_qm *qm)
+{
+	io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x0);
+	io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x0);
+	io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x0);
+	io_clrbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE);
+}
+
+static void hpre_enable_clock_gate(struct hisi_qm *qm)
+{
+	io_write32(qm->io_base + HPRE_CLKGATE_CTL, 0x1);
+	io_write32(qm->io_base + HPRE_PEH_CFG_AUTO_GATE, 0x1);
+	io_write32(qm->io_base + HPRE_CLUSTER_DYN_CTL, 0x1);
+	io_setbits32(qm->io_base + HPRE_CORE_SHB_CFG, HPRE_CORE_GATE_ENABLE);
+}
+
+static TEE_Result hpre_engine_init(struct acc_device *hpre_dev)
+{
+	struct hisi_qm *qm = &hpre_dev->qm;
+	uint32_t val = 0;
+	int32_t ret = 0;
+
+	if (qm->fun_type == HISI_QM_HW_VF)
+		return TEE_SUCCESS;
+
+	hpre_disable_clock_gate(qm);
+	hisi_qm_dev_init(qm);
+
+	io_write32(qm->io_base + HPRE_CFG_AXCACHE, HPRE_AXCACHE_MASK);
+	io_write32(qm->io_base + HPRE_BD_ENDIAN, HPRE_BD_LITTLE_ENDIAN);
+	io_write32(qm->io_base + HPRE_RAS_CE_ENB, HPRE_RAS_CE_MASK);
+	io_write32(qm->io_base + HPRE_RAS_NFE_ENB, HPRE_RAS_NFE_MASK);
+	io_write32(qm->io_base + HPRE_RAS_FE_ENB, HPRE_RAS_FE_MASK);
+	io_write32(qm->io_base + HPRE_HAC_INT_MASK, HPRE_HAC_INT_DISABLE);
+	io_write32(qm->io_base + HPRE_POISON_BYPASS, 0x0);
+	io_write32(qm->io_base + HPRE_COMMON_CNT_CLR_CE, 0x0);
+	io_write32(qm->io_base + HPRE_ECC_BYPASS, 0x0);
+	/* cmd_type is controlled by hac subctrl */
+	io_write32(qm->io_base + HPRE_BD_ARUSR_CFG, HPRE_BD_ARUSR_MASK);
+	io_write32(qm->io_base + HPRE_BD_AWUSR_CFG, HPRE_BD_AWUSR_MASK);
+	io_write32(qm->io_base + HPRE_DATA_RUSER_CFG, HPRE_DATA_USR_MASK);
+	io_write32(qm->io_base + HPRE_DATA_WUSER_CFG, HPRE_DATA_USR_MASK);
+	io_write32(qm->io_base + HPRE_TYPES_ENB, HPRE_RSA_ENB | HPRE_ECC_ENB);
+	io_write32(qm->io_base + HPRE_RDCHN_INI_CFG, 0x1);
+	ret = IO_READ32_POLL_TIMEOUT(qm->io_base + HPRE_RDCHN_INI_ST, val,
+				     val & 0x1, POLL_PERIOD, POLL_TIMEOUT);
+	if (ret) {
+		EMSG("Fail to init rd channel");
+		return TEE_ERROR_BUSY;
+	}
+
+	ret = hpre_set_cluster(qm);
+	if (ret) {
+		EMSG("Fail to init hpre cluster cores");
+		return TEE_ERROR_BUSY;
+	}
+
+	hpre_enable_clock_gate(qm);
+
+	return TEE_SUCCESS;
+}
+
+static enum hisi_drv_status hpre_dev_status_check(struct hisi_qm *qm)
+{
+	uint32_t val = 0;
+
+	val = io_read32(qm->io_base + HPRE_HAC_INT_SRC);
+	if (val & HPRE_RAS_NFE_MASK) {
+		EMSG("HPRE NFE RAS happened, need to reset");
+		return HISI_QM_DRVCRYPT_HW_EACCESS;
+	}
+
+	val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC);
+	if (val) {
+		if (val & HISI_QM_HPRE_NFE_INT_MASK)
+			EMSG("QM NFE RAS happened, need to reset");
+
+		if (val & HISI_QM_INVALID_DB) {
+			EMSG("QM invalid db happened, please check");
+			io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC,
+				   HISI_QM_INVALID_DB);
+		}
+
+		return HISI_QM_DRVCRYPT_HW_EACCESS;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status hpre_qm_init(struct acc_device *hpre_dev)
+{
+	struct hisi_qm *qm = &hpre_dev->qm;
+
+	if (cpu_mmu_enabled()) {
+		qm->io_base = (uintptr_t)phys_to_virt_io(hpre_dev->io_base,
+							 hpre_dev->io_size);
+		if (!qm->io_base) {
+			EMSG("Fail to get qm io_base");
+			return HISI_QM_DRVCRYPT_EFAULT;
+		}
+	} else {
+		qm->io_base = hpre_dev->io_base;
+	}
+
+	qm->vfs_num = hpre_dev->vfs_num;
+	qm->fun_type = hpre_dev->fun_type;
+	qm->sqe_size = HPRE_SQE_SIZE;
+	qm->sqe_log2_size = HPRE_SQE_LOG2_SIZE;
+	if (qm->fun_type == HISI_QM_HW_PF) {
+		hisi_qm_get_version(qm);
+		DMSG("HPRE hardware version is 0x%"PRIx32, qm->version);
+		qm->qp_base = HISI_QM_PF_Q_BASE;
+		qm->qp_num = HISI_QM_PF_Q_NUM;
+		qm->dev_status_check = hpre_dev_status_check;
+	}
+
+	return hisi_qm_init(qm);
+}
+
+static struct acc_device *hpre_pre_init(void)
+{
+	struct acc_device *hpre_dev = NULL;
+
+	hpre_dev = calloc(1, sizeof(*hpre_dev));
+	if (!hpre_dev) {
+		EMSG("Fail to alloc hpre_dev");
+		return NULL;
+	}
+
+	hpre_dev->io_base = HPRE_BAR_BASE;
+	hpre_dev->io_size = HPRE_BAR_SIZE;
+	hpre_dev->fun_type = HISI_QM_HW_PF;
+	SLIST_INSERT_HEAD(&hpre_list, hpre_dev, link);
+
+	return hpre_dev;
+}
+
+static TEE_Result hpre_probe(void)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	struct acc_device *hpre_dev = NULL;
+	struct hisi_qm *qm = NULL;
+
+	DMSG("HPRE driver init start");
+	hpre_dev = hpre_pre_init();
+	if (!hpre_dev)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	qm = &hpre_dev->qm;
+	if (hpre_qm_init(hpre_dev)) {
+		EMSG("Fail to init hpre qm");
+		goto err_with_pre_init;
+	}
+
+	ret = hpre_engine_init(hpre_dev);
+	if (ret) {
+		EMSG("Fail to init engine");
+		goto err_with_qm_init;
+	}
+
+	if (hisi_qm_start(qm)) {
+		EMSG("Fail to start qm");
+		ret = TEE_ERROR_BAD_STATE;
+		goto err_with_qm_init;
+	}
+
+	DMSG("HPRE driver init done");
+	return TEE_SUCCESS;
+
+err_with_qm_init:
+	hisi_qm_uninit(qm);
+err_with_pre_init:
+	SLIST_REMOVE_HEAD(&hpre_list, link);
+	free(hpre_dev);
+
+	return ret;
+}
+
+driver_init(hpre_probe);
diff --git a/core/drivers/crypto/hisilicon/hpre_main.h b/core/drivers/crypto/hisilicon/hpre_main.h
new file mode 100644
index 0000000000000000000000000000000000000000..6fa1830fc0133c3a1c1ecf7e62f16b8db2426c7f
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_main.h
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 HiSilicon Limited.
+ */
+#ifndef _HPRE_MAIN_H
+#define _HPRE_MAIN_H
+
+#include "hisi_qm.h"
+
+#define HPRE_BAR_BASE		0x150000000
+#define HPRE_BAR_SIZE		0x400000
+#define HPRE_SQE_SIZE		64
+#define HPRE_SQE_LOG2_SIZE	6
+#define HPRE_SQE_SM2_KSEL_SHIFT	1
+#define HPRE_SQE_BD_RSV2_SHIFT	7
+#define HPRE_HW_TASK_INIT	0x1
+#define HPRE_HW_TASK_DONE	0x3
+#define TASK_LENGTH(len)	((len) / 8 - 1)
+#define BITS_TO_BYTES(len)	(((len) + 7) / 8)
+#define BYTES_TO_BITS(len)	((len) * 8)
+
+#define HPRE_ETYPE_SHIFT	5
+#define HPRE_ETYPE_MASK		0x7ff
+#define HPRE_ETYPE1_SHIFT	16
+#define HPRE_ETYPE1_MASK	0x3fff
+#define HPRE_DONE_SHIFT		30
+#define HPRE_DONE_MASK		0x3
+#define HPRE_TASK_ETYPE(w0)	(((w0) >> HPRE_ETYPE_SHIFT) & HPRE_ETYPE_MASK)
+#define HPRE_TASK_ETYPE1(w0)	(((w0) >> HPRE_ETYPE1_SHIFT) & HPRE_ETYPE1_MASK)
+#define HPRE_TASK_DONE(w0)	(((w0) >> HPRE_DONE_SHIFT) & HPRE_DONE_MASK)
+
+struct hpre_sqe {
+	/*
+	 * alg : 5
+	 * etype : 11
+	 * etype1 : 14
+	 * done : 2
+	 */
+	uint32_t w0;
+
+	uint8_t task_len1;
+	uint8_t task_len2;
+	uint8_t mrttest_num;
+	/*
+	 * uwkey_enb : 1
+	 * sm2_ksel : 1
+	 * sva_bypass : 1
+	 * sva_status : 4
+	 * bd_rsv2 : 1
+	 */
+	uint8_t ext1;
+
+	uint64_t key;
+	uint64_t in;
+	uint64_t out;
+	uint64_t tag;
+
+	uint16_t sm2enc_klen;
+	/*
+	 * uwkey_sel : 4
+	 * uwkey_wrap_num : 3
+	 * rsvd2 : 9
+	 */
+	uint16_t ext2;
+
+	uint64_t kek_key;
+	uint32_t rsv[3];
+};
+
+enum hpre_alg_type {
+	HPRE_ALG_NC_NCRT = 0x0,
+	HPRE_ALG_NC_CRT = 0x1,
+	HPRE_ALG_KG_STD = 0x2,
+	HPRE_ALG_KG_CRT = 0x3,
+	HPRE_ALG_DH_G2 = 0x4,
+	HPRE_ALG_DH = 0x5,
+	HPRE_ALG_ECDH_MULTIPLY = 0xD,
+	HPRE_ALG_ECDSA_SIGN = 0xE,
+	HPRE_ALG_ECDSA_VERF = 0xF,
+	HPRE_ALG_X_DH_MULTIPLY = 0x10,
+	HPRE_ALG_SM2_KEY_GEN = 0x11,
+	HPRE_ALG_SM2_SIGN = 0x12,
+	HPRE_ALG_SM2_VERF = 0x13,
+	HPRE_ALG_SM2_ENC = 0x14,
+	HPRE_ALG_SM2_DEC = 0x15
+};
+
+uint32_t hpre_init(void);
+struct hisi_qp *hpre_create_qp(uint8_t sq_type);
+enum hisi_drv_status hpre_bin_from_crypto_bin(uint8_t *dst, const uint8_t *src,
+					      uint32_t bsize, uint32_t dsize);
+enum hisi_drv_status hpre_bin_to_crypto_bin(uint8_t *dst, const uint8_t *src,
+					    uint32_t bsize, uint32_t dsize);
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/hpre_montgomery.c b/core/drivers/crypto/hisilicon/hpre_montgomery.c
new file mode 100644
index 0000000000000000000000000000000000000000..045304944fad1ead0da7629d9f1c927e5d321bf9
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_montgomery.c
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
+ * Kunpeng hardware accelerator hpre montgomery algorithm implementation.
+ */
+#include <drvcrypt.h>
+#include <drvcrypt_acipher.h>
+#include <initcall.h>
+#include <malloc.h>
+#include <rng_support.h>
+#include <stdlib_ext.h>
+#include <string.h>
+#include <string_ext.h>
+#include <trace.h>
+
+#include "hpre_main.h"
+#include "hpre_montgomery.h"
+
+#define X25519_CURVE_INDEX 0
+#define X448_CURVE_INDEX 1
+
+struct hpre_mgm_curve {
+	uint32_t key_bits;
+	const uint8_t *p;
+	const uint8_t *a;
+	const uint8_t *x;
+};
+
+/* NID_X25519 */
+/* p = (2 ^ 255 - 19) big endian */
+static const uint8_t g_x25519_p[] = {
+	0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED
+};
+
+/* a = (486662 - 2) / 4  = 121665 big endian */
+static const uint8_t g_x25519_a[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xDB, 0x41
+};
+
+/* big endian */
+static const uint8_t g_x25519_gx[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09
+};
+
+/* NID_X448 */
+/* p = (2 ^ 448 - 2 ^ 224 - 1) big endian */
+static const uint8_t g_x448_p[] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* a = (156326 - 2) / 4  = 39081 big endian */
+static const uint8_t g_x448_a[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xA9
+};
+
+/* big endian */
+static const uint8_t g_x448_gx[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
+};
+
+static const struct hpre_mgm_curve g_curve_list[] = {
+	{
+		.key_bits = 256,
+		.p = g_x25519_p,
+		.a = g_x25519_a,
+		.x = g_x25519_gx,
+	}, {
+		.key_bits = 448,
+		.p = g_x448_p,
+		.a = g_x448_a,
+		.x = g_x448_gx,
+	}
+};
+
+static TEE_Result
+hpre_montgomery_alloc_keypair(struct montgomery_keypair *key,
+			      size_t size_bits)
+{
+	size_t key_size = BITS_TO_BYTES(size_bits);
+
+	if (!key || (size_bits != X25519_KEY_BITS &&
+		     size_bits != X448_KEY_BITS)) {
+		EMSG("Invalid input parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	key->priv = calloc(1, key_size);
+	if (!key->priv)
+		goto priv_err;
+
+	key->pub = calloc(1, key_size);
+	if (!key->pub)
+		goto pub_err;
+
+	return TEE_SUCCESS;
+pub_err:
+	free(key->priv);
+	key->priv = NULL;
+priv_err:
+	EMSG("HPRE montgomery alloc key pair fail");
+
+	return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static TEE_Result gen_random_privkey(uint8_t *priv, size_t key_bits)
+{
+	size_t key_size = BITS_TO_BYTES(key_bits);
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!priv) {
+		EMSG("Privkey param is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = hw_get_random_bytes(priv, key_size);
+	if (ret) {
+		EMSG("Fail to fill privkey");
+		return TEE_ERROR_NO_DATA;
+	}
+
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_montgomery_params_alloc(struct hpre_montgomery_msg *msg)
+{
+	uint32_t size = HPRE_MONTGOMERY_TOTAL_BUF_SIZE(msg->key_bytes);
+
+	msg->key = calloc(1, size);
+	if (!msg->key) {
+		EMSG("Fail to alloc montgomery key buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->key_dma = virt_to_phys(msg->key);
+	msg->in = msg->key + HPRE_X_KEY_SIZE(msg->key_bytes);
+	msg->in_dma = msg->key_dma + HPRE_X_KEY_SIZE(msg->key_bytes);
+	msg->out = msg->in + msg->key_bytes;
+	msg->out_dma = msg->in_dma + msg->key_bytes;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void hpre_montgomery_params_free(struct hpre_montgomery_msg *msg)
+{
+	if (msg->key) {
+		memzero_explicit(msg->key, HPRE_X_KEY_SIZE(msg->key_bytes));
+		free(msg->key);
+		msg->key = NULL;
+	}
+}
+
+static enum hisi_drv_status
+hpre_montgomery_params_pretreatment(struct hpre_montgomery_msg *msg)
+{
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *k = a + msg->key_bytes;
+	uint8_t *u = msg->in;
+	uint8_t *dst = k;
+	uint32_t bsize = msg->key_bytes;
+	uint32_t dsize = msg->curve_bytes;
+	/*
+	 * It is a constraint of HPRE hardware that key_bytes will be set
+	 * to 72 when curve_bytes is between 48 and 72, and the high-order
+	 * bits will be set to 0.
+	 */
+	uint32_t offset = bsize - dsize;
+	int ret = 0;
+
+	/*
+	 * This is a pretreatment of X25519 with a 32-byte integer,
+	 * as described in RFC 7748:
+	 * Set the three LSB of the first byte and MSB of the last
+	 * to zero, set the second MSB of the last byte to 1.
+	 * When receiving u-array, set MSB of last byte to zero.
+	 * HPRE hardware module uses big-endian mode, so the bytes to be
+	 * set are reversed compared to RFC 7748
+	 */
+	if (msg->key_bytes == BITS_TO_BYTES(X25519_KEY_BITS)) {
+		dst[31] &= 0xF8;
+		dst[0] &= 0x7F;
+		dst[0] |= 0x40;
+		u[0] &= 0x7F;
+	} else {
+		/*
+		 * This is a pretreatment of X448 with a 56-byte integer,
+		 * as described in RFC 7748:
+		 * For X448, set the two LSB of the first byte to 0, and MSB of the
+		 * last byte to 1.
+		 * HPRE hardware module uses big-endian mode, so the bytes to be
+		 * set are reversed compared to RFC 7748
+		 */
+		dst[55 + offset] &= 0xFC;
+		dst[0 + offset] |= 0x80;
+	}
+
+	ret = memcmp(u + offset, p + offset, dsize);
+	if (ret >= 0) {
+		EMSG("u >= p");
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status
+hpre_montgomery_params_fill(const struct hpre_mgm_curve *curve,
+			    struct hpre_montgomery_msg *msg,
+			    uint8_t *privkey, uint8_t *pubkey)
+{
+	uint8_t *p = msg->key;
+	uint8_t *a = p + msg->key_bytes;
+	uint8_t *k = a + msg->key_bytes;
+	uint8_t *x = msg->in;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	memcpy(p, curve->p, msg->curve_bytes);
+	memcpy(a, curve->a, msg->curve_bytes);
+	memcpy(k, privkey, msg->curve_bytes);
+	msg->x_bytes = msg->curve_bytes;
+	if (!pubkey)
+		memcpy(x, curve->x, msg->x_bytes);
+	else
+		memcpy(x, pubkey, msg->x_bytes);
+
+	ret = hpre_bin_from_crypto_bin(p, p, msg->key_bytes, msg->curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer montgomery p from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(a, a, msg->key_bytes, msg->curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer montgomery a from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(k, k, msg->key_bytes, msg->curve_bytes);
+	if (ret) {
+		EMSG("Fail to transfer montgomery k from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(x, x, msg->key_bytes, msg->x_bytes);
+	if (ret) {
+		EMSG("Fail to transfer montgomery x from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	return hpre_montgomery_params_pretreatment(msg);
+}
+
+static TEE_Result
+hpre_montgomery_request_init(const struct hpre_mgm_curve *curve,
+			     struct hpre_montgomery_msg *msg,
+			     uint8_t *privkey,
+			     uint8_t *pubkey)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->alg_type = HPRE_ALG_X_DH_MULTIPLY;
+	msg->curve_bytes = BITS_TO_BYTES(curve->key_bits);
+
+	if (curve->key_bits == X25519_KEY_BITS) {
+		msg->key_bytes = BITS_TO_BYTES(HPRE_HW_X25519_KBITS);
+	} else if (curve->key_bits == X448_KEY_BITS) {
+		msg->key_bytes = BITS_TO_BYTES(HPRE_HW_X448_KBITS);
+	} else {
+		EMSG("Curve key bits param error");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = hpre_montgomery_params_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_montgomery_params_fill(curve, msg, privkey, pubkey);
+	if (ret) {
+		hpre_montgomery_params_free(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void hpre_montgomery_request_deinit(struct hpre_montgomery_msg *msg)
+{
+	hpre_montgomery_params_free(msg);
+}
+
+static enum hisi_drv_status hpre_montgomery_fill_sqe(void *bd, void *info)
+{
+	struct hpre_montgomery_msg *msg = info;
+	struct hpre_sqe *sqe = bd;
+
+	sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT);
+	sqe->task_len1 = TASK_LENGTH(msg->key_bytes);
+	sqe->key = msg->key_dma;
+	sqe->in = msg->in_dma;
+	sqe->out = msg->out_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status hpre_montgomery_parse_sqe(void *bd, void *info)
+{
+	struct hpre_montgomery_msg *msg = info;
+	struct hpre_sqe *sqe = bd;
+	uint8_t *rx = msg->out;
+	uint16_t err = 0;
+	uint16_t err1 = 0;
+	uint16_t done = 0;
+
+	err = HPRE_TASK_ETYPE(sqe->w0);
+	err1 = HPRE_TASK_ETYPE1(sqe->w0);
+	done = HPRE_TASK_DONE(sqe->w0);
+	if (done != HPRE_HW_TASK_DONE || err || err1) {
+		EMSG("HPRE do x_dh fail! done=0x%"PRIX16", etype=0x%"PRIX16",etype1=0x%"PRIX16,
+		     done, err, err1);
+		if (done == HPRE_HW_TASK_INIT) {
+			msg->result = HISI_QM_DRVCRYPT_ENOPROC;
+			return HISI_QM_DRVCRYPT_ENOPROC;
+		}
+
+		msg->result = HISI_QM_DRVCRYPT_IN_EPARA;
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	if (hpre_bin_to_crypto_bin(rx, rx, msg->key_bytes, msg->curve_bytes)) {
+		EMSG("Fail to transfer x_dh out from hpre_bin to crypto_bin");
+		msg->result = HISI_QM_DRVCRYPT_EINVAL;
+		return HISI_QM_DRVCRYPT_EINVAL;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result hpre_montgomery_do_task(struct hpre_montgomery_msg *msg)
+{
+	struct hisi_qp *montgomery_qp = NULL;
+	TEE_Result res = TEE_SUCCESS;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	montgomery_qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE1);
+	if (!montgomery_qp) {
+		EMSG("Fail to create montgomery qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	montgomery_qp->fill_sqe = hpre_montgomery_fill_sqe;
+	montgomery_qp->parse_sqe = hpre_montgomery_parse_sqe;
+	ret = hisi_qp_send(montgomery_qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done;
+	}
+
+	ret = hisi_qp_recv_sync(montgomery_qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+	}
+
+done:
+	hisi_qm_release_qp(montgomery_qp);
+
+	return res;
+}
+
+static TEE_Result hpre_montgomery_gen_keypair(struct montgomery_keypair *key,
+					      size_t size_bits)
+{
+	struct hpre_montgomery_msg msg = { };
+	const struct hpre_mgm_curve *curve = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!key || !key->priv || !key->pub) {
+		EMSG("Invalid montgomery_gen_keypair input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (size_bits == X25519_KEY_BITS)
+		curve = &g_curve_list[X25519_CURVE_INDEX];
+	else if (size_bits == X448_KEY_BITS)
+		curve = &g_curve_list[X448_CURVE_INDEX];
+	else
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = gen_random_privkey(key->priv, size_bits);
+	if (ret) {
+		EMSG("Fail to gen privkey");
+		return ret;
+	}
+
+	ret = hpre_montgomery_request_init(curve, &msg, key->priv, NULL);
+	if (ret) {
+		EMSG("Fail to init montgomery key pair");
+		return ret;
+	}
+
+	ret = hpre_montgomery_do_task(&msg);
+	if (ret) {
+		EMSG("Fail to do montgomery key pair task ret = 0x%"PRIX32, ret);
+		goto done;
+	}
+	memcpy(key->pub, msg.out, msg.curve_bytes);
+
+done:
+	hpre_montgomery_request_deinit(&msg);
+
+	return ret;
+}
+
+static TEE_Result
+hpre_montgomery_do_shared_secret(struct drvcrypt_secret_data *sdata)
+{
+	struct hpre_montgomery_msg msg = { };
+	const struct hpre_mgm_curve *curve = NULL;
+	struct montgomery_keypair *key = NULL;
+	uint8_t *pubkey = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!sdata || !sdata->key_priv || !sdata->key_pub) {
+		EMSG("Invalid montgomery_do_shared_secret input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	key = sdata->key_priv;
+	pubkey = sdata->key_pub;
+	if (sdata->size_sec == BITS_TO_BYTES(X25519_KEY_BITS))
+		curve = &g_curve_list[X25519_CURVE_INDEX];
+	else if (sdata->size_sec == BITS_TO_BYTES(X448_KEY_BITS))
+		curve = &g_curve_list[X448_CURVE_INDEX];
+	else
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_montgomery_request_init(curve, &msg, key->priv, pubkey);
+	if (ret) {
+		EMSG("Fail to init montgomery shared secret");
+		return ret;
+	}
+
+	ret = hpre_montgomery_do_task(&msg);
+	if (ret) {
+		EMSG("Fail to do montgomery shared secret task! ret = 0x%"PRIX32,
+		     ret);
+		goto done;
+	}
+	memcpy(sdata->secret.data, msg.out, msg.curve_bytes);
+	sdata->secret.length = msg.curve_bytes;
+	memzero_explicit(msg.out, msg.curve_bytes);
+
+done:
+	hpre_montgomery_request_deinit(&msg);
+
+	return ret;
+}
+
+static struct drvcrypt_montgomery driver_x25519 = {
+	.alloc_keypair = hpre_montgomery_alloc_keypair,
+	.gen_keypair = hpre_montgomery_gen_keypair,
+	.shared_secret = hpre_montgomery_do_shared_secret,
+};
+
+static struct drvcrypt_montgomery driver_x448 = {
+	.alloc_keypair = hpre_montgomery_alloc_keypair,
+	.gen_keypair = hpre_montgomery_gen_keypair,
+	.shared_secret = hpre_montgomery_do_shared_secret,
+};
+
+static TEE_Result hpre_montgomery_init(void)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = drvcrypt_register_x25519(&driver_x25519);
+	if (ret != TEE_SUCCESS) {
+		EMSG("Hpre x25519 register to crypto fail");
+		return ret;
+	}
+
+	ret = drvcrypt_register_x448(&driver_x448);
+	if (ret != TEE_SUCCESS) {
+		EMSG("Hpre x448 register to crypto fail");
+		return ret;
+	}
+
+	return ret;
+}
+
+driver_init(hpre_montgomery_init);
diff --git a/core/drivers/crypto/hisilicon/hpre_montgomery.h b/core/drivers/crypto/hisilicon/hpre_montgomery.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8549e062ad93372accb8b9a43f219e3f102ab45
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_montgomery.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 HiSilicon Limited.
+ */
+#ifndef __HPRE_MONTGOMERY_H__
+#define __HPRE_MONTGOMERY_H__
+
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+#define HPRE_X_KEY_PARAM_NUM 3
+#define X25519_KEY_BITS 256
+#define X448_KEY_BITS 448
+#define HPRE_HW_X25519_KBITS 256
+#define HPRE_HW_X448_KBITS 576
+#define HPRE_MONTGOMERY_TOTAL_BUF_SIZE(key_bytes) ((key_bytes) * 5)
+#define HPRE_X_KEY_SIZE(hsz)	((hsz) * HPRE_X_KEY_PARAM_NUM)
+
+struct hpre_montgomery_msg {
+	uint8_t *key;
+	paddr_t key_dma;
+	uint8_t *in;
+	paddr_t in_dma;
+	uint8_t *out;
+	paddr_t out_dma;
+	uint32_t alg_type;
+	uint32_t key_bytes;
+	uint32_t curve_bytes;
+	uint32_t x_bytes;
+	uint32_t result;
+};
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/hpre_rsa.c b/core/drivers/crypto/hisilicon/hpre_rsa.c
new file mode 100644
index 0000000000000000000000000000000000000000..04b5057933e91d40b6032418317ce98a9d99b3b8
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_rsa.c
@@ -0,0 +1,1025 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, HiSilicon Technologies Co., Ltd.
+ * Kunpeng hardware accelerator hpre rsa algorithm implementation.
+ */
+
+#include <crypto/crypto_impl.h>
+#include <drvcrypt.h>
+#include <drvcrypt_acipher.h>
+#include <drvcrypt_math.h>
+#include <initcall.h>
+#include <malloc.h>
+#include <mbedtls/rsa.h>
+#include <rng_support.h>
+#include <stdlib_ext.h>
+#include <string.h>
+#include <string_ext.h>
+#include <tee/tee_cryp_utl.h>
+#include <trace.h>
+
+#include "hpre_main.h"
+#include "hpre_rsa.h"
+
+static enum hisi_drv_status hpre_rsa_fill_addr_params(struct hpre_rsa_msg *msg,
+						      struct hpre_sqe *sqe)
+{
+	switch (msg->alg_type) {
+	case HPRE_ALG_NC_NCRT:
+	case HPRE_ALG_NC_CRT:
+		if (msg->is_private) {
+			/* DECRYPT */
+			sqe->key = msg->prikey_dma;
+			sqe->in = msg->in_dma;
+			sqe->out = msg->out_dma;
+		} else {
+			/* ENCRYPT */
+			sqe->key = msg->pubkey_dma;
+			sqe->in = msg->in_dma;
+			sqe->out = msg->out_dma;
+		}
+		return HISI_QM_DRVCRYPT_NO_ERR;
+	default:
+		EMSG("Invalid alg_type[%"PRIu32"]", msg->alg_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+}
+
+static enum hisi_drv_status hpre_rsa_fill_sqe(void *bd, void *info)
+{
+	struct hpre_rsa_msg *msg = info;
+	struct hpre_sqe *sqe = bd;
+
+	sqe->w0 = msg->alg_type | SHIFT_U32(0x1, HPRE_DONE_SHIFT);
+	sqe->task_len1 = TASK_LENGTH(msg->key_bytes);
+
+	return hpre_rsa_fill_addr_params(msg, sqe);
+}
+
+static enum hisi_drv_status hpre_rsa_parse_sqe(void *bd, void *info __unused)
+{
+	struct hpre_sqe *sqe = bd;
+	uint16_t err = 0;
+	uint16_t done = 0;
+
+	err = HPRE_TASK_ETYPE(sqe->w0);
+	done = HPRE_TASK_DONE(sqe->w0);
+	if (done != HPRE_HW_TASK_DONE || err) {
+		EMSG("HPRE do rsa fail! done=0x%"PRIX16", etype=0x%"PRIX16,
+		     done, err);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result hpre_rsa_do_task(void *msg)
+{
+	struct hisi_qp *rsa_qp = NULL;
+	TEE_Result res = TEE_SUCCESS;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	rsa_qp = hpre_create_qp(HISI_QM_CHANNEL_TYPE0);
+	if (!rsa_qp) {
+		EMSG("Fail to create rsa qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	rsa_qp->fill_sqe = hpre_rsa_fill_sqe;
+	rsa_qp->parse_sqe = hpre_rsa_parse_sqe;
+	ret = hisi_qp_send(rsa_qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%x"PRIx32, ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+	ret = hisi_qp_recv_sync(rsa_qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%x"PRIx32, ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+done_proc:
+	hisi_qm_release_qp(rsa_qp);
+
+	return res;
+}
+
+static TEE_Result mgf_process(size_t digest_size, uint8_t *seed,
+			      size_t seed_len, uint8_t *mask, size_t mask_len,
+			      struct drvcrypt_rsa_ed *rsa_data)
+{
+	struct drvcrypt_rsa_mgf mgf = { };
+
+	if (!rsa_data->mgf) {
+		EMSG("mgf function is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	mgf.hash_algo = rsa_data->hash_algo;
+	mgf.digest_size = digest_size;
+	mgf.seed.data = seed;
+	mgf.seed.length = seed_len;
+	mgf.mask.data = mask;
+	mgf.mask.length = mask_len;
+
+	return rsa_data->mgf(&mgf);
+}
+
+static TEE_Result xor_process(uint8_t *a, uint8_t *b, uint8_t *out, size_t len)
+{
+	struct drvcrypt_mod_op xor_mod = { };
+
+	xor_mod.n.length = len;
+	xor_mod.a.data = a;
+	xor_mod.a.length = len;
+	xor_mod.b.data = b;
+	xor_mod.b.length = len;
+	xor_mod.result.data = out;
+	xor_mod.result.length = len;
+
+	return drvcrypt_xor_mod_n(&xor_mod);
+}
+
+static size_t hpre_rsa_get_hw_kbytes(size_t key_bits)
+{
+	size_t size = 0;
+
+	if (key_bits <= 1024)
+		size = BITS_TO_BYTES(1024);
+	else if (key_bits <= 2048)
+		size = BITS_TO_BYTES(2048);
+	else if (key_bits <= 3072)
+		size = BITS_TO_BYTES(3072);
+	else if (key_bits <= 4096)
+		size = BITS_TO_BYTES(4096);
+	else
+		EMSG("Invalid key_bits[%zu]", key_bits);
+
+	return size;
+}
+
+static void hpre_rsa_params_free(struct hpre_rsa_msg *msg)
+{
+	switch (msg->alg_type) {
+	case HPRE_ALG_NC_NCRT:
+		if (msg->is_private)
+			free_wipe(msg->prikey);
+		else
+			free(msg->pubkey);
+		break;
+	case HPRE_ALG_NC_CRT:
+		if (msg->is_private)
+			free_wipe(msg->prikey);
+		break;
+	default:
+		EMSG("Invalid alg_type[%"PRIu32"]", msg->alg_type);
+		break;
+	}
+}
+
+static enum hisi_drv_status hpre_rsa_encrypt_alloc(struct hpre_rsa_msg *msg)
+{
+	uint32_t size = HPRE_RSA_NCRT_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc rsa ncrt buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->pubkey = data;
+	msg->pubkey_dma = virt_to_phys(msg->pubkey);
+
+	msg->in = data + (msg->key_bytes * 2);
+	msg->in_dma = msg->pubkey_dma + (msg->key_bytes * 2);
+
+	msg->out = msg->in + msg->key_bytes;
+	msg->out_dma = msg->in_dma + msg->key_bytes;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status
+hpre_rsa_encrypt_bn2bin(struct hpre_rsa_msg *msg,
+			struct drvcrypt_rsa_ed *rsa_data)
+{
+	struct rsa_public_key *key = rsa_data->key.key;
+	uint32_t e_len = 0;
+	uint32_t n_len = 0;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	uint8_t *n = NULL;
+
+	n = msg->pubkey + msg->key_bytes;
+
+	crypto_bignum_bn2bin(key->e, msg->pubkey);
+	crypto_bignum_bn2bin(key->n, n);
+	e_len = crypto_bignum_num_bytes(key->e);
+	n_len = crypto_bignum_num_bytes(key->n);
+
+	ret = hpre_bin_from_crypto_bin(msg->pubkey, msg->pubkey,
+				       msg->key_bytes, e_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa ncrt e from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(n, n, msg->key_bytes, n_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa ncrt n from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(msg->in, rsa_data->message.data,
+				       msg->key_bytes,
+				       rsa_data->message.length);
+	if (ret)
+		EMSG("Fail to transfer rsa plaintext from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static TEE_Result hpre_rsa_encrypt_init(struct hpre_rsa_msg *msg,
+					struct drvcrypt_rsa_ed *rsa_data)
+{
+	size_t n_bytes = rsa_data->key.n_size;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->alg_type = HPRE_ALG_NC_NCRT;
+	msg->is_private = rsa_data->key.isprivate;
+	msg->key_bytes = hpre_rsa_get_hw_kbytes(BYTES_TO_BITS(n_bytes));
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ret = hpre_rsa_encrypt_alloc(msg);
+	if (ret)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	ret = hpre_rsa_encrypt_bn2bin(msg, rsa_data);
+	if (ret) {
+		hpre_rsa_params_free(msg);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_nopad_encrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	size_t n_bytes = rsa_data->key.n_size;
+	struct hpre_rsa_msg msg = { };
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (rsa_data->message.length > n_bytes) {
+		EMSG("Invalid msg length[%zu]", rsa_data->message.length);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = hpre_rsa_encrypt_init(&msg, rsa_data);
+	if (ret) {
+		EMSG("Fail to init rsa msg");
+		return ret;
+	}
+
+	ret = hpre_rsa_do_task(&msg);
+	if (ret)
+		goto encrypt_deinit;
+
+	/* Ciphertext can have valid zero data in NOPAD MODE */
+	memcpy(rsa_data->cipher.data, msg.out + msg.key_bytes - n_bytes,
+	       n_bytes);
+	rsa_data->cipher.length = n_bytes;
+
+encrypt_deinit:
+	hpre_rsa_params_free(&msg);
+
+	return ret;
+}
+
+static TEE_Result pkcs_v1_5_fill_ps(uint8_t *ps, size_t ps_len)
+{
+	size_t i = 0;
+
+	if (hw_get_random_bytes(ps, ps_len)) {
+		EMSG("Fail to get ps data");
+		return TEE_ERROR_NO_DATA;
+	}
+
+	for (i = 0; i < ps_len; i++) {
+		if (ps[i] == 0)
+			ps[i] = PKCS_V1_5_PS_DATA;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsaes_pkcs_v1_5_encode(struct drvcrypt_rsa_ed *rsa_data,
+					 uint8_t *out)
+{
+	size_t msg_len = rsa_data->message.length;
+	size_t out_len = rsa_data->cipher.length;
+	size_t n_bytes = rsa_data->key.n_size;
+	uint8_t *ps = out + PKCS_V1_5_PS_POS;
+	TEE_Result ret = TEE_SUCCESS;
+	size_t ps_len = 0;
+
+	/* PKCS_V1.5 format 0x00 || 0x02 || PS non-zero || 0x00 || M */
+	if ((msg_len + PKCS_V1_5_MSG_MIN_LEN) > n_bytes || out_len < n_bytes) {
+		EMSG("Invalid pkcs_v1.5 encode parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ps_len = n_bytes - PKCS_V1_5_FIXED_LEN - msg_len;
+	ret = pkcs_v1_5_fill_ps(ps, ps_len);
+	if (ret)
+		return ret;
+
+	out[0] = 0;
+	out[1] = ENCRYPT_PAD;
+	out[PKCS_V1_5_FIXED_LEN + ps_len - 1] = 0;
+	memcpy(out + PKCS_V1_5_FIXED_LEN + ps_len, rsa_data->message.data,
+	       msg_len);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_pkcs_encrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	uint32_t n_bytes = rsa_data->key.n_size;
+	struct drvcrypt_rsa_ed rsa_enc_info = *rsa_data;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* Alloc pkcs_v1.5 encode message data buf */
+	rsa_enc_info.message.data = malloc(n_bytes);
+	if (!rsa_enc_info.message.data) {
+		EMSG("Fail to alloc message data buf");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	rsa_enc_info.message.length = n_bytes;
+	ret = rsaes_pkcs_v1_5_encode(rsa_data, rsa_enc_info.message.data);
+	if (ret) {
+		EMSG("Fail to get pkcs_v1.5 encode message data");
+		goto free_data;
+	}
+
+	ret = rsa_nopad_encrypt(&rsa_enc_info);
+	if (ret)
+		goto free_data;
+
+	memcpy(rsa_data->cipher.data, rsa_enc_info.cipher.data,
+	       rsa_enc_info.cipher.length);
+	rsa_data->cipher.length = rsa_enc_info.cipher.length;
+
+free_data:
+	free(rsa_enc_info.message.data);
+
+	return ret;
+}
+
+static TEE_Result rsa_oaep_fill_db(struct drvcrypt_rsa_ed *rsa_data,
+				   uint8_t *db)
+{
+	size_t lhash_len = rsa_data->digest_size;
+	size_t n_bytes = rsa_data->key.n_size;
+	size_t db_len = n_bytes - lhash_len - 1;
+	size_t ps_len = 0;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* oaep db format lhash || ps zero || 01 || M */
+	ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data,
+				    rsa_data->label.length, db, lhash_len);
+	if (ret) {
+		EMSG("Fail to get label hash");
+		return ret;
+	}
+
+	ps_len = db_len - lhash_len - rsa_data->message.length - 1;
+	db[lhash_len + ps_len] = 1;
+	memcpy(db + lhash_len + ps_len + 1, rsa_data->message.data,
+	       rsa_data->message.length);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_oaep_fill_maskdb(struct drvcrypt_rsa_ed *rsa_data,
+				       uint8_t *seed, uint8_t *db,
+				       uint8_t *mask_db)
+{
+	size_t lhash_len = rsa_data->digest_size;
+	size_t n_bytes = rsa_data->key.n_size;
+	size_t db_len = n_bytes - lhash_len - 1;
+	uint8_t seed_mgf[OAEP_MAX_DB_LEN] = { };
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = mgf_process(lhash_len, seed, lhash_len, seed_mgf, db_len,
+			  rsa_data);
+	if (ret) {
+		EMSG("Fail to get seed_mgf");
+		return ret;
+	}
+
+	return xor_process(db, seed_mgf, mask_db, db_len);
+}
+
+static TEE_Result rsa_oaep_fill_maskseed(struct drvcrypt_rsa_ed *rsa_data,
+					 uint8_t *seed, uint8_t *em)
+{
+	uint8_t mask_db_mgf[OAEP_MAX_HASH_LEN] = { 0 };
+	size_t lhash_len = rsa_data->digest_size;
+	size_t n_bytes = rsa_data->key.n_size;
+	size_t db_len = n_bytes - lhash_len - 1;
+	uint8_t *mask_db = em + lhash_len + 1;
+	uint8_t *mask_seed = em + 1;
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = mgf_process(lhash_len, mask_db, db_len, mask_db_mgf, lhash_len,
+			  rsa_data);
+	if (ret) {
+		EMSG("Fail to get mask_db_mgf");
+		return ret;
+	}
+
+	return xor_process(seed, mask_db_mgf, mask_seed, lhash_len);
+}
+
+static TEE_Result rsa_oaep_encode(struct drvcrypt_rsa_ed *rsa_data,
+				  uint8_t *em)
+{
+	size_t lhash_len = rsa_data->digest_size;
+	uint8_t db[OAEP_MAX_DB_LEN] = { };
+	uint8_t seed[OAEP_MAX_HASH_LEN] = { };
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* oaep format 00 || maskedseed || maskeddb */
+	em[0] = 0;
+
+	ret = rsa_oaep_fill_db(rsa_data, db);
+	if (ret)
+		return ret;
+
+	ret = hw_get_random_bytes(seed, lhash_len);
+	if (ret)
+		return ret;
+
+	ret = rsa_oaep_fill_maskdb(rsa_data, seed, db, em + lhash_len + 1);
+	if (ret)
+		return ret;
+
+	return rsa_oaep_fill_maskseed(rsa_data, seed, em);
+}
+
+static TEE_Result rsa_oaep_encrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	size_t n_bytes = rsa_data->key.n_size;
+	struct drvcrypt_rsa_ed rsa_enc_info = *rsa_data;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* Alloc oaep encode message data buf */
+	rsa_enc_info.message.data = malloc(n_bytes);
+	if (!rsa_enc_info.message.data) {
+		EMSG("Fail to alloc message data buf");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	rsa_enc_info.message.length = n_bytes;
+	ret = rsa_oaep_encode(rsa_data, rsa_enc_info.message.data);
+	if (ret) {
+		EMSG("Fail to get oaep encode message data");
+		goto free_data;
+	}
+
+	ret = rsa_nopad_encrypt(&rsa_enc_info);
+	if (ret)
+		goto free_data;
+
+	memcpy(rsa_data->cipher.data, rsa_enc_info.cipher.data,
+	       rsa_enc_info.cipher.length);
+	rsa_data->cipher.length = rsa_enc_info.cipher.length;
+
+free_data:
+	free(rsa_enc_info.message.data);
+
+	return ret;
+}
+
+static TEE_Result hpre_rsa_encrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	if (!rsa_data) {
+		EMSG("Invalid rsa encrypt input parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	switch (rsa_data->rsa_id) {
+	case DRVCRYPT_RSA_NOPAD:
+	case DRVCRYPT_RSASSA_PKCS_V1_5:
+	case DRVCRYPT_RSASSA_PSS:
+		return rsa_nopad_encrypt(rsa_data);
+	case DRVCRYPT_RSA_PKCS_V1_5:
+		return rsa_pkcs_encrypt(rsa_data);
+	case DRVCRYPT_RSA_OAEP:
+		return rsa_oaep_encrypt(rsa_data);
+	default:
+		EMSG("Invalid rsa id");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+}
+
+static enum hisi_drv_status hpre_rsa_crt_decrypt_alloc(struct hpre_rsa_msg *msg)
+{
+	uint32_t size = HPRE_RSA_CRT_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc rsa crt total buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->prikey = data;
+	msg->prikey_dma = virt_to_phys(msg->prikey);
+
+	msg->in = data + (msg->key_bytes * 2) + (msg->key_bytes >> 1);
+	msg->in_dma = msg->prikey_dma + (msg->key_bytes * 2) +
+		      (msg->key_bytes >> 1);
+
+	msg->out = msg->in + msg->key_bytes;
+	msg->out_dma = msg->in_dma + msg->key_bytes;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status
+hpre_rsa_ncrt_decrypt_alloc(struct hpre_rsa_msg *msg)
+{
+	uint32_t size = HPRE_RSA_NCRT_TOTAL_BUF_SIZE(msg->key_bytes);
+	uint8_t *data = NULL;
+
+	data = calloc(1, size);
+	if (!data) {
+		EMSG("Fail to alloc rsa ncrt buf");
+		return HISI_QM_DRVCRYPT_ENOMEM;
+	}
+
+	msg->prikey = data;
+	msg->prikey_dma = virt_to_phys(msg->prikey);
+
+	msg->in = data + (msg->key_bytes * 2);
+	msg->in_dma = msg->prikey_dma + (msg->key_bytes * 2);
+
+	msg->out = msg->in + msg->key_bytes;
+	msg->out_dma = msg->in_dma + msg->key_bytes;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status
+hpre_rsa_crt_decrypt_bn2bin(struct hpre_rsa_msg *msg,
+			    struct drvcrypt_rsa_ed *rsa_data)
+{
+	struct rsa_keypair *key = rsa_data->key.key;
+	uint32_t p_bytes = msg->key_bytes >> 1;
+	uint32_t dq_len = crypto_bignum_num_bytes(key->dq);
+	uint32_t dp_len = crypto_bignum_num_bytes(key->dp);
+	uint32_t q_len = crypto_bignum_num_bytes(key->q);
+	uint32_t p_len = crypto_bignum_num_bytes(key->p);
+	uint32_t qp_len = crypto_bignum_num_bytes(key->qp);
+	uint8_t *dq = msg->prikey;
+	uint8_t *dp = msg->prikey + p_bytes;
+	uint8_t *q = dp + p_bytes;
+	uint8_t *p = q + p_bytes;
+	uint8_t *qp = p + p_bytes;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	crypto_bignum_bn2bin(key->dq, dq);
+	crypto_bignum_bn2bin(key->dp, dp);
+	crypto_bignum_bn2bin(key->q, q);
+	crypto_bignum_bn2bin(key->p, p);
+	crypto_bignum_bn2bin(key->qp, qp);
+
+	ret = hpre_bin_from_crypto_bin(dq, dq, p_bytes, dq_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa crt dq from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(dp, dp, p_bytes, dp_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa crt dp from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(q, q, p_bytes, q_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa crt q from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(p, p, p_bytes, p_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa crt p from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(qp, qp, p_bytes, qp_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa crt qinv from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(msg->in, rsa_data->cipher.data,
+				       msg->key_bytes, rsa_data->cipher.length);
+	if (ret)
+		EMSG("Fail to transfer rsa ciphertext from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static enum hisi_drv_status
+hpre_rsa_ncrt_decrypt_bn2bin(struct hpre_rsa_msg *msg,
+			     struct drvcrypt_rsa_ed *rsa_data)
+{
+	struct rsa_keypair *key = rsa_data->key.key;
+	uint32_t d_len = 0;
+	uint32_t n_len = 0;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	uint8_t *n = NULL;
+
+	n = msg->prikey + msg->key_bytes;
+
+	crypto_bignum_bn2bin(key->d, msg->prikey);
+	crypto_bignum_bn2bin(key->n, n);
+	d_len = crypto_bignum_num_bytes(key->d);
+	n_len = crypto_bignum_num_bytes(key->n);
+
+	ret = hpre_bin_from_crypto_bin(msg->prikey, msg->prikey, msg->key_bytes,
+				       d_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa ncrt d from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(n, n, msg->key_bytes, n_len);
+	if (ret) {
+		EMSG("Fail to transfer rsa ncrt n from crypto_bin to hpre_bin");
+		return ret;
+	}
+
+	ret = hpre_bin_from_crypto_bin(msg->in, rsa_data->cipher.data,
+				       msg->key_bytes, rsa_data->cipher.length);
+	if (ret)
+		EMSG("Fail to transfer rsa ciphertext from crypto_bin to hpre_bin");
+
+	return ret;
+}
+
+static bool hpre_rsa_is_crt_mod(struct rsa_keypair *key)
+{
+	if (key->p && crypto_bignum_num_bits(key->p) &&
+	    key->q && crypto_bignum_num_bits(key->q) &&
+	    key->dp && crypto_bignum_num_bits(key->dp) &&
+	    key->dq && crypto_bignum_num_bits(key->dq) &&
+	    key->qp && crypto_bignum_num_bits(key->qp))
+		return true;
+
+	return false;
+}
+
+static TEE_Result hpre_rsa_decrypt_init(struct hpre_rsa_msg *msg,
+					struct drvcrypt_rsa_ed *rsa_data)
+{
+	struct rsa_keypair *key = rsa_data->key.key;
+	size_t n_bytes = rsa_data->key.n_size;
+	bool is_crt = false;
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	msg->is_private = rsa_data->key.isprivate;
+	msg->key_bytes = hpre_rsa_get_hw_kbytes(BYTES_TO_BITS(n_bytes));
+	if (!msg->key_bytes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	is_crt = hpre_rsa_is_crt_mod(key);
+	if (is_crt) {
+		msg->alg_type = HPRE_ALG_NC_CRT;
+		ret = hpre_rsa_crt_decrypt_alloc(msg);
+		if (ret)
+			return TEE_ERROR_OUT_OF_MEMORY;
+
+		ret = hpre_rsa_crt_decrypt_bn2bin(msg, rsa_data);
+		if (ret) {
+			hpre_rsa_params_free(msg);
+			return TEE_ERROR_BAD_STATE;
+		}
+	} else {
+		msg->alg_type = HPRE_ALG_NC_NCRT;
+		ret = hpre_rsa_ncrt_decrypt_alloc(msg);
+		if (ret)
+			return TEE_ERROR_OUT_OF_MEMORY;
+
+		ret = hpre_rsa_ncrt_decrypt_bn2bin(msg, rsa_data);
+		if (ret) {
+			hpre_rsa_params_free(msg);
+			return TEE_ERROR_BAD_STATE;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_nopad_decrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	size_t n_bytes = rsa_data->key.n_size;
+	struct hpre_rsa_msg msg = { };
+	uint32_t offset = 0;
+	TEE_Result ret = TEE_SUCCESS;
+	uint8_t *pos = NULL;
+
+	if (rsa_data->cipher.length > n_bytes) {
+		EMSG("Invalid cipher length[%zu]", rsa_data->cipher.length);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = hpre_rsa_decrypt_init(&msg, rsa_data);
+	if (ret) {
+		EMSG("Fail to init rsa msg");
+		return ret;
+	}
+
+	ret = hpre_rsa_do_task(&msg);
+	if (ret)
+		goto decrypt_deinit;
+
+	pos = msg.out + msg.key_bytes - n_bytes;
+	if (rsa_data->rsa_id == DRVCRYPT_RSA_NOPAD) {
+		/* Plaintext can not have valid zero data in NOPAD MODE */
+		while ((offset < n_bytes - 1) && (pos[offset] == 0))
+			offset++;
+	}
+
+	rsa_data->message.length = n_bytes - offset;
+	memcpy(rsa_data->message.data, pos + offset, rsa_data->message.length);
+
+decrypt_deinit:
+	hpre_rsa_params_free(&msg);
+
+	return ret;
+}
+
+static TEE_Result rsaes_pkcs_v1_5_decode(struct drvcrypt_rsa_ed *rsa_data,
+					 uint8_t *out, size_t *out_len)
+{
+	size_t em_len = rsa_data->message.length;
+	uint8_t *em = rsa_data->message.data;
+	size_t ps_len = 0;
+	size_t i = 0;
+
+	/* PKCS_V1.5 EM format 0x00 || 0x02 || PS non-zero || 0x00 || M */
+	if (em_len < PKCS_V1_5_MSG_MIN_LEN || em[0] != 0 ||
+	    em[1] != ENCRYPT_PAD) {
+		EMSG("Invalid pkcs_v1.5 decode parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	for (i = PKCS_V1_5_PS_POS; i < em_len; i++) {
+		if (em[i] == 0)
+			break;
+	}
+
+	if (i >= em_len) {
+		EMSG("Fail to find zero pos");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ps_len = i - PKCS_V1_5_PS_POS;
+	if (em_len - ps_len - PKCS_V1_5_FIXED_LEN > *out_len ||
+	    ps_len < PKCS_V1_5_PS_MIN_LEN) {
+		EMSG("Invalid pkcs_v1.5 decode ps_len");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	*out_len = em_len - ps_len - PKCS_V1_5_FIXED_LEN;
+	memcpy(out, em + ps_len + PKCS_V1_5_FIXED_LEN, *out_len);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_pkcs_decrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	uint32_t n_bytes = rsa_data->key.n_size;
+	struct drvcrypt_rsa_ed rsa_dec_info = *rsa_data;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* Alloc pkcs_v1.5 encode message data buf */
+	rsa_dec_info.message.data = malloc(n_bytes);
+	if (!rsa_dec_info.message.data) {
+		EMSG("Fail to alloc message data buf");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	rsa_dec_info.message.length = n_bytes;
+	ret = rsa_nopad_decrypt(&rsa_dec_info);
+	if (ret)
+		goto free_data;
+
+	ret = rsaes_pkcs_v1_5_decode(&rsa_dec_info, rsa_data->message.data,
+				     &rsa_data->message.length);
+	if (ret)
+		EMSG("Fail to get pkcs_v1.5 decode message data");
+
+free_data:
+	free(rsa_dec_info.message.data);
+
+	return ret;
+}
+
+static TEE_Result rsa_oaep_get_seed(struct drvcrypt_rsa_ed *rsa_data,
+				    uint8_t *mask_db, uint8_t *seed)
+{
+	size_t db_len = rsa_data->key.n_size - rsa_data->digest_size - 1;
+	uint8_t mask_db_mgf[OAEP_MAX_HASH_LEN] = { };
+	size_t lhash_len = rsa_data->digest_size;
+	uint8_t *mask_seed = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	mask_seed = rsa_data->message.data + 1;
+
+	ret = mgf_process(lhash_len, mask_db, db_len, mask_db_mgf, lhash_len,
+			  rsa_data);
+	if (ret) {
+		EMSG("Fail to get mask_db mgf result");
+		return ret;
+	}
+
+	return xor_process(mask_seed, mask_db_mgf, seed, lhash_len);
+}
+
+static TEE_Result rsa_oaep_get_db(struct drvcrypt_rsa_ed *rsa_data,
+				  uint8_t *mask_db, uint8_t *seed, uint8_t *db)
+{
+	size_t db_len = rsa_data->key.n_size - rsa_data->digest_size - 1;
+	size_t lhash_len = rsa_data->digest_size;
+	uint8_t seed_mgf[OAEP_MAX_DB_LEN] = { };
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = mgf_process(lhash_len, seed, lhash_len, seed_mgf, db_len,
+			  rsa_data);
+	if (ret) {
+		EMSG("Fail to get seed mgf result");
+		return ret;
+	}
+
+	return xor_process(mask_db, seed_mgf, db, db_len);
+}
+
+static TEE_Result rsa_oaep_get_msg(struct drvcrypt_rsa_ed *rsa_data,
+				   uint8_t *db, uint8_t *out, size_t *out_len)
+{
+	size_t db_len = rsa_data->key.n_size - rsa_data->digest_size - 1;
+	size_t lhash_len = rsa_data->digest_size;
+	uint8_t hash[OAEP_MAX_HASH_LEN] = { };
+	size_t msg_len = 0;
+	size_t lp_len = 0;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* oaep db format lhash || ps zero || 01 || M */
+	ret = tee_hash_createdigest(rsa_data->hash_algo, rsa_data->label.data,
+				    rsa_data->label.length, hash, lhash_len);
+	if (ret) {
+		EMSG("Fail to get label hash");
+		return ret;
+	}
+
+	if (memcmp(hash, db, lhash_len)) {
+		EMSG("Hash is not equal");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	for (lp_len = lhash_len; lp_len < db_len; lp_len++) {
+		if (db[lp_len] != 0)
+			break;
+	}
+
+	if (lp_len == db_len) {
+		EMSG("Fail to find fixed 01 in db");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	msg_len = db_len - lp_len - 1;
+	if (msg_len > rsa_data->message.length) {
+		DMSG("Message space is not enough");
+		*out_len = msg_len;
+		return TEE_ERROR_SHORT_BUFFER;
+	}
+
+	*out_len = msg_len;
+	memcpy(out, db + lp_len + 1, msg_len);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result rsa_oaep_decode(struct drvcrypt_rsa_ed *rsa_data,
+				  uint8_t *out, size_t *out_len)
+{
+	size_t lhash_len = rsa_data->digest_size;
+	uint8_t seed[OAEP_MAX_HASH_LEN] = { };
+	uint8_t db[OAEP_MAX_DB_LEN] = { };
+	uint8_t *mask_db = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* oaep format 00 || maskedseed || maskeddb */
+	mask_db = rsa_data->message.data + lhash_len + 1;
+	ret = rsa_oaep_get_seed(rsa_data, mask_db, seed);
+	if (ret)
+		return ret;
+
+	ret = rsa_oaep_get_db(rsa_data, mask_db, seed, db);
+	if (ret)
+		return ret;
+
+	return rsa_oaep_get_msg(rsa_data, db, out, out_len);
+}
+
+static TEE_Result rsa_oaep_decrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	size_t n_bytes = rsa_data->key.n_size;
+	struct drvcrypt_rsa_ed rsa_dec_info = *rsa_data;
+	TEE_Result ret = TEE_SUCCESS;
+
+	/* Alloc oaep encode message data buf */
+	rsa_dec_info.message.data = malloc(n_bytes);
+	if (!rsa_dec_info.message.data) {
+		EMSG("Fail to alloc message data buf");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	rsa_dec_info.message.length = n_bytes;
+	ret = rsa_nopad_decrypt(&rsa_dec_info);
+	if (ret)
+		goto free_data;
+
+	ret = rsa_oaep_decode(&rsa_dec_info, rsa_data->message.data,
+			      &rsa_data->message.length);
+	if (ret)
+		EMSG("Fail to get oaep decode message data");
+
+free_data:
+	free(rsa_dec_info.message.data);
+
+	return ret;
+}
+
+static TEE_Result hpre_rsa_decrypt(struct drvcrypt_rsa_ed *rsa_data)
+{
+	if (!rsa_data) {
+		EMSG("Invalid rsa decrypt input parameter");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	switch (rsa_data->rsa_id) {
+	case DRVCRYPT_RSA_NOPAD:
+	case DRVCRYPT_RSASSA_PKCS_V1_5:
+	case DRVCRYPT_RSASSA_PSS:
+		return rsa_nopad_decrypt(rsa_data);
+	case DRVCRYPT_RSA_PKCS_V1_5:
+		return rsa_pkcs_decrypt(rsa_data);
+	case DRVCRYPT_RSA_OAEP:
+		return rsa_oaep_decrypt(rsa_data);
+	default:
+		EMSG("Invalid rsa id");
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+}
+
+static const struct drvcrypt_rsa driver_rsa = {
+	.alloc_keypair = sw_crypto_acipher_alloc_rsa_keypair,
+	.alloc_publickey = sw_crypto_acipher_alloc_rsa_public_key,
+	.free_publickey = sw_crypto_acipher_free_rsa_public_key,
+	.free_keypair = sw_crypto_acipher_free_rsa_keypair,
+	.gen_keypair = sw_crypto_acipher_gen_rsa_key,
+	.encrypt = hpre_rsa_encrypt,
+	.decrypt = hpre_rsa_decrypt,
+	.optional = {
+		/*
+		 * If ssa_sign or verify is NULL, the framework will fill
+		 * data format directly by soft calculation. Then call api
+		 * encrypt or decrypt.
+		 */
+		.ssa_sign = NULL,
+		.ssa_verify = NULL,
+	},
+};
+
+static TEE_Result hpre_rsa_init(void)
+{
+	TEE_Result ret = drvcrypt_register_rsa(&driver_rsa);
+
+	if (ret != TEE_SUCCESS)
+		EMSG("hpre rsa register to crypto fail");
+
+	return ret;
+}
+
+driver_init(hpre_rsa_init);
diff --git a/core/drivers/crypto/hisilicon/hpre_rsa.h b/core/drivers/crypto/hisilicon/hpre_rsa.h
new file mode 100644
index 0000000000000000000000000000000000000000..eebf061a362978a13fd34e024bf983dc900d5408
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/hpre_rsa.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, HiSilicon Technologies Co., Ltd.
+ */
+
+#ifndef __HPRE_RSA_H__
+#define __HPRE_RSA_H__
+
+#include <stdint.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+#define PKCS_V1_5_MSG_MIN_LEN			11
+#define PKCS_V1_5_PS_MIN_LEN			8
+#define PKCS_V1_5_PS_POS			2
+#define PKCS_V1_5_FIXED_LEN			3
+#define PKCS_V1_5_PS_DATA			0x5a
+#define OAEP_MAX_HASH_LEN			64
+#define OAEP_MAX_DB_LEN				512
+#define PRIME_QUALITY_FLAG			1024
+#define HPRE_RSA_CRT_TOTAL_BUF_SIZE(kbytes)	((kbytes) * 6)
+#define HPRE_RSA_CRT_KEY_BUF_SIZE(kbytes)	((kbytes) >> 10)
+#define HPRE_RSA_NCRT_TOTAL_BUF_SIZE(kbytes)	((kbytes) * 4)
+
+enum pkcs_v1_5_pad_type {
+	SIGN_PAD = 1,
+	ENCRYPT_PAD = 2
+};
+
+/*
+ * When the mode is encrypt, the size of the buffer is
+ * HPRE_RSA_NCRT_TOTAL_BUF_SIZE(kbytes) for both crt and ncrt;
+ * when the mode is decrypt, the size of the buffer is
+ * HPRE_RSA_CRT_TOTAL_BUF_SIZE(kbytes) for crt and
+ * HPRE_RSA_NCRT_TOTAL_BUF_SIZE(kbytes) for ncrt.
+ */
+struct hpre_rsa_msg {
+	uint8_t *pubkey;
+	paddr_t pubkey_dma;
+	uint8_t *prikey;
+	paddr_t prikey_dma;
+	uint8_t *in;
+	paddr_t in_dma;
+	uint8_t *out;
+	paddr_t out_dma;
+	uint32_t alg_type;
+	uint32_t key_bytes;
+	bool is_private;    /* True if private key */
+};
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/sec_authenc.c b/core/drivers/crypto/hisilicon/sec_authenc.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7e17706f226b7cea6c1afe4d434c088036409bb
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_authenc.c
@@ -0,0 +1,809 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator sec authenc algorithm implementation.
+ */
+
+#include <crypto/crypto_impl.h>
+#include <drvcrypt.h>
+#include <drvcrypt_authenc.h>
+#include <initcall.h>
+#include <tee_api_types.h>
+#include <trace.h>
+#include <utee_defines.h>
+
+#include "sec_authenc.h"
+#include "sec_cipher.h"
+#include "sec_hash.h"
+#include "sec_main.h"
+
+static enum hisi_drv_status sec_aead_bd_fill(void *bd, void *msg)
+{
+	struct authenc_ctx *ae_ctx = msg;
+	struct hisi_sec_sqe *sqe = bd;
+	uint8_t scene = 0;
+	uint8_t de = 0;
+
+	sqe->type_auth_cipher = BD_TYPE2 | SHIFT_U32(NO_AUTH, SEC_AUTH_OFFSET);
+	scene = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET);
+	de = SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET);
+	sqe->sds_sa_type = de | scene;
+	sqe->type2.cipher_src_offset = ae_ctx->aad.length;
+	sqe->type2.icvw_kmode = SHIFT_U32(ae_ctx->c_key_len, SEC_CKEY_OFFSET) |
+				SHIFT_U32(ae_ctx->mode, SEC_CMODE_OFFSET) |
+				ae_ctx->tag_len;
+	sqe->type2.clen_ivhlen = ae_ctx->payload_len;
+	sqe->type2.alen_ivllen = ae_ctx->aad.length;
+	sqe->type2.c_alg = ae_ctx->algo;
+
+	if (ae_ctx->encrypt) {
+		sqe->type_auth_cipher |= SHIFT_U32(CIPHER_ENCRYPT,
+						   SEC_CIPHER_OFFSET);
+		sqe->sds_sa_type |= SEC_CIPHER_THEN_DIGEST;
+	} else {
+		sqe->type_auth_cipher |= SHIFT_U32(CIPHER_DECRYPT,
+						   SEC_CIPHER_OFFSET);
+		sqe->sds_sa_type |= SEC_DIGEST_THEN_CIPHER;
+	}
+
+	sqe->type2.data_dst_addr = ae_ctx->dst_dma;
+	sqe->type2.data_src_addr = ae_ctx->src_dma;
+	sqe->type2.c_ivin_addr = ae_ctx->civ_dma;
+	sqe->type2.c_key_addr = ae_ctx->key_dma;
+	sqe->type2.mac_addr = ae_ctx->tag_dma;
+	sqe->type2.a_ivin_addr = ae_ctx->aiv_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_aead_bd_parse(void *bd, void *msg)
+{
+	struct hisi_sec_sqe *sqe = bd;
+	struct authenc_ctx *ctx = msg;
+	uint16_t done = 0;
+
+	ctx->result = SEC_GET_FIELD(sqe->type2.done_flag, SEC_ICV_MASK, 1);
+	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
+		EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->type2.error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_aead_bd3_fill(void *bd, void *msg)
+{
+	struct authenc_ctx *ae_ctx = msg;
+	struct hisi_sec_bd3_sqe *sqe = bd;
+
+	sqe->bd_param = BD_TYPE3 | SHIFT_U32(SCENE_NOTHING,
+					     SEC_SCENE_OFFSET_V3) |
+			SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET_V3);
+	sqe->auth_mac_key = NO_AUTH;
+	sqe->cipher_src_offset = ae_ctx->aad.length;
+	sqe->c_icv_key = SHIFT_U32(ae_ctx->c_key_len, SEC_CKEY_OFFSET_V3) |
+			 SHIFT_U32(ae_ctx->tag_len, SEC_ICV_LEN_OFFSET_V3);
+	sqe->c_len_ivin = ae_ctx->payload_len;
+
+	sqe->a_len_key = ae_ctx->aad.length;
+	sqe->c_mode_alg = ae_ctx->mode |
+			  SHIFT_U32(ae_ctx->algo, SEC_CALG_OFFSET_V3);
+
+	if (ae_ctx->encrypt) {
+		sqe->c_icv_key |= CIPHER_ENCRYPT;
+		sqe->huk_iv_seq = SHIFT_U32(SEC_CIPHER_THEN_DIGEST,
+					    SEC_SEQ_OFFSET_V3);
+	} else {
+		sqe->c_icv_key |= CIPHER_DECRYPT;
+		sqe->huk_iv_seq = SHIFT_U32(SEC_DIGEST_THEN_CIPHER,
+					    SEC_SEQ_OFFSET_V3);
+	}
+
+	sqe->no_scene.c_ivin_addr = ae_ctx->civ_dma;
+	sqe->data_dst_addr = ae_ctx->dst_dma;
+	sqe->data_src_addr = ae_ctx->src_dma;
+	sqe->c_key_addr = ae_ctx->key_dma;
+	sqe->mac_addr = ae_ctx->tag_dma;
+	sqe->a_ivin_addr = ae_ctx->aiv_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_aead_bd3_parse(void *bd, void *msg)
+{
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	struct authenc_ctx *ctx = msg;
+	uint16_t done = 0;
+
+	ctx->result = SEC_GET_FIELD(sqe->done_flag, SEC_ICV_MASK, 1);
+	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
+		EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result sec_do_aead_task(struct hisi_qp *qp, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hisi_qp_send(qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	ret = hisi_qp_recv_sync(qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result authenc_algo_check(uint32_t algo)
+{
+	switch (algo) {
+	case TEE_ALG_AES_GCM:
+	case TEE_ALG_AES_CCM:
+		return TEE_SUCCESS;
+	default:
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+}
+
+static uint8_t crypto_set_alg(uint32_t alg)
+{
+	switch (alg) {
+	case TEE_MAIN_ALGO_AES:
+		return C_ALG_AES;
+	default:
+		return 0;
+	}
+}
+
+static uint8_t crypto_set_mode(uint32_t mode)
+{
+	switch (mode) {
+	case TEE_CHAIN_MODE_CCM:
+		return C_MODE_CCM;
+	case TEE_CHAIN_MODE_GCM:
+		return C_MODE_GCM;
+	default:
+		return 0;
+	}
+}
+
+static TEE_Result sec_authenc_ctx_allocate(void **ctx, uint32_t algo)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!ctx) {
+		EMSG("ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = authenc_algo_check(algo);
+	if (ret)
+		return ret;
+
+	ae_drv_ctx = calloc(1, sizeof(struct authenc_ctx));
+	if (!ae_drv_ctx) {
+		EMSG("Fail to calloc ae_drv_ctx");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	ae_drv_ctx->algo = crypto_set_alg(TEE_ALG_GET_MAIN_ALG(algo));
+	ae_drv_ctx->mode = crypto_set_mode(TEE_ALG_GET_CHAIN_MODE(algo));
+
+	ret = crypto_aes_gcm_alloc_ctx(&ae_soft_ctx);
+	if (ret) {
+		EMSG("soft ctx is NULL");
+		goto free_ctx;
+	}
+
+	ae_drv_ctx->ae_soft_ctx = ae_soft_ctx;
+	ae_drv_ctx->is_hw_supported = true;
+
+	ae_drv_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0);
+	if (!ae_drv_ctx->qp) {
+		ret = TEE_ERROR_BUSY;
+		goto free_soft_ctx;
+	}
+
+	if (ae_drv_ctx->qp->qm->version == HISI_QM_HW_V2) {
+		ae_drv_ctx->qp->fill_sqe = sec_aead_bd_fill;
+		ae_drv_ctx->qp->parse_sqe = sec_aead_bd_parse;
+	} else {
+		ae_drv_ctx->qp->fill_sqe = sec_aead_bd3_fill;
+		ae_drv_ctx->qp->parse_sqe = sec_aead_bd3_parse;
+	}
+
+	*ctx = ae_drv_ctx;
+
+	return TEE_SUCCESS;
+
+free_soft_ctx:
+	ae_soft_ctx->ops->free_ctx(ae_soft_ctx);
+free_ctx:
+	free(ae_drv_ctx);
+	return ret;
+}
+
+static void sec_authenc_ctx_free(void *ctx)
+{
+	struct authenc_ctx *ae_drv_ctx = ctx;
+
+	if (!ae_drv_ctx)
+		return;
+
+	ae_drv_ctx->ae_soft_ctx->ops->free_ctx(ae_drv_ctx->ae_soft_ctx);
+
+	hisi_qm_release_qp(ae_drv_ctx->qp);
+	memzero_explicit(ae_drv_ctx->key, ae_drv_ctx->key_len);
+
+	if (ae_drv_ctx->src.data) {
+		free(ae_drv_ctx->src.data);
+		ae_drv_ctx->src.data = NULL;
+	}
+
+	if (ae_drv_ctx->dst.data) {
+		free(ae_drv_ctx->dst.data);
+		ae_drv_ctx->dst.data = NULL;
+	}
+
+	free(ae_drv_ctx);
+}
+
+static TEE_Result authenc_init_params_check(struct drvcrypt_authenc_init *dinit)
+{
+	if (!dinit) {
+		EMSG("dinit is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (!dinit->ctx) {
+		EMSG("ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (!dinit->key.length || !dinit->key.data) {
+		EMSG("key is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (!dinit->nonce.data || !dinit->nonce.length) {
+		EMSG("iv is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static bool is_hw_supported(struct drvcrypt_authenc_init *dinit)
+{
+	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
+
+	if (ae_drv_ctx->mode == C_MODE_GCM) {
+		if (dinit->nonce.length != GCM_IV_SIZE)
+			return false;
+
+		if (dinit->aad_len > MAX_GCM_AAD_SIZE) {
+			EMSG("Invalid aad len");
+			return false;
+		}
+
+		if (dinit->tag_len < SEC_MIN_GCM_TAG_LEN ||
+		    dinit->tag_len > SEC_MAX_TAG_LEN) {
+			EMSG("Invalid tag len");
+			return false;
+		}
+	} else {
+		if (dinit->nonce.length < MIN_CCM_NONCE_SIZE ||
+		    dinit->nonce.length > MAX_CCM_NONCE_SIZE) {
+			EMSG("Invalid nonce len");
+			return false;
+		}
+
+		if (dinit->aad_len > MAX_CCM_AAD_SIZE) {
+			EMSG("Invalid aad len");
+			return false;
+		}
+
+		if (dinit->tag_len < SEC_MIN_CCM_TAG_LEN ||
+		    dinit->tag_len > SEC_MAX_TAG_LEN ||
+		    dinit->tag_len % TAG_ALIGN) {
+			EMSG("Invalid tag len");
+			return false;
+		}
+	}
+
+	if (dinit->payload_len + dinit->aad_len > SEC_MAX_AEAD_LENGTH ||
+	    (ae_drv_ctx->qp->qm->version == HISI_QM_HW_V2 &&
+	    dinit->payload_len == 0)) {
+		EMSG("Invalid src len");
+		return false;
+	}
+
+	return true;
+}
+
+static TEE_Result sec_aead_set_key(struct drvcrypt_authenc_init *dinit)
+{
+	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
+
+	ae_drv_ctx->key_len = dinit->key.length;
+
+	switch (ae_drv_ctx->key_len) {
+	case AES_KEYSIZE_128:
+		ae_drv_ctx->c_key_len = CKEY_LEN_128_BIT;
+		break;
+	case AES_KEYSIZE_192:
+		ae_drv_ctx->c_key_len = CKEY_LEN_192_BIT;
+		break;
+	case AES_KEYSIZE_256:
+		ae_drv_ctx->c_key_len = CKEY_LEN_256_BIT;
+		break;
+	default:
+		EMSG("Invalid AES key size");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	memcpy(ae_drv_ctx->key, dinit->key.data, dinit->key.length);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_aead_set_iv(struct drvcrypt_authenc_init *dinit)
+{
+	struct authenc_ctx *ae_drv_ctx = dinit->ctx;
+	uint32_t data_size = dinit->payload_len;
+	uint8_t adata = 0;
+	uint8_t flags = 0;
+	uint8_t cm = 0;
+	uint8_t cl = 0;
+
+	ae_drv_ctx->civ_len = MAX_IV_SIZE;
+	if (ae_drv_ctx->mode == C_MODE_GCM) {
+		ae_drv_ctx->civ_len = dinit->nonce.length;
+		memcpy(ae_drv_ctx->civ, dinit->nonce.data, dinit->nonce.length);
+		return TEE_SUCCESS;
+	}
+
+	if (dinit->aad_len)
+		adata = AAD_NOT_NULL;
+
+	cm = ((dinit->tag_len - IV_CM_CAL_NUM) / IV_CM_CAL_NUM) & IV_CL_MASK;
+	cl = IV_CL_CAL_NUM - dinit->nonce.length;
+	flags = cl | SHIFT_U32(cm, IV_CM_OFFSET) |
+		SHIFT_U32(adata, IV_FLAGS_OFFSET);
+
+	memcpy(ae_drv_ctx->civ + NONCE_OFFSET, dinit->nonce.data,
+	       dinit->nonce.length);
+	memcpy(ae_drv_ctx->aiv + NONCE_OFFSET, dinit->nonce.data,
+	       dinit->nonce.length);
+
+	ae_drv_ctx->aiv[0] = flags;
+	ae_drv_ctx->aiv[IV_LAST_BYTE1] = data_size & IV_LAST_BYTE_MASK;
+	data_size >>= IV_BYTE_OFFSET;
+	ae_drv_ctx->aiv[IV_LAST_BYTE2] = data_size & IV_LAST_BYTE_MASK;
+	data_size >>= IV_BYTE_OFFSET;
+	ae_drv_ctx->aiv[IV_LAST_BYTE3] = data_size & IV_LAST_BYTE_MASK;
+
+	ae_drv_ctx->civ[0] = cl;
+	ae_drv_ctx->civ[MAX_IV_SIZE - 1] = IV_CTR_INIT;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_aead_get_dma(struct authenc_ctx *ae_drv_ctx)
+{
+	ae_drv_ctx->key_dma = virt_to_phys(ae_drv_ctx->key);
+	ae_drv_ctx->civ_dma = virt_to_phys(ae_drv_ctx->civ);
+	ae_drv_ctx->tag_dma = virt_to_phys(ae_drv_ctx->tag);
+	ae_drv_ctx->src_dma = virt_to_phys(ae_drv_ctx->src.data);
+	ae_drv_ctx->dst_dma = virt_to_phys(ae_drv_ctx->dst.data);
+
+	if (ae_drv_ctx->mode == C_MODE_GCM)
+		return TEE_SUCCESS;
+	ae_drv_ctx->aiv_dma = virt_to_phys(ae_drv_ctx->aiv);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_aead_data_alloc(struct authenc_ctx *ae_drv_ctx)
+{
+	ae_drv_ctx->src.length = ae_drv_ctx->payload_len +
+				 ae_drv_ctx->aad.length;
+	ae_drv_ctx->src.data = malloc(ae_drv_ctx->src.length);
+	if (!ae_drv_ctx->src.data) {
+		EMSG("Fail to malloc src");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	ae_drv_ctx->dst.length = ae_drv_ctx->src.length;
+	ae_drv_ctx->dst.data = malloc(ae_drv_ctx->dst.length);
+	if (!ae_drv_ctx->dst.data) {
+		EMSG("Fail to malloc dst");
+		free(ae_drv_ctx->src.data);
+		ae_drv_ctx->src.data = NULL;
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result ae_soft_calc_init(struct authenc_ctx *ae_drv_ctx,
+				    struct drvcrypt_authenc_init *dinit)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+	TEE_OperationMode mode = 0;
+
+	if (ae_drv_ctx->algo == C_ALG_AES && ae_drv_ctx->mode == C_MODE_GCM) {
+		ae_drv_ctx->is_hw_supported = false;
+		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
+		if (!dinit->encrypt)
+			mode = 1;
+		ret = ae_soft_ctx->ops->init(ae_soft_ctx, mode,
+			dinit->key.data, dinit->key.length,
+			dinit->nonce.data, dinit->nonce.length,
+			dinit->tag_len, dinit->aad_len,
+			dinit->payload_len);
+		if (ret)
+			EMSG("Fail to init by soft ctx");
+
+		return ret;
+	}
+
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static TEE_Result sec_authenc_initialize(struct drvcrypt_authenc_init *dinit)
+{
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+	bool hw_support = false;
+
+	ret = authenc_init_params_check(dinit);
+	if (ret)
+		return ret;
+
+	ae_drv_ctx = dinit->ctx;
+	hw_support = is_hw_supported(dinit);
+	if (!hw_support)
+		return ae_soft_calc_init(ae_drv_ctx, dinit);
+
+	ae_drv_ctx->encrypt = dinit->encrypt;
+	ae_drv_ctx->payload_len = dinit->payload_len;
+	ae_drv_ctx->aad.length = dinit->aad_len;
+	ae_drv_ctx->tag_len = dinit->tag_len;
+
+	ret = sec_aead_set_key(dinit);
+	if (ret)
+		return ret;
+
+	ret = sec_aead_set_iv(dinit);
+	if (ret)
+		goto clean_key;
+
+	ret = sec_aead_data_alloc(ae_drv_ctx);
+	if (ret)
+		goto clean_key;
+
+	ret = sec_aead_get_dma(ae_drv_ctx);
+	if (ret)
+		goto free_data;
+
+	return TEE_SUCCESS;
+free_data:
+	if (ae_drv_ctx->src.data) {
+		free(ae_drv_ctx->src.data);
+		ae_drv_ctx->src.data = NULL;
+	}
+	if (ae_drv_ctx->dst.data) {
+		free(ae_drv_ctx->dst.data);
+		ae_drv_ctx->src.data = NULL;
+	}
+clean_key:
+	memzero_explicit(ae_drv_ctx->key, sizeof(ae_drv_ctx->key));
+	return ret;
+}
+
+static TEE_Result
+sec_authenc_update_aad(struct drvcrypt_authenc_update_aad *dupdate)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!dupdate || !dupdate->ctx) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ae_drv_ctx = dupdate->ctx;
+	if (!ae_drv_ctx->is_hw_supported) {
+		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
+		ret = ae_soft_ctx->ops->update_aad(ae_soft_ctx,
+			dupdate->aad.data, dupdate->aad.length);
+		if (ret)
+			EMSG("Fail to update aad by soft ctx");
+
+		return ret;
+	}
+
+	if (dupdate->aad.length + ae_drv_ctx->src_offset >
+	    ae_drv_ctx->src.length) {
+		EMSG("Invalid aad length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+	/*
+	 * Both aad and ptx need to be filled in the src field.
+	 * Here, aad is placed in the header of the src field.
+	 */
+	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset,
+	       dupdate->aad.data, dupdate->aad.length);
+	ae_drv_ctx->src_offset += dupdate->aad.length;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result update_params_check(struct drvcrypt_authenc_update_payload *d)
+{
+	struct authenc_ctx *ae_drv_ctx = NULL;
+
+	ae_drv_ctx = d->ctx;
+	if (!ae_drv_ctx->src.data || !ae_drv_ctx->dst.data) {
+		EMSG("Invalid input/output data");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (d->src.length + ae_drv_ctx->src_offset > ae_drv_ctx->src.length) {
+		EMSG("Invalid update src length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (d->dst.length + ae_drv_ctx->src_offset > ae_drv_ctx->dst.length) {
+		EMSG("Invalid update dst length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+sec_authenc_update_payload(struct drvcrypt_authenc_update_payload *d)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!d || !d->ctx) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ae_drv_ctx = d->ctx;
+	if (!ae_drv_ctx->is_hw_supported) {
+		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
+		ret = ae_soft_ctx->ops->update_payload(ae_soft_ctx,
+				(TEE_OperationMode)(d->encrypt == 0),
+				d->src.data, d->src.length, d->dst.data);
+		if (ret)
+			EMSG("Fail to update payload by soft ctx");
+
+		return ret;
+	}
+
+	ret = update_params_check(d);
+	if (ret)
+		return ret;
+
+	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset,
+	       d->src.data, d->src.length);
+
+	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
+	if (ret)
+		return ret;
+
+	memcpy(d->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
+	       d->dst.length);
+	ae_drv_ctx->src_offset += d->src.length;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result final_params_check(struct drvcrypt_authenc_final *dfinal)
+{
+	struct authenc_ctx *ae_drv_ctx = dfinal->ctx;
+
+	if (!ae_drv_ctx->src.data || !ae_drv_ctx->dst.data) {
+		EMSG("Invalid input/output data");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (dfinal->src.length + ae_drv_ctx->src_offset >
+	    ae_drv_ctx->src.length) {
+		EMSG("Invalid dfinal src length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (dfinal->dst.length + ae_drv_ctx->src_offset >
+	    ae_drv_ctx->dst.length) {
+		EMSG("Invalid dfinal dst length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (dfinal->tag.length > SEC_MAX_TAG_LEN) {
+		EMSG("Invalid dfinal tag length");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_authenc_enc_final(struct drvcrypt_authenc_final *dfinal)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!dfinal || !dfinal->ctx) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ae_drv_ctx = dfinal->ctx;
+	if (!ae_drv_ctx->is_hw_supported) {
+		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
+		ret = ae_soft_ctx->ops->enc_final(ae_soft_ctx,
+			dfinal->src.data, dfinal->src.length,
+			dfinal->dst.data, dfinal->tag.data,
+			&dfinal->tag.length);
+		if (ret)
+			EMSG("Fail to do enc final by soft ctx");
+
+		return ret;
+	}
+
+	ret = final_params_check(dfinal);
+	if (ret)
+		return ret;
+	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset, dfinal->src.data,
+	       dfinal->src.length);
+
+	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
+
+	memcpy(dfinal->tag.data, ae_drv_ctx->tag, dfinal->tag.length);
+	memcpy(dfinal->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
+	       dfinal->dst.length);
+
+	return ret;
+}
+
+static TEE_Result sec_authenc_dec_final(struct drvcrypt_authenc_final *dfinal)
+{
+	struct crypto_authenc_ctx *ae_soft_ctx = NULL;
+	struct authenc_ctx *ae_drv_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!dfinal || !dfinal->ctx) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ae_drv_ctx = dfinal->ctx;
+	if (!ae_drv_ctx->is_hw_supported) {
+		ae_soft_ctx = ae_drv_ctx->ae_soft_ctx;
+		ret =  ae_soft_ctx->ops->dec_final(ae_soft_ctx,
+			dfinal->src.data, dfinal->src.length,
+			dfinal->dst.data, dfinal->tag.data,
+			dfinal->tag.length);
+		if (ret)
+			EMSG("Fail to do dec final by soft ctx");
+
+		return ret;
+	}
+
+	ret = final_params_check(dfinal);
+	if (ret)
+		return ret;
+	memcpy(ae_drv_ctx->src.data + ae_drv_ctx->src_offset, dfinal->src.data,
+	       dfinal->src.length);
+	memcpy(ae_drv_ctx->tag, dfinal->tag.data, dfinal->tag.length);
+
+	ret = sec_do_aead_task(ae_drv_ctx->qp, ae_drv_ctx);
+	if (ret)
+		return ret;
+
+	memcpy(dfinal->dst.data, ae_drv_ctx->dst.data + ae_drv_ctx->src_offset,
+	       dfinal->dst.length);
+	if (ae_drv_ctx->result == SEC_TAG_ERR) {
+		EMSG("Integrity check failed");
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void sec_authenc_do_final(void *ctx __unused)
+{
+}
+
+static void sec_authenc_copy_state(void *dst_ctx, void *src_ctx)
+{
+	struct authenc_ctx *dst = dst_ctx;
+	struct authenc_ctx *src = src_ctx;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!src->is_hw_supported) {
+		dst->is_hw_supported = false;
+		src->ae_soft_ctx->ops->copy_state(dst->ae_soft_ctx,
+						  src->ae_soft_ctx);
+		return;
+	}
+
+	dst->algo = src->algo;
+	dst->mode = src->mode;
+	dst->encrypt = src->encrypt;
+	dst->key_len = src->key_len;
+	dst->tag_len = src->tag_len;
+	dst->c_key_len = src->c_key_len;
+	dst->aad.length = src->aad.length;
+	dst->src_offset = src->src_offset;
+	dst->payload_len = src->payload_len;
+	dst->is_hw_supported = src->is_hw_supported;
+	memcpy(dst->key, src->key, src->key_len);
+	memcpy(dst->civ, src->civ, src->civ_len);
+	/* The len of aiv is always MAX_IV_SIZE */
+	memcpy(dst->aiv, src->aiv, MAX_IV_SIZE);
+	ret = sec_aead_data_alloc(dst);
+	if (ret)
+		return;
+	memcpy(dst->src.data, src->src.data,
+	       src->aad.length + src->payload_len);
+	memcpy(dst->dst.data, src->dst.data,
+	       src->aad.length + src->payload_len);
+
+	ret = sec_aead_get_dma(dst);
+	if (ret) {
+		memzero_explicit(dst->key, dst->key_len);
+		free(dst->src.data);
+		dst->src.data = NULL;
+		free(dst->dst.data);
+		dst->dst.data = NULL;
+	}
+}
+
+static struct drvcrypt_authenc driver_authenc = {
+	.alloc_ctx = sec_authenc_ctx_allocate,
+	.free_ctx = sec_authenc_ctx_free,
+	.init = sec_authenc_initialize,
+	.update_aad = sec_authenc_update_aad,
+	.update_payload = sec_authenc_update_payload,
+	.enc_final = sec_authenc_enc_final,
+	.dec_final = sec_authenc_dec_final,
+	.final = sec_authenc_do_final,
+	.copy_state = sec_authenc_copy_state,
+};
+
+static TEE_Result sec_authenc_init(void)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = drvcrypt_register_authenc(&driver_authenc);
+	if (ret)
+		EMSG("Sec authenc register to crypto fail ret=%#"PRIx32, ret);
+
+	return ret;
+}
+driver_init(sec_authenc_init);
diff --git a/core/drivers/crypto/hisilicon/sec_authenc.h b/core/drivers/crypto/hisilicon/sec_authenc.h
new file mode 100644
index 0000000000000000000000000000000000000000..c4a575e61208580bd1f7fbad5b0d0a9388796939
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_authenc.h
@@ -0,0 +1,74 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2022-2024 HiSilicon Limited. */
+
+#ifndef __SEC_AUTHENC_H__
+#define __SEC_AUTHENC_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hisi_qm.h"
+
+#define SEC_MAX_AEAD_LENGTH		16777199
+#define SEC_MIN_AEAD_LENGTH		4
+#define SEC_TAG_ERR			0x2
+#define SEC_MIN_GCM_TAG_LEN		8
+#define SEC_MIN_CCM_TAG_LEN		4
+#define SEC_MAX_TAG_LEN			16
+#define SEC_CIPHER_THEN_DIGEST		0
+#define SEC_DIGEST_THEN_CIPHER		1
+
+#define MAX_GCM_AAD_SIZE		65535
+#define MAX_CCM_AAD_SIZE		65279
+#define GCM_IV_SIZE			12
+#define MAX_CCM_NONCE_SIZE		12
+#define MIN_CCM_NONCE_SIZE		7
+#define TAG_ALIGN			2
+#define MAX_KEY_SIZE			32
+#define MAX_IV_SIZE			16
+#define NONCE_OFFSET			1
+#define IV_LAST_BYTE1			15
+#define IV_LAST_BYTE2			14
+#define IV_LAST_BYTE3			13
+#define IV_CTR_INIT			1
+#define IV_CL_CAL_NUM			14
+#define IV_CM_CAL_NUM			2
+#define IV_CL_MASK			0x7
+#define IV_FLAGS_OFFSET			0x6
+#define IV_CM_OFFSET			0x3
+#define IV_LAST_BYTE_MASK		0xFF
+#define IV_BYTE_OFFSET			0x8
+#define AAD_NOT_NULL			1
+
+struct authenc_ctx {
+	struct hisi_qp *qp;
+	bool encrypt;
+	uint8_t civ[MAX_IV_SIZE];
+	uint8_t aiv[MAX_IV_SIZE];
+	uint8_t key[MAX_KEY_SIZE];
+	uint8_t tag[SEC_MAX_TAG_LEN];
+	struct drvcrypt_buf aad;
+	struct drvcrypt_buf src;
+	struct drvcrypt_buf dst;
+
+	uint8_t algo;
+	uint8_t mode;
+	uint32_t result;
+	bool is_hw_supported;
+	struct crypto_authenc_ctx *ae_soft_ctx;
+	size_t src_offset;
+	size_t payload_len;
+	size_t key_len;
+	size_t civ_len;
+	size_t tag_len;
+	uint8_t c_key_len;
+
+	/* aead dma */
+	paddr_t key_dma;
+	paddr_t civ_dma;
+	paddr_t aiv_dma;
+	paddr_t src_dma;
+	paddr_t dst_dma;
+	paddr_t tag_dma;
+};
+#endif /* __SEC_AUTHENC_H__ */
diff --git a/core/drivers/crypto/hisilicon/sec_cipher.c b/core/drivers/crypto/hisilicon/sec_cipher.c
new file mode 100644
index 0000000000000000000000000000000000000000..84019e14c2cf0d272caa23ab2f7e3e347fac06a3
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_cipher.c
@@ -0,0 +1,774 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator sec cipher algorithm implementation.
+ */
+
+#include <drvcrypt.h>
+#include <drvcrypt_cipher.h>
+#include <initcall.h>
+#include <trace.h>
+#include <utee_defines.h>
+
+#include "sec_cipher.h"
+#include "sec_main.h"
+
+static TEE_Result sec_do_cipher_task(struct hisi_qp *qp, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+
+	ret = hisi_qp_send(qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	ret = hisi_qp_recv_sync(qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_des_get_c_key_len(size_t key_len,
+					       uint8_t *c_key_len)
+{
+	if (key_len == DES_KEY_SIZE) {
+		*c_key_len = CKEY_LEN_DES;
+	} else {
+		EMSG("Invalid DES key size");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_3des_get_c_key_len(size_t key_len,
+						uint8_t *c_key_len)
+{
+	if (key_len == SEC_3DES_2KEY_SIZE) {
+		*c_key_len = CKEY_LEN_3DES_2KEY;
+	} else if (key_len == SEC_3DES_3KEY_SIZE) {
+		*c_key_len = CKEY_LEN_3DES_3KEY;
+	} else {
+		EMSG("Invalid 3DES key size");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_aes_get_c_key_len(size_t key_len,
+					       enum sec_c_mode mode,
+					       uint8_t *c_key_len)
+{
+	switch (mode) {
+	case C_MODE_ECB:
+	case C_MODE_CBC:
+	case C_MODE_CTR:
+		switch (key_len) {
+		case AES_KEYSIZE_128:
+			*c_key_len = CKEY_LEN_128_BIT;
+			break;
+		case AES_KEYSIZE_192:
+			*c_key_len = CKEY_LEN_192_BIT;
+			break;
+		case AES_KEYSIZE_256:
+			*c_key_len = CKEY_LEN_256_BIT;
+			break;
+		default:
+			EMSG("Invalid AES key size");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		break;
+	case C_MODE_XTS:
+		switch (key_len) {
+		case XTS_KEYSIZE_128:
+			*c_key_len = CKEY_LEN_128_BIT;
+			break;
+		case XTS_KEYSIZE_256:
+			*c_key_len = CKEY_LEN_256_BIT;
+			break;
+		default:
+			EMSG("Invalid AES-XTS key size");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		break;
+	default:
+		EMSG("Unsupported AES mode");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_sm4_get_c_key_len(size_t key_len,
+					       enum sec_c_mode mode,
+					       uint8_t *c_key_len)
+{
+	switch (mode) {
+	case C_MODE_ECB:
+	case C_MODE_CBC:
+	case C_MODE_CTR:
+		if (key_len != AES_KEYSIZE_128) {
+			EMSG("Invalid SM4 key size");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		*c_key_len = CKEY_LEN_128_BIT;
+		break;
+	case C_MODE_XTS:
+		if (key_len != XTS_KEYSIZE_128) {
+			EMSG("Invalid SM4-XTS key size");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		*c_key_len = CKEY_LEN_128_BIT;
+		break;
+	default:
+		EMSG("Unsupported SM4 mode");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_set_key(struct sec_cipher_ctx *c_ctx,
+				     uint8_t *key1, size_t key1_len,
+				     uint8_t *key2, size_t key2_len)
+{
+	size_t key_len = key1_len + key2_len;
+	TEE_Result ret = TEE_SUCCESS;
+	uint8_t c_key_len = 0;
+
+	switch (c_ctx->alg) {
+	case C_ALG_DES:
+		ret = sec_cipher_des_get_c_key_len(key_len, &c_key_len);
+		break;
+	case C_ALG_3DES:
+		ret = sec_cipher_3des_get_c_key_len(key_len, &c_key_len);
+		break;
+	case C_ALG_AES:
+		ret = sec_cipher_aes_get_c_key_len(key_len, c_ctx->mode,
+						   &c_key_len);
+		break;
+	case C_ALG_SM4:
+		ret = sec_cipher_sm4_get_c_key_len(key_len, c_ctx->mode,
+						   &c_key_len);
+		break;
+	default:
+		EMSG("Invalid cipher type %#"PRIx8, c_ctx->alg);
+		ret = TEE_ERROR_NOT_IMPLEMENTED;
+		break;
+	}
+
+	if (ret)
+		return ret;
+
+	c_ctx->key_dma = virt_to_phys(c_ctx->key);
+	if (!c_ctx->key_dma) {
+		EMSG("c_key_dma is NULL");
+		return TEE_ERROR_GENERIC;
+	}
+
+	c_ctx->key_len = key_len;
+	c_ctx->c_key_len = c_key_len;
+
+	memcpy(c_ctx->key, key1, key1_len);
+	memcpy(c_ctx->key + key1_len, key2, key2_len);
+
+	return TEE_SUCCESS;
+}
+
+static void ctr_iv_inc(uint64_t *ctr, uint32_t inc)
+{
+	uint64_t v0 = TEE_U64_FROM_BIG_ENDIAN(ctr[0]);
+	uint64_t v1 = TEE_U64_FROM_BIG_ENDIAN(ctr[1]);
+
+	/* increment counter (128-bit int) by inc */
+	if (ADD_OVERFLOW(v1, inc, &v1))
+		v0++;
+
+	ctr[0] = TEE_U64_TO_BIG_ENDIAN(v0);
+	ctr[1] = TEE_U64_TO_BIG_ENDIAN(v1);
+}
+
+static void xts_multi_galois(unsigned char *data)
+{
+	int i = 0;
+	uint8_t t = 0;
+	uint8_t tt = 0;
+
+	for (i = 0; i < AES_SM4_IV_SIZE; i++) {
+		tt = data[i] >> LEFT_MOST_BIT;
+		data[i] = ((data[i] << 1) | t) & 0xFF;
+		t = tt;
+	}
+	if (tt)
+		data[0] ^= 0x87;
+}
+
+/*
+ * When the IV is delivered by segment,
+ * the AES/SM4-ECB is used to update the IV to be used next time.
+ */
+static TEE_Result xts_iv_update(struct sec_cipher_ctx *c_ctx)
+{
+	size_t xts_key_len = c_ctx->key_len / 2;
+	struct sec_cipher_ctx ecb_ctx = { };
+	TEE_Result ret = TEE_SUCCESS;
+	size_t i = 0;
+
+	ecb_ctx.alg = c_ctx->alg;
+	ecb_ctx.mode = C_MODE_ECB;
+	ret = sec_cipher_set_key(&ecb_ctx, c_ctx->key + xts_key_len,
+				 xts_key_len, NULL, 0);
+	if (ret)
+		return ret;
+
+	ecb_ctx.encrypt = true;
+	ecb_ctx.in = (uint8_t *)c_ctx->iv;
+	ecb_ctx.out = (uint8_t *)c_ctx->iv;
+	ecb_ctx.in_dma = c_ctx->iv_dma;
+	ecb_ctx.out_dma = c_ctx->iv_dma;
+	ecb_ctx.len = c_ctx->iv_len;
+
+	ret = sec_do_cipher_task(c_ctx->qp, &ecb_ctx);
+	if (ret) {
+		EMSG("Fail to encrypt xts iv, ret=%#"PRIx32, ret);
+		return ret;
+	}
+
+	for (i = 0; i < DIV_ROUND_UP(c_ctx->len, AES_SM4_BLOCK_SIZE); i++)
+		xts_multi_galois((uint8_t *)c_ctx->iv);
+
+	ecb_ctx.encrypt = false;
+	ret = sec_do_cipher_task(c_ctx->qp, &ecb_ctx);
+	if (ret)
+		EMSG("Fail to decrypt xts iv, ret=%#"PRIx32, ret);
+
+	return ret;
+}
+
+static TEE_Result sec_update_iv(struct sec_cipher_ctx *c_ctx)
+{
+	TEE_Result ret = TEE_SUCCESS;
+	size_t offset = 0;
+
+	switch (c_ctx->mode) {
+	case C_MODE_CBC:
+		offset = c_ctx->len - c_ctx->iv_len;
+		if (c_ctx->encrypt && c_ctx->len >= c_ctx->iv_len)
+			memcpy(c_ctx->iv, c_ctx->out + offset, c_ctx->iv_len);
+		if (!c_ctx->encrypt && c_ctx->len >= c_ctx->iv_len)
+			memcpy(c_ctx->iv, c_ctx->in + offset, c_ctx->iv_len);
+		break;
+	case C_MODE_CTR:
+		/*
+		 * Increase the iv counter with the number of processed blocks.
+		 */
+		ctr_iv_inc(c_ctx->iv, c_ctx->len >> CTR_MODE_LEN_SHIFT);
+		break;
+	case C_MODE_XTS:
+		ret = xts_iv_update(c_ctx);
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+static TEE_Result sec_cipher_iv_check(struct sec_cipher_ctx *c_ctx,
+				      size_t iv_size)
+{
+	TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
+
+	switch (c_ctx->mode) {
+	case C_MODE_ECB:
+		if (!iv_size)
+			ret = TEE_SUCCESS;
+		break;
+	case C_MODE_CBC:
+		if (c_ctx->alg == C_ALG_DES || c_ctx->alg == C_ALG_3DES) {
+			if (iv_size == DES_CBC_IV_SIZE)
+				ret = TEE_SUCCESS;
+			break;
+		}
+		fallthrough;
+	case C_MODE_XTS:
+	case C_MODE_CTR:
+		if (c_ctx->alg == C_ALG_AES || c_ctx->alg == C_ALG_SM4) {
+			if (iv_size == AES_SM4_IV_SIZE)
+				ret = TEE_SUCCESS;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (ret)
+		EMSG("Fail to check iv_size");
+
+	return ret;
+}
+
+static TEE_Result sec_cipher_set_iv(struct sec_cipher_ctx *c_ctx,
+				    uint8_t *iv, size_t iv_len)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!iv && iv_len) {
+		EMSG("iv is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = sec_cipher_iv_check(c_ctx, iv_len);
+	if (ret)
+		return ret;
+
+	c_ctx->iv_len = iv_len;
+	c_ctx->iv_dma = virt_to_phys(c_ctx->iv);
+	if (!c_ctx->iv_dma) {
+		EMSG("c_iv_dma is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	memcpy(c_ctx->iv, iv, c_ctx->iv_len);
+
+	return TEE_SUCCESS;
+}
+
+static enum hisi_drv_status sec_cipher_bd_fill(void *bd, void *msg)
+{
+	struct sec_cipher_ctx *c_ctx = msg;
+	struct hisi_sec_sqe *sqe = bd;
+	uint8_t cipher = 0;
+	uint8_t scene = 0;
+	uint8_t de = 0;
+
+	sqe->type_auth_cipher = BD_TYPE2;
+	scene = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET);
+	de = SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET);
+	sqe->sds_sa_type = de | scene;
+	sqe->type2.clen_ivhlen = c_ctx->len;
+
+	sqe->type2.c_alg = c_ctx->alg;
+	sqe->type2.icvw_kmode = SHIFT_U32(c_ctx->mode, SEC_CMODE_OFFSET) |
+				SHIFT_U32(c_ctx->c_key_len, SEC_CKEY_OFFSET);
+
+	if (c_ctx->encrypt)
+		cipher = SHIFT_U32(CIPHER_ENCRYPT, SEC_CIPHER_OFFSET);
+	else
+		cipher = SHIFT_U32(CIPHER_DECRYPT, SEC_CIPHER_OFFSET);
+
+	sqe->type_auth_cipher |= cipher;
+
+	sqe->type2.data_dst_addr = c_ctx->out_dma;
+	sqe->type2.data_src_addr = c_ctx->in_dma;
+	sqe->type2.c_key_addr = c_ctx->key_dma;
+	sqe->type2.c_ivin_addr = c_ctx->iv_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_cipher_bd_parse(void *bd, void *msg __unused)
+{
+	struct hisi_sec_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
+		EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->type2.error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_cipher_bd3_fill(void *bd, void *msg)
+{
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	struct sec_cipher_ctx *c_ctx = msg;
+
+	sqe->bd_param = BD_TYPE3 | SHIFT_U32(SCENE_NOTHING,
+					     SEC_SCENE_OFFSET_V3) |
+			SHIFT_U32(DATA_DST_ADDR_ENABLE, SEC_DE_OFFSET_V3);
+	sqe->c_len_ivin = c_ctx->len;
+	sqe->c_mode_alg = c_ctx->mode |
+			  SHIFT_U32(c_ctx->alg, SEC_CALG_OFFSET_V3);
+	sqe->c_icv_key = SHIFT_U32(c_ctx->c_key_len, SEC_CKEY_OFFSET_V3);
+
+	if (c_ctx->encrypt)
+		sqe->c_icv_key |= CIPHER_ENCRYPT;
+	else
+		sqe->c_icv_key |= CIPHER_DECRYPT;
+
+	sqe->data_dst_addr = c_ctx->out_dma;
+	sqe->data_src_addr = c_ctx->in_dma;
+	sqe->c_key_addr = c_ctx->key_dma;
+	sqe->no_scene.c_ivin_addr = c_ctx->iv_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_cipher_bd3_parse(void *bd, void *msg __unused)
+{
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
+		EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result cipher_algo_check(uint32_t algo)
+{
+	switch (algo) {
+	case TEE_ALG_AES_ECB_NOPAD:
+	case TEE_ALG_AES_CBC_NOPAD:
+	case TEE_ALG_AES_CTR:
+	case TEE_ALG_AES_XTS:
+	case TEE_ALG_DES_ECB_NOPAD:
+	case TEE_ALG_DES3_ECB_NOPAD:
+	case TEE_ALG_DES_CBC_NOPAD:
+	case TEE_ALG_DES3_CBC_NOPAD:
+	case TEE_ALG_SM4_CBC_NOPAD:
+	case TEE_ALG_SM4_ECB_NOPAD:
+	case TEE_ALG_SM4_XTS:
+	case TEE_ALG_SM4_CTR:
+		break;
+	default:
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result crypto_set_alg(struct sec_cipher_ctx *c_ctx, uint32_t alg)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	switch (alg) {
+	case TEE_MAIN_ALGO_DES:
+		c_ctx->alg = C_ALG_DES;
+		break;
+	case TEE_MAIN_ALGO_DES3:
+		c_ctx->alg = C_ALG_3DES;
+		break;
+	case TEE_MAIN_ALGO_AES:
+		c_ctx->alg = C_ALG_AES;
+		break;
+	case TEE_MAIN_ALGO_SM4:
+		c_ctx->alg = C_ALG_SM4;
+		break;
+	default:
+		EMSG("Invalid cipher type %#"PRIx32, alg);
+		ret = TEE_ERROR_NOT_IMPLEMENTED;
+		break;
+	}
+
+	return ret;
+}
+
+static TEE_Result crypto_set_mode(struct sec_cipher_ctx *c_ctx, uint32_t mode)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	switch (mode) {
+	case TEE_CHAIN_MODE_ECB_NOPAD:
+		c_ctx->mode = C_MODE_ECB;
+		break;
+	case TEE_CHAIN_MODE_CBC_NOPAD:
+		c_ctx->mode = C_MODE_CBC;
+		break;
+	case TEE_CHAIN_MODE_XTS:
+		c_ctx->mode = C_MODE_XTS;
+		break;
+	case TEE_CHAIN_MODE_CTR:
+		c_ctx->mode = C_MODE_CTR;
+		break;
+	default:
+		EMSG("Invalid cipher mode type %#"PRIx32, mode);
+		ret = TEE_ERROR_NOT_IMPLEMENTED;
+		break;
+	}
+
+	return ret;
+}
+
+static TEE_Result sec_cipher_ctx_allocate(void **ctx, uint32_t algo)
+{
+	struct sec_cipher_ctx *c_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!ctx) {
+		EMSG("ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = cipher_algo_check(algo);
+	if (ret)
+		return ret;
+
+	c_ctx = calloc(1, sizeof(struct sec_cipher_ctx));
+	if (!c_ctx) {
+		EMSG("c_ctx is NULL");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	ret = crypto_set_alg(c_ctx, TEE_ALG_GET_MAIN_ALG(algo));
+	if (ret)
+		goto free_c_ctx;
+
+	ret = crypto_set_mode(c_ctx, TEE_ALG_GET_CHAIN_MODE(algo));
+	if (ret)
+		goto free_c_ctx;
+
+	c_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0);
+	if (!c_ctx->qp) {
+		ret = TEE_ERROR_BUSY;
+		goto free_c_ctx;
+	}
+
+	if (c_ctx->qp->qm->version == HISI_QM_HW_V2) {
+		c_ctx->qp->fill_sqe = sec_cipher_bd_fill;
+		c_ctx->qp->parse_sqe = sec_cipher_bd_parse;
+	} else {
+		c_ctx->qp->fill_sqe = sec_cipher_bd3_fill;
+		c_ctx->qp->parse_sqe = sec_cipher_bd3_parse;
+	}
+
+	c_ctx->offs = 0;
+	*ctx = c_ctx;
+
+	return TEE_SUCCESS;
+
+free_c_ctx:
+	free(c_ctx);
+
+	return ret;
+}
+
+static void sec_cipher_ctx_free(void *ctx)
+{
+	struct sec_cipher_ctx *c_ctx = ctx;
+
+	if (!c_ctx)
+		return;
+
+	hisi_qm_release_qp(c_ctx->qp);
+	memzero_explicit(c_ctx->key, c_ctx->key_len);
+	free(c_ctx);
+}
+
+static TEE_Result sec_cipher_initialize(struct drvcrypt_cipher_init *dinit)
+{
+	struct sec_cipher_ctx *c_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!dinit || !dinit->ctx || !dinit->key1.data) {
+		EMSG("drvcrypt_cipher init param error");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	c_ctx = dinit->ctx;
+
+	ret = sec_cipher_set_key(c_ctx, dinit->key1.data, dinit->key1.length,
+				 dinit->key2.data, dinit->key2.length);
+	if (ret)
+		return ret;
+
+	ret = sec_cipher_set_iv(c_ctx, dinit->iv.data, dinit->iv.length);
+	if (ret)
+		return ret;
+
+	c_ctx->encrypt = dinit->encrypt;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_cryptlen_check(struct sec_cipher_ctx *c_ctx,
+					    size_t length)
+{
+	if (c_ctx->mode == C_MODE_XTS && length < AES_SM4_BLOCK_SIZE) {
+		EMSG("Invalid xts src len");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if ((c_ctx->mode == C_MODE_ECB || c_ctx->mode == C_MODE_CBC) &&
+	    (length & (AES_SM4_BLOCK_SIZE - 1))) {
+		EMSG("Invalid ecb cbc src len");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_cipher_param_check(struct drvcrypt_cipher_update *dupdate)
+{
+	struct sec_cipher_ctx *c_ctx = NULL;
+
+	if (!dupdate || !dupdate->src.data || !dupdate->dst.data ||
+	    dupdate->src.length != dupdate->dst.length ||
+	    dupdate->src.length > MAX_CIPHER_LENGTH || !dupdate->src.length) {
+		EMSG("Dupdate input param error");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	c_ctx = dupdate->ctx;
+	switch (c_ctx->alg) {
+	case C_ALG_SM4:
+	case C_ALG_AES:
+		if (sec_cipher_cryptlen_check(c_ctx, dupdate->src.length))
+			return TEE_ERROR_BAD_PARAMETERS;
+		break;
+	case C_ALG_DES:
+	case C_ALG_3DES:
+		if (dupdate->src.length % TEE_DES_BLOCK_SIZE) {
+			EMSG("Invalid src len");
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+		break;
+	default:
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_alloc_buffer(struct sec_cipher_ctx *c_ctx)
+{
+	c_ctx->in = malloc(c_ctx->len);
+	if (!c_ctx->in) {
+		EMSG("Fail to alloc c_in buf");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	c_ctx->in_dma = virt_to_phys(c_ctx->in);
+
+	c_ctx->out = malloc(c_ctx->len);
+	if (!c_ctx->out) {
+		EMSG("Fail to alloc c_out buf");
+		goto free_c_in;
+	}
+
+	c_ctx->out_dma = virt_to_phys(c_ctx->out);
+
+	return TEE_SUCCESS;
+
+free_c_in:
+	free(c_ctx->in);
+	c_ctx->in = NULL;
+	return TEE_ERROR_OUT_OF_MEMORY;
+}
+
+static void sec_free_buffer(struct sec_cipher_ctx *c_ctx)
+{
+	free(c_ctx->in);
+	free(c_ctx->out);
+	c_ctx->in = NULL;
+	c_ctx->out = NULL;
+}
+
+static TEE_Result sec_cipher_update(struct drvcrypt_cipher_update *dupdate)
+{
+	struct sec_cipher_ctx *c_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+	size_t padding_size = 0;
+
+	ret = sec_cipher_param_check(dupdate);
+	if (ret)
+		return ret;
+
+	c_ctx = dupdate->ctx;
+	if (c_ctx->mode == C_MODE_CTR && (c_ctx->offs & CTR_SRC_ALIGN_MASK))
+		padding_size = c_ctx->offs % CTR_SRC_BLOCK_SIZE;
+
+	c_ctx->offs += dupdate->src.length;
+	c_ctx->len = dupdate->src.length + padding_size;
+	ret = sec_alloc_buffer(c_ctx);
+	if (ret)
+		return ret;
+
+	memset(c_ctx->in, 0, padding_size);
+	memcpy(c_ctx->in + padding_size, dupdate->src.data,
+	       dupdate->src.length);
+
+	ret = sec_do_cipher_task(c_ctx->qp, c_ctx);
+	if (ret)
+		goto free_buffer;
+
+	ret = sec_update_iv(c_ctx);
+	if (ret) {
+		EMSG("Fail to update iv, ret=%#"PRIx32, ret);
+		goto free_buffer;
+	}
+
+	memcpy(dupdate->dst.data, c_ctx->out + padding_size,
+	       dupdate->src.length);
+
+free_buffer:
+	sec_free_buffer(c_ctx);
+	return ret;
+}
+
+static void sec_cipher_final(void *ctx __unused)
+{
+}
+
+static void sec_cipher_copy_state(void *dst_ctx, void *src_ctx)
+{
+	struct sec_cipher_ctx *dst_c_ctx = dst_ctx;
+	struct sec_cipher_ctx *src_c_ctx = src_ctx;
+
+	dst_c_ctx->alg = src_c_ctx->alg;
+	dst_c_ctx->mode = src_c_ctx->mode;
+	dst_c_ctx->encrypt = src_c_ctx->encrypt;
+	dst_c_ctx->offs = src_c_ctx->offs;
+
+	if (src_c_ctx->key_len) {
+		dst_c_ctx->key_len = src_c_ctx->key_len;
+		dst_c_ctx->c_key_len = src_c_ctx->c_key_len;
+		memcpy(dst_c_ctx->key, src_c_ctx->key, dst_c_ctx->key_len);
+		dst_c_ctx->key_dma = virt_to_phys(dst_c_ctx->key);
+	} else {
+		dst_c_ctx->key_len = 0;
+		dst_c_ctx->c_key_len = 0;
+	}
+
+	if (src_c_ctx->iv_len) {
+		dst_c_ctx->iv_len = src_c_ctx->iv_len;
+		memcpy(dst_c_ctx->iv, src_c_ctx->iv, dst_c_ctx->iv_len);
+		dst_c_ctx->iv_dma = virt_to_phys(dst_c_ctx->iv);
+	} else {
+		dst_c_ctx->iv_len = 0;
+	}
+}
+
+static struct drvcrypt_cipher driver_cipher = {
+	.alloc_ctx = sec_cipher_ctx_allocate,
+	.free_ctx = sec_cipher_ctx_free,
+	.init = sec_cipher_initialize,
+	.update = sec_cipher_update,
+	.final = sec_cipher_final,
+	.copy_state = sec_cipher_copy_state,
+};
+
+static TEE_Result sec_cipher_init(void)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = drvcrypt_register_cipher(&driver_cipher);
+	if (ret)
+		EMSG("Sec cipher register to crypto fail ret=%#"PRIx32, ret);
+
+	return ret;
+}
+driver_init(sec_cipher_init);
diff --git a/core/drivers/crypto/hisilicon/sec_cipher.h b/core/drivers/crypto/hisilicon/sec_cipher.h
new file mode 100644
index 0000000000000000000000000000000000000000..cbfa3eef859a4b6f620b9c9ca54b102e08fe1d8c
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_cipher.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2022-2024 HiSilicon Limited. */
+
+#ifndef __SEC_CIPHER_H__
+#define __SEC_CIPHER_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "hisi_qm.h"
+
+#define DES_KEY_SIZE			8
+#define SEC_3DES_2KEY_SIZE		(2 * DES_KEY_SIZE)
+#define SEC_3DES_3KEY_SIZE		(3 * DES_KEY_SIZE)
+#define SEC_SM4_XTS_KEY_SIZE		32
+#define SEC_SM4_ECB_KEY_SIZE		16
+#define SEC_MAX_CIPHER_KEY_SIZE		64
+#define MAX_CIPHER_LENGTH		16776704
+#define MIN_CIPHER_LENGTH		16
+#define XTS_KEYSIZE_128			32
+#define XTS_KEYSIZE_256			64
+#define DES_CBC_IV_SIZE			8
+#define AES_SM4_IV_SIZE			16
+#define SEC_MAX_IV_SIZE			2
+#define CTR_MODE_LEN_SHIFT		4
+#define CTR_128BIT_COUNTER		16
+#define AES_SM4_BLOCK_SIZE		16
+#define LEFT_MOST_BIT			7
+#define CTR_SRC_ALIGN_MASK		0xf
+#define CTR_SRC_BLOCK_SIZE		0x10
+
+#define CKEY_LEN_128_BIT		0x1
+#define CKEY_LEN_192_BIT		0x2
+#define CKEY_LEN_256_BIT		0x3
+#define CKEY_LEN_SM4			0x0
+#define CKEY_LEN_DES			0x1
+#define CKEY_LEN_3DES_3KEY		0x1
+#define CKEY_LEN_3DES_2KEY		0x3
+
+enum sec_c_alg {
+	C_ALG_DES = 0x0,
+	C_ALG_3DES = 0x1,
+	C_ALG_AES = 0x2,
+	C_ALG_SM4 = 0x3,
+};
+
+enum sec_c_mode {
+	C_MODE_ECB = 0x0,
+	C_MODE_CBC = 0x1,
+	C_MODE_CFB = 0x2,
+	C_MODE_OFB = 0x3,
+	C_MODE_CTR = 0x4,
+	C_MODE_CCM = 0x5,
+	C_MODE_GCM = 0x6,
+	C_MODE_XTS = 0x7,
+	C_MODE_CTS = 0x9,
+};
+
+enum sec_cipher_dir {
+	NO_CIPHER,
+	CIPHER_ENCRYPT,
+	CIPHER_DECRYPT,
+	HARDWARE_COPY,
+};
+
+struct sec_cipher_ctx {
+	uint8_t key[SEC_MAX_CIPHER_KEY_SIZE];
+	uint64_t iv[SEC_MAX_IV_SIZE];
+	uint64_t key_dma;
+	uint64_t iv_dma;
+	uint8_t *in;
+	uint64_t in_dma;
+	uint8_t *out;
+	uint64_t out_dma;
+	struct hisi_qp *qp;
+	size_t offs;
+	uint32_t len;
+	uint8_t alg;
+	uint8_t mode;
+	uint8_t iv_len;
+	uint8_t key_len;
+	uint8_t c_key_len;
+	bool encrypt;
+};
+#endif /* __SEC_CIPHER_H__ */
diff --git a/core/drivers/crypto/hisilicon/sec_hash.c b/core/drivers/crypto/hisilicon/sec_hash.c
new file mode 100644
index 0000000000000000000000000000000000000000..389261fb8ea4caaa1309f82dadd42dc14cba0c51
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_hash.c
@@ -0,0 +1,652 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator sec hash algorithm implementation.
+ */
+
+#include <drvcrypt_hash.h>
+#include <initcall.h>
+
+#include "sec_hash.h"
+#include "sec_main.h"
+
+static enum hisi_drv_status sec_digest_set_hmac_key(struct hashctx *ctx,
+						    struct hisi_sec_sqe *sqe)
+{
+	if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) {
+		EMSG("Invalid digest key len(%ld)", ctx->key_len);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	/* If the length of key is not word-aligned, increment by 1 */
+	sqe->type2.mac_key_alg |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len,
+							 SEC_ENCODE_BYTES),
+					    SEC_AKEY_OFFSET);
+	sqe->type2.a_key_addr = ctx->key_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void sec_digest_fill_long_bd2(struct hashctx *ctx,
+				     struct hisi_sec_sqe *sqe)
+{
+	uint64_t total_bits = 0;
+
+	if (ctx->has_next && !ctx->iv_len) {
+		/* LONG BD FIRST */
+		sqe->ai_apd_cs |= AI_GEN_INNER;
+		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET);
+		ctx->iv_len = ctx->mac_len;
+	} else if (ctx->has_next && ctx->iv_len) {
+		/* LONG BD MIDDLE */
+		sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR;
+		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_NOPAD, SEC_APAD_OFFSET);
+		sqe->type2.a_ivin_addr = sqe->type2.mac_addr;
+		ctx->iv_len = ctx->mac_len;
+	} else if (!ctx->has_next && ctx->iv_len) {
+		/* LONG BD END */
+		sqe->ai_apd_cs |= AI_GEN_IVIN_ADDR;
+		sqe->ai_apd_cs |= SHIFT_U32(AUTHPAD_PAD, SEC_APAD_OFFSET);
+		sqe->type2.a_ivin_addr = sqe->type2.mac_addr;
+		total_bits = ctx->long_data_len * BYTE_BITS;
+		sqe->type2.long_a_data_len = total_bits;
+		ctx->iv_len = 0;
+	} else {
+		/* SHORT BD */
+		ctx->iv_len = 0;
+	}
+}
+
+static struct crypto_hash *to_hash_ctx(struct crypto_hash_ctx *ctx)
+{
+	return container_of(ctx, struct crypto_hash, hash_ctx);
+}
+
+static uint32_t sec_digest_get_alg_type(uint32_t algo)
+{
+	switch (algo) {
+	case TEE_ALG_MD5:
+		return A_ALG_MD5;
+	case TEE_ALG_HMAC_MD5:
+		return A_ALG_HMAC_MD5;
+	case TEE_ALG_SHA1:
+		return A_ALG_SHA1;
+	case TEE_ALG_HMAC_SHA1:
+		return A_ALG_HMAC_SHA1;
+	case TEE_ALG_SHA224:
+		return A_ALG_SHA224;
+	case TEE_ALG_HMAC_SHA224:
+		return A_ALG_HMAC_SHA224;
+	case TEE_ALG_SM3:
+		return A_ALG_SM3;
+	case TEE_ALG_HMAC_SM3:
+		return A_ALG_HMAC_SM3;
+	case TEE_ALG_SHA256:
+		return A_ALG_SHA256;
+	case TEE_ALG_HMAC_SHA256:
+		return A_ALG_HMAC_SHA256;
+	case TEE_ALG_SHA384:
+		return A_ALG_SHA384;
+	case TEE_ALG_HMAC_SHA384:
+		return A_ALG_HMAC_SHA384;
+	case TEE_ALG_SHA512:
+		return A_ALG_SHA512;
+	case TEE_ALG_HMAC_SHA512:
+		return A_ALG_HMAC_SHA512;
+	default:
+		return A_ALG_MAX;
+	}
+}
+
+static enum hisi_drv_status sec_digest_fill_sqe(void *bd, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_sec_sqe *sqe = bd;
+	struct hashctx *ctx = msg;
+	uint32_t alg_type = 0;
+
+	if (!ctx->in_len) {
+		EMSG("Digest bd2 not support 0 packet");
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	sqe->type_auth_cipher = BD_TYPE2;
+	sqe->sds_sa_type = SHIFT_U32(SCENE_NOTHING, SEC_SCENE_OFFSET);
+	sqe->type_auth_cipher |= SHIFT_U32(AUTH_MAC_CALCULATE, SEC_AUTH_OFFSET);
+	sqe->type2.alen_ivllen = ctx->in_len;
+
+	sqe->type2.data_src_addr = ctx->in_dma;
+	sqe->type2.mac_addr = ctx->out_dma;
+	sqe->type2.mac_key_alg |= ctx->mac_len / SEC_ENCODE_BYTES;
+
+	if (ctx->mode == WCRYPTO_DIGEST_HMAC) {
+		ret = sec_digest_set_hmac_key(ctx, sqe);
+		if (ret)
+			return ret;
+	}
+
+	alg_type = sec_digest_get_alg_type(ctx->algo);
+	if (alg_type >= A_ALG_MAX) {
+		EMSG("Fail to get digest alg type");
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+	sqe->type2.mac_key_alg |= SHIFT_U32(alg_type, SEC_AEAD_ALG_OFFSET);
+
+	sec_digest_fill_long_bd2(ctx, sqe);
+
+	return ret;
+}
+
+static enum hisi_drv_status
+sec_digest_set_hmac_bd3_key(struct hashctx *ctx, struct hisi_sec_bd3_sqe *sqe)
+{
+	if (ctx->key_len > SEC_DIGEST_MAX_KEY_SIZE || !ctx->key_len) {
+		EMSG("Invalid digest key len(%ld)", ctx->key_len);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	/* If the length of key is not word-aligned, increment by 1 */
+	sqe->auth_mac_key |= SHIFT_U64(DIV_ROUND_UP(ctx->key_len,
+						    SEC_ENCODE_BYTES),
+				       SEC_AKEY_OFFSET_V3);
+	sqe->a_key_addr = ctx->key_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static void sec_digest_fill_long_bd3(struct hashctx *ctx,
+				     struct hisi_sec_bd3_sqe *sqe)
+{
+	uint64_t total_bits = 0;
+
+	if (ctx->has_next && !ctx->iv_len) {
+		/* LONG BD FIRST */
+		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_INNER,
+					       SEC_AI_GEN_OFFSET_V3);
+		sqe->stream_scene.auth_pad = AUTHPAD_NOPAD;
+		ctx->iv_len = ctx->mac_len;
+	} else if (ctx->has_next && ctx->iv_len) {
+		/* LONG BD MIDDLE */
+		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR,
+					       SEC_AI_GEN_OFFSET_V3);
+		sqe->stream_scene.auth_pad = AUTHPAD_NOPAD;
+		sqe->a_ivin_addr = sqe->mac_addr;
+		ctx->iv_len = ctx->mac_len;
+	} else if (!ctx->has_next && ctx->iv_len) {
+		/* LONG BD END */
+		sqe->auth_mac_key |= SHIFT_U32(AI_GEN_IVIN_ADDR,
+					       SEC_AI_GEN_OFFSET_V3);
+		sqe->stream_scene.auth_pad = AUTHPAD_PAD;
+		sqe->a_ivin_addr = sqe->mac_addr;
+		total_bits = ctx->long_data_len * BYTE_BITS;
+		sqe->stream_scene.long_a_data_len = total_bits;
+		ctx->iv_len = 0;
+	} else {
+		/* SHORT BD */
+		ctx->iv_len = 0;
+	}
+}
+
+static enum hisi_drv_status sec_digest_fill_bd3_sqe(void *bd, void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	struct hashctx *ctx = msg;
+	uint32_t alg_type = 0;
+
+	sqe->bd_param = BD_TYPE3 | SHIFT_U32(ctx->scene, SEC_SCENE_OFFSET_V3);
+	sqe->a_len_key = ctx->in_len;
+	sqe->auth_mac_key = AUTH_MAC_CALCULATE;
+	sqe->data_src_addr = ctx->in_dma;
+	sqe->mac_addr = ctx->out_dma;
+
+	if (ctx->mode == WCRYPTO_DIGEST_HMAC) {
+		ret = sec_digest_set_hmac_bd3_key(ctx, sqe);
+		if (ret)
+			return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	sqe->auth_mac_key |= SHIFT_U64(ctx->mac_len / SEC_ENCODE_BYTES,
+				       SEC_MAC_OFFSET_V3);
+	alg_type = sec_digest_get_alg_type(ctx->algo);
+	if (alg_type >= A_ALG_MAX) {
+		EMSG("Fail to get digest bd3 alg");
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+	sqe->auth_mac_key |= SHIFT_U32(alg_type, SEC_AUTH_ALG_OFFSET_V3);
+	sec_digest_fill_long_bd3(ctx, sqe);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result sec_digest_do_task(struct hisi_qp *qp, void *msg)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = hisi_qp_send(qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	ret = hisi_qp_recv_sync(qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static enum hisi_drv_status sec_parse_digest_sqe(void *bd, void *msg __unused)
+{
+	struct hisi_sec_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
+		EMSG("SEC BD2 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->type2.error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_parse_digest_bd3_sqe(void *bd,
+						     void *msg __unused)
+{
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
+		EMSG("SEC BD3 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+TEE_Result hisi_sec_digest_ctx_init(struct hashctx *hash_ctx,
+				    const uint8_t *key, size_t len)
+{
+	if (!hash_ctx) {
+		EMSG("Input hash_ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash_ctx->in_len = 0;
+	hash_ctx->iv_len = 0;
+	hash_ctx->has_next = false;
+	hash_ctx->long_data_len = 0;
+	hash_ctx->scene = SCENE_NOTHING;
+
+	/*
+	 * In reset ctx scenarios, sec_hash_initialize will be called.
+	 * To ensure in data is NULL, reset ctx need to free in data
+	 * which is not NULL.
+	 */
+	free(hash_ctx->in);
+	hash_ctx->in = NULL;
+
+	if (len) {
+		hash_ctx->key_len = len;
+		memcpy(hash_ctx->key, key, len);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_hash_initialize(struct crypto_hash_ctx *ctx)
+{
+	struct crypto_hash *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+
+	if (!ctx) {
+		EMSG("Input ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = to_hash_ctx(ctx);
+	hash_ctx = hash->ctx;
+
+	return hisi_sec_digest_ctx_init(hash_ctx, NULL, 0);
+}
+
+TEE_Result hisi_sec_digest_do_update(struct hashctx *hash_ctx,
+				     const uint8_t *data, size_t len)
+{
+	TEE_Result ret = TEE_SUCCESS;
+	size_t left_size = 0;
+
+	hash_ctx->long_data_len += len;
+
+	if (!hash_ctx->in) {
+		if (len <= SMALL_BUF_SIZE)
+			hash_ctx->buf_len = SMALL_BUF_SIZE;
+		else if (len <= MAX_AUTH_LENGTH)
+			hash_ctx->buf_len = ROUNDUP(len, HISI_QM_ALIGN128);
+		else
+			hash_ctx->buf_len = MAX_AUTH_LENGTH;
+
+		hash_ctx->in_len = 0;
+		hash_ctx->in = malloc(hash_ctx->buf_len);
+		if (!hash_ctx->in) {
+			EMSG("Fail to alloc in data buf");
+			return TEE_ERROR_OUT_OF_MEMORY;
+		}
+		hash_ctx->in_dma = virt_to_phys(hash_ctx->in);
+	}
+
+	while (len > 0) {
+		if (hash_ctx->in_len + len <= hash_ctx->buf_len) {
+			memcpy(hash_ctx->in + hash_ctx->in_len, data, len);
+			hash_ctx->in_len += len;
+			len = 0;
+		} else {
+			left_size = hash_ctx->buf_len - hash_ctx->in_len;
+			memcpy(hash_ctx->in + hash_ctx->in_len, data,
+			       left_size);
+			hash_ctx->in_len = hash_ctx->buf_len;
+			hash_ctx->scene = SCENE_STREAM;
+			hash_ctx->has_next = true;
+			data += left_size;
+			len -= left_size;
+			ret = sec_digest_do_task(hash_ctx->qp, hash_ctx);
+			if (ret) {
+				EMSG("Fail to do digest task! ret = %#"PRIx32,
+				     ret);
+				return ret;
+			}
+			hash_ctx->iv_len = hash_ctx->mac_len;
+			hash_ctx->in_len = 0;
+		}
+	}
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_hash_do_update(struct crypto_hash_ctx *ctx,
+				     const uint8_t *data, size_t len)
+{
+	struct crypto_hash *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+
+	if (!len) {
+		IMSG("This is 0 len task, skip");
+		return TEE_SUCCESS;
+	}
+
+	if (!ctx || (!data && len)) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = to_hash_ctx(ctx);
+	hash_ctx = hash->ctx;
+
+	return hisi_sec_digest_do_update(hash_ctx, data, len);
+}
+
+TEE_Result hisi_sec_digest_do_final(struct hashctx *hash_ctx, uint8_t *digest,
+				    size_t len)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!digest || len == 0) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (hash_ctx->mac_len & WORD_ALIGNMENT_MASK) {
+		EMSG("Invalid digest out_bytes");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash_ctx->has_next = false;
+	ret = sec_digest_do_task(hash_ctx->qp, hash_ctx);
+	if (ret) {
+		EMSG("Fail to do digest task! ret = %#"PRIx32, ret);
+		return ret;
+	}
+
+	memcpy(digest, hash_ctx->out, MIN(hash_ctx->mac_len, len));
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_hash_do_final(struct crypto_hash_ctx *ctx,
+				    uint8_t *digest, size_t len)
+{
+	struct crypto_hash *hash = to_hash_ctx(ctx);
+	struct hashctx *hash_ctx = hash->ctx;
+
+	return hisi_sec_digest_do_final(hash_ctx, digest, len);
+}
+
+void hisi_sec_digest_ctx_free(struct hashctx *hash_ctx)
+{
+	hisi_qm_release_qp(hash_ctx->qp);
+
+	free(hash_ctx->in);
+	hash_ctx->in = NULL;
+
+	memzero_explicit(hash_ctx->key, SEC_DIGEST_MAX_KEY_SIZE);
+
+	free(hash_ctx);
+}
+
+static void sec_hash_ctx_free(struct crypto_hash_ctx *ctx)
+{
+	struct crypto_hash *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+
+	if (!ctx)
+		return;
+
+	hash = to_hash_ctx(ctx);
+	hash_ctx = hash->ctx;
+	if (!hash_ctx)
+		return;
+	hisi_sec_digest_ctx_free(hash_ctx);
+
+	hash->ctx = NULL;
+
+	free(hash);
+}
+
+void hisi_sec_digest_copy_state(struct hashctx *out_hash_ctx,
+				struct hashctx *in_hash_ctx)
+{
+	out_hash_ctx->iv_len = in_hash_ctx->iv_len;
+	out_hash_ctx->buf_len = in_hash_ctx->buf_len;
+	out_hash_ctx->key_len = in_hash_ctx->key_len;
+	out_hash_ctx->has_next = in_hash_ctx->has_next;
+	out_hash_ctx->long_data_len = in_hash_ctx->long_data_len;
+
+	if (in_hash_ctx->in) {
+		out_hash_ctx->in = malloc(out_hash_ctx->buf_len);
+		if (!out_hash_ctx->in) {
+			EMSG("Fail to alloc in buf");
+			return;
+		}
+		out_hash_ctx->in_dma = virt_to_phys(out_hash_ctx->in);
+		out_hash_ctx->in_len = in_hash_ctx->in_len;
+		memcpy(out_hash_ctx->in, in_hash_ctx->in,
+		       out_hash_ctx->buf_len);
+	}
+
+	memcpy(out_hash_ctx->iv, in_hash_ctx->iv, out_hash_ctx->iv_len);
+	memcpy(out_hash_ctx->key, in_hash_ctx->key, out_hash_ctx->key_len);
+}
+
+static void sec_hash_copy_state(struct crypto_hash_ctx *out_ctx,
+				struct crypto_hash_ctx *in_ctx)
+{
+	struct crypto_hash *out_hash = NULL;
+	struct crypto_hash *in_hash = NULL;
+	struct hashctx *out_hash_ctx = NULL;
+	struct hashctx *in_hash_ctx = NULL;
+
+	if (!out_ctx || !in_ctx) {
+		EMSG("Invalid input parameters");
+		return;
+	}
+
+	out_hash = to_hash_ctx(out_ctx);
+	in_hash = to_hash_ctx(in_ctx);
+
+	out_hash_ctx = out_hash->ctx;
+	in_hash_ctx = in_hash->ctx;
+
+	hisi_sec_digest_copy_state(out_hash_ctx, in_hash_ctx);
+}
+
+static struct crypto_hash_ops hash_ops = {
+	.init = sec_hash_initialize,
+	.update = sec_hash_do_update,
+	.final = sec_hash_do_final,
+	.free_ctx = sec_hash_ctx_free,
+	.copy_state = sec_hash_copy_state,
+};
+
+static size_t sec_hash_get_mac_len(uint32_t type)
+{
+	switch (type) {
+	case TEE_ALG_MD5:
+	case TEE_ALG_HMAC_MD5:
+		return HASH_MAC_LEN128;
+	case TEE_ALG_SHA1:
+	case TEE_ALG_HMAC_SHA1:
+		return HASH_MAC_LEN160;
+	case TEE_ALG_SHA224:
+	case TEE_ALG_HMAC_SHA224:
+		return HASH_MAC_LEN224;
+	case TEE_ALG_SM3:
+	case TEE_ALG_HMAC_SM3:
+	case TEE_ALG_SHA256:
+	case TEE_ALG_HMAC_SHA256:
+		return HASH_MAC_LEN256;
+	case TEE_ALG_SHA384:
+	case TEE_ALG_HMAC_SHA384:
+		return HASH_MAC_LEN384;
+	case TEE_ALG_SHA512:
+	case TEE_ALG_HMAC_SHA512:
+		return HASH_MAC_LEN512;
+	default:
+		return 0;
+	}
+}
+
+static TEE_Result sec_hash_get_dma(struct hashctx *hash_ctx)
+{
+	hash_ctx->key_dma = virt_to_phys(hash_ctx->key);
+	if (!hash_ctx->key_dma) {
+		EMSG("Fail to get key_dma");
+		return TEE_ERROR_GENERIC;
+	}
+
+	hash_ctx->iv_dma = virt_to_phys(hash_ctx->iv);
+	if (!hash_ctx->iv_dma) {
+		EMSG("Fail to get iv_dma");
+		return TEE_ERROR_GENERIC;
+	}
+
+	hash_ctx->out_dma = virt_to_phys(hash_ctx->out);
+	if (!hash_ctx->out_dma) {
+		EMSG("Fail to get out_dma");
+		return TEE_ERROR_GENERIC;
+	}
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result hisi_sec_hash_ctx_init(struct hashctx *hash_ctx, uint32_t algo)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	hash_ctx->mac_len = sec_hash_get_mac_len(algo);
+	if (!hash_ctx->mac_len) {
+		EMSG("Invalid algo type %#"PRIx32, algo);
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	hash_ctx->algo = algo;
+	hash_ctx->mode = algo >> HASH_MODE_OFFSET;
+
+	ret = sec_hash_get_dma(hash_ctx);
+	if (ret)
+		return ret;
+
+	hash_ctx->qp = sec_create_qp(HISI_QM_CHANNEL_TYPE0);
+	if (!hash_ctx->qp) {
+		EMSG("Fail to create hash qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	if (hash_ctx->qp->qm->version == HISI_QM_HW_V2) {
+		hash_ctx->qp->fill_sqe = sec_digest_fill_sqe;
+		hash_ctx->qp->parse_sqe = sec_parse_digest_sqe;
+	} else {
+		hash_ctx->qp->fill_sqe = sec_digest_fill_bd3_sqe;
+		hash_ctx->qp->parse_sqe = sec_parse_digest_bd3_sqe;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_hash_ctx_allocate(struct crypto_hash_ctx **ctx,
+					uint32_t algo)
+{
+	struct crypto_hash *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!ctx) {
+		EMSG("Ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = calloc(1, sizeof(*hash));
+	if (!hash) {
+		EMSG("Fail to alloc hash");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	hash_ctx = calloc(1, sizeof(*hash_ctx));
+	if (!hash_ctx) {
+		EMSG("Fail to alloc hash_ctx");
+		ret = TEE_ERROR_OUT_OF_MEMORY;
+		goto free_hash;
+	}
+
+	ret = hisi_sec_hash_ctx_init(hash_ctx, algo);
+	if (ret)
+		goto free_ctx;
+
+	hash->hash_ctx.ops = &hash_ops;
+	hash->ctx = hash_ctx;
+	*ctx = &hash->hash_ctx;
+
+	return TEE_SUCCESS;
+
+free_ctx:
+	free(hash_ctx);
+free_hash:
+	free(hash);
+
+	return ret;
+}
+
+static TEE_Result sec_hash_init(void)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = drvcrypt_register_hash(&sec_hash_ctx_allocate);
+	if (ret)
+		EMSG("Sec hash register to crypto fail ret=%#"PRIx32, ret);
+
+	return ret;
+}
+driver_init(sec_hash_init);
diff --git a/core/drivers/crypto/hisilicon/sec_hash.h b/core/drivers/crypto/hisilicon/sec_hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..9b3554bc23b1b32e5cd470b33987f8815c64e61e
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_hash.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2022-2024 HiSilicon Limited. */
+#ifndef __SEC_HASH_H__
+#define __SEC_HASH_H__
+
+#include <stdint.h>
+#include <tee_api_types.h>
+
+#define WORD_ALIGNMENT_MASK		0x3
+#define HASH_MODE_OFFSET		28
+#define WCRYPTO_DIGEST_HMAC		3
+#define WCRYPTO_DIGEST_NORMAL		5
+#define MAX_AUTH_LENGTH			16776704
+#define HASH_MAC_LEN128			16
+#define HASH_MAC_LEN160			20
+#define HASH_MAC_LEN224			28
+#define HASH_MAC_LEN256			32
+#define HASH_MAC_LEN384			48
+#define HASH_MAC_LEN512			64
+#define SEC_DIGEST_MAX_KEY_SIZE		128
+#define SEC_DIGEST_MAX_MAC_SIZE		64
+#define SEC_DIGEST_MAX_IV_SIZE		64
+#define SMALL_BUF_SIZE			0x1000
+
+struct hashctx {
+	uint8_t key[SEC_DIGEST_MAX_KEY_SIZE];
+	uint8_t iv[SEC_DIGEST_MAX_IV_SIZE];
+	uint8_t out[SEC_DIGEST_MAX_MAC_SIZE];
+	bool has_next;
+	uint8_t mode;
+	uint32_t algo;
+	uint32_t scene;
+	struct hisi_qp *qp;
+	uint8_t *in;
+	uint64_t in_dma;
+	size_t buf_len;
+	size_t in_len;
+	uint64_t out_dma;
+	size_t mac_len;
+	uint64_t key_dma;
+	size_t key_len;
+	uint64_t iv_dma;
+	size_t iv_len;
+	uint64_t long_data_len;
+};
+
+/*
+ * Format the hash context to keep the reference to the
+ * operation driver
+ */
+struct crypto_hash {
+	struct crypto_hash_ctx hash_ctx; /* Crypto Hash API context */
+	struct hashctx *ctx; /* Hash Context */
+};
+
+/*
+ * Format the hmac context to keep the reference to the
+ * operation driver
+ */
+struct crypto_hmac {
+	struct crypto_mac_ctx hmac_op; /* Crypto Hash API context */
+	struct hashctx *ctx; /* Hash Context */
+};
+
+enum A_ALG {
+	A_ALG_SHA1     = 0x0,
+	A_ALG_SHA256   = 0x1,
+	A_ALG_MD5      = 0x2,
+	A_ALG_SHA224   = 0x3,
+	A_ALG_SHA384   = 0x4,
+	A_ALG_SHA512   = 0x5,
+	A_ALG_SHA512_224 = 0x6,
+	A_ALG_SHA512_256 = 0x7,
+	A_ALG_HMAC_SHA1   = 0x10,
+	A_ALG_HMAC_SHA256 = 0x11,
+	A_ALG_HMAC_MD5      = 0x12,
+	A_ALG_HMAC_SHA224 = 0x13,
+	A_ALG_HMAC_SHA384 = 0x14,
+	A_ALG_HMAC_SHA512 = 0x15,
+	A_ALG_HMAC_SHA512_224 = 0x16,
+	A_ALG_HMAC_SHA512_256 = 0x17,
+	A_ALG_AES_XCBC_MAC_96  = 0x20,
+	A_ALG_AES_XCBC_PRF_128 = 0x20,
+	A_ALG_AES_CMAC = 0x21,
+	A_ALG_AES_GMAC = 0x22,
+	A_ALG_SM3       = 0x25,
+	A_ALG_HMAC_SM3 = 0x26,
+	A_ALG_MAX
+};
+
+enum {
+	AI_GEN_INNER        = 0x0,
+	AI_GEN_IVIN_ADDR    = 0x1,
+	AI_GEN_CAL_IV_ADDR  = 0x2,
+	AI_GEN_TRNG         = 0x3,
+};
+
+enum {
+	AUTHPAD_PAD,
+	AUTHPAD_NOPAD,
+};
+
+TEE_Result hisi_sec_hash_ctx_init(struct hashctx *hash_ctx, uint32_t algo);
+TEE_Result hisi_sec_digest_ctx_init(struct hashctx *hash_ctx,
+				    const uint8_t *key, size_t len);
+TEE_Result hisi_sec_digest_do_update(struct hashctx *hashctx,
+				     const uint8_t *data, size_t len);
+TEE_Result hisi_sec_digest_do_final(struct hashctx *hashctx, uint8_t *digest,
+				    size_t len);
+void hisi_sec_digest_ctx_free(struct hashctx *hash_ctx);
+void hisi_sec_digest_copy_state(struct hashctx *out_hash_ctx,
+				struct hashctx *in_hash_ctx);
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/sec_hmac.c b/core/drivers/crypto/hisilicon/sec_hmac.c
new file mode 100644
index 0000000000000000000000000000000000000000..95a35cd67e8bc0a22aed2b2834c6585113b7cf8a
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_hmac.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator sec hmac algorithm implementation.
+ */
+
+#include <drvcrypt_mac.h>
+#include <initcall.h>
+
+#include "sec_hash.h"
+#include "sec_main.h"
+
+static struct crypto_hmac *to_hmac_ctx(struct crypto_mac_ctx *ctx)
+{
+	return container_of(ctx, struct crypto_hmac, hmac_op);
+}
+
+static TEE_Result sec_hmac_initialize(struct crypto_mac_ctx *ctx,
+				      const uint8_t *key, size_t len)
+{
+	struct crypto_hmac *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+
+	if (!ctx || !key) {
+		EMSG("Input ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = to_hmac_ctx(ctx);
+	hash_ctx = hash->ctx;
+
+	return hisi_sec_digest_ctx_init(hash_ctx, key, len);
+}
+
+static TEE_Result sec_hmac_do_update(struct crypto_mac_ctx *ctx,
+				     const uint8_t *data, size_t len)
+{
+	struct crypto_hmac *hash = NULL;
+	struct hashctx *hashctx = NULL;
+
+	if (!len) {
+		IMSG("This is 0 len task, skip");
+		return TEE_SUCCESS;
+	}
+
+	if (!ctx || (!data && len)) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = to_hmac_ctx(ctx);
+	hashctx = hash->ctx;
+
+	return hisi_sec_digest_do_update(hashctx, data, len);
+}
+
+static TEE_Result sec_hmac_do_final(struct crypto_mac_ctx *ctx, uint8_t *digest,
+				    size_t len)
+{
+	struct crypto_hmac *hash = to_hmac_ctx(ctx);
+	struct hashctx *hash_ctx = hash->ctx;
+
+	return hisi_sec_digest_do_final(hash_ctx, digest, len);
+}
+
+static void sec_hmac_ctx_free(struct crypto_mac_ctx *ctx)
+{
+	struct crypto_hmac *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+
+	if (!ctx)
+		return;
+
+	hash = to_hmac_ctx(ctx);
+	hash_ctx = hash->ctx;
+	if (!hash_ctx)
+		return;
+
+	memzero_explicit(hash_ctx->key, hash_ctx->key_len);
+	hisi_sec_digest_ctx_free(hash_ctx);
+
+	hash->ctx = NULL;
+
+	free(hash);
+}
+
+static void sec_hmac_copy_state(struct crypto_mac_ctx *out_ctx,
+				struct crypto_mac_ctx *in_ctx)
+{
+	struct crypto_hmac *out_hash = NULL;
+	struct crypto_hmac *in_hash = NULL;
+	struct hashctx *out_hash_ctx = NULL;
+	struct hashctx *in_hash_ctx = NULL;
+
+	if (!out_ctx || !in_ctx) {
+		EMSG("Invalid input parameters");
+		return;
+	}
+
+	out_hash = to_hmac_ctx(out_ctx);
+	in_hash = to_hmac_ctx(in_ctx);
+
+	out_hash_ctx = out_hash->ctx;
+	in_hash_ctx = in_hash->ctx;
+
+	hisi_sec_digest_copy_state(out_hash_ctx, in_hash_ctx);
+}
+
+static struct crypto_mac_ops hash_ops = {
+	.init = sec_hmac_initialize,
+	.update = sec_hmac_do_update,
+	.final = sec_hmac_do_final,
+	.free_ctx = sec_hmac_ctx_free,
+	.copy_state = sec_hmac_copy_state,
+};
+
+static TEE_Result sec_hmac_ctx_allocate(struct crypto_mac_ctx **ctx,
+					uint32_t algo)
+{
+	struct crypto_hmac *hash = NULL;
+	struct hashctx *hash_ctx = NULL;
+	TEE_Result ret = TEE_SUCCESS;
+
+	if (!ctx) {
+		EMSG("Ctx is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	hash = calloc(1, sizeof(*hash));
+	if (!hash) {
+		EMSG("Fail to alloc hash");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	hash_ctx = calloc(1, sizeof(*hash_ctx));
+	if (!hash_ctx) {
+		EMSG("Fail to alloc hashctx");
+		ret = TEE_ERROR_OUT_OF_MEMORY;
+		goto free_hash;
+	}
+
+	ret = hisi_sec_hash_ctx_init(hash_ctx, algo);
+	if (ret)
+		goto free_ctx;
+
+	hash->hmac_op.ops = &hash_ops;
+	hash->ctx = hash_ctx;
+	*ctx = &hash->hmac_op;
+
+	return 0;
+
+free_ctx:
+	free(hash_ctx);
+free_hash:
+	free(hash);
+
+	return ret;
+}
+
+static TEE_Result sec_hmac_init(void)
+{
+	TEE_Result ret = TEE_SUCCESS;
+
+	ret = drvcrypt_register_hmac(&sec_hmac_ctx_allocate);
+	if (ret)
+		EMSG("Sec hmac register to crypto fail");
+
+	return ret;
+}
+driver_init(sec_hmac_init);
diff --git a/core/drivers/crypto/hisilicon/sec_main.c b/core/drivers/crypto/hisilicon/sec_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..679356f65f8d112d2b5b6fe8913c731368aef2df
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_main.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright 2022-2024 HiSilicon Limited.
+ * Kunpeng hardware accelerator SEC module init.
+ */
+
+#include <initcall.h>
+#include <io.h>
+#include <malloc.h>
+#include <sys/queue.h>
+#include <trace.h>
+#include <util.h>
+
+#include "sec_main.h"
+
+#define AM_CFG_SINGLE_PORT_MAX_TRANS	0x300014
+#define SEC_CORE_INT_MASK		0x301000
+#define SEC_CORE_INT_SOURCE		0x301010
+#define SEC_RAS_CE_ENABLE		0x301050
+#define SEC_RAS_FE_ENABLE		0x301054
+#define SEC_RAS_NFE_ENABLE		0x301058
+#define SEC_MEM_START_INIT		0x301100
+#define SEC_MEM_INIT_DONE		0x301104
+#define SEC_CONTROL_REG			0x301200
+#define SEC_INTERFACE_USER_CTRL0	0x301220
+#define SEC_INTERFACE_USER_CTRL1	0x301224
+#define SEC_SAA_EN			0x301270
+#define SEC_BD_ERR_CHK_EN0		0x301380
+#define SEC_BD_ERR_CHK_EN1		0x301384
+#define SEC_BD_ERR_CHK_EN2		0x301388
+#define SEC_BD_ERR_CHK_EN3		0x30138c
+#define SEC_DYNAMIC_GATE_V3		0x30121c
+#define SEC_BD_ERR_CHK_EN2_V3		0x301508
+#define SEC_CORE_AUTO_GATE_V3		0x30212c
+#define SEC_INTERFACE_USER_CTRL0_V3	0x302220
+#define SEC_INTERFACE_USER_CTRL1_V3	0x302224
+#define SEC_SINGLE_PORT_MAX_TRANS	0x2060
+#define SEC_ABNML_INT_DISABLE		0x0
+#define SEC_RAS_CE_ENB_MASK		0x88
+#define SEC_RAS_FE_ENB			0x0
+#define SEC_RAS_NFE_ENB_MASK		0x177
+#define SEC_CLK_GATE_ENABLE		BIT(3)
+#define SEC_DYNAMIC_GATE_EN		0x7bff
+#define SEC_CORE_AUTO_GATE_EN		GENMASK_32(3, 0)
+#define SEC_TRNG_EN_MASK		BIT(8)
+#define SEC_SAA_ENABLE			0x17f
+#define SEC_SAA_ENABLE_V3		0xf
+#define SEC_BD_ERR_CHK0			0xefffffff
+#define SEC_BD_ERR_CHK1			0x7ffff7fd
+#define SEC_BD_ERR_CHK2			0xffff7fff
+#define SEC_BD_ERR_CHK3			0xffffbfff
+#define SEC_USER0_CFG			0x20200
+#define SEC_USER0_SMMU_NORMAL		(BIT(23) | BIT(15))
+#define SEC_USER1_CFG			0x12141214
+#define SEC_USER1_SMMU_NORMAL		(BIT(31) | BIT(23) | BIT(15) | BIT(7))
+#define SEC_USER0_CFG_V3		0x20200
+#define SEC_USER1_CFG_V3		0x8c494
+
+static SLIST_HEAD(, acc_device) sec_list = SLIST_HEAD_INITIALIZER(sec_list);
+
+struct hisi_qp *sec_create_qp(uint8_t sq_type)
+{
+	struct acc_device *sec_dev = NULL;
+	struct acc_device *cur_dev = NULL;
+	uint32_t free_qp_num = 0;
+	uint32_t max_qp_num = 0;
+
+	/* Find the SEC device with the most remaining qp numbers */
+	SLIST_FOREACH(cur_dev, &sec_list, link) {
+		if (cur_dev->qm.fun_type == HISI_QM_HW_PF)
+			free_qp_num = HISI_QM_PF_Q_NUM - cur_dev->qm.qp_in_used;
+		else
+			free_qp_num = HISI_QM_VF_Q_NUM - cur_dev->qm.qp_in_used;
+		if (free_qp_num > max_qp_num) {
+			max_qp_num = free_qp_num;
+			sec_dev = cur_dev;
+		}
+	}
+
+	if (!sec_dev) {
+		EMSG("No available sec device");
+		return NULL;
+	}
+
+	return hisi_qm_create_qp(&sec_dev->qm, sq_type);
+}
+
+static void sec_enable_clock_gate(struct hisi_qm *qm)
+{
+	if (qm->version == HISI_QM_HW_V2)
+		return;
+
+	io_setbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE);
+	io_write32(qm->io_base + SEC_DYNAMIC_GATE_V3, SEC_DYNAMIC_GATE_EN);
+	io_write32(qm->io_base + SEC_CORE_AUTO_GATE_V3, SEC_CORE_AUTO_GATE_EN);
+}
+
+static enum hisi_drv_status sec_engine_init(struct acc_device *sec_dev)
+{
+	struct hisi_qm *qm = &sec_dev->qm;
+	uint32_t val = 0;
+
+	if (qm->fun_type == HISI_QM_HW_VF)
+		return HISI_QM_DRVCRYPT_NO_ERR;
+
+	/* QM_HW_V2 version need to close clock gating */
+	io_clrbits32(qm->io_base + SEC_CONTROL_REG, SEC_CLK_GATE_ENABLE);
+
+	hisi_qm_dev_init(qm);
+
+	io_write32(qm->io_base + SEC_MEM_START_INIT, 0x1);
+	if (IO_READ32_POLL_TIMEOUT(qm->io_base + SEC_MEM_INIT_DONE, val,
+				   val & 0x1, POLL_PERIOD, POLL_TIMEOUT)) {
+		EMSG("Fail to init sec mem");
+		return HISI_QM_DRVCRYPT_ETMOUT;
+	}
+
+	io_setbits32(qm->io_base + SEC_CONTROL_REG, sec_dev->endian);
+
+	if (qm->version == HISI_QM_HW_V2) {
+		/* SMMU bypass */
+		io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0,
+			   SEC_USER0_CFG);
+		io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1,
+			   SEC_USER1_CFG);
+		io_write32(qm->io_base + AM_CFG_SINGLE_PORT_MAX_TRANS,
+			   SEC_SINGLE_PORT_MAX_TRANS);
+		io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE);
+		/* HW V2 enable SM4 extra mode, as CTR/ECB */
+		io_write32(qm->io_base + SEC_BD_ERR_CHK_EN0, SEC_BD_ERR_CHK0);
+		/* Enable SM4 xts mode multiple iv */
+		io_write32(qm->io_base + SEC_BD_ERR_CHK_EN1, SEC_BD_ERR_CHK1);
+		/* disable PBKDF2 len check */
+		io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2, SEC_BD_ERR_CHK2);
+		io_write32(qm->io_base + SEC_BD_ERR_CHK_EN3, SEC_BD_ERR_CHK3);
+	} else {
+		/* cmd_type is controlled by HAC subctrl, default normal */
+		io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL0_V3,
+			   SEC_USER0_CFG_V3);
+		io_write32(qm->io_base + SEC_INTERFACE_USER_CTRL1_V3,
+			   SEC_USER1_CFG_V3);
+		io_write32(qm->io_base + SEC_SAA_EN, SEC_SAA_ENABLE_V3);
+		/* disable PBKDF2 salt len check */
+		io_write32(qm->io_base + SEC_BD_ERR_CHK_EN2_V3,
+			   SEC_BD_ERR_CHK2);
+	}
+	io_write32(qm->io_base + SEC_RAS_CE_ENABLE, SEC_RAS_CE_ENB_MASK);
+	io_write32(qm->io_base + SEC_RAS_FE_ENABLE, SEC_RAS_FE_ENB);
+	io_write32(qm->io_base + SEC_RAS_NFE_ENABLE, SEC_RAS_NFE_ENB_MASK);
+	io_write32(qm->io_base + SEC_CORE_INT_MASK, SEC_ABNML_INT_DISABLE);
+
+	sec_enable_clock_gate(qm);
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_dev_status_check(struct hisi_qm *qm)
+{
+	uint32_t val = 0;
+
+	val = io_read32(qm->io_base + SEC_CORE_INT_SOURCE);
+	if (val & SEC_RAS_NFE_ENB_MASK) {
+		EMSG("SEC NFE RAS happened, need to reset");
+		return HISI_QM_DRVCRYPT_HW_EACCESS;
+	}
+
+	val = io_read32(qm->io_base + HISI_QM_ABNML_INT_SRC);
+	if (val) {
+		if (val & HISI_QM_SEC_NFE_INT_MASK)
+			EMSG("QM NFE RAS happened, need to reset");
+
+		if (val & HISI_QM_INVALID_DB) {
+			EMSG("QM invalid db happened, please check");
+			io_write32(qm->io_base + HISI_QM_ABNML_INT_SRC,
+				   HISI_QM_INVALID_DB);
+		}
+
+		return HISI_QM_DRVCRYPT_HW_EACCESS;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_qm_init(struct acc_device *sec_dev)
+{
+	struct hisi_qm *qm = &sec_dev->qm;
+
+	qm->io_base = (vaddr_t)phys_to_virt_io(sec_dev->io_base,
+						 sec_dev->io_size);
+	if (!qm->io_base) {
+		EMSG("Fail to get qm io_base");
+		return HISI_QM_DRVCRYPT_EFAULT;
+	}
+
+	qm->fun_type = sec_dev->fun_type;
+	qm->vfs_num = sec_dev->vfs_num;
+	qm->sqe_size = SEC_SQE_SIZE;
+	qm->sqe_log2_size = SEC_SQE_LOG2_SIZE;
+	if (qm->fun_type == HISI_QM_HW_PF) {
+		hisi_qm_get_version(qm);
+		DMSG("SEC hardware version is %#"PRIx32, qm->version);
+		qm->qp_base = HISI_QM_PF_Q_BASE;
+		qm->qp_num = HISI_QM_PF_Q_NUM;
+		qm->dev_status_check = sec_dev_status_check;
+	}
+
+	return hisi_qm_init(qm);
+}
+
+static struct acc_device *sec_alloc(void)
+{
+	struct acc_device *sec_dev = NULL;
+
+	sec_dev = calloc(1, sizeof(*sec_dev));
+	if (!sec_dev) {
+		EMSG("Fail to alloc sec_dev");
+		return NULL;
+	}
+
+	sec_dev->io_base = SEC_BAR;
+	sec_dev->io_size = SEC_SIZE;
+	sec_dev->fun_type = HISI_QM_HW_PF;
+	SLIST_INSERT_HEAD(&sec_list, sec_dev, link);
+
+	return sec_dev;
+}
+
+static void sec_free(struct acc_device *sec_dev)
+{
+	SLIST_REMOVE_HEAD(&sec_list, link);
+	free(sec_dev);
+}
+
+static TEE_Result sec_probe(void)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	struct acc_device *sec_dev = NULL;
+	struct hisi_qm *qm = NULL;
+
+	DMSG("SEC driver init start");
+	sec_dev = sec_alloc();
+	if (!sec_dev)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	qm = &sec_dev->qm;
+	ret = sec_qm_init(sec_dev);
+	if (ret) {
+		EMSG("Fail to init sec qm, ret=%d", ret);
+		goto err_with_pre_init;
+	}
+
+	ret = sec_engine_init(sec_dev);
+	if (ret) {
+		EMSG("fail to init engine, ret=%d", ret);
+		goto err_with_qm_init;
+	}
+
+	ret = hisi_qm_start(qm);
+	if (ret) {
+		EMSG("Fail to start qm, ret=%d", ret);
+		goto err_with_qm_init;
+	}
+
+	DMSG("SEC driver init done");
+	return TEE_SUCCESS;
+
+err_with_qm_init:
+	hisi_qm_uninit(qm);
+err_with_pre_init:
+	sec_free(sec_dev);
+
+	return TEE_ERROR_BAD_STATE;
+}
+
+driver_init(sec_probe);
diff --git a/core/drivers/crypto/hisilicon/sec_main.h b/core/drivers/crypto/hisilicon/sec_main.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed1c599f99a2d90131d914f4424536791a78dcdb
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_main.h
@@ -0,0 +1,352 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2022-2024 HiSilicon Limited. */
+#ifndef __SEC_MAIN_H
+#define __SEC_MAIN_H
+
+#include "hisi_qm.h"
+
+#ifdef CFG_HISILICON_ACC_V3
+#define SEC_BAR			0x160000000
+#else
+#define SEC_BAR			0x141800000
+#endif
+#define SEC_SIZE		0x400000
+
+#define SEC_SQE_SIZE		128
+#define SEC_SQE_LOG2_SIZE	7
+#define AES_KEYSIZE_128		16
+#define AES_KEYSIZE_192		24
+#define AES_KEYSIZE_256		32
+#define SEC_HW_TASK_DONE	0x1
+#define SEC_DONE_MASK		0x0001
+#define SEC_ICV_MASK		0x000E
+#define SEC_HW_ICV_ERR		0x2
+#define SEC_ENCODE_BYTES	4
+#define BYTE_BITS		0x8
+
+#define SEC_SCENE_OFFSET	3
+#define SEC_DE_OFFSET		1
+#define SEC_CIPHER_OFFSET	4
+#define SEC_AUTH_OFFSET		6
+#define SEC_CMODE_OFFSET	12
+#define SEC_CKEY_OFFSET		9
+#define SEC_AKEY_OFFSET		5
+#define SEC_AEAD_ALG_OFFSET	11
+#define SEC_HUK_OFFSET		4
+#define SEC_APAD_OFFSET		2
+
+#define SEC_DE_OFFSET_V3	9
+#define SEC_SCENE_OFFSET_V3	5
+#define SEC_CKEY_OFFSET_V3	13
+#define SEC_CALG_OFFSET_V3	4
+#define SEC_AKEY_OFFSET_V3	9
+#define SEC_MAC_OFFSET_V3	4
+#define SEC_AUTH_ALG_OFFSET_V3	15
+#define SEC_CIPHER_AUTH_V3	0xbf
+#define SEC_AUTH_CIPHER_V3	0x40
+#define SEC_AI_GEN_OFFSET_V3	2
+#define SEC_SEQ_OFFSET_V3	6
+#define SEC_ICV_LEN_OFFSET_V3	4
+#define SEC_DK_LEN_OFFSET_V3	16
+#define SEC_KEY_SEL_OFFSET_V3	21
+#define SEC_GET_FIELD(val, mask, shift) (((val) & (mask)) >> (shift))
+
+struct hisi_sec_sqe_type2 {
+	/*
+	 * mac_len: 0~4 bits
+	 * a_key_len: 5~10 bits
+	 * a_alg: 11~16 bits
+	 */
+	uint32_t mac_key_alg;
+
+	/*
+	 * c_icv_len: 0~5 bits
+	 * c_width: 6~8 bits
+	 * c_key_len: 9~11 bits
+	 * c_mode: 12~15 bits
+	 */
+	uint16_t icvw_kmode;
+
+	/* c_alg: 0~3 bits */
+	uint8_t c_alg;
+
+	uint8_t rsvd4;
+	/*
+	 * a_len: 0~23 bits
+	 * iv_offset_l: 24~31 bits
+	 */
+	uint32_t alen_ivllen;
+
+	/*
+	 * c_len: 0~23 bits
+	 * iv_offset_h: 24~31 bits
+	 */
+	uint32_t clen_ivhlen;
+
+	uint16_t auth_src_offset;
+	uint16_t cipher_src_offset;
+	uint16_t cs_ip_header_offset;
+	uint16_t cs_udp_header_offset;
+	uint16_t pass_word_len;
+	uint16_t dk_len;
+	uint8_t salt3;
+	uint8_t salt2;
+	uint8_t salt1;
+	uint8_t salt0;
+
+	uint16_t tag;
+	uint16_t rsvd5;
+
+	/*
+	 * c_pad_type: 0~3 bits
+	 * c_pad_len: 4~11 bits
+	 * c_pad_data_type: 12~15 bits
+	 */
+	uint16_t cph_pad;
+	/* c_pad_len_field: 0~1 bits */
+	uint16_t c_pad_len_field;
+
+	uint64_t long_a_data_len;
+	uint64_t a_ivin_addr;
+	uint64_t a_key_addr;
+	uint64_t mac_addr;
+	uint64_t c_ivin_addr;
+	uint64_t c_key_addr;
+	uint64_t data_src_addr;
+	uint64_t data_dst_addr;
+
+	/*
+	 * done: 0 bit
+	 * icv: 1~3 bits
+	 * csc: 4~6 bits
+	 * flag: 7~10 bits
+	 */
+	uint16_t done_flag;
+
+	uint8_t error_type;
+	uint8_t warning_type;
+	uint8_t mac_i3;
+	uint8_t mac_i2;
+	uint8_t mac_i1;
+	uint8_t mac_i0;
+	uint16_t check_sum_i;
+	uint8_t tls_pad_len_i;
+	uint8_t rsvd12;
+	uint32_t counter;
+};
+
+struct hisi_sec_sqe {
+	/*
+	 * type:  0~3 bits;
+	 * cipher: 4~5 bits;
+	 * auth: 6~7 bits;
+	 */
+	uint8_t type_auth_cipher;
+	/*
+	 * seq: 0 bits;
+	 * de: 1~2 bits;
+	 * scene: 3~6 bits;
+	 * src_addr_type: 7 bits;
+	 */
+	uint8_t sds_sa_type;
+	/*
+	 * src_addr_type: 0~1 bits not used now.
+	 * dst_addr_type: 2~4 bits;
+	 * mac_addr_type: 5~7 bits;
+	 */
+	uint8_t sdm_addr_type;
+
+	uint8_t rsvd0;
+	/*
+	 * nonce_len(type): 0~3 bits;
+	 * huk: 4 bit;
+	 * key_s: 5 bit
+	 * ci_gen: 6~7 bits
+	 */
+	uint8_t huk_ci_key;
+	/*
+	 * ai_gen: 0~1 bits;
+	 * a_pad : 2~3 bits;
+	 * c_s : 4~5 bits;
+	 */
+	uint8_t ai_apd_cs;
+	/*
+	 * rhf(type2): 0 bit;
+	 * c_key_type: 1~2 bits;
+	 * a_key_type: 3~4 bits
+	 * write_frame_len(type2): 5~7bits;
+	 */
+	uint8_t rca_key_frm;
+
+	uint8_t iv_tls_ld;
+	struct hisi_sec_sqe_type2 type2; /* the other scene */
+};
+
+struct bd3_stream_scene {
+	uint64_t c_ivin_addr;
+	uint64_t long_a_data_len;
+
+	/*
+	 * auth_pad: 0~1 bits
+	 * stream_protocol: 2~4 bits
+	 * reserved: 5~7 bits
+	 */
+	uint8_t auth_pad;
+	uint8_t plaintext_type;
+	uint16_t pad_len_1p3;
+} __packed __aligned(4);
+
+struct bd3_no_scene {
+	uint64_t c_ivin_addr;
+	uint32_t rsvd0;
+	uint32_t rsvd1;
+	uint32_t rsvd2;
+} __packed __aligned(4);
+
+struct bd3_pbkdf2_scene {
+	uint64_t c_ivin_addr;
+
+	/*
+	 * pbkdf2_salt_len: 0~23 bits
+	 * rsvd0: 24~31 bits
+	 */
+	uint32_t pbkdf2_salt_len;
+
+	/*
+	 * c_num: 0~23 bits
+	 * rsvd1: 24~31 bits
+	 */
+	uint32_t c_num;
+
+	/*
+	 * pass_word_len: 0~15 bits
+	 * dk_len: 16~31 bits
+	 */
+	uint32_t pass_word_dk_len;
+} __packed __aligned(4);
+
+struct hisi_sec_bd3_sqe {
+	/*
+	 * type: 0~3 bit
+	 * bd_invalid: 4 bit
+	 * scene: 5~8 bit
+	 * de: 9~10 bit
+	 * src_addr_type: 11~13 bit
+	 * dst_addr_type: 14~16 bit
+	 * mac_addr_type: 17~19 bit
+	 * reserved: 20~31 bits
+	 */
+	uint32_t bd_param;
+
+	/*
+	 * cipher: 0~1 bits
+	 * ci_gen: 2~3 bit
+	 * c_icv_len: 4~9 bit
+	 * c_width: 10~12 bits
+	 * c_key_len: 13~15 bits
+	 */
+	uint16_t c_icv_key;
+
+	/*
+	 * c_mode : 0~3 bits
+	 * c_alg : 4~7 bits
+	 */
+	uint8_t c_mode_alg;
+
+	/*
+	 * nonce_len : 0~3 bits
+	 * huk : 4 bits
+	 * cal_iv_addr_en : 5 bits
+	 * seq : 6 bits
+	 * reserved : 7 bits
+	 */
+	uint8_t huk_iv_seq;
+
+	uint64_t tag;
+	uint64_t data_src_addr;
+	uint64_t a_key_addr;
+	uint64_t a_ivin_addr;
+	uint64_t rsvd;
+	uint64_t c_key_addr;
+
+	/*
+	 * auth: 0~1 bits
+	 * ai_gen: 2~3 bits
+	 * mac_len: 4~8 bits
+	 * akey_len: 9~14 bits
+	 * a_alg: 15~20 bits
+	 * key_sel: 21~24 bits
+	 * ctr_count_mode/sm4_xts: 25~26 bits
+	 * sva_prefetch: 27 bits
+	 * key_wrap_num:28~30 bits
+	 * update_key: 31 bits
+	 */
+	uint32_t auth_mac_key;
+	uint32_t salt;
+	uint16_t auth_src_offset;
+	uint16_t cipher_src_offset;
+
+	/*
+	 * auth_len: 0~23 bit
+	 * auth_key_offset: 24~31 bits
+	 */
+	uint32_t a_len_key;
+
+	/*
+	 * cipher_len: 0~23 bit
+	 * auth_ivin_offset: 24~31 bits
+	 */
+	uint32_t c_len_ivin;
+	uint64_t data_dst_addr;
+	uint64_t mac_addr;
+	union {
+		struct bd3_stream_scene stream_scene;
+		struct bd3_no_scene no_scene;
+		struct bd3_pbkdf2_scene pbkdf2_scene;
+	};
+
+	/*
+	 * done: 0 bit
+	 * icv: 1~3 bit
+	 * csc: 4~6 bit
+	 * flag: 7~10 bit
+	 * reserved: 11~15 bit
+	 */
+	uint16_t done_flag;
+	uint8_t error_type;
+	uint8_t warning_type;
+	uint64_t kek_key_addr;
+	uint32_t counter;
+} __packed __aligned(4);
+
+enum sec_bd_type {
+	BD_TYPE1 = 0x1,
+	BD_TYPE2 = 0x2,
+	BD_TYPE3 = 0x3,
+};
+
+enum sec_bd_scene {
+	SCENE_NOTHING = 0x0,
+	SCENE_STREAM = 0x7,
+	SCENE_PBKDF2 = 0x8,
+};
+
+enum sec_auth_dir {
+	NO_AUTH,
+	AUTH_MAC_CALCULATE,
+	AUTH_MAC_VERIFY,
+};
+
+enum sec_bd_seq {
+	DATA_DST_ADDR_DISABLE,
+	DATA_DST_ADDR_ENABLE,
+};
+
+/*
+ * Create task queue pair for SEC.
+ *
+ * @sq_type Task type of the submmission queue.
+ */
+struct hisi_qp *sec_create_qp(uint8_t sq_type);
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/sec_pbkdf2.c b/core/drivers/crypto/hisilicon/sec_pbkdf2.c
new file mode 100644
index 0000000000000000000000000000000000000000..fdef550b59f88451a15768db77f5baeb3157fa06
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_pbkdf2.c
@@ -0,0 +1,349 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, HiSilicon Technologies Co., Ltd.
+ * Kunpeng hardware accelerator pbkdf2 implementation.
+ */
+
+#include <tee/tee_cryp_pbkdf2.h>
+#include <tee/tee_cryp_utl.h>
+
+#include "sec_main.h"
+#include "sec_pbkdf2.h"
+
+static enum hisi_drv_status sec_pbkdf2_parse_sqe(void *bd, void *msg __unused)
+{
+	struct hisi_sec_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->type2.done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->type2.error_type) {
+		EMSG("SEC do pbkdf2 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->type2.error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_pbkdf2_fill_sqe(void *bd, void *msg)
+{
+	struct sec_pbkdf2_msg *pbkdf2_msg = msg;
+	struct hisi_sec_sqe *sqe = bd;
+
+	sqe->type_auth_cipher = BD_TYPE2;
+	sqe->type_auth_cipher |= SHIFT_U32(AUTH_MAC_CALCULATE, SEC_AUTH_OFFSET);
+	sqe->sds_sa_type = SHIFT_U32(SCENE_PBKDF2, SEC_SCENE_OFFSET);
+
+	sqe->type2.mac_key_alg = SHIFT_U32(pbkdf2_msg->derive_type,
+					   SEC_AEAD_ALG_OFFSET);
+	/* mac_len = 1 and a_key_len = 1 only for hardware check */
+	sqe->type2.mac_key_alg |= 0x1;
+	sqe->type2.mac_key_alg |= SHIFT_U32(0x1, SEC_AKEY_OFFSET);
+
+	sqe->type2.alen_ivllen = pbkdf2_msg->salt_len;
+	sqe->type2.clen_ivhlen = pbkdf2_msg->c_num;
+	sqe->type2.pass_word_len = (uint16_t)pbkdf2_msg->key_len;
+	sqe->type2.dk_len = (uint16_t)pbkdf2_msg->out_len;
+
+	if (IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE))
+		sqe->huk_ci_key = SHIFT_U32(SEC_HUK_ENABLE, SEC_HUK_OFFSET);
+	else
+		sqe->type2.a_key_addr = pbkdf2_msg->key_dma;
+
+	sqe->type2.data_src_addr = pbkdf2_msg->salt_dma;
+	sqe->type2.mac_addr = pbkdf2_msg->out_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_pbkdf2_parse_bd3_sqe(void *bd,
+						     void *msg __unused)
+{
+	struct hisi_sec_bd3_sqe *sqe = bd;
+	uint16_t done = 0;
+
+	done = SEC_GET_FIELD(sqe->done_flag, SEC_DONE_MASK, 0);
+	if (done != SEC_HW_TASK_DONE || sqe->error_type) {
+		EMSG("SEC do pbkdf2 fail! done=%#"PRIx16", etype=%#"PRIx8,
+		     done, sqe->error_type);
+		return HISI_QM_DRVCRYPT_IN_EPARA;
+	}
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static enum hisi_drv_status sec_pbkdf2_fill_bd3_sqe(void *bd, void *msg)
+{
+	struct sec_pbkdf2_msg *pbkdf2_msg = msg;
+	struct hisi_sec_bd3_sqe *sqe = bd;
+
+	sqe->bd_param = BD_TYPE3 | SHIFT_U32(SCENE_PBKDF2, SEC_SCENE_OFFSET_V3);
+	sqe->auth_mac_key = AUTH_MAC_CALCULATE;
+	sqe->auth_mac_key |= SHIFT_U32(pbkdf2_msg->derive_type,
+				       SEC_AUTH_ALG_OFFSET_V3);
+	/* mac_len = 1 and a_key_len = 1 only for hardware check */
+	sqe->auth_mac_key |= SHIFT_U32(0x1, SEC_AKEY_OFFSET_V3);
+	sqe->auth_mac_key |= SHIFT_U32(0x1, SEC_MAC_OFFSET_V3);
+	sqe->a_len_key = pbkdf2_msg->salt_len;
+	sqe->pbkdf2_scene.pbkdf2_salt_len = pbkdf2_msg->salt_len;
+	sqe->pbkdf2_scene.pass_word_dk_len = pbkdf2_msg->key_len;
+	sqe->pbkdf2_scene.c_num = pbkdf2_msg->c_num;
+	sqe->pbkdf2_scene.pass_word_dk_len |= SHIFT_U32(pbkdf2_msg->out_len,
+						SEC_DK_LEN_OFFSET_V3);
+
+	if (IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE))
+		sqe->auth_mac_key |= SHIFT_U32(SEC_IMG_ROTKEY_AP,
+					       SEC_KEY_SEL_OFFSET_V3);
+	else
+		sqe->a_key_addr = pbkdf2_msg->key_dma;
+
+	sqe->data_src_addr = pbkdf2_msg->salt_dma;
+	sqe->mac_addr = pbkdf2_msg->out_dma;
+
+	return HISI_QM_DRVCRYPT_NO_ERR;
+}
+
+static TEE_Result sec_pbkdf2_do_task(void *msg)
+{
+	enum hisi_drv_status ret = HISI_QM_DRVCRYPT_NO_ERR;
+	TEE_Result res = TEE_SUCCESS;
+	struct hisi_qp *qp = NULL;
+
+	qp = sec_create_qp(HISI_QM_CHANNEL_TYPE1);
+	if (!qp) {
+		EMSG("Fail to create pbkdf2 qp");
+		return TEE_ERROR_BUSY;
+	}
+
+	if (qp->qm->version == HISI_QM_HW_V2) {
+		qp->fill_sqe = sec_pbkdf2_fill_sqe;
+		qp->parse_sqe = sec_pbkdf2_parse_sqe;
+	} else {
+		qp->fill_sqe = sec_pbkdf2_fill_bd3_sqe;
+		qp->parse_sqe = sec_pbkdf2_parse_bd3_sqe;
+	}
+
+	ret = hisi_qp_send(qp, msg);
+	if (ret) {
+		EMSG("Fail to send task, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+	ret = hisi_qp_recv_sync(qp, msg);
+	if (ret) {
+		EMSG("Recv task error, ret=%d", ret);
+		res = TEE_ERROR_BAD_STATE;
+		goto done_proc;
+	}
+
+done_proc:
+	hisi_qm_release_qp(qp);
+
+	return res;
+}
+
+static TEE_Result sec_pbkdf2_dk_iteration_check(uint32_t alg, uint32_t c_num,
+						size_t dk_len)
+{
+	TEE_Result ret = TEE_SUCCESS;
+	size_t hash_len = 0;
+	size_t t_num = 0;
+	size_t time = 0;
+
+	if (dk_len > SEC_MAX_DK_LEN) {
+		EMSG("Unsupported derived key len %zu", dk_len);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (c_num > SEC_MAX_ITERATION_NUM) {
+		EMSG("Unsupported iteration count %"PRIu32, c_num);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (c_num <= SEC_CRITICAL_ITERATION_NUM)
+		return TEE_SUCCESS;
+
+	ret = tee_alg_get_digest_size(alg, &hash_len);
+	if (ret || hash_len == 0) {
+		EMSG("Fail to get digest size");
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	t_num = ROUNDUP_DIV(dk_len, hash_len);
+
+	if (alg < TEE_ALG_HMAC_SHA384 || alg > TEE_ALG_HMAC_SHA512)
+		time = t_num * SEC_PER_BLOCK_TIME1_NS * c_num;
+	else
+		time = t_num * SEC_PER_BLOCK_TIME2_NS * c_num;
+
+	if (time > SEC_MAX_TIMEOUT_NS) {
+		EMSG("Time %zu is more than sec max timeout", time);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_pbkdf2_params_check(uint32_t hash_id, size_t password_len,
+					  size_t salt_len, uint32_t c_num,
+					  size_t derived_key_len)
+{
+	uint32_t alg = TEE_ALG_HMAC_ALGO(hash_id);
+
+	if (!password_len || !salt_len || !c_num || !derived_key_len) {
+		EMSG("Invalid input parameters");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if ((alg < TEE_ALG_HMAC_SHA384 || alg > TEE_ALG_HMAC_SHA512) &&
+	    (password_len > (SEC_MAX_PASSWORD_LEN / 2))) {
+		EMSG("Password_len %zu does not match alg %#"PRIx32,
+		     password_len, alg);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (password_len > SEC_MAX_PASSWORD_LEN) {
+		EMSG("Unsupported password len %zu", password_len);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	if (salt_len > SEC_MAX_SALT_LEN) {
+		EMSG("Unsupported salt len %zu", salt_len);
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	return sec_pbkdf2_dk_iteration_check(alg, c_num, derived_key_len);
+}
+
+static TEE_Result sec_pbkdf2_set_derive_type(uint32_t hash_id,
+					     struct sec_pbkdf2_msg *msg)
+{
+	uint32_t alg = TEE_ALG_HMAC_ALGO(hash_id);
+
+	switch (alg) {
+	case TEE_ALG_HMAC_SHA1:
+		msg->derive_type = SEC_HMAC_SHA1;
+		break;
+	case TEE_ALG_HMAC_SHA224:
+		msg->derive_type = SEC_HMAC_SHA224;
+		break;
+	case TEE_ALG_HMAC_SHA256:
+		msg->derive_type = SEC_HMAC_SHA256;
+		break;
+	case TEE_ALG_HMAC_SHA384:
+		msg->derive_type = SEC_HMAC_SHA384;
+		break;
+	case TEE_ALG_HMAC_SHA512:
+		msg->derive_type = SEC_HMAC_SHA512;
+		break;
+	case TEE_ALG_HMAC_SM3:
+		msg->derive_type = SEC_HMAC_SM3;
+		break;
+	default:
+		EMSG("Invalid hamc alg type %#"PRIx32, alg);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result sec_pbkdf2_set_buf(const uint8_t *password,
+				     const uint8_t *salt,
+				     struct sec_pbkdf2_msg *msg)
+{
+	msg->key_dma = virt_to_phys(msg->base_key);
+	if (!msg->key_dma) {
+		EMSG("Fail to get key dma addr");
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	msg->salt_dma = virt_to_phys(msg->salt);
+	if (!msg->salt_dma) {
+		EMSG("Fail to get salt dma addr");
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	msg->out_dma = virt_to_phys(msg->out);
+	if (!msg->out_dma) {
+		EMSG("Fail to get out dma addr");
+		return TEE_ERROR_BAD_STATE;
+	}
+
+	if (password)
+		memcpy(msg->base_key, password, msg->key_len);
+
+	memcpy(msg->salt, salt, msg->salt_len);
+
+	return TEE_SUCCESS;
+}
+
+static void sec_pbkdf2_clean_buf(struct sec_pbkdf2_msg *msg)
+{
+	memzero_explicit(msg->base_key, msg->key_len);
+	memzero_explicit(msg->salt, msg->salt_len);
+}
+
+static TEE_Result sec_pbkdf2_msg_init(uint32_t hash_id, size_t password_len,
+				      size_t salt_len, size_t derived_key_len,
+				      uint32_t iteration_count,
+				      struct sec_pbkdf2_msg *msg)
+{
+	msg->key_len = password_len;
+	msg->salt_len = salt_len;
+	msg->out_len = derived_key_len;
+	msg->c_num = iteration_count;
+	return sec_pbkdf2_set_derive_type(hash_id, msg);
+}
+
+TEE_Result tee_cryp_pbkdf2(uint32_t hash_id, const uint8_t *password,
+			   size_t password_len, const uint8_t *salt,
+			   size_t salt_len, uint32_t iteration_count,
+			   uint8_t *derived_key, size_t derived_key_len)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+	struct sec_pbkdf2_msg *msg = NULL;
+
+	if (!IS_ENABLED(CFG_CRYPTO_HW_PBKDF2_WITH_EFUSE) && !password) {
+		EMSG("Password buf is NULL");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (!salt || !derived_key) {
+		EMSG("Invalid pbkdf2 buf");
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	ret = sec_pbkdf2_params_check(hash_id, password_len, salt_len,
+				      iteration_count, derived_key_len);
+	if (ret)
+		return ret;
+
+	msg = calloc(1, sizeof(*msg));
+	if (!msg) {
+		EMSG("Fail to calloc msg");
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	ret = sec_pbkdf2_msg_init(hash_id, password_len, salt_len,
+				  derived_key_len, iteration_count, msg);
+	if (ret)
+		goto free_msg;
+
+	ret = sec_pbkdf2_set_buf(password, salt, msg);
+	if (ret)
+		goto free_msg;
+
+	ret = sec_pbkdf2_do_task(msg);
+	if (ret)
+		goto clean_buf;
+
+	memcpy(derived_key, msg->out, msg->out_len);
+
+clean_buf:
+	sec_pbkdf2_clean_buf(msg);
+free_msg:
+	free(msg);
+
+	return ret;
+}
diff --git a/core/drivers/crypto/hisilicon/sec_pbkdf2.h b/core/drivers/crypto/hisilicon/sec_pbkdf2.h
new file mode 100644
index 0000000000000000000000000000000000000000..644dbe40fcf24cf9f84fedb14c6d8b6362047503
--- /dev/null
+++ b/core/drivers/crypto/hisilicon/sec_pbkdf2.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/* Copyright (c) 2022-2024 HiSilicon Limited. */
+
+#ifndef __SEC_PBKDF2_H__
+#define __SEC_PBKDF2_H__
+
+#define SEC_MAX_SALT_LEN		1024
+#define SEC_MAX_PASSWORD_LEN		128
+#define SEC_MAX_DK_LEN			512
+#define SEC_MAX_ITERATION_NUM		16777215
+#define SEC_HMAC_SHA1			0x10
+#define SEC_HMAC_SHA256			0x11
+#define SEC_HMAC_SHA224			0x13
+#define SEC_HMAC_SHA384			0x14
+#define SEC_HMAC_SHA512			0x15
+#define SEC_HMAC_SM3			0x26
+#define SEC_HUK_ENABLE			0x1
+#define SEC_IMG_ROTKEY_AP		0x6
+#define SEC_CRITICAL_ITERATION_NUM	1000000
+#define SEC_PER_BLOCK_TIME1_NS		(3 * 48)
+#define SEC_PER_BLOCK_TIME2_NS		(3 * 68)
+#define SEC_MAX_TIMEOUT_NS		4000000000
+
+struct sec_pbkdf2_msg {
+	uint8_t salt[SEC_MAX_SALT_LEN];
+	uint8_t base_key[SEC_MAX_PASSWORD_LEN];
+	uint8_t out[SEC_MAX_DK_LEN];
+	uintptr_t salt_dma;
+	uintptr_t key_dma;
+	uintptr_t out_dma;
+	uint32_t salt_len;
+	uint32_t key_len;
+	uint32_t out_len;
+	uint32_t c_num;
+	uint32_t derive_type;
+};
+
+#endif
diff --git a/core/drivers/crypto/hisilicon/sub.mk b/core/drivers/crypto/hisilicon/sub.mk
index 9a1747084ffdebe8fa20127a387a4d1824f23bdb..0e1030eceb5f832d869a45305da8a5a2b480a9f0 100644
--- a/core/drivers/crypto/hisilicon/sub.mk
+++ b/core/drivers/crypto/hisilicon/sub.mk
@@ -1,3 +1,12 @@
-incdirs-y += include
-
 srcs-y += hisi_qm.c
+srcs-y += sec_main.c
+srcs-y += sec_hash.c
+srcs-y += sec_hmac.c
+srcs-y += sec_cipher.c
+srcs-y += sec_authenc.c
+srcs-y += sec_pbkdf2.c
+srcs-$(CFG_HISILICON_ACC_V3) += hpre_main.c
+srcs-$(CFG_HISILICON_ACC_V3) += hpre_dh.c
+srcs-$(CFG_HISILICON_ACC_V3) += hpre_ecc.c
+srcs-$(CFG_HISILICON_ACC_V3) += hpre_montgomery.c
+srcs-$(CFG_HISILICON_ACC_V3) += hpre_rsa.c
diff --git a/core/drivers/crypto/se050/adaptors/include/se050.h b/core/drivers/crypto/se050/adaptors/include/se050.h
index e5f8f66225466fcc5642ebb92ec2492f0ab67873..85b613bca7abd26e5dd1f0319b4ed22139dcf0c7 100644
--- a/core/drivers/crypto/se050/adaptors/include/se050.h
+++ b/core/drivers/crypto/se050/adaptors/include/se050.h
@@ -34,6 +34,7 @@
 #define SE051C_ID 0xA8FA
 #define SE051W_ID 0xA739
 #define SE050F_ID 0xA92A
+#define SE052F2_ID 0xB501
 
 TEE_Result se050_core_early_init(struct se050_scp_key *keys);
 
diff --git a/core/drivers/crypto/se050/adaptors/utils/scp_config.c b/core/drivers/crypto/se050/adaptors/utils/scp_config.c
index 493dede8419f884a288a80fea1b381baec270071..fcdcf1a3ff0de6ecd74c3cac6e4bf74b477a4f87 100644
--- a/core/drivers/crypto/se050/adaptors/utils/scp_config.c
+++ b/core/drivers/crypto/se050/adaptors/utils/scp_config.c
@@ -43,6 +43,7 @@ static bool scp03_enabled;
 #define SE051C 12
 #define SE051W 13
 #define SE050F 14
+#define SE052F2 15
 
 static const struct se050_scp_key se050_default_keys[] = {
 	[SE050A1] = {
@@ -165,6 +166,14 @@ static const struct se050_scp_key se050_default_keys[] = {
 		.dek = { 0x86, 0x95, 0x93, 0x23, 0x98, 0x54, 0xDC, 0x0D,
 			0x86, 0x99, 0x00, 0x50, 0x0C, 0xA7, 0x9C, 0x15, },
 	},
+	[SE052F2] = {
+		.enc = { 0x3a, 0xe4, 0x41, 0xc7, 0x47, 0xe3, 0x2e, 0xbc,
+			0x16, 0xb3, 0xbb, 0x2d, 0x84, 0x3c, 0x6d, 0xd8 },
+		.mac = { 0x6c, 0x18, 0xf3, 0xd0, 0x8f, 0xee, 0x1c, 0xb9,
+			0x6a, 0x3c, 0x8d, 0xe5, 0xd3, 0x53, 0x8a, 0xaa },
+		.dek = { 0xb0, 0xe6, 0xa5, 0x69, 0x7d, 0xbd, 0x92, 0x92,
+			0x43, 0xa4, 0x82, 0xcf, 0x9e, 0x4d, 0x65, 0x22 },
+	},
 };
 
 static sss_status_t get_id_from_ofid(uint32_t ofid, uint32_t *id)
@@ -215,6 +224,9 @@ static sss_status_t get_id_from_ofid(uint32_t ofid, uint32_t *id)
 	case SE050F_ID:
 		*id = SE050F;
 		break;
+	case SE052F2_ID:
+		*id = SE052F2;
+		break;
 	default:
 		return kStatus_SSS_Fail;
 	}
diff --git a/core/drivers/crypto/se050/core/rsa.c b/core/drivers/crypto/se050/core/rsa.c
index 475d2b99a8e878b3e6972231baa7e595f36e6931..6f89a8f3b12c4a3dda25dd572823be64fef65aa2 100644
--- a/core/drivers/crypto/se050/core/rsa.c
+++ b/core/drivers/crypto/se050/core/rsa.c
@@ -689,6 +689,7 @@ static TEE_Result encrypt_fallback(struct drvcrypt_rsa_ed *p)
 						       p->key.key,
 						       p->label.data,
 						       p->label.length,
+						       p->mgf_algo,
 						       p->message.data,
 						       p->message.length,
 						       p->cipher.data,
@@ -720,7 +721,8 @@ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data)
 				  &rsa_data->cipher.length);
 
 	case DRVCRYPT_RSA_OAEP:
-		if (rsa_data->hash_algo != TEE_ALG_SHA1)
+		if (rsa_data->hash_algo != TEE_ALG_SHA1 ||
+		    rsa_data->hash_algo != rsa_data->mgf_algo)
 			return encrypt_fallback(rsa_data);
 
 		return encrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1,
@@ -764,6 +766,7 @@ static TEE_Result decrypt_fallback(struct drvcrypt_rsa_ed *p)
 						       p->key.key,
 						       p->label.data,
 						       p->label.length,
+						       p->mgf_algo,
 						       p->cipher.data,
 						       p->cipher.length,
 						       p->message.data,
@@ -798,7 +801,8 @@ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data)
 				  &rsa_data->message.length);
 
 	case DRVCRYPT_RSA_OAEP:
-		if (rsa_data->hash_algo != TEE_ALG_SHA1)
+		if (rsa_data->hash_algo != TEE_ALG_SHA1 ||
+		    rsa_data->hash_algo != rsa_data->mgf_algo)
 			return decrypt_fallback(rsa_data);
 
 		return decrypt_es(TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1,
diff --git a/core/drivers/crypto/se050/core/storage.c b/core/drivers/crypto/se050/core/storage.c
index 0f937b81304d71c7830985136adf0e192794b92f..ad51e79ef581c78ec85de4c6c6406f8c15493a42 100644
--- a/core/drivers/crypto/se050/core/storage.c
+++ b/core/drivers/crypto/se050/core/storage.c
@@ -71,21 +71,21 @@ TEE_Result crypto_storage_obj_del(struct tee_obj *o)
 		return TEE_SUCCESS;
 
 	status = sss_se05x_key_object_init(&k_object, se050_kstore);
-	if (status != kStatus_SSS_Success) {
-		ret = TEE_ERROR_BAD_STATE;
-		goto out;
-	}
+	if (status != kStatus_SSS_Success)
+		return TEE_ERROR_BAD_STATE;
 
 	status = sss_se05x_key_object_get_handle(&k_object, val);
 	if (status != kStatus_SSS_Success) {
-		EMSG("se05x: can not communicate with the secure element");
+		if (IS_ENABLED(CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR))
+			EMSG("se05x: key not found in secure element");
 		ret = TEE_ERROR_BAD_STATE;
 		goto out;
 	}
 
 	status = sss_se05x_key_store_erase_key(se050_kstore, &k_object);
 	if (status != kStatus_SSS_Success) {
-		EMSG("se05x: can not communicate with the secure element");
+		if (IS_ENABLED(CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR))
+			EMSG("se05x: key can't be removed from secure element");
 		ret = TEE_ERROR_BAD_STATE;
 		goto out;
 	}
diff --git a/core/drivers/crypto/se050/crypto.mk b/core/drivers/crypto/se050/crypto.mk
index 473cd82aab6f0f9eed5ac16df4625db2990de9ff..8c4adf0696569665b8f983b3cca1521e809ff08f 100644
--- a/core/drivers/crypto/se050/crypto.mk
+++ b/core/drivers/crypto/se050/crypto.mk
@@ -29,7 +29,7 @@ CFG_CORE_SE05X_INIT_NVM ?= n
 # confirmation from the SE that the NVM object has been removed.
 CFG_CORE_SE05X_BLOCK_OBJ_DEL_ON_ERROR ?= n
 # Select the SE05X applet version for aligning the built-in features
-+CFG_CORE_SE05X_VER ?= 03_XX
+CFG_CORE_SE05X_VER ?= 03_XX
 
 # I2C bus baudrate (depends on SoC)
 CFG_CORE_SE05X_BAUDRATE ?= 3400000
diff --git a/core/drivers/crypto/stm32/authenc.c b/core/drivers/crypto/stm32/authenc.c
index 4ff320c3f39bcf33751843fbaec8a8231ff3078b..bf305b02f5fd5186b589532499851305cc38ba62 100644
--- a/core/drivers/crypto/stm32/authenc.c
+++ b/core/drivers/crypto/stm32/authenc.c
@@ -355,15 +355,15 @@ static TEE_Result stm32_ae_allocate(void **ctx, uint32_t algo)
  * Registration of the Authenc Driver
  */
 static struct drvcrypt_authenc driver_authenc = {
-	.alloc_ctx = &stm32_ae_allocate,
-	.free_ctx = &stm32_ae_free,
-	.init = &stm32_ae_initialize,
-	.update_aad = &stm32_ae_update_aad,
-	.update_payload = &stm32_ae_update_payload,
-	.enc_final = &stm32_ae_enc_final,
-	.dec_final = &stm32_ae_dec_final,
-	.final = &stm32_ae_final,
-	.copy_state = &stm32_ae_copy_state,
+	.alloc_ctx = stm32_ae_allocate,
+	.free_ctx = stm32_ae_free,
+	.init = stm32_ae_initialize,
+	.update_aad = stm32_ae_update_aad,
+	.update_payload = stm32_ae_update_payload,
+	.enc_final = stm32_ae_enc_final,
+	.dec_final = stm32_ae_dec_final,
+	.final = stm32_ae_final,
+	.copy_state = stm32_ae_copy_state,
 };
 
 TEE_Result stm32_register_authenc(void)
diff --git a/core/drivers/crypto/stm32/cipher.c b/core/drivers/crypto/stm32/cipher.c
index ec66c4f6f75da001113f4d107abb1cd5605299d5..a9a28e0bd8146626fa615f42894452a609001bea 100644
--- a/core/drivers/crypto/stm32/cipher.c
+++ b/core/drivers/crypto/stm32/cipher.c
@@ -27,6 +27,9 @@ struct cryp_ctx {
 struct saes_ctx {
 	struct stm32_saes_context ctx;
 	enum stm32_saes_chaining_mode algo;
+	/* Fallback to software implementation on 192bit AES key */
+	bool use_fallback;
+	struct crypto_cipher_ctx *fallback_ctx;
 };
 
 /*
@@ -47,6 +50,8 @@ struct ip_cipher_ops {
 			   const uint8_t *iv, size_t iv_len);
 	TEE_Result (*update)(union ip_ctx *ctx, bool last_block, uint8_t *src,
 			     uint8_t *dst, size_t len);
+	void (*final)(union ip_ctx *ctx);
+	void (*copy_state)(union ip_ctx *dst_ctx, union ip_ctx *src_ctx);
 };
 
 struct stm32_cipher_ctx {
@@ -87,6 +92,17 @@ static TEE_Result cryp_update(union ip_ctx *ip_ctx, bool last_block,
 	return stm32_cryp_update(&ip_ctx->cryp.ctx, last_block, src, dst, len);
 }
 
+static void cryp_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx)
+{
+	memcpy(&dst_ip_ctx->cryp, &src_ip_ctx->cryp, sizeof(dst_ip_ctx->cryp));
+}
+
+static const struct ip_cipher_ops cryp_ops = {
+	.init = cryp_init,
+	.update = cryp_update,
+	.copy_state = cryp_copy_state,
+};
+
 static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt,
 			    const uint8_t *key, size_t key_len,
 			    const uint8_t *iv, size_t iv_len)
@@ -96,6 +112,34 @@ static TEE_Result saes_init(union ip_ctx *ip_ctx, bool is_decrypt,
 	if (!IS_ENABLED(CFG_STM32_SAES))
 		return TEE_ERROR_NOT_IMPLEMENTED;
 
+	if (key_len == AES_KEYSIZE_192) {
+		struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
+		TEE_OperationMode mode = TEE_MODE_ILLEGAL_VALUE;
+		TEE_Result res = TEE_ERROR_GENERIC;
+
+		if (!IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) {
+			EMSG("STM32 SAES does not support 192bit keys");
+
+			return TEE_ERROR_NOT_IMPLEMENTED;
+		}
+
+		if (is_decrypt)
+			mode = TEE_MODE_DECRYPT;
+		else
+			mode = TEE_MODE_ENCRYPT;
+
+		res = ctx->ops->init(ctx, mode, key, key_len, NULL, 0, iv,
+				     iv_len);
+		if (res)
+			return res;
+
+		ip_ctx->saes.use_fallback = true;
+
+		return TEE_SUCCESS;
+	}
+
+	ip_ctx->saes.use_fallback = false;
+
 	return stm32_saes_init(&ip_ctx->saes.ctx, is_decrypt, ip_ctx->saes.algo,
 			       key_sel, key, key_len, iv, iv_len);
 }
@@ -106,17 +150,48 @@ static TEE_Result saes_update(union ip_ctx *ip_ctx, bool last_block,
 	if (!IS_ENABLED(CFG_STM32_SAES))
 		return TEE_ERROR_NOT_IMPLEMENTED;
 
+	if (ip_ctx->saes.use_fallback) {
+		struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
+
+		assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
+
+		return ctx->ops->update(ctx, last_block, src, len, dst);
+	}
+
 	return stm32_saes_update(&ip_ctx->saes.ctx, last_block, src, dst, len);
 }
 
-const struct ip_cipher_ops cryp_ops = {
-	.init = cryp_init,
-	.update = cryp_update,
-};
+static void saes_final(union ip_ctx *ip_ctx)
+{
+	struct crypto_cipher_ctx *ctx = ip_ctx->saes.fallback_ctx;
+
+	if (ip_ctx->saes.use_fallback) {
+		assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
+		ctx->ops->final(ctx);
+	}
+}
+
+static void saes_copy_state(union ip_ctx *dst_ip_ctx, union ip_ctx *src_ip_ctx)
+{
+	struct saes_ctx *src_ctx = &src_ip_ctx->saes;
+	struct crypto_cipher_ctx *fb_ctx = src_ctx->fallback_ctx;
+
+	memcpy(&dst_ip_ctx->saes.ctx, &src_ctx->ctx, sizeof(src_ctx->ctx));
+
+	dst_ip_ctx->saes.algo = src_ctx->algo;
+	dst_ip_ctx->saes.use_fallback = src_ctx->use_fallback;
 
-const struct ip_cipher_ops saes_ops = {
+	if (src_ctx->use_fallback) {
+		assert(IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK));
+		fb_ctx->ops->copy_state(dst_ip_ctx->saes.fallback_ctx, fb_ctx);
+	}
+}
+
+static const struct ip_cipher_ops saes_ops = {
 	.init = saes_init,
 	.update = saes_update,
+	.final = saes_final,
+	.copy_state = saes_copy_state,
 };
 
 static struct stm32_cipher_ctx *
@@ -146,22 +221,19 @@ static TEE_Result stm32_cipher_update(struct drvcrypt_cipher_update *dupdate)
 }
 
 static void stm32_cipher_final(void *ctx __unused)
-{
-}
-
-static void stm32_cipher_free(void *ctx)
 {
 	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
 
-	free(c);
+	if (c->ops->final)
+		c->ops->final(&c->ip_ctx);
 }
 
 static void stm32_cipher_copy_state(void *dst_ctx, void *src_ctx)
 {
-	struct stm32_cipher_ctx *src = to_stm32_cipher_ctx(src_ctx);
-	struct stm32_cipher_ctx *dst = to_stm32_cipher_ctx(dst_ctx);
+	struct stm32_cipher_ctx *src_c = to_stm32_cipher_ctx(src_ctx);
+	struct stm32_cipher_ctx *dst_c = to_stm32_cipher_ctx(dst_ctx);
 
-	memcpy(dst, src, sizeof(*dst));
+	src_c->ops->copy_state(&dst_c->ip_ctx, &src_c->ip_ctx);
 }
 
 static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
@@ -179,27 +251,6 @@ static TEE_Result alloc_cryp_ctx(void **ctx, enum stm32_cryp_algo_mode algo)
 	return TEE_SUCCESS;
 }
 
-static TEE_Result alloc_saes_ctx(void **ctx, enum stm32_saes_chaining_mode algo)
-{
-	struct stm32_cipher_ctx *c = calloc(1, sizeof(*c));
-
-	if (!c)
-		return TEE_ERROR_OUT_OF_MEMORY;
-
-	FMSG("Using SAES %d", algo);
-	c->ip_ctx.saes.algo = algo;
-	c->ops = &saes_ops;
-	*ctx = &c->c_ctx;
-
-	return TEE_SUCCESS;
-}
-
-/*
- * Allocate the SW cipher data context for CRYP peripheral.
- *
- * @ctx   [out] Caller context variable
- * @algo  Algorithm ID of the context
- */
 static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo)
 {
 	/*
@@ -225,49 +276,102 @@ static TEE_Result stm32_cryp_cipher_allocate(void **ctx, uint32_t algo)
 	}
 }
 
-/*
- * Allocate the SW cipher data context for SAES peripheral.
- *
- * @ctx   [out] Caller context variable
- * @algo  Algorithm ID of the context
- */
+static void stm32_cryp_cipher_free(void *ctx)
+{
+	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
+
+	free(c);
+}
+
 static TEE_Result stm32_saes_cipher_allocate(void **ctx, uint32_t algo)
 {
-	/*
-	 * Convert TEE_ALGO id to internal id
-	 */
+	enum stm32_saes_chaining_mode saes_algo = STM32_SAES_MODE_ECB;
+	struct crypto_cipher_ctx *fallback_ctx = NULL;
+	struct stm32_cipher_ctx *saes_ctx = NULL;
+	TEE_Result res = TEE_SUCCESS;
+
 	switch (algo) {
 	case TEE_ALG_AES_ECB_NOPAD:
-		return alloc_saes_ctx(ctx, STM32_SAES_MODE_ECB);
+		saes_algo = STM32_SAES_MODE_ECB;
+		if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
+			res = crypto_aes_ecb_alloc_ctx(&fallback_ctx);
+		break;
 	case TEE_ALG_AES_CBC_NOPAD:
-		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CBC);
+		saes_algo = STM32_SAES_MODE_CBC;
+		if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
+			res = crypto_aes_cbc_alloc_ctx(&fallback_ctx);
+		break;
 	case TEE_ALG_AES_CTR:
-		return alloc_saes_ctx(ctx, STM32_SAES_MODE_CTR);
+		saes_algo = STM32_SAES_MODE_CTR;
+		if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
+			res = crypto_aes_ctr_alloc_ctx(&fallback_ctx);
+		break;
 	default:
 		return TEE_ERROR_NOT_IMPLEMENTED;
 	}
+	if (res)
+		return res;
+
+	saes_ctx = calloc(1, sizeof(*saes_ctx));
+	if (!saes_ctx) {
+		if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK))
+			fallback_ctx->ops->free_ctx(fallback_ctx);
+
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	FMSG("Using SAES %d", saes_algo);
+	saes_ctx->ip_ctx.saes.algo = saes_algo;
+	saes_ctx->ops = &saes_ops;
+	saes_ctx->ip_ctx.saes.fallback_ctx = fallback_ctx;
+	*ctx = &saes_ctx->c_ctx;
+
+	return TEE_SUCCESS;
+}
+
+static void stm32_saes_cipher_free(void *ctx)
+{
+	struct stm32_cipher_ctx *c = to_stm32_cipher_ctx(ctx);
+
+	if (IS_ENABLED(CFG_STM32_SAES_SW_FALLBACK)) {
+		struct crypto_cipher_ctx *fb_ctx = c->ip_ctx.saes.fallback_ctx;
+
+		fb_ctx->ops->free_ctx(fb_ctx);
+	}
+
+	free(c);
 }
 
 static struct drvcrypt_cipher driver_cipher_cryp = {
-	.alloc_ctx = &stm32_cryp_cipher_allocate,
-	.free_ctx = &stm32_cipher_free,
-	.init = &stm32_cipher_initialize,
-	.update = &stm32_cipher_update,
-	.final = &stm32_cipher_final,
-	.copy_state = &stm32_cipher_copy_state,
+	.alloc_ctx = stm32_cryp_cipher_allocate,
+	.free_ctx = stm32_cryp_cipher_free,
+	.init = stm32_cipher_initialize,
+	.update = stm32_cipher_update,
+	.final = stm32_cipher_final,
+	.copy_state = stm32_cipher_copy_state,
 };
 
 static struct drvcrypt_cipher driver_cipher_saes = {
-	.alloc_ctx = &stm32_saes_cipher_allocate,
-	.free_ctx = &stm32_cipher_free,
-	.init = &stm32_cipher_initialize,
-	.update = &stm32_cipher_update,
-	.final = &stm32_cipher_final,
-	.copy_state = &stm32_cipher_copy_state,
+	.alloc_ctx = stm32_saes_cipher_allocate,
+	.free_ctx = stm32_saes_cipher_free,
+	.init = stm32_cipher_initialize,
+	.update = stm32_cipher_update,
+	.final = stm32_cipher_final,
+	.copy_state = stm32_cipher_copy_state,
 };
 
 TEE_Result stm32_register_cipher(enum stm32_cipher_ip_id cipher_ip)
 {
+	void *op = drvcrypt_get_ops(CRYPTO_CIPHER);
+
+	if (op) {
+		EMSG("%s already registered for CRYPTO_CIPHER",
+		     op == &driver_cipher_cryp ? "CRYP peripheral" :
+		     op == &driver_cipher_saes ? "SAES peripheral" :
+		     "Other cipher driver");
+		return TEE_ERROR_GENERIC;
+	}
+
 	if (cipher_ip == SAES_IP)
 		return drvcrypt_register_cipher(&driver_cipher_saes);
 	else if (cipher_ip == CRYP_IP)
diff --git a/core/drivers/crypto/stm32/stm32_cryp.c b/core/drivers/crypto/stm32/stm32_cryp.c
index 70ad4e38da1585c3b8260e25fe57354592caef4e..4dc952c1f06852150032630f54cb37898257d617 100644
--- a/core/drivers/crypto/stm32/stm32_cryp.c
+++ b/core/drivers/crypto/stm32/stm32_cryp.c
@@ -14,6 +14,7 @@
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
 #include <kernel/mutex.h>
+#include <kernel/pm.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <stdint.h>
@@ -84,6 +85,7 @@
 
 #define CRYP_TIMEOUT_US			1000000U
 #define TIMEOUT_US_1MS			1000U
+#define CRYP_RESET_DELAY_US		U(2)
 
 /* CRYP control register fields */
 #define _CRYP_CR_RESET_VALUE		0x0U
@@ -322,14 +324,26 @@ static TEE_Result __must_check read_block(struct stm32_cryp_context *ctx,
 	return read_align_block(ctx, (void *)data);
 }
 
+static TEE_Result stm32_cryp_reset(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!cryp_pdata.reset)
+		return TEE_SUCCESS;
+
+	res = rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS);
+	if (res)
+		return res;
+
+	udelay(CRYP_RESET_DELAY_US);
+
+	return rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS);
+}
+
 static void cryp_end(struct stm32_cryp_context *ctx, TEE_Result prev_error)
 {
-	if (prev_error) {
-		if (rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS))
-			panic();
-		if (rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS))
-			panic();
-	}
+	if (prev_error && stm32_cryp_reset())
+		panic();
 
 	/* Disable the CRYP peripheral */
 	io_clrbits32(ctx->base + _CRYP_CR, _CRYP_CR_CRYPEN);
@@ -1108,7 +1122,7 @@ TEE_Result stm32_cryp_update(struct stm32_cryp_context *ctx, bool last_block,
 	 */
 	if (last_block && algo_mode_is_ecb_cbc(ctx->cr) &&
 	    is_encrypt(ctx->cr) &&
-	    (ROUNDDOWN(data_size, ctx->block_u32 * sizeof(uint32_t)) !=
+	    (ROUNDDOWN2(data_size, ctx->block_u32 * sizeof(uint32_t)) !=
 	     data_size)) {
 		if (data_size < ctx->block_u32 * sizeof(uint32_t) * 2) {
 			/*
@@ -1229,6 +1243,29 @@ out:
 	return res;
 }
 
+static TEE_Result stm32_cryp_pm(enum pm_op op, uint32_t pm_hint,
+				const struct pm_callback_handle *hdl __unused)
+{
+	switch (op) {
+	case PM_OP_SUSPEND:
+		clk_disable(cryp_pdata.clock);
+		return TEE_SUCCESS;
+	case PM_OP_RESUME:
+		if (clk_enable(cryp_pdata.clock))
+			panic();
+
+		if (PM_HINT_IS_STATE(pm_hint, CONTEXT) && stm32_cryp_reset())
+			panic();
+
+		return TEE_SUCCESS;
+	default:
+		/* Unexpected PM operation */
+		assert(0);
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+}
+DECLARE_KEEP_PAGER(stm32_cryp_pm);
+
 static TEE_Result stm32_cryp_probe(const void *fdt, int node,
 				   const void *compt_data __unused)
 {
@@ -1248,7 +1285,7 @@ static TEE_Result stm32_cryp_probe(const void *fdt, int node,
 		return res;
 
 	res = rstctrl_dt_get_by_index(fdt, node, 0, &rstctrl);
-	if (res)
+	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
 		return res;
 
 	cryp_pdata.clock = clk;
@@ -1259,15 +1296,10 @@ static TEE_Result stm32_cryp_probe(const void *fdt, int node,
 	if (!cryp_pdata.base.va)
 		panic();
 
-	stm32mp_register_secure_periph_iomem(cryp_pdata.base.pa);
-
 	if (clk_enable(cryp_pdata.clock))
 		panic();
 
-	if (rstctrl_assert_to(cryp_pdata.reset, TIMEOUT_US_1MS))
-		panic();
-
-	if (rstctrl_deassert_to(cryp_pdata.reset, TIMEOUT_US_1MS))
+	if (stm32_cryp_reset())
 		panic();
 
 	if (IS_ENABLED(CFG_CRYPTO_DRV_AUTHENC)) {
@@ -1286,6 +1318,8 @@ static TEE_Result stm32_cryp_probe(const void *fdt, int node,
 		}
 	}
 
+	register_pm_core_service_cb(stm32_cryp_pm, NULL, "stm32-cryp");
+
 	return TEE_SUCCESS;
 }
 
diff --git a/core/drivers/crypto/stm32/stm32_saes.c b/core/drivers/crypto/stm32/stm32_saes.c
index 75f8bf8b6d30531538e85f1f140c493122f3afe8..47a1fceda23d8451382757bba1fc8b9a210a7f40 100644
--- a/core/drivers/crypto/stm32/stm32_saes.c
+++ b/core/drivers/crypto/stm32/stm32_saes.c
@@ -13,6 +13,7 @@
 #include <kernel/dt.h>
 #include <kernel/huk_subkey.h>
 #include <kernel/mutex.h>
+#include <kernel/pm.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <stdint.h>
@@ -142,6 +143,7 @@ static struct mutex saes_lock = MUTEX_INITIALIZER;
 static struct stm32_saes_platdata {
 	vaddr_t base;
 	struct clk *clk;
+	struct clk *clk_rng;
 	struct rstctrl *reset;
 } saes_pdata;
 
@@ -565,28 +567,28 @@ TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
 	}
 
 	if (is_dec)
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK,
-					 _SAES_CR_MODE_DEC);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_MODE_MASK,
+					_SAES_CR_MODE_DEC);
 	else
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_MODE_MASK,
-					 _SAES_CR_MODE_ENC);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_MODE_MASK,
+					_SAES_CR_MODE_ENC);
 
 	/* Save chaining mode */
 	switch (ch_mode) {
 	case STM32_SAES_MODE_ECB:
-		ctx->cr |= SET_CHAINING_MODE(ECB, ctx->cr);
+		ctx->cr = SET_CHAINING_MODE(ECB, ctx->cr);
 		break;
 	case STM32_SAES_MODE_CBC:
-		ctx->cr |= SET_CHAINING_MODE(CBC, ctx->cr);
+		ctx->cr = SET_CHAINING_MODE(CBC, ctx->cr);
 		break;
 	case STM32_SAES_MODE_CTR:
-		ctx->cr |= SET_CHAINING_MODE(CTR, ctx->cr);
+		ctx->cr = SET_CHAINING_MODE(CTR, ctx->cr);
 		break;
 	case STM32_SAES_MODE_GCM:
-		ctx->cr |= SET_CHAINING_MODE(GCM, ctx->cr);
+		ctx->cr = SET_CHAINING_MODE(GCM, ctx->cr);
 		break;
 	case STM32_SAES_MODE_CCM:
-		ctx->cr |= SET_CHAINING_MODE(CCM, ctx->cr);
+		ctx->cr = SET_CHAINING_MODE(CCM, ctx->cr);
 		break;
 	default:
 		return TEE_ERROR_BAD_PARAMETERS;
@@ -601,8 +603,8 @@ TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
 	 *
 	 * But note that wrap key only accept _SAES_CR_DATATYPE_NONE.
 	 */
-	ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_DATATYPE_MASK,
-				 _SAES_CR_DATATYPE_BYTE);
+	ctx->cr = set_field_u32(ctx->cr, _SAES_CR_DATATYPE_MASK,
+				_SAES_CR_DATATYPE_BYTE);
 
 	/* Configure keysize */
 	switch (key_size) {
@@ -619,8 +621,8 @@ TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
 	/* Configure key */
 	switch (key_select) {
 	case STM32_SAES_KEY_SOFT:
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
-					 _SAES_CR_KEYSEL_SOFT);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
+					_SAES_CR_KEYSEL_SOFT);
 		/* Save key */
 		switch (key_size) {
 		case AES_KEYSIZE_128:
@@ -651,20 +653,20 @@ TEE_Result stm32_saes_init(struct stm32_saes_context *ctx, bool is_dec,
 		}
 		break;
 	case STM32_SAES_KEY_DHU:
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
-					 _SAES_CR_KEYSEL_DHUK);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
+					_SAES_CR_KEYSEL_DHUK);
 		break;
 	case STM32_SAES_KEY_BH:
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
-					 _SAES_CR_KEYSEL_BHK);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
+					_SAES_CR_KEYSEL_BHK);
 		break;
 	case STM32_SAES_KEY_BHU_XOR_BH:
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
-					 _SAES_CR_KEYSEL_BHU_XOR_BH_K);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
+					_SAES_CR_KEYSEL_BHU_XOR_BH_K);
 		break;
 	case STM32_SAES_KEY_WRAPPED:
-		ctx->cr |= set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
-					 _SAES_CR_KEYSEL_SOFT);
+		ctx->cr = set_field_u32(ctx->cr, _SAES_CR_KEYSEL_MASK,
+					_SAES_CR_KEYSEL_SOFT);
 		break;
 
 	default:
@@ -1348,17 +1350,15 @@ out:
 static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata,
 				       const void *fdt, int node)
 {
-	struct dt_node_info dt_saes = { };
 	TEE_Result res = TEE_ERROR_GENERIC;
+	size_t reg_size = 0;
+	paddr_t reg = 0;
 
-	dt_saes.reg = fdt_reg_base_address(fdt, node);
-	dt_saes.reg_size = fdt_reg_size(fdt, node);
-
-	if (dt_saes.reg == DT_INFO_INVALID_REG ||
-	    dt_saes.reg_size == DT_INFO_INVALID_REG_SIZE)
-		return TEE_ERROR_BAD_PARAMETERS;
+	res = clk_dt_get_by_name(fdt, node, "bus", &pdata->clk);
+	if (res != TEE_SUCCESS)
+		return res;
 
-	res = clk_dt_get_by_index(fdt, node, 0, &pdata->clk);
+	res = clk_dt_get_by_name(fdt, node, "rng", &pdata->clk_rng);
 	if (res != TEE_SUCCESS)
 		return res;
 
@@ -1366,28 +1366,18 @@ static TEE_Result stm32_saes_parse_fdt(struct stm32_saes_platdata *pdata,
 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
 		return res;
 
-	pdata->base = (vaddr_t)phys_to_virt(dt_saes.reg, MEM_AREA_IO_SEC,
-					    dt_saes.reg_size);
+	if (fdt_reg_info(fdt, node, &reg, &reg_size))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	pdata->base = (vaddr_t)phys_to_virt(reg, MEM_AREA_IO_SEC, reg_size);
 	if (!pdata->base)
 		panic();
 
 	return TEE_SUCCESS;
 }
 
-static TEE_Result stm32_saes_probe(const void *fdt, int node,
-				   const void *compat_data __unused)
+static void stm32_saes_reset(void)
 {
-	TEE_Result res = TEE_SUCCESS;
-
-	assert(!saes_pdata.base);
-
-	res = stm32_saes_parse_fdt(&saes_pdata, fdt, node);
-	if (res)
-		return res;
-
-	if (clk_enable(saes_pdata.clk))
-		panic();
-
 	if (saes_pdata.reset) {
 		/* External reset of SAES */
 		if (rstctrl_assert_to(saes_pdata.reset, TIMEOUT_US_1MS))
@@ -1403,6 +1393,48 @@ static TEE_Result stm32_saes_probe(const void *fdt, int node,
 		udelay(SAES_RESET_DELAY);
 		io_clrbits32(saes_pdata.base + _SAES_CR, _SAES_CR_IPRST);
 	}
+}
+
+static TEE_Result stm32_saes_pm(enum pm_op op, uint32_t pm_hint,
+				const struct pm_callback_handle *hdl __unused)
+{
+	switch (op) {
+	case PM_OP_SUSPEND:
+		clk_disable(saes_pdata.clk);
+		clk_disable(saes_pdata.clk_rng);
+		return TEE_SUCCESS;
+
+	case PM_OP_RESUME:
+		if (clk_enable(saes_pdata.clk) ||
+		    clk_enable(saes_pdata.clk_rng))
+			panic();
+
+		if (PM_HINT_IS_STATE(pm_hint, CONTEXT))
+			stm32_saes_reset();
+
+		return TEE_SUCCESS;
+	default:
+		break;
+	}
+
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static TEE_Result stm32_saes_probe(const void *fdt, int node,
+				   const void *compat_data __unused)
+{
+	TEE_Result res = TEE_SUCCESS;
+
+	assert(!saes_pdata.base);
+
+	res = stm32_saes_parse_fdt(&saes_pdata, fdt, node);
+	if (res)
+		return res;
+
+	if (clk_enable(saes_pdata.clk) || clk_enable(saes_pdata.clk_rng))
+		panic();
+
+	stm32_saes_reset();
 
 	if (IS_ENABLED(CFG_CRYPTO_DRV_CIPHER)) {
 		res = stm32_register_cipher(SAES_IP);
@@ -1412,6 +1444,8 @@ static TEE_Result stm32_saes_probe(const void *fdt, int node,
 		}
 	}
 
+	register_pm_core_service_cb(stm32_saes_pm, NULL, "stm32-saes");
+
 	return TEE_SUCCESS;
 }
 
@@ -1423,5 +1457,5 @@ static const struct dt_device_match saes_match_table[] = {
 DEFINE_DT_DRIVER(stm32_saes_dt_driver) = {
 	.name = "stm32-saes",
 	.match_table = saes_match_table,
-	.probe = &stm32_saes_probe,
+	.probe = stm32_saes_probe,
 };
diff --git a/core/drivers/crypto/versal/rsa.c b/core/drivers/crypto/versal/rsa.c
index bbfe979128d068308923a3e157ae325ae4af9f0d..1baf390d57182a7e8f6bf7647a63c04e76f1d988 100644
--- a/core/drivers/crypto/versal/rsa.c
+++ b/core/drivers/crypto/versal/rsa.c
@@ -44,6 +44,7 @@ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data)
 						rsa_data->key.key,
 						rsa_data->label.data,
 						rsa_data->label.length,
+						rsa_data->mgf_algo,
 						rsa_data->message.data,
 						rsa_data->message.length,
 						rsa_data->cipher.data,
@@ -53,6 +54,7 @@ static TEE_Result do_encrypt(struct drvcrypt_rsa_ed *rsa_data)
 						rsa_data->key.key,
 						rsa_data->label.data,
 						rsa_data->label.length,
+						rsa_data->mgf_algo,
 						rsa_data->message.data,
 						rsa_data->message.length,
 						rsa_data->cipher.data,
@@ -133,6 +135,7 @@ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data)
 						rsa_data->key.key,
 						rsa_data->label.data,
 						rsa_data->label.length,
+						rsa_data->mgf_algo,
 						rsa_data->cipher.data,
 						rsa_data->cipher.length,
 						rsa_data->message.data,
@@ -142,6 +145,7 @@ static TEE_Result do_decrypt(struct drvcrypt_rsa_ed *rsa_data)
 						rsa_data->key.key,
 						rsa_data->label.data,
 						rsa_data->label.length,
+						rsa_data->mgf_algo,
 						rsa_data->cipher.data,
 						rsa_data->cipher.length,
 						rsa_data->message.data,
diff --git a/core/drivers/ffa_console.c b/core/drivers/ffa_console.c
new file mode 100644
index 0000000000000000000000000000000000000000..ac5951488e4a5429c71516277d8f9b4e527b0738
--- /dev/null
+++ b/core/drivers/ffa_console.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, NVIDIA CORPORATION
+ */
+
+#include <compiler.h>
+#include <console.h>
+#include <drivers/ffa_console.h>
+#include <drivers/serial.h>
+#include <kernel/thread_arch.h>
+
+#define FFA_CONSOLE_LOG_32		(0x8400008A)
+
+static void ffa_console_putc(struct serial_chip *chip __unused, int ch)
+{
+	thread_hvc(FFA_CONSOLE_LOG_32, 1, ch, 0);
+}
+
+static const struct serial_ops ffa_console_ops = {
+	.putc = ffa_console_putc,
+};
+DECLARE_KEEP_PAGER(ffa_console_ops);
+
+static struct serial_chip ffa_console = {
+	.ops = &ffa_console_ops
+};
+
+void ffa_console_init(void)
+{
+	register_serial_console(&ffa_console);
+}
diff --git a/core/drivers/firewall/firewall.c b/core/drivers/firewall/firewall.c
new file mode 100644
index 0000000000000000000000000000000000000000..8cdea215e929d6ed66108ea36fe40c85e96eaa78
--- /dev/null
+++ b/core/drivers/firewall/firewall.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <config.h>
+#include <drivers/firewall.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <malloc.h>
+#include <trace.h>
+
+/* The firewall framework requires device tree support */
+static_assert(IS_ENABLED(CFG_DT));
+
+static TEE_Result firewall_get(struct dt_pargs *parg, void *data,
+			       struct firewall_query **out_fw)
+{
+	struct firewall_query *fw = NULL;
+	unsigned int i = 0;
+
+	assert(parg->args_count >= 0);
+
+	fw = calloc(1, sizeof(*fw));
+	if (!fw)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	fw->ctrl = (struct firewall_controller *)data;
+	fw->arg_count = parg->args_count;
+
+	if (fw->arg_count) {
+		fw->args = calloc(fw->arg_count, sizeof(*fw->args));
+		if (!fw->args) {
+			free(fw);
+			return TEE_ERROR_OUT_OF_MEMORY;
+		}
+	}
+
+	for (i = 0; i < (unsigned int)parg->args_count; i++)
+		fw->args[i] = parg->args[i];
+
+	*out_fw = fw;
+
+	return TEE_SUCCESS;
+}
+
+/* Firewall device API */
+
+void firewall_put(struct firewall_query *fw)
+{
+	if (fw) {
+		free(fw->args);
+		free(fw);
+	}
+}
+
+TEE_Result firewall_dt_get_by_index(const void *fdt, int node, uint32_t index,
+				    struct firewall_query **out_fw)
+{
+	return dt_driver_device_from_node_idx_prop("access-controllers", fdt,
+						   node, index,
+						   DT_DRIVER_FIREWALL,
+						   out_fw);
+}
+
+TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name,
+				   struct firewall_query **out_fw)
+{
+	int index = 0;
+
+	index = fdt_stringlist_search(fdt, node, "access-controllers-names",
+				      name);
+	if (index == -FDT_ERR_NOTFOUND)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+	else if (index < 0)
+		return TEE_ERROR_GENERIC;
+
+	return firewall_dt_get_by_index(fdt, node, index, out_fw);
+}
+
+TEE_Result firewall_set_configuration(struct firewall_query *fw)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->set_conf)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->set_conf(fw);
+}
+
+TEE_Result firewall_set_memory_configuration(struct firewall_query *fw,
+					     paddr_t paddr, size_t size)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->set_memory_conf)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->set_memory_conf(fw, paddr, size);
+}
+
+TEE_Result firewall_check_access(struct firewall_query *fw)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->check_access)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->check_access(fw);
+}
+
+TEE_Result firewall_acquire_access(struct firewall_query *fw)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->acquire_access)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->acquire_access(fw);
+}
+
+TEE_Result firewall_check_memory_access(struct firewall_query *fw,
+					paddr_t paddr, size_t size, bool read,
+					bool write)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->check_memory_access)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->check_memory_access(fw, paddr, size, read, write);
+}
+
+TEE_Result firewall_acquire_memory_access(struct firewall_query *fw,
+					  paddr_t paddr, size_t size, bool read,
+					  bool write)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (!fw->ctrl->ops->acquire_memory_access)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	return fw->ctrl->ops->acquire_memory_access(fw, paddr, size, read,
+						    write);
+}
+
+void firewall_release_access(struct firewall_query *fw)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (fw->ctrl->ops->release_access)
+		fw->ctrl->ops->release_access(fw);
+}
+
+void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr,
+				    size_t size, bool read, bool write)
+{
+	assert(fw && fw->ctrl && fw->ctrl->ops);
+
+	if (fw->ctrl->ops->release_memory_access)
+		fw->ctrl->ops->release_memory_access(fw, paddr, size, read,
+						     write);
+}
+
+/* Firewall controller API */
+
+TEE_Result firewall_dt_controller_register(const void *fdt, int node,
+					   struct firewall_controller *ctrl)
+{
+	assert(ctrl);
+
+	DMSG("Registering %s firewall controller", ctrl->name);
+
+	return dt_driver_register_provider(fdt, node,
+					   (get_of_device_func)firewall_get,
+					   ctrl, DT_DRIVER_FIREWALL);
+}
diff --git a/core/drivers/firewall/stm32_etzpc.c b/core/drivers/firewall/stm32_etzpc.c
new file mode 100644
index 0000000000000000000000000000000000000000..0c6c58759280681890e5ceff194ab3c12e444250
--- /dev/null
+++ b/core/drivers/firewall/stm32_etzpc.c
@@ -0,0 +1,920 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2024, STMicroelectronics
+ */
+
+/*
+ * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and
+ * internal memories. The driver expects a single instance of the controller
+ * in the platform.
+ */
+
+#include <assert.h>
+#include <drivers/clk_dt.h>
+#include <drivers/firewall.h>
+#include <drivers/firewall_device.h>
+#include <drivers/stm32_etzpc.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#ifdef CFG_STM32MP15
+#include <drivers/stm32mp1_rcc.h>
+#endif
+#include <initcall.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <kernel/spinlock.h>
+#include <kernel/tee_misc.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <stm32_util.h>
+#include <util.h>
+
+/* ID Registers */
+#define ETZPC_TZMA0_SIZE		U(0x000)
+#define ETZPC_DECPROT0			U(0x010)
+#define ETZPC_DECPROT_LOCK0		U(0x030)
+#define ETZPC_HWCFGR			U(0x3F0)
+#define ETZPC_VERR			U(0x3F4)
+
+/* ID Registers fields */
+#define ETZPC_TZMA0_SIZE_LOCK		BIT(31)
+#define ETZPC_DECPROT0_MASK		GENMASK_32(1, 0)
+#define ETZPC_HWCFGR_NUM_TZMA_MASK	GENMASK_32(7, 0)
+#define ETZPC_HWCFGR_NUM_TZMA_SHIFT	0
+#define ETZPC_HWCFGR_NUM_PER_SEC_MASK	GENMASK_32(15, 8)
+#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT	8
+#define ETZPC_HWCFGR_NUM_AHB_SEC_MASK	GENMASK_32(23, 16)
+#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT	16
+#define ETZPC_HWCFGR_CHUNKS1N4_MASK	GENMASK_32(31, 24)
+#define ETZPC_HWCFGR_CHUNKS1N4_SHIFT	24
+
+#define DECPROT_SHIFT			1
+#define IDS_PER_DECPROT_REGS		U(16)
+#define IDS_PER_DECPROT_LOCK_REGS	U(32)
+
+/*
+ * Implementation uses uint8_t to store each securable DECPROT configuration
+ * and uint16_t to store each securable TZMA configuration. When resuming
+ * from deep suspend, the DECPROT configurations are restored.
+ */
+#define PERIPH_PM_LOCK_BIT		BIT(7)
+#define PERIPH_PM_ATTR_MASK		GENMASK_32(2, 0)
+#define TZMA_PM_LOCK_BIT		BIT(15)
+#define TZMA_PM_VALUE_MASK		GENMASK_32(9, 0)
+
+/*
+ * struct stm32_etzpc_platdata - Driver data set at initialization
+ *
+ * @name:	Name of the peripheral
+ * @clk:	ETZPC clock
+ * @periph_cfg:	Peripheral DECPROT configuration
+ * @tzma_cfg:	TZMA configuration
+ * @base:	ETZPC IOMEM base address
+ */
+struct stm32_etzpc_platdata {
+	char *name;
+	struct clk *clk;
+	uint8_t *periph_cfg;
+	uint16_t *tzma_cfg;
+	struct io_pa_va base;
+};
+
+/*
+ * struct stm32_etzpc_driver_data - configuration data from the hardware
+ *
+ * @num_tzma:	 Number of TZMA zones, read from the hardware
+ * @num_per_sec: Number of securable AHB & APB periphs, read from the hardware
+ * @num_ahb_sec: Number of securable AHB master zones, read from the hardware
+ */
+struct stm32_etzpc_driver_data {
+	unsigned int num_tzma;
+	unsigned int num_per_sec;
+	unsigned int num_ahb_sec;
+};
+
+/*
+ * struct etzpc_device - ETZPC device driver instance
+ * @pdata:	Platform data set during initialization
+ * @ddata:	Device configuration data from the hardware
+ * @lock:	Access contention
+ */
+struct etzpc_device {
+	struct stm32_etzpc_platdata pdata;
+	struct stm32_etzpc_driver_data ddata;
+	unsigned int lock;
+};
+
+static struct etzpc_device *etzpc_device;
+
+static const char *const etzpc_decprot_strings[] __maybe_unused = {
+	[ETZPC_DECPROT_S_RW] = "ETZPC_DECPROT_S_RW",
+	[ETZPC_DECPROT_NS_R_S_W] = "ETZPC_DECPROT_NS_R_S_W",
+	[ETZPC_DECPROT_MCU_ISOLATION] = "ETZPC_DECPROT_MCU_ISOLATION",
+	[ETZPC_DECPROT_NS_RW] = "ETZPC_DECPROT_NS_RW",
+};
+
+static uint32_t etzpc_lock(void)
+{
+	return cpu_spin_lock_xsave(&etzpc_device->lock);
+}
+
+static void etzpc_unlock(uint32_t exceptions)
+{
+	cpu_spin_unlock_xrestore(&etzpc_device->lock, exceptions);
+}
+
+static bool valid_decprot_id(unsigned int id)
+{
+	return id < etzpc_device->ddata.num_per_sec;
+}
+
+static bool __maybe_unused valid_tzma_id(unsigned int id)
+{
+	return id < etzpc_device->ddata.num_tzma;
+}
+
+static enum etzpc_decprot_attributes etzpc_binding2decprot(uint32_t mode)
+{
+	switch (mode) {
+	case DECPROT_S_RW:
+		return ETZPC_DECPROT_S_RW;
+	case DECPROT_NS_R_S_W:
+		return ETZPC_DECPROT_NS_R_S_W;
+#ifdef CFG_STM32MP15
+	case DECPROT_MCU_ISOLATION:
+		return ETZPC_DECPROT_MCU_ISOLATION;
+#endif
+	case DECPROT_NS_RW:
+		return ETZPC_DECPROT_NS_RW;
+	default:
+		panic();
+	}
+}
+
+static void
+sanitize_decprot_config(uint32_t decprot_id __maybe_unused,
+			enum etzpc_decprot_attributes attr __maybe_unused)
+{
+#ifdef CFG_STM32MP15
+	/*
+	 * STM32MP15: check dependency on RCC TZEN/MCKPROT configuration
+	 * when a ETZPC resource is secured or isolated for Cortex-M
+	 * coprocessor.
+	 */
+	switch (attr) {
+	case ETZPC_DECPROT_S_RW:
+	case ETZPC_DECPROT_NS_R_S_W:
+		if (!stm32_rcc_is_secure()) {
+			IMSG("WARNING: RCC tzen:0, insecure ETZPC hardening %"PRIu32":%s",
+			     decprot_id, etzpc_decprot_strings[attr]);
+			if (!IS_ENABLED(CFG_INSECURE))
+				panic();
+		}
+		break;
+	case ETZPC_DECPROT_MCU_ISOLATION:
+		if (!stm32_rcc_is_secure() || !stm32_rcc_is_mckprot()) {
+			IMSG("WARNING: RCC tzen:%u mckprot:%u, insecure ETZPC hardening %"PRIu32":%s",
+			     stm32_rcc_is_secure(), stm32_rcc_is_mckprot(),
+			     decprot_id, etzpc_decprot_strings[attr]);
+			if (!IS_ENABLED(CFG_INSECURE))
+				panic();
+		}
+		break;
+	case ETZPC_DECPROT_NS_RW:
+		break;
+	default:
+		assert(0);
+		break;
+	}
+#endif
+}
+
+static void etzpc_configure_decprot(uint32_t decprot_id,
+				    enum etzpc_decprot_attributes attr)
+{
+	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS);
+	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+	uint32_t masked_decprot = (uint32_t)attr & ETZPC_DECPROT0_MASK;
+	vaddr_t base = etzpc_device->pdata.base.va;
+	unsigned int exceptions = 0;
+
+	assert(valid_decprot_id(decprot_id));
+
+	FMSG("ID : %"PRIu32", config %i", decprot_id, attr);
+
+	sanitize_decprot_config(decprot_id, attr);
+
+	exceptions = etzpc_lock();
+
+	io_clrsetbits32(base + ETZPC_DECPROT0 + offset,
+			ETZPC_DECPROT0_MASK << shift,
+			masked_decprot << shift);
+
+	etzpc_unlock(exceptions);
+}
+
+enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
+{
+	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_REGS);
+	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
+	vaddr_t base = etzpc_device->pdata.base.va;
+	uint32_t value = 0;
+
+	assert(valid_decprot_id(decprot_id));
+
+	value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) &
+		ETZPC_DECPROT0_MASK;
+
+	return (enum etzpc_decprot_attributes)value;
+}
+
+static void etzpc_lock_decprot(uint32_t decprot_id)
+{
+	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
+	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
+	vaddr_t base = etzpc_device->pdata.base.va;
+	uint32_t exceptions = 0;
+
+	assert(valid_decprot_id(decprot_id));
+
+	exceptions = etzpc_lock();
+
+	io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask);
+
+	etzpc_unlock(exceptions);
+}
+
+static bool decprot_is_locked(uint32_t decprot_id)
+{
+	size_t offset = U(4) * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
+	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
+	vaddr_t base = etzpc_device->pdata.base.va;
+
+	assert(valid_decprot_id(decprot_id));
+
+	return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask;
+}
+
+void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
+{
+	size_t offset = sizeof(uint32_t) * tzma_id;
+	vaddr_t base = etzpc_device->pdata.base.va;
+	uint32_t exceptions = 0;
+
+	assert(valid_tzma_id(tzma_id));
+
+	exceptions = etzpc_lock();
+
+	io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value);
+
+	etzpc_unlock(exceptions);
+}
+
+static uint16_t etzpc_get_tzma(uint32_t tzma_id)
+{
+	size_t offset = sizeof(uint32_t) * tzma_id;
+	vaddr_t base = etzpc_device->pdata.base.va;
+
+	assert(valid_tzma_id(tzma_id));
+
+	return io_read32(base + ETZPC_TZMA0_SIZE + offset);
+}
+
+static void etzpc_lock_tzma(uint32_t tzma_id)
+{
+	size_t offset = sizeof(uint32_t) * tzma_id;
+	vaddr_t base = etzpc_device->pdata.base.va;
+	uint32_t exceptions = 0;
+
+	assert(valid_tzma_id(tzma_id));
+
+	exceptions = etzpc_lock();
+
+	io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK);
+
+	etzpc_unlock(exceptions);
+}
+
+static bool tzma_is_locked(uint32_t tzma_id)
+{
+	size_t offset = sizeof(uint32_t) * tzma_id;
+	vaddr_t base = etzpc_device->pdata.base.va;
+
+	assert(valid_tzma_id(tzma_id));
+
+	return io_read32(base + ETZPC_TZMA0_SIZE + offset) &
+	       ETZPC_TZMA0_SIZE_LOCK;
+}
+
+static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused,
+			   const struct pm_callback_handle *pm_handle __unused)
+{
+	struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata;
+	struct stm32_etzpc_platdata *pdata = &etzpc_device->pdata;
+	unsigned int n = 0;
+
+	if (op == PM_OP_SUSPEND) {
+		for (n = 0; n < ddata->num_per_sec; n++) {
+			pdata->periph_cfg[n] =
+				(uint8_t)etzpc_get_decprot(n);
+			if (decprot_is_locked(n))
+				pdata->periph_cfg[n] |= PERIPH_PM_LOCK_BIT;
+		}
+
+		for (n = 0; n < ddata->num_tzma; n++) {
+			pdata->tzma_cfg[n] =
+				(uint8_t)etzpc_get_tzma(n);
+			if (tzma_is_locked(n))
+				pdata->tzma_cfg[n] |= TZMA_PM_LOCK_BIT;
+		}
+
+		return TEE_SUCCESS;
+	}
+
+	/* PM_OP_RESUME */
+	for (n = 0; n < ddata->num_per_sec; n++) {
+		unsigned int attr = pdata->periph_cfg[n] & PERIPH_PM_ATTR_MASK;
+
+		etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr);
+
+		if (pdata->periph_cfg[n] & PERIPH_PM_LOCK_BIT)
+			etzpc_lock_decprot(n);
+	}
+
+	for (n = 0; n < ddata->num_tzma; n++) {
+		uint16_t value = pdata->tzma_cfg[n] & TZMA_PM_VALUE_MASK;
+
+		etzpc_configure_tzma(n, value);
+
+		if (pdata->tzma_cfg[n] & TZMA_PM_LOCK_BIT)
+			etzpc_lock_tzma(n);
+	}
+
+	return TEE_SUCCESS;
+}
+DECLARE_KEEP_PAGER(etzpc_pm);
+
+static TEE_Result stm32_etzpc_check_access(struct firewall_query *firewall)
+{
+	enum etzpc_decprot_attributes attr_req = ETZPC_DECPROT_MAX;
+	uint32_t id = 0;
+
+	if (!firewall || firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	id = firewall->args[0] & ETZPC_ID_MASK;
+	attr_req = etzpc_binding2decprot((firewall->args[0] &
+					  ETZPC_MODE_MASK) >> ETZPC_MODE_SHIFT);
+
+	if (id < etzpc_device->ddata.num_per_sec) {
+		if (etzpc_get_decprot(id) == attr_req)
+			return TEE_SUCCESS;
+		else
+			return TEE_ERROR_ACCESS_DENIED;
+	} else {
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+}
+
+static TEE_Result stm32_etzpc_acquire_access(struct firewall_query *firewall)
+{
+	enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MCU_ISOLATION;
+	uint32_t id = 0;
+
+	if (!firewall || firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	id = firewall->args[0] & ETZPC_ID_MASK;
+	if (id < etzpc_device->ddata.num_per_sec) {
+		attr = etzpc_get_decprot(id);
+		if (attr != ETZPC_DECPROT_S_RW &&
+		    attr != ETZPC_DECPROT_NS_R_S_W)
+			return TEE_ERROR_ACCESS_DENIED;
+	} else {
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+stm32_etzpc_acquire_memory_access(struct firewall_query *firewall,
+				  paddr_t paddr, size_t size,
+				  bool read __unused, bool write __unused)
+{
+	paddr_t tzma_base = 0;
+	size_t prot_size = 0;
+	uint32_t id = 0;
+
+	if (!firewall || firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	id = firewall->args[0] & ETZPC_ID_MASK;
+	switch (id) {
+	case ETZPC_TZMA0_ID:
+		tzma_base = ROM_BASE;
+		prot_size = etzpc_get_tzma(0) * SMALL_PAGE_SIZE;
+		break;
+	case ETZPC_TZMA1_ID:
+		tzma_base = SYSRAM_BASE;
+		prot_size = etzpc_get_tzma(1) * SMALL_PAGE_SIZE;
+		break;
+	default:
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	DMSG("Acquiring access for TZMA%u, secured from %#"PRIxPA" to %#"PRIxPA,
+	     id == ETZPC_TZMA0_ID ? 0 : 1, tzma_base, tzma_base + prot_size);
+
+	if (core_is_buffer_inside(paddr, size, tzma_base, prot_size))
+		return TEE_SUCCESS;
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+#ifdef CFG_STM32MP15
+static bool pager_permits_decprot_config(uint32_t decprot_id,
+					 enum etzpc_decprot_attributes attr)
+{
+	paddr_t ram_base = 0;
+	size_t ram_size = 0;
+
+	if (!IS_ENABLED(CFG_WITH_PAGER))
+		return true;
+
+	switch (decprot_id) {
+	case ETZPC_TZMA1_ID:
+		ram_base = SYSRAM_BASE;
+		ram_size = SYSRAM_SEC_SIZE;
+		break;
+	case STM32MP1_ETZPC_SRAM1_ID:
+		ram_base = SRAM1_BASE;
+		ram_size = SRAM1_SIZE;
+		break;
+	case STM32MP1_ETZPC_SRAM2_ID:
+		ram_base = SRAM2_BASE;
+		ram_size = SRAM2_SIZE;
+		break;
+	case STM32MP1_ETZPC_SRAM3_ID:
+		ram_base = SRAM3_BASE;
+		ram_size = SRAM3_SIZE;
+		break;
+	case STM32MP1_ETZPC_SRAM4_ID:
+		ram_base = SRAM4_BASE;
+		ram_size = SRAM4_SIZE;
+		break;
+	default:
+		return true;
+	}
+
+	if (stm32mp1_ram_intersect_pager_ram(ram_base, ram_size) &&
+	    attr != ETZPC_DECPROT_S_RW) {
+		EMSG("Internal RAM %#"PRIxPA"..%#"PRIxPA" is used by pager, must be secure",
+		     ram_base, ram_base + ram_size);
+		return false;
+	}
+
+	return true;
+}
+#endif /* CFG_STM32MP15 */
+
+static bool decprot_id_is_internal_ram(uint32_t id)
+{
+	switch (id) {
+	case STM32MP1_ETZPC_SRAM1_ID:
+	case STM32MP1_ETZPC_SRAM2_ID:
+	case STM32MP1_ETZPC_SRAM3_ID:
+#ifdef CFG_STM32MP15
+	case STM32MP1_ETZPC_SRAM4_ID:
+	case STM32MP1_ETZPC_RETRAM_ID:
+#endif
+		return true;
+	default:
+		return false;
+	}
+}
+
+static TEE_Result stm32_etzpc_configure_memory(struct firewall_query *firewall,
+					       paddr_t paddr, size_t size)
+{
+	enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
+	bool lock = false;
+	uint32_t mode = 0;
+	uint32_t id = 0;
+
+	if (firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	id = firewall->args[0] & ETZPC_ID_MASK;
+	mode = (firewall->args[0] & ETZPC_MODE_MASK) >> ETZPC_MODE_SHIFT;
+	attr = etzpc_binding2decprot(mode);
+	lock = firewall->args[0] & ETZPC_LOCK_MASK;
+
+	if (decprot_id_is_internal_ram(id)) {
+		/* Use OP-TEE SRAM addresses, not the alias one */
+		paddr = stm32mp1_pa_or_sram_alias_pa(paddr);
+
+		/* Target address range must match the full SRAM range */
+		switch (id) {
+		case STM32MP1_ETZPC_SRAM1_ID:
+			if (paddr != SRAM1_BASE || size != SRAM1_SIZE)
+				return TEE_ERROR_BAD_PARAMETERS;
+			break;
+		case STM32MP1_ETZPC_SRAM2_ID:
+			if (paddr != SRAM2_BASE || size != SRAM2_SIZE)
+				return TEE_ERROR_BAD_PARAMETERS;
+			break;
+		case STM32MP1_ETZPC_SRAM3_ID:
+			if (paddr != SRAM3_BASE || size != SRAM3_SIZE)
+				return TEE_ERROR_BAD_PARAMETERS;
+			break;
+#ifdef CFG_STM32MP15
+		case STM32MP1_ETZPC_SRAM4_ID:
+			if (paddr != SRAM4_BASE || size != SRAM4_SIZE)
+				return TEE_ERROR_BAD_PARAMETERS;
+			break;
+		case STM32MP1_ETZPC_RETRAM_ID:
+			if (paddr != RETRAM_BASE || size != RETRAM_SIZE)
+				return TEE_ERROR_BAD_PARAMETERS;
+			break;
+#endif /*CFG_STM32MP15*/
+		default:
+			panic();
+		}
+
+		if (decprot_is_locked(id)) {
+			if (etzpc_get_decprot(id) != attr) {
+				EMSG("Internal RAM configuration locked");
+				return TEE_ERROR_ACCESS_DENIED;
+			}
+
+			return TEE_SUCCESS;
+		}
+
+#ifdef CFG_STM32MP15
+		if (!pager_permits_decprot_config(id, attr))
+			return TEE_ERROR_ACCESS_DENIED;
+#endif
+
+		etzpc_configure_decprot(id, attr);
+		if (lock)
+			etzpc_lock_decprot(id);
+	} else if (id == ETZPC_TZMA0_ID || id == ETZPC_TZMA1_ID) {
+		unsigned int tzma_id = 0;
+		uint16_t tzma_r0size = 0;
+		paddr_t ram_base = 0;
+		size_t ram_size = 0;
+
+		switch (id) {
+		case ETZPC_TZMA0_ID:
+			ram_base = ROM_BASE;
+			ram_size = ROM_SIZE;
+			tzma_id = 0;
+			break;
+		case ETZPC_TZMA1_ID:
+			ram_base = SYSRAM_BASE;
+			ram_size = SYSRAM_SIZE;
+			tzma_id = 1;
+			break;
+		default:
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+		/* TZMA configuration supports only page aligned sizes */
+		if (!IS_ALIGNED(paddr, SMALL_PAGE_SIZE) ||
+		    !IS_ALIGNED(size, SMALL_PAGE_SIZE))
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		/*
+		 * TZMA supports only 2 access rights configuration
+		 * for RAM ranges: secure or non-secure.
+		 * Secure RAM range must start from RAM base address
+		 * and non-secure RAM range must end at RAM top address.
+		 */
+		switch (attr) {
+		case ETZPC_DECPROT_S_RW:
+			if (paddr != ram_base || size > ram_size)
+				return TEE_ERROR_BAD_PARAMETERS;
+			tzma_r0size = ram_size / SMALL_PAGE_SIZE;
+			break;
+		case ETZPC_DECPROT_NS_RW:
+			if (paddr < ram_base ||
+			    paddr + size != ram_base + ram_size)
+				return TEE_ERROR_BAD_PARAMETERS;
+			tzma_r0size = (paddr - ram_base) / SMALL_PAGE_SIZE;
+			break;
+		default:
+			EMSG("Invalid TZMA mode %"PRIu32, mode);
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+#ifdef CFG_STM32MP15
+		if (!pager_permits_decprot_config(id, attr))
+			return TEE_ERROR_ACCESS_DENIED;
+#endif
+
+		if (tzma_is_locked(tzma_id)) {
+			if (etzpc_get_tzma(tzma_id) != tzma_r0size) {
+				EMSG("TZMA configuration locked");
+				return TEE_ERROR_ACCESS_DENIED;
+			}
+
+			return TEE_SUCCESS;
+		}
+
+		etzpc_configure_tzma(tzma_id, tzma_r0size);
+		if (lock)
+			etzpc_lock_tzma(tzma_id);
+	} else {
+		EMSG("Unknown firewall ID: %"PRIu32, id);
+
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_etzpc_configure(struct firewall_query *firewall)
+{
+	enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
+	uint32_t id = 0;
+
+	if (firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	id = firewall->args[0] & ETZPC_ID_MASK;
+
+	if (id < etzpc_device->ddata.num_per_sec) {
+		uint32_t mode = 0;
+
+		/*
+		 * Peripheral configuration, we assume the configuration is as
+		 * follows:
+		 * firewall->args[0]: Firewall configuration to apply
+		 */
+
+		mode = (firewall->args[0] & ETZPC_MODE_MASK) >>
+		       ETZPC_MODE_SHIFT;
+		attr = etzpc_binding2decprot(mode);
+
+		if (decprot_is_locked(id)) {
+			if (etzpc_get_decprot(id) != attr) {
+				EMSG("Peripheral configuration locked");
+				return TEE_ERROR_ACCESS_DENIED;
+			}
+
+			DMSG("Compliant locked config for periph %"PRIu32" - attr %s",
+			     id, etzpc_decprot_strings[attr]);
+
+			return TEE_SUCCESS;
+		}
+
+#ifdef CFG_STM32MP15
+		if (!pager_permits_decprot_config(id, attr))
+			return TEE_ERROR_ACCESS_DENIED;
+#endif
+
+		DMSG("Setting access config for periph %"PRIu32" - attr %s", id,
+		     etzpc_decprot_strings[attr]);
+
+		etzpc_configure_decprot(id, attr);
+		if (firewall->args[0] & ETZPC_LOCK_MASK)
+			etzpc_lock_decprot(id);
+
+		return TEE_SUCCESS;
+	}
+	EMSG("Unknown firewall ID: %"PRIu32, id);
+
+	return TEE_ERROR_BAD_PARAMETERS;
+}
+
+static void stm32_etzpc_set_driverdata(void)
+{
+	struct stm32_etzpc_driver_data *ddata = &etzpc_device->ddata;
+	vaddr_t base = etzpc_device->pdata.base.va;
+	uint32_t reg = io_read32(base + ETZPC_HWCFGR);
+
+	ddata->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >>
+			   ETZPC_HWCFGR_NUM_TZMA_SHIFT;
+	ddata->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >>
+			      ETZPC_HWCFGR_NUM_PER_SEC_SHIFT;
+	ddata->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >>
+			      ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT;
+
+	DMSG("ETZPC revision 0x%02"PRIx8", per_sec %u, ahb_sec %u, tzma %u",
+	     io_read8(base + ETZPC_VERR),
+	     ddata->num_per_sec, ddata->num_ahb_sec, ddata->num_tzma);
+}
+
+static void fdt_etzpc_conf_decprot(const void *fdt, int node)
+{
+	const fdt32_t *cuint = NULL;
+	size_t i = 0;
+	int len = 0;
+
+	cuint = fdt_getprop(fdt, node, "st,decprot", &len);
+	if (!cuint) {
+		DMSG("No ETZPC DECPROT configuration in DT");
+		return;
+	}
+
+	clk_enable(etzpc_device->pdata.clk);
+
+	for (i = 0; i < len / sizeof(uint32_t); i++) {
+		uint32_t value = fdt32_to_cpu(cuint[i]);
+		uint32_t id = value & ETZPC_ID_MASK;
+		uint32_t mode = (value & ETZPC_MODE_MASK) >> ETZPC_MODE_SHIFT;
+		bool lock = value & ETZPC_LOCK_MASK;
+		enum etzpc_decprot_attributes attr = ETZPC_DECPROT_MAX;
+
+		if (!valid_decprot_id(id)) {
+			DMSG("Invalid DECPROT %"PRIu32, id);
+			panic();
+		}
+
+		attr = etzpc_binding2decprot(mode);
+
+#ifdef CFG_STM32MP15
+		if (!pager_permits_decprot_config(id, attr))
+			panic();
+#endif
+
+		etzpc_configure_decprot(id, attr);
+
+		if (lock)
+			etzpc_lock_decprot(id);
+	}
+
+	clk_disable(etzpc_device->pdata.clk);
+}
+
+static TEE_Result
+stm32_etzpc_dt_probe_bus(const void *fdt, int node,
+			 struct firewall_controller *ctrl __maybe_unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct firewall_query *fw = NULL;
+	int subnode = 0;
+
+	DMSG("Populating %s firewall bus", ctrl->name);
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		unsigned int i = 0;
+
+		if (fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED)
+			continue;
+
+		if (IS_ENABLED(CFG_INSECURE) &&
+		    stm32mp_allow_probe_shared_device(fdt, subnode)) {
+			DMSG("Skipping firewall attributes check for %s",
+			     fdt_get_name(fdt, subnode, NULL));
+			goto skip_check;
+		}
+
+		DMSG("Acquiring firewall access for %s when probing bus",
+		     fdt_get_name(fdt, subnode, NULL));
+
+		do {
+			/*
+			 * The access-controllers property is mandatory for
+			 * firewall bus devices
+			 */
+			res = firewall_dt_get_by_index(fdt, subnode, i, &fw);
+			if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+				/* Stop when nothing more to parse */
+				break;
+			} else if (res) {
+				EMSG("%s: Error on node %s: %#"PRIx32,
+				     ctrl->name,
+				     fdt_get_name(fdt, subnode, NULL), res);
+				panic();
+			}
+
+			res = firewall_acquire_access(fw);
+			if (res) {
+				EMSG("%s: %s not accessible: %#"PRIx32,
+				     ctrl->name,
+				     fdt_get_name(fdt, subnode, NULL), res);
+				panic();
+			}
+
+			firewall_put(fw);
+			i++;
+		} while (true);
+
+skip_check:
+		res = dt_driver_maybe_add_probe_node(fdt, subnode);
+		if (res) {
+			EMSG("Failed on node %s with %#"PRIx32,
+			     fdt_get_name(fdt, subnode, NULL), res);
+			panic();
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result init_etzpc_from_dt(const void *fdt, int node)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info etzpc_info = { };
+	int len = 0;
+
+	fdt_fill_device_info(fdt, &etzpc_info, node);
+	if (etzpc_info.reg == DT_INFO_INVALID_REG ||
+	    etzpc_info.reg_size == DT_INFO_INVALID_REG_SIZE)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	etzpc_device->pdata.base.pa = etzpc_info.reg;
+	etzpc_device->pdata.name = strdup(fdt_get_name(fdt, node, &len));
+	io_pa_or_va_secure(&etzpc_device->pdata.base, etzpc_info.reg_size);
+	res = clk_dt_get_by_index(fdt, node, 0, &etzpc_device->pdata.clk);
+	if (res)
+		return res;
+
+	stm32_etzpc_set_driverdata();
+
+	etzpc_device->pdata.periph_cfg =
+		calloc(etzpc_device->ddata.num_per_sec,
+		       sizeof(*etzpc_device->pdata.periph_cfg));
+	if (!etzpc_device->pdata.periph_cfg)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	etzpc_device->pdata.tzma_cfg =
+		calloc(etzpc_device->ddata.num_tzma,
+		       sizeof(*etzpc_device->pdata.tzma_cfg));
+	if (!etzpc_device->pdata.tzma_cfg) {
+		free(etzpc_device->pdata.periph_cfg);
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static const struct firewall_controller_ops firewall_ops = {
+	.set_conf = stm32_etzpc_configure,
+	.set_memory_conf = stm32_etzpc_configure_memory,
+	.check_access = stm32_etzpc_check_access,
+	.acquire_access = stm32_etzpc_acquire_access,
+	.acquire_memory_access = stm32_etzpc_acquire_memory_access,
+};
+
+static TEE_Result stm32_etzpc_probe(const void *fdt, int node,
+				    const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct firewall_controller *controller = NULL;
+
+	etzpc_device = calloc(1, sizeof(*etzpc_device));
+	if (!etzpc_device)
+		panic();
+
+	res = init_etzpc_from_dt(fdt, node);
+	if (res) {
+		free(etzpc_device->pdata.periph_cfg);
+		free(etzpc_device->pdata.tzma_cfg);
+		free(etzpc_device->pdata.name);
+		free(etzpc_device);
+		free(controller);
+		return res;
+	}
+
+	controller = calloc(1, sizeof(*controller));
+	if (!controller)
+		panic();
+
+	controller->base = &etzpc_device->pdata.base;
+	controller->name = etzpc_device->pdata.name;
+	controller->priv = etzpc_device;
+	controller->ops = &firewall_ops;
+
+	res = firewall_dt_controller_register(fdt, node, controller);
+	if (res)
+		panic("Cannot register ETZPC as a firewall controller");
+
+	fdt_etzpc_conf_decprot(fdt, node);
+
+	res = stm32_etzpc_dt_probe_bus(fdt, node, controller);
+	if (res)
+		panic("Cannot populate bus");
+
+	register_pm_core_service_cb(etzpc_pm, NULL, "stm32-etzpc");
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match etzpc_match_table[] = {
+	{ .compatible = "st,stm32-etzpc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(etzpc_dt_driver) = {
+	.name = "stm32-etzpc",
+	.match_table = etzpc_match_table,
+	.probe = stm32_etzpc_probe,
+};
diff --git a/core/drivers/firewall/stm32_iac.c b/core/drivers/firewall/stm32_iac.c
new file mode 100644
index 0000000000000000000000000000000000000000..988d610c60c79a0e1815d2692de096448814bab5
--- /dev/null
+++ b/core/drivers/firewall/stm32_iac.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/interrupt.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <tee_api_defines.h>
+#include <trace.h>
+#include <util.h>
+
+/* IAC offset register */
+#define _IAC_IER0		U(0x000)
+#define _IAC_ISR0		U(0x080)
+#define _IAC_ICR0		U(0x100)
+#define _IAC_IISR0		U(0x36C)
+
+#define _IAC_HWCFGR2		U(0x3EC)
+#define _IAC_HWCFGR1		U(0x3F0)
+#define _IAC_VERR		U(0x3F4)
+
+/* IAC_HWCFGR2 register fields */
+#define _IAC_HWCFGR2_CFG1_MASK	GENMASK_32(3, 0)
+#define _IAC_HWCFGR2_CFG1_SHIFT	0
+#define _IAC_HWCFGR2_CFG2_MASK	GENMASK_32(7, 4)
+#define _IAC_HWCFGR2_CFG2_SHIFT	4
+
+/* IAC_HWCFGR1 register fields */
+#define _IAC_HWCFGR1_CFG1_MASK	GENMASK_32(3, 0)
+#define _IAC_HWCFGR1_CFG1_SHIFT	0
+#define _IAC_HWCFGR1_CFG2_MASK	GENMASK_32(7, 4)
+#define _IAC_HWCFGR1_CFG2_SHIFT	4
+#define _IAC_HWCFGR1_CFG3_MASK	GENMASK_32(11, 8)
+#define _IAC_HWCFGR1_CFG3_SHIFT	8
+#define _IAC_HWCFGR1_CFG4_MASK	GENMASK_32(15, 12)
+#define _IAC_HWCFGR1_CFG4_SHIFT	12
+#define _IAC_HWCFGR1_CFG5_MASK	GENMASK_32(24, 16)
+#define _IAC_HWCFGR1_CFG5_SHIFT	16
+
+/* IAC_VERR register fields */
+#define _IAC_VERR_MINREV_MASK	GENMASK_32(3, 0)
+#define _IAC_VERR_MINREV_SHIFT	0
+#define _IAC_VERR_MAJREV_MASK	GENMASK_32(7, 4)
+#define _IAC_VERR_MAJREV_SHIFT	4
+
+/* Periph ID per register */
+#define _PERIPH_IDS_PER_REG	32
+
+#define _IAC_FLD_PREP(field, value)	(SHIFT_U32((value), \
+						   (field ## _SHIFT)) & \
+					 (field ## _MASK))
+#define _IAC_FLD_GET(field, value)	(((uint32_t)(value) & \
+					  (field ## _MASK)) >> \
+					 (field ## _SHIFT))
+
+#define IAC_EXCEPT_MSB_BIT(x)		((x) * _PERIPH_IDS_PER_REG + \
+					 _PERIPH_IDS_PER_REG - 1)
+#define IAC_EXCEPT_LSB_BIT(x)		((x) * _PERIPH_IDS_PER_REG)
+#define IAC_FIRST_ILAC_IN_REG(x)	(__builtin_ffs((x)) - 1)
+#define IAC_ILAC_ID(reg_val, offset)	(IAC_FIRST_ILAC_IN_REG(reg_val) + \
+					 IAC_EXCEPT_LSB_BIT(offset))
+
+/**
+ * struct iac_driver_data - Hardware information on the IAC peripheral
+ *
+ * @version: Peripheral version number
+ * @num_ilac: Number of IAC lines
+ */
+struct iac_driver_data {
+	uint32_t version;
+	uint8_t num_ilac;
+};
+
+/**
+ * struct stm32_iac_platdata - Platform data for the IAC driver
+ *
+ * @irq_chip: Reference to the main IRQ chip of the platform
+ * @base: Virtual base address of the IAC peripheral
+ * @irq: ID of the IAC interrupt
+ */
+struct stm32_iac_platdata {
+	struct itr_chip *irq_chip;
+	vaddr_t base;
+	size_t irq;
+};
+
+/**
+ * struct iac_device - IAC device private data
+ * @pdata: Platform data read from the DT
+ * @ddata: Device data read from the hardware
+ * @itr: Interrupt handler reference
+ */
+struct iac_device {
+	struct stm32_iac_platdata pdata;
+	struct iac_driver_data *ddata;
+	struct itr_handler *itr;
+};
+
+static struct iac_device iac_dev;
+
+static void stm32_iac_get_hwdata(void)
+{
+	struct iac_driver_data *ddata = iac_dev.ddata;
+	vaddr_t base = iac_dev.pdata.base;
+	uint32_t regval = 0;
+
+	regval = io_read32(base + _IAC_HWCFGR1);
+	ddata->num_ilac = _IAC_FLD_GET(_IAC_HWCFGR1_CFG5, regval);
+
+	ddata->version = io_read32(base + _IAC_VERR);
+
+	DMSG("IAC version %"PRIu32".%"PRIu32,
+	     _IAC_FLD_GET(_IAC_VERR_MAJREV, ddata->version),
+	     _IAC_FLD_GET(_IAC_VERR_MINREV, ddata->version));
+
+	DMSG("HW cap: enabled, num ilac:[%"PRIu8"]", ddata->num_ilac);
+}
+
+static TEE_Result stm32_iac_parse_fdt(const void *fdt, int node)
+{
+	struct stm32_iac_platdata *pdata = &iac_dev.pdata;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info dt_info = { };
+	struct io_pa_va base = { };
+
+	fdt_fill_device_info(fdt, &dt_info, node);
+	if (dt_info.reg == DT_INFO_INVALID_REG)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq);
+	if (res)
+		return res;
+
+	base.pa = dt_info.reg;
+	pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size);
+
+	return TEE_SUCCESS;
+}
+
+static enum itr_return stm32_iac_itr(struct itr_handler *h __unused)
+{
+	struct iac_driver_data *ddata = iac_dev.ddata;
+	vaddr_t base = iac_dev.pdata.base;
+	unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
+	unsigned int i = 0;
+	uint32_t isr = 0;
+
+	for (i = 0; i < nreg; i++) {
+		uint32_t offset = sizeof(uint32_t) * i;
+		unsigned int j = 0;
+
+		isr = io_read32(base + _IAC_ISR0 + offset);
+		isr &= io_read32(base + _IAC_IER0 + offset);
+
+		if (!isr)
+			continue;
+
+		EMSG("IAC exceptions [%d:%d]: %#"PRIx32, IAC_EXCEPT_MSB_BIT(i),
+		     IAC_EXCEPT_LSB_BIT(i), isr);
+
+		for (j = 0; j < _PERIPH_IDS_PER_REG; j++) {
+			EMSG("IAC exception ID: %d", IAC_ILAC_ID(isr, i));
+
+			io_write32(base + _IAC_ICR0 + offset,
+				   BIT(IAC_FIRST_ILAC_IN_REG(isr)));
+
+			isr = io_read32(base + _IAC_ISR0 + offset);
+			isr &= io_read32(base + _IAC_IER0 + offset);
+
+			if (!isr)
+				break;
+		}
+	}
+
+	stm32_rif_access_violation_action();
+	if (IS_ENABLED(CFG_STM32_PANIC_ON_IAC_EVENT))
+		panic();
+
+	return ITRR_HANDLED;
+}
+
+static void stm32_iac_setup(void)
+{
+	struct iac_driver_data *ddata = iac_dev.ddata;
+	vaddr_t base = iac_dev.pdata.base;
+	unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
+	unsigned int i = 0;
+
+	for (i = 0; i < nreg; i++) {
+		vaddr_t reg_ofst = base + sizeof(uint32_t) * i;
+
+		/* Clear status flags */
+		io_write32(reg_ofst + _IAC_ICR0, ~0x0);
+		/* Enable all peripherals of nreg */
+		io_write32(reg_ofst + _IAC_IER0, ~0x0);
+	}
+}
+
+static TEE_Result probe_iac_device(const void *fdt, int node)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool is_tdcid = false;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	/* IAC must be managed by the trusted domain CID */
+	if (!is_tdcid)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	res = stm32_iac_parse_fdt(fdt, node);
+	if (res)
+		return res;
+
+	stm32_iac_get_hwdata();
+	stm32_iac_setup();
+
+	res = interrupt_alloc_add_handler(iac_dev.pdata.irq_chip,
+					  iac_dev.pdata.irq, stm32_iac_itr,
+					  ITRF_TRIGGER_LEVEL, NULL,
+					  &iac_dev.itr);
+	if (res)
+		panic();
+
+	interrupt_enable(iac_dev.pdata.irq_chip, iac_dev.itr->it);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_iac_probe(const void *fdt, int node,
+				  const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	iac_dev.ddata = calloc(1, sizeof(*iac_dev.ddata));
+	if (!iac_dev.ddata)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = probe_iac_device(fdt, node);
+	if (res)
+		free(iac_dev.ddata);
+
+	return res;
+}
+
+static const struct dt_device_match stm32_iac_match_table[] = {
+	{ .compatible = "st,stm32mp25-iac" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_iac_dt_driver) = {
+	.name = "stm32-iac",
+	.match_table = stm32_iac_match_table,
+	.probe = stm32_iac_probe,
+};
diff --git a/core/drivers/firewall/stm32_rif.c b/core/drivers/firewall/stm32_rif.c
new file mode 100644
index 0000000000000000000000000000000000000000..3045d47ed042ff6b66afe4fafc2f326c663a063c
--- /dev/null
+++ b/core/drivers/firewall/stm32_rif.c
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <drivers/stm32_rif.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <io.h>
+#include <kernel/panic.h>
+#include <mm/core_memprot.h>
+
+#define MAX_CID_BITFIELD	U(3)
+
+/**
+ * get_scid_mask() - Get the static CID mask according to the number of
+ *		     supported CIDs
+ *
+ * @nb_cid_supp: Number of CIDs supported. Cannot be 0.
+ */
+static uint32_t get_scid_mask(unsigned int nb_cid_supp)
+{
+	uint32_t msb_nb_cid_supp = 0;
+
+	assert(nb_cid_supp);
+
+	msb_nb_cid_supp = sizeof(nb_cid_supp) * 8 -
+			  __builtin_clz((nb_cid_supp - 1) | 1);
+
+	/* SCID bitfield highend can't be > SCID_SHIFT + MAX_CID_BITFIELD */
+	assert(msb_nb_cid_supp <= MAX_CID_BITFIELD);
+
+	return GENMASK_32(_CIDCFGR_SCID_SHIFT + msb_nb_cid_supp - 1,
+			  _CIDCFGR_SCID_SHIFT);
+}
+
+TEE_Result stm32_rif_check_access(uint32_t cidcfgr,
+				  uint32_t semcr,
+				  unsigned int nb_cid_supp,
+				  unsigned int cid_to_check)
+{
+	uint32_t scid_mask = get_scid_mask(nb_cid_supp);
+
+	if (!(cidcfgr & _CIDCFGR_CFEN))
+		return TEE_SUCCESS;
+
+	if (stm32_rif_scid_ok(cidcfgr, scid_mask, cid_to_check))
+		return TEE_SUCCESS;
+
+	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, cid_to_check)) {
+		if (!(semcr & _SEMCR_MUTEX) ||
+		    ((semcr & scid_mask) >> _CIDCFGR_SCID_SHIFT) ==
+		    cid_to_check) {
+			return TEE_SUCCESS;
+		}
+	}
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+void stm32_rif_parse_cfg(uint32_t rif_conf, struct rif_conf_data *conf_data,
+			 unsigned int nb_channel)
+{
+	uint32_t channel_id = 0;
+	unsigned int conf_index = 0;
+
+	/* Shift corresponding to the desired resources */
+	channel_id = RIF_CHANNEL_ID(rif_conf);
+	if (channel_id >= nb_channel)
+		panic("Bad RIF controllers number");
+
+	/* Some peripherals have more than 32 RIF channels */
+	conf_index = channel_id / 32;
+
+	/* Privilege configuration */
+	if (rif_conf & BIT(RIF_PRIV_SHIFT))
+		conf_data->priv_conf[conf_index] |= BIT(channel_id);
+
+	/* Security RIF configuration */
+	if (rif_conf & BIT(RIF_SEC_SHIFT))
+		conf_data->sec_conf[conf_index] |= BIT(channel_id);
+
+	/* RIF configuration lock */
+	if (rif_conf & BIT(RIF_LOCK_SHIFT) && conf_data->lock_conf)
+		conf_data->lock_conf[conf_index] |= BIT(channel_id);
+
+	/* CID configuration */
+	conf_data->cid_confs[channel_id] = (rif_conf & RIF_PERx_CID_MASK) >>
+					   RIF_PERx_CID_SHIFT;
+
+	/* Store that this RIF resource is to be configured */
+	conf_data->access_mask[conf_index] |= BIT(channel_id);
+}
+
+bool stm32_rif_semaphore_is_available(vaddr_t addr)
+{
+	return !(io_read32(addr) & _SEMCR_MUTEX);
+}
+
+TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr, unsigned int nb_cid_supp)
+{
+	uint32_t scid_mask = get_scid_mask(nb_cid_supp);
+
+	/* Take the semaphore */
+	io_setbits32(addr, _SEMCR_MUTEX);
+
+	/* Check that the Cortex-A has the semaphore */
+	if (stm32_rif_semaphore_is_available(addr) ||
+	    ((io_read32(addr) & scid_mask) >> _CIDCFGR_SCID_SHIFT) != RIF_CID1)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result stm32_rif_release_semaphore(vaddr_t addr, unsigned int nb_cid_supp)
+{
+	uint32_t scid_mask = get_scid_mask(nb_cid_supp);
+
+	if (stm32_rif_semaphore_is_available(addr))
+		return TEE_SUCCESS;
+
+	/* Release the semaphore */
+	io_clrbits32(addr, _SEMCR_MUTEX);
+
+	/* Check that current compartment no more owns the semaphore */
+	if (!stm32_rif_semaphore_is_available(addr) &&
+	    ((io_read32(addr) & scid_mask) >> _CIDCFGR_SCID_SHIFT) == RIF_CID1)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	return TEE_SUCCESS;
+}
diff --git a/core/drivers/firewall/stm32_rifsc.c b/core/drivers/firewall/stm32_rifsc.c
new file mode 100644
index 0000000000000000000000000000000000000000..a0fff9250bf505cc77697c7f0032e2158df21c62
--- /dev/null
+++ b/core/drivers/firewall/stm32_rifsc.c
@@ -0,0 +1,883 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics
+ */
+
+#include <drivers/firewall.h>
+#include <drivers/stm32_rif.h>
+#include <drivers/stm32_shared_io.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stm32_util.h>
+#include <tee_api_defines.h>
+#include <trace.h>
+#include <util.h>
+
+/* RIFSC offset register */
+#define _RIFSC_RISC_SECCFGR0		U(0x10)
+#define _RIFSC_RISC_PRIVCFGR0		U(0x30)
+#define _RIFSC_RISC_RCFGLOCKR0		U(0x50)
+#define _RIFSC_RISC_PER0_CIDCFGR	U(0x100)
+#define _RIFSC_RISC_PER0_SEMCR		U(0x104)
+#define _RIFSC_RIMC_CR			U(0xC00)
+#define _RIFSC_RIMC_ATTR0		U(0xC10)
+
+#define _RIFSC_HWCFGR3			U(0xFE8)
+#define _RIFSC_HWCFGR2			U(0xFEC)
+#define _RIFSC_HWCFGR1			U(0xFF0)
+#define _RIFSC_VERR			U(0xFF4)
+
+/* RIFSC_HWCFGR2 register fields */
+#define _RIFSC_HWCFGR2_CFG1_MASK	GENMASK_32(15, 0)
+#define _RIFSC_HWCFGR2_CFG1_SHIFT	U(0)
+#define _RIFSC_HWCFGR2_CFG2_MASK	GENMASK_32(23, 16)
+#define _RIFSC_HWCFGR2_CFG2_SHIFT	U(16)
+#define _RIFSC_HWCFGR2_CFG3_MASK	GENMASK_32(31, 24)
+#define _RIFSC_HWCFGR2_CFG3_SHIFT	U(24)
+
+/* RIFSC_HWCFGR1 register fields */
+#define _RIFSC_HWCFGR1_CFG1_MASK	GENMASK_32(3, 0)
+#define _RIFSC_HWCFGR1_CFG1_SHIFT	U(0)
+#define _RIFSC_HWCFGR1_CFG2_MASK	GENMASK_32(7, 4)
+#define _RIFSC_HWCFGR1_CFG2_SHIFT	U(4)
+#define _RIFSC_HWCFGR1_CFG3_MASK	GENMASK_32(11, 8)
+#define _RIFSC_HWCFGR1_CFG3_SHIFT	U(8)
+#define _RIFSC_HWCFGR1_CFG4_MASK	GENMASK_32(15, 12)
+#define _RIFSC_HWCFGR1_CFG4_SHIFT	U(12)
+#define _RIFSC_HWCFGR1_CFG5_MASK	GENMASK_32(19, 16)
+#define _RIFSC_HWCFGR1_CFG5_SHIFT	U(16)
+#define _RIFSC_HWCFGR1_CFG6_MASK	GENMASK_32(23, 20)
+#define _RIFSC_HWCFGR1_CFG6_SHIFT	U(20)
+
+/*
+ * RISC_CR register fields
+ */
+#define _RIFSC_RISC_CR_GLOCK		BIT(0)
+
+/*
+ * RIMC_CR register fields
+ */
+#define _RIFSC_RIMC_CR_GLOCK		BIT(0)
+#define _RIFSC_RIMC_CR_TDCID_MASK	GENMASK_32(6, 4)
+
+/* RIFSC_VERR register fields */
+#define _RIFSC_VERR_MINREV_MASK		GENMASK_32(3, 0)
+#define _RIFSC_VERR_MINREV_SHIFT	U(0)
+#define _RIFSC_VERR_MAJREV_MASK		GENMASK_32(7, 4)
+#define _RIFSC_VERR_MAJREV_SHIFT	U(4)
+
+/* Periph id per register */
+#define _PERIPH_IDS_PER_REG		U(32)
+#define _OFFSET_PERX_CIDCFGR		U(0x8)
+
+#define RIFSC_RISC_CIDCFGR_CFEN_MASK	BIT(0)
+#define RIFSC_RISC_CIDCFGR_CFEN_SHIFT	U(0)
+#define RIFSC_RISC_CIDCFGR_SEM_EN_MASK	BIT(1)
+#define RIFSC_RISC_CIDCFGR_SEM_EN_SHIFT	U(1)
+#define RIFSC_RISC_CIDCFGR_SCID_MASK	GENMASK_32(6, 4)
+#define RIFSC_RISC_CIDCFGR_SCID_SHIFT	U(4)
+#define RIFSC_RISC_CIDCFGR_LOCK_MASK	BIT(10)
+#define RIFSC_RISC_CIDCFGR_LOCK_SHIFT	U(10)
+#define RIFSC_RISC_CIDCFGR_SEML_MASK	GENMASK_32(23, 16)
+#define RIFSC_RISC_CIDCFGR_SEML_SHIFT	U(16)
+
+#define RIFSC_RISC_PERx_CID_MASK	(RIFSC_RISC_CIDCFGR_CFEN_MASK | \
+					 RIFSC_RISC_CIDCFGR_SEM_EN_MASK | \
+					 RIFSC_RISC_CIDCFGR_SCID_MASK | \
+					 RIFSC_RISC_CIDCFGR_SCID_SHIFT)
+
+#define RIFSC_RISC_PERx_CID_SHIFT	U(0)
+
+#define RIFSC_RIMC_MODE_MASK		BIT(2)
+#define RIFSC_RIMC_MCID_MASK		GENMASK_32(6, 4)
+#define RIFSC_RIMC_MSEC_MASK		BIT(8)
+#define RIFSC_RIMC_MPRIV_MASK		BIT(9)
+#define RIFSC_RIMC_M_ID_MASK		GENMASK_32(23, 16)
+
+#define RIFSC_RIMC_ATTRx_MASK		(RIFSC_RIMC_MODE_MASK | \
+					 RIFSC_RIMC_MCID_MASK | \
+					 RIFSC_RIMC_MSEC_MASK | \
+					 RIFSC_RIMC_MPRIV_MASK)
+
+/* max entries */
+#define MAX_RIMU			U(16)
+#define MAX_RISUP			U(128)
+
+#define _RIF_FLD_GET(field, value)	(((uint32_t)(value) & \
+					  (field ## _MASK)) >>\
+					 (field ## _SHIFT))
+
+struct risup_cfg {
+	uint32_t cid_attr;
+	uint32_t id;
+	bool sec;
+	bool priv;
+	bool lock;
+	bool pm_sem;
+};
+
+struct rimu_cfg {
+	uint32_t id;
+	uint32_t attr;
+};
+
+struct rifsc_driver_data {
+	bool rif_en;
+	bool sec_en;
+	bool priv_en;
+	uint8_t nb_rimu;
+	uint8_t nb_risup;
+	uint8_t nb_risal;
+	uint8_t version;
+};
+
+struct rifsc_platdata {
+	uintptr_t base;
+	struct rifsc_driver_data *drv_data;
+	struct risup_cfg *risup;
+	unsigned int nrisup;
+	struct rimu_cfg *rimu;
+	unsigned int nrimu;
+	bool is_tdcid;
+};
+
+/* There is only 1 instance of the RIFSC subsystem */
+static struct rifsc_driver_data rifsc_drvdata;
+static struct rifsc_platdata rifsc_pdata;
+
+static void stm32_rifsc_get_driverdata(struct rifsc_platdata *pdata)
+{
+	uint32_t regval = 0;
+
+	regval = io_read32(pdata->base + _RIFSC_HWCFGR1);
+	rifsc_drvdata.rif_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG1, regval) != 0;
+	rifsc_drvdata.sec_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG2, regval) != 0;
+	rifsc_drvdata.priv_en = _RIF_FLD_GET(_RIFSC_HWCFGR1_CFG3, regval) != 0;
+
+	regval = io_read32(pdata->base + _RIFSC_HWCFGR2);
+	rifsc_drvdata.nb_risup = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG1, regval);
+	rifsc_drvdata.nb_rimu = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG2, regval);
+	rifsc_drvdata.nb_risal = _RIF_FLD_GET(_RIFSC_HWCFGR2_CFG3, regval);
+
+	pdata->drv_data = &rifsc_drvdata;
+
+	rifsc_drvdata.version = io_read8(pdata->base + _RIFSC_VERR);
+
+	DMSG("RIFSC version %"PRIu32".%"PRIu32,
+	     _RIF_FLD_GET(_RIFSC_VERR_MAJREV, rifsc_drvdata.version),
+	     _RIF_FLD_GET(_RIFSC_VERR_MINREV, rifsc_drvdata.version));
+
+	DMSG("HW cap: enabled[rif:sec:priv]:[%s:%s:%s] nb[risup|rimu|risal]:[%"PRIu8",%"PRIu8",%"PRIu8"]",
+	     rifsc_drvdata.rif_en ? "true" : "false",
+	     rifsc_drvdata.sec_en ? "true" : "false",
+	     rifsc_drvdata.priv_en ? "true" : "false",
+	     rifsc_drvdata.nb_risup,
+	     rifsc_drvdata.nb_rimu,
+	     rifsc_drvdata.nb_risal);
+}
+
+static TEE_Result stm32_rifsc_glock_config(const void *fdt, int node,
+					   struct rifsc_platdata *pdata)
+{
+	const fdt32_t *cuint = NULL;
+	uint32_t glock_conf = 0;
+	int len = 0;
+
+	cuint = fdt_getprop(fdt, node, "st,glocked", &len);
+	if (!cuint) {
+		DMSG("No global lock on RIF configuration");
+		return TEE_SUCCESS;
+	}
+	assert(len == sizeof(uint32_t));
+
+	glock_conf = fdt32_to_cpu(*cuint);
+
+	if (glock_conf & RIFSC_RIMU_GLOCK) {
+		DMSG("Setting global lock on RIMU configuration");
+
+		io_setbits32(pdata->base + _RIFSC_RIMC_CR,
+			     _RIFSC_RIMC_CR_GLOCK);
+
+		if (!(io_read32(pdata->base + _RIFSC_RIMC_CR) &
+		      _RIFSC_RIMC_CR_GLOCK))
+			return TEE_ERROR_ACCESS_DENIED;
+	}
+
+	if (glock_conf & RIFSC_RISUP_GLOCK) {
+		DMSG("Setting global lock on RISUP configuration");
+
+		io_setbits32(pdata->base, _RIFSC_RISC_CR_GLOCK);
+
+		if (!(io_read32(pdata->base) & _RIFSC_RISC_CR_GLOCK))
+			return TEE_ERROR_ACCESS_DENIED;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_dt_conf_risup(const void *fdt, int node,
+					    struct rifsc_platdata *pdata)
+{
+	const fdt32_t *conf_list = NULL;
+	unsigned int i = 0;
+	int len = 0;
+
+	conf_list = fdt_getprop(fdt, node, "st,protreg", &len);
+	if (!conf_list) {
+		DMSG("No RISUP configuration in DT");
+		return TEE_ERROR_ITEM_NOT_FOUND;
+	}
+	assert(!(len % sizeof(uint32_t)));
+
+	pdata->nrisup = len / sizeof(uint32_t);
+	pdata->risup = calloc(pdata->nrisup, sizeof(*pdata->risup));
+	if (!pdata->risup)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	for (i = 0; i < pdata->nrisup; i++) {
+		uint32_t value = fdt32_to_cpu(conf_list[i]);
+		struct risup_cfg *risup = pdata->risup + i;
+
+		risup->id = _RIF_FLD_GET(RIF_PER_ID, value);
+		risup->sec = _RIF_FLD_GET(RIF_SEC, value) != 0;
+		risup->priv = _RIF_FLD_GET(RIF_PRIV, value) != 0;
+		risup->lock = _RIF_FLD_GET(RIF_LOCK, value) != 0;
+		risup->cid_attr = _RIF_FLD_GET(RIF_PERx_CID, value);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_dt_conf_rimu(const void *fdt, int node,
+					   struct rifsc_platdata *pdata)
+{
+	const fdt32_t *conf_list = NULL;
+	unsigned int i = 0;
+	int len = 0;
+
+	conf_list = fdt_getprop(fdt, node, "st,rimu", &len);
+	if (!conf_list) {
+		DMSG("No RIMU configuration in DT");
+		return TEE_ERROR_ITEM_NOT_FOUND;
+	}
+	assert(!(len % sizeof(uint32_t)));
+
+	pdata->nrimu = len / sizeof(uint32_t);
+	pdata->rimu = calloc(pdata->nrimu, sizeof(*pdata->rimu));
+	if (!pdata->rimu)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	for (i = 0; i < pdata->nrimu; i++) {
+		uint32_t value = fdt32_to_cpu(*conf_list);
+		struct rimu_cfg *rimu = pdata->rimu + i;
+
+		rimu->id = _RIF_FLD_GET(RIMUPROT_RIMC_M_ID, value) -
+			   RIMU_ID_OFFSET;
+		rimu->attr = _RIF_FLD_GET(RIMUPROT_RIMC_ATTRx, value);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_parse_fdt(const void *fdt, int node,
+					struct rifsc_platdata *pdata)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct io_pa_va base = { };
+	size_t reg_size = 0;
+
+	if (fdt_reg_info(fdt, node, &base.pa, &reg_size))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	pdata->base = io_pa_or_va_secure(&base, reg_size);
+
+	res = stm32_rifsc_check_tdcid(&rifsc_pdata.is_tdcid);
+	if (res)
+		panic();
+
+	res = stm32_rifsc_dt_conf_risup(fdt, node, pdata);
+	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
+		return res;
+
+	if (rifsc_pdata.is_tdcid) {
+		res = stm32_rifsc_dt_conf_rimu(fdt, node, pdata);
+		if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
+			return res;
+	}
+
+	return stm32_rifsc_dt_conf_rimu(fdt, node, pdata);
+}
+
+static TEE_Result stm32_risup_cfg(struct rifsc_platdata *pdata,
+				  struct risup_cfg *risup)
+{
+	uintptr_t offset = sizeof(uint32_t) * (risup->id / _PERIPH_IDS_PER_REG);
+	uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id;
+	struct rifsc_driver_data *drv_data = pdata->drv_data;
+	uint32_t shift = risup->id % _PERIPH_IDS_PER_REG;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!risup || risup->id >= drv_data->nb_risup)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (drv_data->sec_en)
+		io_clrsetbits32_stm32shregs(pdata->base + _RIFSC_RISC_SECCFGR0 +
+					    offset, BIT(shift),
+					    SHIFT_U32(risup->sec, shift));
+
+	if (drv_data->priv_en)
+		io_clrsetbits32_stm32shregs(pdata->base +
+					    _RIFSC_RISC_PRIVCFGR0 + offset,
+					    BIT(shift),
+					    SHIFT_U32(risup->priv, shift));
+
+	if (rifsc_pdata.is_tdcid) {
+		if (drv_data->rif_en)
+			io_write32(pdata->base + _RIFSC_RISC_PER0_CIDCFGR +
+				   cidcfgr_offset, risup->cid_attr);
+
+		/* Lock configuration for this RISUP */
+		if (risup->lock) {
+			DMSG("Locking RIF conf for peripheral ID: %"PRIu32,
+			     risup->id);
+			io_setbits32_stm32shregs(pdata->base +
+						 _RIFSC_RISC_RCFGLOCKR0 +
+						 offset, BIT(shift));
+		}
+	}
+
+	/* Take semaphore if the resource is in semaphore mode and secured */
+	if (stm32_rif_semaphore_enabled_and_ok(risup->cid_attr, RIF_CID1)) {
+		if (!(io_read32(pdata->base + _RIFSC_RISC_SECCFGR0 + offset) &
+		      BIT(shift))) {
+			res =
+			stm32_rif_release_semaphore(pdata->base +
+						    _RIFSC_RISC_PER0_SEMCR +
+						    cidcfgr_offset,
+						    MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Couldn't release semaphore for resource %"PRIu32,
+				     risup->id);
+				return TEE_ERROR_ACCESS_DENIED;
+			}
+		} else {
+			res =
+			stm32_rif_acquire_semaphore(pdata->base +
+						    _RIFSC_RISC_PER0_SEMCR +
+						    cidcfgr_offset,
+						    MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Couldn't acquire semaphore for resource %"PRIu32,
+				     risup->id);
+				return TEE_ERROR_ACCESS_DENIED;
+			}
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_risup_setup(struct rifsc_platdata *pdata)
+{
+	struct rifsc_driver_data *drv_data = pdata->drv_data;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+
+	for (i = 0; i < pdata->nrisup && i < drv_data->nb_risup; i++) {
+		struct risup_cfg *risup = pdata->risup + i;
+
+		res = stm32_risup_cfg(pdata, risup);
+		if (res) {
+			EMSG("risup cfg(%d/%d) error", i + 1, pdata->nrisup);
+			return res;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rimu_cfg(struct rifsc_platdata *pdata,
+				 struct rimu_cfg *rimu)
+{
+	uintptr_t offset =  _RIFSC_RIMC_ATTR0 + (sizeof(uint32_t) * rimu->id);
+	struct rifsc_driver_data *drv_data = pdata->drv_data;
+
+	if (!rimu || rimu->id >= drv_data->nb_rimu)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (drv_data->rif_en)
+		io_write32(pdata->base + offset, rimu->attr);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rimu_setup(struct rifsc_platdata *pdata)
+{
+	struct rifsc_driver_data *drv_data = pdata->drv_data;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+
+	for (i = 0; i < pdata->nrimu && i < drv_data->nb_rimu; i++) {
+		struct rimu_cfg *rimu = pdata->rimu + i;
+
+		res = stm32_rimu_cfg(pdata, rimu);
+		if (res) {
+			EMSG("rimu cfg(%d/%d) error", i + 1, pdata->nrimu);
+			return res;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_check_access(struct firewall_query *firewall)
+{
+	uintptr_t rifsc_base = rifsc_pdata.base;
+	unsigned int cid_reg_offset = 0;
+	unsigned int periph_offset = 0;
+	unsigned int resource_id = 0;
+	uint32_t cid_to_check = 0;
+	unsigned int reg_id = 0;
+	bool priv_check = true;
+	bool sec_check = true;
+	uint32_t privcfgr = 0;
+	uint32_t seccfgr = 0;
+	uint32_t cidcfgr = 0;
+
+	assert(rifsc_base);
+
+	if (!firewall || firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * Peripheral configuration, we assume the configuration is as
+	 * follows:
+	 * firewall->args[0]: RIF configuration to check
+	 */
+	resource_id = firewall->args[0] & RIF_PER_ID_MASK;
+	if (resource_id >= RIMU_ID_OFFSET)
+		return TEE_SUCCESS;
+
+	reg_id = resource_id / _PERIPH_IDS_PER_REG;
+	periph_offset = resource_id % _PERIPH_IDS_PER_REG;
+	cid_reg_offset = _OFFSET_PERX_CIDCFGR * resource_id;
+	cidcfgr = io_read32(rifsc_base + _RIFSC_RISC_PER0_CIDCFGR +
+			    cid_reg_offset);
+	seccfgr = io_read32(rifsc_base + _RIFSC_RISC_SECCFGR0 + 0x4 * reg_id);
+	privcfgr = io_read32(rifsc_base + _RIFSC_RISC_PRIVCFGR0 + 0x4 * reg_id);
+	sec_check = (BIT(RIF_SEC_SHIFT) & firewall->args[0]) != 0;
+	priv_check = (BIT(RIF_PRIV_SHIFT) & firewall->args[0]) != 0;
+	cid_to_check = (firewall->args[0] & RIF_SCID_MASK) >> RIF_SCID_SHIFT;
+
+	if (!sec_check && seccfgr & BIT(periph_offset))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	if (!priv_check && (privcfgr & BIT(periph_offset)))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	if (!(cidcfgr & _CIDCFGR_CFEN))
+		return TEE_SUCCESS;
+
+	if ((cidcfgr & _CIDCFGR_SEMEN &&
+	     !stm32_rif_semaphore_enabled_and_ok(cidcfgr, cid_to_check)) ||
+	    (!(cidcfgr & _CIDCFGR_SEMEN) &&
+	     !stm32_rif_scid_ok(cidcfgr, RIFSC_RISC_CIDCFGR_SCID_MASK,
+				cid_to_check)))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_acquire_access(struct firewall_query *firewall)
+{
+	uintptr_t rifsc_base = rifsc_pdata.base;
+	unsigned int cid_reg_offset = 0;
+	unsigned int periph_offset = 0;
+	unsigned int resource_id = 0;
+	unsigned int reg_id = 0;
+	uint32_t cidcfgr = 0;
+	uint32_t seccfgr = 0;
+
+	assert(rifsc_base);
+
+	if (!firewall || !firewall->arg_count)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * Peripheral configuration, we assume the configuration is as
+	 * follows:
+	 * firewall->args[0]: Firewall ID of the resource to acquire
+	 */
+	resource_id = firewall->args[0] & RIF_PER_ID_MASK;
+	if (resource_id >= RIMU_ID_OFFSET)
+		return TEE_SUCCESS;
+
+	reg_id = resource_id / _PERIPH_IDS_PER_REG;
+	periph_offset = resource_id % _PERIPH_IDS_PER_REG;
+
+	cid_reg_offset = _OFFSET_PERX_CIDCFGR * resource_id;
+	cidcfgr = io_read32(rifsc_base + _RIFSC_RISC_PER0_CIDCFGR +
+			    cid_reg_offset);
+
+	seccfgr = io_read32(rifsc_base + _RIFSC_RISC_SECCFGR0 + 0x4 * reg_id);
+	if (!(seccfgr & BIT(periph_offset)))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	/* Only check CID attributes */
+	if (!(cidcfgr & _CIDCFGR_CFEN))
+		return TEE_SUCCESS;
+
+	if (cidcfgr & _CIDCFGR_SEMEN) {
+		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		/* Take the semaphore, static CID is irrelevant here */
+		return stm32_rif_acquire_semaphore(rifsc_base +
+						   _RIFSC_RISC_PER0_SEMCR +
+						   cid_reg_offset,
+						   MAX_CID_SUPPORTED);
+	}
+
+	if (!stm32_rif_scid_ok(cidcfgr, RIFSC_RISC_CIDCFGR_SCID_MASK, RIF_CID1))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_set_config(struct firewall_query *firewall)
+{
+	struct rimu_cfg rimu = { };
+	unsigned int id = 0;
+	uint32_t conf = 0;
+
+	if (!firewall || firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * Peripheral configuration, we assume the configuration is as
+	 * follows:
+	 * firewall->args[0]: RIF configuration to set
+	 */
+	id = firewall->args[0] & RIF_PER_ID_MASK;
+	conf = firewall->args[0];
+
+	if (id < RIMU_ID_OFFSET) {
+		struct risup_cfg risup = { };
+		uint32_t cidcfgr = 0;
+
+		risup.id = id;
+		risup.sec = (BIT(RIF_SEC_SHIFT) & conf) != 0;
+		risup.priv = (BIT(RIF_PRIV_SHIFT) & conf) != 0;
+		risup.lock = (BIT(RIF_LOCK_SHIFT) & conf) != 0;
+		risup.cid_attr = _RIF_FLD_GET(RIF_PERx_CID, conf);
+
+		if (!rifsc_pdata.is_tdcid) {
+			cidcfgr = io_read32(rifsc_pdata.base +
+					    _OFFSET_PERX_CIDCFGR * risup.id +
+					    _RIFSC_RISC_PER0_CIDCFGR);
+
+			if (cidcfgr != risup.cid_attr)
+				return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+		DMSG("Setting config for peripheral: %u, %s, %s, cid attr: %#"PRIx32", %s",
+		     id, risup.sec ? "Secure" : "Non secure",
+		     risup.priv ? "Privileged" : "Non privileged",
+		     risup.cid_attr, risup.lock ? "Locked" : "Unlocked");
+
+		return stm32_risup_cfg(&rifsc_pdata, &risup);
+	}
+
+	if (!rifsc_pdata.is_tdcid)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	rimu.id = _RIF_FLD_GET(RIMUPROT_RIMC_M_ID, conf) - RIMU_ID_OFFSET;
+	rimu.attr = _RIF_FLD_GET(RIMUPROT_RIMC_ATTRx, conf);
+
+	return stm32_rimu_cfg(&rifsc_pdata, &rimu);
+}
+
+static void stm32_rifsc_release_access(struct firewall_query *firewall)
+{
+	uintptr_t rifsc_base = rifsc_pdata.base;
+	uint32_t cidcfgr = 0;
+	uint32_t id = 0;
+
+	assert(rifsc_base && firewall && firewall->arg_count);
+
+	id = firewall->args[0];
+
+	if (id >= RIMU_ID_OFFSET)
+		return;
+
+	cidcfgr = io_read32(rifsc_base + _RIFSC_RISC_PER0_CIDCFGR +
+			    _OFFSET_PERX_CIDCFGR * id);
+
+	/* Only thing possible is to release a semaphore taken by OP-TEE CID */
+	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+		if (stm32_rif_release_semaphore(rifsc_base +
+						_RIFSC_RISC_PER0_SEMCR +
+						id * _OFFSET_PERX_CIDCFGR,
+						MAX_CID_SUPPORTED))
+			panic("Could not release the RIF semaphore");
+}
+
+static TEE_Result stm32_rifsc_sem_pm_suspend(void)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) {
+		uint32_t semcfgr = io_read32(rifsc_pdata.base +
+					     _RIFSC_RISC_PER0_SEMCR +
+					     _OFFSET_PERX_CIDCFGR * i);
+		struct risup_cfg *risup = rifsc_pdata.risup + i;
+
+		/* Save semaphores that were taken by the CID1 */
+		risup->pm_sem = semcfgr & _SEMCR_MUTEX &&
+				((semcfgr & _SEMCR_SEMCID_MASK) >>
+				 _SEMCR_SEMCID_SHIFT) == RIF_CID1;
+
+		FMSG("RIF semaphore %s for ID: %"PRIu32,
+		     risup->pm_sem ? "SAVED" : "NOT SAVED", risup->id);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_sem_pm_resume(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+
+	for (i = 0; i < rifsc_pdata.nrisup && i < rifsc_drvdata.nb_risup; i++) {
+		struct risup_cfg *risup = rifsc_pdata.risup + i;
+		uintptr_t cidcfgr_offset = _OFFSET_PERX_CIDCFGR * risup->id;
+		uintptr_t offset = sizeof(uint32_t) *
+				   (risup->id / _PERIPH_IDS_PER_REG);
+		uintptr_t perih_offset = risup->id % _PERIPH_IDS_PER_REG;
+		uint32_t seccgfr = io_read32(rifsc_pdata.base +
+					     _RIFSC_RISC_SECCFGR0 + offset);
+		uint32_t privcgfr = io_read32(rifsc_pdata.base +
+					      _RIFSC_RISC_PRIVCFGR0 + offset);
+		uint32_t lockcfgr = io_read32(rifsc_pdata.base +
+					      _RIFSC_RISC_RCFGLOCKR0 + offset);
+
+		/* Update RISUPs fields */
+		risup->cid_attr = io_read32(rifsc_pdata.base +
+					    _RIFSC_RISC_PER0_CIDCFGR +
+					    cidcfgr_offset);
+		risup->sec = (seccgfr & BIT(perih_offset)) != 0;
+		risup->priv = (privcgfr & BIT(perih_offset)) != 0;
+		risup->lock = (lockcfgr & BIT(perih_offset)) != 0;
+
+		/* Acquire available appropriate semaphores */
+		if (!stm32_rif_semaphore_enabled_and_ok(risup->cid_attr,
+							RIF_CID1) ||
+		    !risup->pm_sem)
+			continue;
+
+		res = stm32_rif_acquire_semaphore(rifsc_pdata.base +
+						  _RIFSC_RISC_PER0_SEMCR +
+						  cidcfgr_offset,
+						  MAX_CID_SUPPORTED);
+		if (res) {
+			EMSG("Could not acquire semaphore for resource %"PRIu32,
+			     risup->id);
+			return TEE_ERROR_ACCESS_DENIED;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+stm32_rifsc_sem_pm(enum pm_op op, unsigned int pm_hint,
+		   const struct pm_callback_handle *pm_handle __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pm_hint != PM_HINT_CONTEXT_STATE)
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME)
+		res = stm32_rifsc_sem_pm_resume();
+	else
+		res = stm32_rifsc_sem_pm_suspend();
+
+	return res;
+}
+
+TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state)
+{
+	if (!rifsc_pdata.base)
+		return TEE_ERROR_DEFER_DRIVER_INIT;
+
+	if (((io_read32(rifsc_pdata.base + _RIFSC_RIMC_CR) &
+	     _RIFSC_RIMC_CR_TDCID_MASK)) == (RIF_CID1 << _CIDCFGR_SCID_SHIFT))
+		*tdcid_state = true;
+	else
+		*tdcid_state = false;
+
+	return TEE_SUCCESS;
+}
+
+static const struct firewall_controller_ops firewall_ops = {
+	.set_conf = stm32_rifsc_set_config,
+	.check_access = stm32_rifsc_check_access,
+	.acquire_access = stm32_rifsc_acquire_access,
+	.release_access = stm32_rifsc_release_access,
+};
+
+/**
+ * stm32_rifsc_dt_probe_bus() - Add bus device tree subnodes that are accessible
+ * by OP-TEE and secure to the driver probe list. This is used at boot time
+ * only, as a sanity check between device tree and firewalls hardware
+ * configurations to prevent undesired accesses when access to a device is not
+ * authorized. This function tries to acquire access to every resource entries
+ * listed in the access-controllers property of each of the subnodes. It panics
+ * if it fails to do so. When CFG_INSECURE is enabled, platform can bypass this
+ * access control test for specific devices assigned to non-secure world and
+ * used by OP-TEE, such as an UART console device.
+ *
+ * @fdt: FDT to work on
+ * @node: RIFSC node
+ * @ctrl: RIFSC firewall controller reference
+ */
+static TEE_Result
+stm32_rifsc_dt_probe_bus(const void *fdt, int node,
+			 struct firewall_controller *ctrl __maybe_unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct firewall_query *fw = NULL;
+	int subnode = 0;
+
+	DMSG("Populating %s firewall bus", ctrl->name);
+
+	fdt_for_each_subnode(subnode, fdt, node) {
+		unsigned int i = 0;
+
+		if (fdt_get_status(fdt, subnode) == DT_STATUS_DISABLED)
+			continue;
+
+		if (IS_ENABLED(CFG_INSECURE) &&
+		    stm32mp_allow_probe_shared_device(fdt, subnode)) {
+			DMSG("Skipping firewall attributes check for %s",
+			     fdt_get_name(fdt, subnode, NULL));
+			goto skip_check;
+		}
+
+		DMSG("Acquiring firewall access for %s when probing bus",
+		     fdt_get_name(fdt, subnode, NULL));
+
+		do {
+			/*
+			 * The access-controllers property is mandatory for
+			 * firewall bus devices
+			 */
+			res = firewall_dt_get_by_index(fdt, subnode, i, &fw);
+			if (res == TEE_ERROR_ITEM_NOT_FOUND) {
+				/* Stop when nothing more to parse */
+				break;
+			} else if (res) {
+				EMSG("%s: Error on node %s: %#"PRIx32,
+				     ctrl->name,
+				     fdt_get_name(fdt, subnode, NULL), res);
+				panic();
+			}
+
+			res = firewall_acquire_access(fw);
+			if (res) {
+				EMSG("%s: %s not accessible: %#"PRIx32,
+				     ctrl->name,
+				     fdt_get_name(fdt, subnode, NULL), res);
+				panic();
+			}
+
+			firewall_put(fw);
+			i++;
+		} while (true);
+
+skip_check:
+		res = dt_driver_maybe_add_probe_node(fdt, subnode);
+		if (res) {
+			EMSG("Failed on node %s with %#"PRIx32,
+			     fdt_get_name(fdt, subnode, NULL), res);
+			panic();
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rifsc_probe(const void *fdt, int node,
+				    const void *compat_data __unused)
+{
+	struct firewall_controller *controller = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = stm32_rifsc_parse_fdt(fdt, node, &rifsc_pdata);
+	if (res) {
+		EMSG("Could not parse RIFSC node, res = %#"PRIx32, res);
+		panic();
+	}
+
+	if (!rifsc_pdata.drv_data)
+		stm32_rifsc_get_driverdata(&rifsc_pdata);
+
+	res = stm32_risup_setup(&rifsc_pdata);
+	if (res) {
+		EMSG("Could not setup RISUPs, res = %#"PRIx32, res);
+		panic();
+	}
+
+	if (rifsc_pdata.is_tdcid) {
+		res = stm32_rimu_setup(&rifsc_pdata);
+		if (res) {
+			EMSG("Could not setup RIMUs, res = %#"PRIx32, res);
+			panic();
+		}
+	}
+
+	res = stm32_rifsc_glock_config(fdt, node, &rifsc_pdata);
+	if (res)
+		panic("Couldn't lock RIFSC configuration");
+
+	controller = calloc(1, sizeof(*controller));
+	if (!controller)
+		panic();
+
+	controller->name = "RIFSC";
+	controller->priv = &rifsc_pdata;
+	controller->ops = &firewall_ops;
+
+	res = firewall_dt_controller_register(fdt, node, controller);
+	if (res)
+		panic();
+
+	res = stm32_rifsc_dt_probe_bus(fdt, node, controller);
+	if (res)
+		panic();
+
+	register_pm_core_service_cb(stm32_rifsc_sem_pm, NULL,
+				    "stm32-rifsc-semaphores");
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match rifsc_match_table[] = {
+	{ .compatible = "st,stm32mp25-rifsc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(rifsc_dt_driver) = {
+	.name = "stm32-rifsc",
+	.match_table = rifsc_match_table,
+	.probe = stm32_rifsc_probe,
+};
diff --git a/core/drivers/firewall/stm32_risab.c b/core/drivers/firewall/stm32_risab.c
new file mode 100644
index 0000000000000000000000000000000000000000..3697e4fff47f6ed81c4901116428a66815ed4252
--- /dev/null
+++ b/core/drivers/firewall/stm32_risab.c
@@ -0,0 +1,815 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/firewall.h>
+#include <drivers/stm32_rif.h>
+#include <drivers/stm32_risab.h>
+#include <dt-bindings/firewall/stm32mp25-risab.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/pm.h>
+#include <kernel/tee_misc.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <stdint.h>
+#include <string_ext.h>
+#include <stm32_sysconf.h>
+#include <util.h>
+
+#define _RISAB_CR				U(0x0)
+#define _RISAB_IASR				U(0x8)
+#define _RISAB_IACR				U(0xC)
+#define _RISAB_RCFGLOCKR			U(0x10)
+#define _RISAB_IAESR				U(0x20)
+#define _RISAB_IADDR				U(0x24)
+#define _RISAB_PGy_SECCFGR(y)			(U(0x100) + (0x4 * (y)))
+#define _RISAB_PGy_PRIVCFGR(y)			(U(0x200) + (0x4 * (y)))
+#define _RISAB_RISAB_PGy_C2PRIVCFGR(y)		(U(0x600) + (0x4 * (y)))
+#define _RISAB_CIDxPRIVCFGR(x)			(U(0x800) + (0x20 * (x)))
+#define _RISAB_CIDxRDCFGR(x)			(U(0x808) + (0x20 * (x)))
+#define _RISAB_CIDxWRCFGR(x)			(U(0x810) + (0x20 * (x)))
+#define _RISAB_PGy_CIDCFGR(y)			(U(0xA00) + (0x4 * (y)))
+#define _RISAB_HWCFGR3				U(0xFE8)
+#define _RISAB_HWCFGR2				U(0xFEC)
+#define _RISAB_HWCFGR1				U(0xFF0)
+#define _RISAB_VERR				U(0xFF4)
+#define _RISAB_IPIDR				U(0xFF8)
+#define _RISAB_SIDR				U(0xFFC)
+
+/* RISAB_CR bitfields */
+#define _RISAB_CR_SRWIAD			BIT(31)
+
+/* RISAB_IACR bitfields */
+#define _RISAB_IACR_CAEF			BIT(0)
+#define _RISAB_IACR_IAEF			BIT(1)
+#define _RISAB_IACR_MASK			(_RISAB_IACR_CAEF | \
+						 _RISAB_IACR_IAEF)
+
+/* Define RISAB_PG_SECCFGR bitfields */
+#define _RISAB_PG_SECCFGR_MASK			GENMASK_32(7, 0)
+
+/* Define RISAB_PG_PRIVCFGR bitfields */
+#define _RISAB_PG_PRIVCFGR_MASK			GENMASK_32(7, 0)
+
+/* CIDCFGR bitfields */
+#define _RISAB_PG_CIDCFGR_CFEN			BIT(0)
+#define _RISAB_PG_CIDCFGR_DCEN			BIT(2)
+#define _RISAB_PG_CIDCFGR_DDCID_SHIFT		U(4)
+#define _RISAB_PG_CIDCFGR_DDCID_MASK		GENMASK_32(6, 4)
+#define _RISAB_PG_CIDCFGR_CONF_MASK		(_RISAB_PG_CIDCFGR_CFEN | \
+						 _RISAB_PG_CIDCFGR_DCEN | \
+						 _RISAB_PG_CIDCFGR_DDCID_MASK)
+
+/* Miscellaneous */
+#define _RISAB_NB_PAGES_MAX			U(32)
+#define _RISAB_PAGE_SIZE			U(0x1000)
+#define _RISAB_NB_MAX_CID_SUPPORTED		U(7)
+
+#define RISAB_NAME_LEN_MAX			U(20)
+
+struct mem_region {
+	paddr_t base;
+	size_t size;
+};
+
+struct stm32_risab_rif_conf {
+	unsigned int first_page;
+	unsigned int nb_pages_cfged;
+	uint32_t plist[_RISAB_NB_MAX_CID_SUPPORTED];
+	uint32_t rlist[_RISAB_NB_MAX_CID_SUPPORTED];
+	uint32_t wlist[_RISAB_NB_MAX_CID_SUPPORTED];
+	uint32_t cidcfgr;
+	uint32_t dprivcfgr;
+	uint32_t seccfgr;
+};
+
+struct stm32_risab_pdata {
+	unsigned int nb_regions_cfged;
+	struct clk *clock;
+	struct mem_region region_cfged;
+	struct stm32_risab_rif_conf *subr_cfg;
+	struct io_pa_va base;
+	unsigned int conf_lock;
+	char risab_name[RISAB_NAME_LEN_MAX];
+	uint32_t pages_configured;
+	bool srwiad;
+
+	SLIST_ENTRY(stm32_risab_pdata) link;
+};
+
+static SLIST_HEAD(, stm32_risab_pdata) risab_list =
+		SLIST_HEAD_INITIALIZER(risab_list);
+
+static bool is_tdcid;
+
+static vaddr_t risab_base(struct stm32_risab_pdata *risab)
+{
+	return io_pa_or_va_secure(&risab->base, 1);
+}
+
+void stm32_risab_clear_illegal_access_flags(void)
+{
+	struct stm32_risab_pdata *risab = NULL;
+
+	SLIST_FOREACH(risab, &risab_list, link) {
+		vaddr_t base = risab_base(risab);
+
+		if (!io_read32(base + _RISAB_IASR))
+			continue;
+
+		io_write32(base + _RISAB_IACR, _RISAB_IACR_CAEF |
+			   _RISAB_IACR_IAEF);
+	}
+}
+
+#ifdef CFG_TEE_CORE_DEBUG
+void stm32_risab_print_erroneous_data(void)
+{
+	struct stm32_risab_pdata *risab = NULL;
+
+	SLIST_FOREACH(risab, &risab_list, link) {
+		vaddr_t base = risab_base(risab);
+
+		/* Check if faulty address on this RISAB */
+		if (!io_read32(base + _RISAB_IASR))
+			continue;
+
+		EMSG("\n\nDUMPING DATA FOR %s\n\n", risab->risab_name);
+		EMSG("=====================================================");
+		EMSG("Status register (IAESR): %#"PRIx32,
+		     io_read32(base + _RISAB_IAESR));
+		EMSG("-----------------------------------------------------");
+		EMSG("Faulty address (IADDR): %#"PRIx32,
+		     io_read32(base + _RISAB_IADDR));
+		EMSG("=====================================================\n");
+	};
+}
+#endif /* CFG_TEE_CORE_DEBUG */
+
+static bool regs_access_granted(struct stm32_risab_pdata *risab_d,
+				unsigned int reg_idx)
+{
+	unsigned int first_page = risab_d->subr_cfg[reg_idx].first_page;
+	uint32_t cidcfgr = io_read32(risab_base(risab_d) +
+				     _RISAB_PGy_CIDCFGR(first_page));
+
+	/* Trusted CID access */
+	if (is_tdcid &&
+	    ((cidcfgr & _RISAB_PG_CIDCFGR_CFEN &&
+	      !(cidcfgr & _RISAB_PG_CIDCFGR_DCEN)) ||
+	     !(cidcfgr & _RISAB_PG_CIDCFGR_CFEN)))
+		return true;
+
+	/* Delegated CID access check */
+	if (cidcfgr & _RISAB_PG_CIDCFGR_CFEN &&
+	    cidcfgr & _RISAB_PG_CIDCFGR_DCEN &&
+	    ((cidcfgr & _RISAB_PG_CIDCFGR_DDCID_MASK) >>
+	     _RISAB_PG_CIDCFGR_DDCID_SHIFT) == RIF_CID1)
+		return true;
+
+	return false;
+}
+
+static void set_block_seccfgr(struct stm32_risab_pdata *risab_d,
+			      struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+
+	for (i = subr_cfg->first_page; i <= last_page; i++)
+		io_clrsetbits32(base + _RISAB_PGy_SECCFGR(i),
+				_RISAB_PG_SECCFGR_MASK, subr_cfg->seccfgr);
+}
+
+static void set_block_dprivcfgr(struct stm32_risab_pdata *risab_d,
+				struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+
+	for (i = subr_cfg->first_page; i <= last_page; i++)
+		io_clrsetbits32(base + _RISAB_PGy_PRIVCFGR(i),
+				_RISAB_PG_PRIVCFGR_MASK,
+				subr_cfg->dprivcfgr);
+}
+
+static void set_cidcfgr(struct stm32_risab_pdata *risab_d,
+			struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+
+	for (i = subr_cfg->first_page; i <= last_page; i++) {
+		/*
+		 * When TDCID, OP-TEE should be the one to set the CID filtering
+		 * configuration. Clearing previous configuration prevents
+		 * undesired events during the only legitimate configuration.
+		 */
+		io_clrsetbits32(base + _RISAB_PGy_CIDCFGR(i),
+				_RISAB_PG_CIDCFGR_CONF_MASK,
+				subr_cfg->cidcfgr);
+	}
+}
+
+static void set_read_conf(struct stm32_risab_pdata *risab_d,
+			  struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+	uint32_t mask = GENMASK_32(last_page, subr_cfg->first_page);
+
+	for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+		if (subr_cfg->rlist[i])
+			io_setbits32(base + _RISAB_CIDxRDCFGR(i), mask);
+	}
+}
+
+static void set_write_conf(struct stm32_risab_pdata *risab_d,
+			   struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+	uint32_t mask = GENMASK_32(last_page, subr_cfg->first_page);
+
+	for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+		if (subr_cfg->wlist[i])
+			io_setbits32(base + _RISAB_CIDxWRCFGR(i), mask);
+	}
+}
+
+static void set_cid_priv_conf(struct stm32_risab_pdata *risab_d,
+			      struct stm32_risab_rif_conf *subr_cfg)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+	unsigned int last_page = subr_cfg->first_page +
+				 subr_cfg->nb_pages_cfged - 1;
+	uint32_t mask = GENMASK_32(last_page, subr_cfg->first_page);
+
+	for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+		if (subr_cfg->plist[i])
+			io_clrsetbits32(base + _RISAB_CIDxPRIVCFGR(i), mask,
+					subr_cfg->plist[i]);
+	}
+}
+
+static void apply_rif_config(struct stm32_risab_pdata *risab_d)
+{
+	vaddr_t base = risab_base(risab_d);
+	unsigned int i = 0;
+
+	/* If TDCID, we expect to restore default RISAB configuration */
+	if (is_tdcid) {
+		for (i = 0; i < _RISAB_NB_PAGES_MAX; i++) {
+			io_clrbits32(base + _RISAB_PGy_CIDCFGR(i),
+				     _RISAB_PG_CIDCFGR_CONF_MASK);
+			io_clrbits32(base + _RISAB_PGy_SECCFGR(i),
+				     _RISAB_PG_SECCFGR_MASK);
+			io_clrbits32(base + _RISAB_PGy_PRIVCFGR(i),
+				     _RISAB_PG_PRIVCFGR_MASK);
+		}
+		for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+			io_clrbits32(base + _RISAB_CIDxRDCFGR(i), UINT32_MAX);
+			io_clrbits32(base + _RISAB_CIDxWRCFGR(i), UINT32_MAX);
+			io_clrbits32(base + _RISAB_CIDxPRIVCFGR(i), UINT32_MAX);
+		}
+	}
+
+	for (i = 0; i < risab_d->nb_regions_cfged; i++) {
+		set_block_dprivcfgr(risab_d, &risab_d->subr_cfg[i]);
+
+		/* Only cortex A35 running OP-TEE can access RISAB1/2 */
+		if (virt_to_phys((void *)base) != RISAB1_BASE &&
+		    virt_to_phys((void *)base) != RISAB2_BASE) {
+			/* Delegate RIF configuration or not */
+			if (!is_tdcid)
+				DMSG("Cannot set %s CID config for region %u",
+				     risab_d->risab_name, i);
+			else
+				set_cidcfgr(risab_d, &risab_d->subr_cfg[i]);
+
+			if (!regs_access_granted(risab_d, i))
+				panic();
+		} else {
+			set_cidcfgr(risab_d, &risab_d->subr_cfg[i]);
+		}
+
+		/*
+		 * This sequence will generate an IAC if the CID filtering
+		 * configuration is inconsistent with these desired rights
+		 * to apply. Start by default setting security configuration
+		 * for all blocks.
+		 */
+		set_block_seccfgr(risab_d, &risab_d->subr_cfg[i]);
+
+		/* Grant page access to some CIDs, in read and/or write */
+		set_read_conf(risab_d, &risab_d->subr_cfg[i]);
+		set_write_conf(risab_d, &risab_d->subr_cfg[i]);
+
+		/* For each granted CID define privilege access per page */
+		set_cid_priv_conf(risab_d, &risab_d->subr_cfg[i]);
+	}
+}
+
+static void parse_risab_rif_conf(struct stm32_risab_pdata *risab_d,
+				 struct stm32_risab_rif_conf *subr_cfg,
+				 uint32_t rif_conf, bool check_overlap)
+{
+	unsigned int first_page = subr_cfg->first_page;
+	unsigned int last_page = first_page + subr_cfg->nb_pages_cfged - 1;
+	uint32_t reg_pages_cfged = GENMASK_32(last_page, first_page);
+	unsigned int i = 0;
+
+	assert(last_page <= _RISAB_NB_PAGES_MAX);
+
+	DMSG("Configuring pages %u to %u", first_page, last_page);
+
+	/* Parse secure configuration */
+	if (rif_conf & BIT(RISAB_SEC_SHIFT)) {
+		subr_cfg->seccfgr = _RISAB_PG_SECCFGR_MASK;
+		/*
+		 * Memory region overlapping should only be checked at platform
+		 * setup when memory mapping is first applied. A region's
+		 * attributes can later be dynamically modified but not its
+		 * bounds.
+		 */
+		if (check_overlap &&
+		    reg_pages_cfged & risab_d->pages_configured)
+			panic("Memory region overlap detected");
+	} else {
+		subr_cfg->seccfgr = 0;
+	}
+
+	/* Parse default privilege configuration */
+	if (rif_conf & BIT(RISAB_DPRIV_SHIFT)) {
+		subr_cfg->dprivcfgr = _RISAB_PG_PRIVCFGR_MASK;
+		if (check_overlap &&
+		    reg_pages_cfged & risab_d->pages_configured)
+			panic("Memory region overlap detected");
+	} else {
+		subr_cfg->dprivcfgr = 0;
+	}
+
+	if (check_overlap)
+		risab_d->pages_configured |= reg_pages_cfged;
+
+	for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+		/* RISAB compartment priv configuration */
+		if (rif_conf & BIT(i))
+			subr_cfg->plist[i] |= GENMASK_32(last_page, first_page);
+
+		/* RISAB compartment read configuration */
+		if (rif_conf & BIT(i + RISAB_READ_LIST_SHIFT))
+			subr_cfg->rlist[i] |= GENMASK_32(last_page, first_page);
+
+		/* RISAB compartment write configuration */
+		if (rif_conf & BIT(i + RISAB_WRITE_LIST_SHIFT))
+			subr_cfg->wlist[i] |= GENMASK_32(last_page, first_page);
+	}
+
+	/* CID filtering configuration */
+	if (rif_conf & BIT(RISAB_CFEN_SHIFT))
+		subr_cfg->cidcfgr |= _RISAB_PG_CIDCFGR_CFEN;
+
+	if (rif_conf & BIT(RISAB_DCEN_SHIFT))
+		subr_cfg->cidcfgr |= _RISAB_PG_CIDCFGR_DCEN;
+
+	if (rif_conf & RISAB_DCCID_MASK) {
+		uint32_t ddcid = SHIFT_U32((rif_conf & RISAB_DCCID_MASK) >>
+					   RISAB_DCCID_SHIFT,
+					   _RISAB_PG_CIDCFGR_DDCID_SHIFT);
+
+		assert(((rif_conf & RISAB_DCCID_MASK) >> RISAB_DCCID_SHIFT) <
+		       _RISAB_NB_MAX_CID_SUPPORTED);
+
+		subr_cfg->cidcfgr |= ddcid;
+	}
+}
+
+static TEE_Result parse_dt(const void *fdt, int node,
+			   struct stm32_risab_pdata *risab_d)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const fdt32_t *mem_regions = NULL;
+	struct dt_node_info info = { };
+	const fdt32_t *cuint = NULL;
+	int mem_reg_node = 0;
+	unsigned int i = 0;
+	int lenp = 0;
+
+	fdt_fill_device_info(fdt, &info, node);
+	assert(info.reg != DT_INFO_INVALID_REG &&
+	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
+
+	risab_d->base.pa = info.reg;
+
+	/* Gate the IP */
+	res = clk_dt_get_by_index(fdt, node, 0, &risab_d->clock);
+	if (res)
+		return res;
+
+	strlcpy(risab_d->risab_name, fdt_get_name(fdt, node, NULL),
+		sizeof(risab_d->risab_name));
+
+	cuint = fdt_getprop(fdt, node, "st,srwiad", NULL);
+	if (cuint)
+		risab_d->srwiad = true;
+
+	/* Get the memory region being configured */
+	cuint = fdt_getprop(fdt, node, "st,mem-map", &lenp);
+	if (!cuint)
+		panic("Missing st,mem-map property in configure memory region");
+
+	assert((unsigned int)(lenp / sizeof(uint32_t)) == 2);
+
+	risab_d->region_cfged.base = fdt32_to_cpu(cuint[0]);
+	risab_d->region_cfged.size = fdt32_to_cpu(cuint[1]);
+
+	/* Get the memory regions to configure */
+	mem_regions = fdt_getprop(fdt, node, "memory-region", &lenp);
+	if (!mem_regions)
+		panic("No memory region to configure");
+
+	risab_d->nb_regions_cfged = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(risab_d->nb_regions_cfged < _RISAB_NB_PAGES_MAX);
+
+	risab_d->subr_cfg = calloc(risab_d->nb_regions_cfged,
+				   sizeof(*risab_d->subr_cfg));
+	if (!risab_d->subr_cfg)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	for (i = 0; i < risab_d->nb_regions_cfged; i++) {
+		uint32_t phandle = fdt32_to_cpu(mem_regions[i]);
+		size_t sub_region_offset = 0;
+		paddr_t address = 0;
+		size_t length = 0;
+
+		mem_reg_node = fdt_node_offset_by_phandle(fdt, phandle);
+		if (mem_reg_node < 0)
+			return TEE_ERROR_ITEM_NOT_FOUND;
+
+		/*
+		 * Get the reg property to determine the number of pages
+		 * to configure
+		 */
+		address = fdt_reg_base_address(fdt, mem_reg_node);
+		length = fdt_reg_size(fdt, mem_reg_node);
+
+		assert(IS_ALIGNED(address, _RISAB_PAGE_SIZE) &&
+		       IS_ALIGNED(length, _RISAB_PAGE_SIZE));
+
+		/*
+		 * Get the sub region offset and check if it is not out
+		 * of bonds
+		 */
+		sub_region_offset = address - risab_d->region_cfged.base;
+
+		if (!core_is_buffer_inside(address, length,
+					   risab_d->region_cfged.base,
+					   risab_d->region_cfged.size)) {
+			EMSG("Region %#"PRIxPA"..%#"PRIxPA" outside RISAB area %#"PRIxPA"...%#"PRIxPA,
+			     address, address + length,
+			     risab_d->region_cfged.base,
+			     risab_d->region_cfged.base +
+			     risab_d->region_cfged.size);
+			return TEE_ERROR_BAD_PARAMETERS;
+		}
+
+		risab_d->subr_cfg[i].first_page = sub_region_offset /
+						  _RISAB_PAGE_SIZE;
+		risab_d->subr_cfg[i].nb_pages_cfged = length /
+						      _RISAB_PAGE_SIZE;
+		if (!risab_d->subr_cfg[i].nb_pages_cfged)
+			panic("Range to configure is < to the size of a page");
+
+		/* Get the RIF configuration for this region */
+		cuint = fdt_getprop(fdt, mem_reg_node, "st,protreg", &lenp);
+		if (!cuint)
+			panic("No RIF configuration available");
+
+		/* There should be only one configuration for this region */
+		assert((unsigned int)(lenp / sizeof(uint32_t)) == 1);
+
+		parse_risab_rif_conf(risab_d, &risab_d->subr_cfg[i],
+				     fdt32_to_cpu(cuint[0]),
+				     true /*check_overlap*/);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static void enable_srwiad_if_set(struct stm32_risab_pdata *risab_d)
+{
+	if (is_tdcid && risab_d->srwiad)
+		io_setbits32(risab_base(risab_d), _RISAB_CR_SRWIAD);
+};
+
+static void disable_srwiad_if_unset(struct stm32_risab_pdata *risab_d)
+{
+	if (is_tdcid && !risab_d->srwiad)
+		io_clrbits32(risab_base(risab_d), _RISAB_CR_SRWIAD);
+};
+
+static void clear_iac_regs(struct stm32_risab_pdata *risab_d)
+{
+	io_setbits32(risab_base(risab_d) + _RISAB_IACR, _RISAB_IACR_MASK);
+}
+
+static void set_vderam_syscfg(struct stm32_risab_pdata *risab_d)
+{
+	/*
+	 * Set the VDERAMCR_VDERAM_EN bit if the VDERAM should be accessed by
+	 * the system. Else, clear it so that VDEC/VENC can access it.
+	 */
+	if (risab_d->nb_regions_cfged)
+		stm32mp_syscfg_write(SYSCFG_VDERAMCR, VDERAMCR_VDERAM_EN,
+				     VDERAMCR_MASK);
+	else
+		stm32mp_syscfg_write(SYSCFG_VDERAMCR, 0, VDERAMCR_MASK);
+}
+
+static struct stm32_risab_rif_conf *
+get_subreg_by_range(struct stm32_risab_pdata *risab, paddr_t paddr, size_t size)
+{
+	unsigned int nb_page = size / _RISAB_PAGE_SIZE;
+	unsigned int i = 0;
+
+	for (i = 0; i < risab->nb_regions_cfged; i++) {
+		unsigned int first_page = (paddr - risab->region_cfged.base) /
+					  _RISAB_PAGE_SIZE;
+
+		if (first_page == risab->subr_cfg[i].first_page &&
+		    nb_page == risab->subr_cfg[i].nb_pages_cfged)
+			return risab->subr_cfg + i;
+	}
+
+	return NULL;
+}
+
+static TEE_Result stm32_risab_check_access(struct firewall_query *fw,
+					   paddr_t paddr, size_t size,
+					   bool read, bool write)
+{
+	struct stm32_risab_rif_conf *reg_conf = NULL;
+	struct stm32_risab_pdata *risab = NULL;
+	unsigned int first_page = 0;
+	uint32_t write_cids = 0;
+	uint32_t read_cids = 0;
+	uint32_t priv_cids = 0;
+	uint32_t dprivcfgr = 0;
+	uint32_t seccfgr = 0;
+	uint32_t cidcfgr = 0;
+	uint32_t q_conf = 0;
+	unsigned int i = 0;
+	vaddr_t base = 0;
+
+	assert(fw->ctrl->priv && (read || write));
+
+	risab = fw->ctrl->priv;
+	base = risab_base(risab);
+
+	if (!IS_ALIGNED(paddr, _RISAB_PAGE_SIZE) ||
+	    !IS_ALIGNED(size, _RISAB_PAGE_SIZE)) {
+		EMSG("Physical address %"PRIxPA" or size:%#zx misaligned with RISAB page boundaries",
+		     paddr, size);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (fw->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/*
+	 * RISAF region configuration, we assume the query is as
+	 * follows:
+	 * fw->args[0]: Configuration of the region
+	 */
+	q_conf = fw->args[0];
+
+	reg_conf = get_subreg_by_range(risab, paddr, size);
+	if (!reg_conf)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	first_page = reg_conf->first_page;
+
+	seccfgr = io_read32(base + _RISAB_PGy_SECCFGR(first_page));
+	/* Security level is exclusive on memories */
+	if (!!(q_conf & BIT(RISAB_SEC_SHIFT)) ^ !!(seccfgr & BIT(first_page))) {
+		if (!(q_conf & BIT(RISAB_SEC_SHIFT) &&
+		      (io_read32(base + _RISAB_CR) & _RISAB_CR_SRWIAD)))
+			return TEE_ERROR_ACCESS_DENIED;
+	}
+
+	dprivcfgr = io_read32(base + _RISAB_PGy_PRIVCFGR(first_page));
+	cidcfgr = io_read32(base + _RISAB_PGy_CIDCFGR(first_page));
+
+	if (!(cidcfgr & _RISAB_PG_CIDCFGR_CFEN)) {
+		if (dprivcfgr && !(q_conf & BIT(RISAB_DPRIV_SHIFT)))
+			return TEE_ERROR_ACCESS_DENIED;
+		else
+			return TEE_SUCCESS;
+	}
+
+	read_cids = SHIFT_U32(q_conf & RISAB_RLIST_MASK, RISAB_READ_LIST_SHIFT);
+	write_cids = SHIFT_U32(q_conf & RISAB_WLIST_MASK,
+			       RISAB_WRITE_LIST_SHIFT);
+	priv_cids = q_conf & RISAB_PLIST_MASK;
+
+	for (i = 0; i < _RISAB_NB_MAX_CID_SUPPORTED; i++) {
+		uint32_t read_list = io_read32(base + _RISAB_CIDxRDCFGR(i));
+		uint32_t write_list = io_read32(base + _RISAB_CIDxWRCFGR(i));
+		uint32_t priv_list = io_read32(base + _RISAB_CIDxPRIVCFGR(i));
+
+		if (read && (read_cids & BIT(i)) &&
+		    !(read_list & BIT(first_page)))
+			return TEE_ERROR_ACCESS_DENIED;
+
+		if (write && (write_cids & BIT(i)) &&
+		    !(write_list & BIT(first_page)))
+			return TEE_ERROR_ACCESS_DENIED;
+
+		if ((priv_list & BIT(first_page)) && !(priv_cids & BIT(i)))
+			return TEE_ERROR_ACCESS_DENIED;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_risab_pm_resume(struct stm32_risab_pdata *risab)
+{
+	unsigned int i = 0;
+
+	if (risab->base.pa == RISAB6_BASE)
+		set_vderam_syscfg(risab);
+	enable_srwiad_if_set(risab);
+	clear_iac_regs(risab);
+
+	for (i = 0; i < risab->nb_regions_cfged; i++) {
+		/* Restoring RISAB RIF configuration */
+		set_block_dprivcfgr(risab, &risab->subr_cfg[i]);
+
+		if (!is_tdcid)
+			DMSG("Cannot set %s CID configuration for region %u",
+			     risab->risab_name, i);
+		else
+			set_cidcfgr(risab, &risab->subr_cfg[i]);
+
+		if (!regs_access_granted(risab, i))
+			continue;
+
+		/*
+		 * This sequence will generate an IAC if the CID filtering
+		 * configuration is inconsistent with these desired rights
+		 * to apply.
+		 */
+		set_block_seccfgr(risab, &risab->subr_cfg[i]);
+		set_read_conf(risab, &risab->subr_cfg[i]);
+		set_write_conf(risab, &risab->subr_cfg[i]);
+		set_cid_priv_conf(risab, &risab->subr_cfg[i]);
+	}
+
+	disable_srwiad_if_unset(risab);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_risab_pm_suspend(struct stm32_risab_pdata *risab)
+{
+	vaddr_t base = risab_base(risab);
+	size_t i = 0;
+
+	for (i = 0; i < risab->nb_regions_cfged; i++) {
+		size_t j = 0;
+		unsigned int first_page = risab->subr_cfg[i].first_page;
+
+		/* Save all configuration fields that need to be restored */
+		risab->subr_cfg[i].seccfgr =
+			io_read32(base + _RISAB_PGy_SECCFGR(first_page));
+		risab->subr_cfg[i].dprivcfgr =
+			io_read32(base + _RISAB_PGy_PRIVCFGR(first_page));
+		risab->subr_cfg[i].cidcfgr =
+			io_read32(base + _RISAB_PGy_CIDCFGR(first_page));
+
+		for (j = 0; j < _RISAB_NB_MAX_CID_SUPPORTED; j++) {
+			risab->subr_cfg[i].rlist[j] =
+				io_read32(base + _RISAB_CIDxRDCFGR(j));
+			risab->subr_cfg[i].wlist[j] =
+				io_read32(base + _RISAB_CIDxWRCFGR(j));
+			risab->subr_cfg[i].plist[j] =
+				io_read32(base + _RISAB_CIDxPRIVCFGR(j));
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+stm32_risab_pm(enum pm_op op, unsigned int pm_hint,
+	       const struct pm_callback_handle *pm_handle)
+{
+	struct stm32_risab_pdata *risab = pm_handle->handle;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME)
+		res = stm32_risab_pm_resume(risab);
+	else
+		res = stm32_risab_pm_suspend(risab);
+
+	return res;
+}
+
+static const struct firewall_controller_ops firewall_ops = {
+	.check_memory_access = stm32_risab_check_access,
+};
+
+static TEE_Result stm32_risab_probe(const void *fdt, int node,
+				    const void *compat_data __maybe_unused)
+{
+	struct firewall_controller *controller = NULL;
+	struct stm32_risab_pdata *risab_d = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	risab_d = calloc(1, sizeof(*risab_d));
+	if (!risab_d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = parse_dt(fdt, node, risab_d);
+	if (res)
+		goto err;
+
+	if (clk_enable(risab_d->clock))
+		panic("Can't enable RISAB clock");
+
+	if (is_tdcid) {
+		if (risab_d->base.pa == RISAB6_BASE)
+			set_vderam_syscfg(risab_d);
+		clear_iac_regs(risab_d);
+		enable_srwiad_if_set(risab_d);
+	}
+
+	apply_rif_config(risab_d);
+
+	disable_srwiad_if_unset(risab_d);
+
+	controller = calloc(1, sizeof(*controller));
+	if (!controller) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto err;
+	}
+
+	controller->base = &risab_d->base;
+	controller->name = risab_d->risab_name;
+	controller->priv = risab_d;
+	controller->ops = &firewall_ops;
+
+	SLIST_INSERT_HEAD(&risab_list, risab_d, link);
+
+	res = firewall_dt_controller_register(fdt, node, controller);
+	if (res)
+		panic();
+
+	register_pm_core_service_cb(stm32_risab_pm, risab_d, "stm32-risab");
+
+	return TEE_SUCCESS;
+
+err:
+	clk_disable(risab_d->clock);
+	free(risab_d->subr_cfg);
+	free(risab_d);
+
+	return res;
+}
+
+static const struct dt_device_match risab_match_table[] = {
+	{ .compatible = "st,stm32mp25-risab" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(risab_dt_driver) = {
+	.name = "stm32-risab",
+	.match_table = risab_match_table,
+	.probe = stm32_risab_probe,
+};
diff --git a/core/drivers/firewall/stm32_risaf.c b/core/drivers/firewall/stm32_risaf.c
new file mode 100644
index 0000000000000000000000000000000000000000..737b30febd0b1ead6d3da7b163ee83abc7bc86c6
--- /dev/null
+++ b/core/drivers/firewall/stm32_risaf.c
@@ -0,0 +1,735 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics
+ */
+
+#include <assert.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_rif.h>
+#include <drivers/stm32_risaf.h>
+#include <dt-bindings/firewall/stm32mp25-risaf.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/pm.h>
+#include <kernel/tee_misc.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <platform_config.h>
+#include <stdint.h>
+#include <util.h>
+
+/* RISAF general registers (base relative) */
+#define _RISAF_CR			U(0x00)
+#define _RISAF_SR			U(0x04)
+#define _RISAF_IASR			U(0x08)
+#define _RISAF_IACR			U(0xC)
+#define _RISAF_IAESR0			U(0x20)
+#define _RISAF_IADDR0			U(0x24)
+#define _RISAF_IAESR1			U(0x28)
+#define _RISAF_IADDR1			U(0x2C)
+#define _RISAF_KEYR			U(0x30)
+#define _RISAF_HWCFGR			U(0xFF0)
+#define _RISAF_VERR			U(0xFF4)
+#define _RISAF_IPIDR			U(0xFF8)
+#define _RISAF_SIDR			U(0xFFC)
+
+/* RISAF general register field description */
+/* _RISAF_CR register fields */
+#define _RISAF_CR_GLOCK			BIT(0)
+/* _RISAF_SR register fields */
+#define _RISAF_SR_KEYVALID		BIT(0)
+#define _RISAF_SR_KEYRDY		BIT(1)
+#define _RISAF_SR_ENCDIS		BIT(2)
+/* _RISAF_IACR register fields */
+#define _RISAF_IACR_CAEF		BIT(0)
+#define _RISAF_IACR_IAEF0		BIT(1)
+#define _RISAF_IACR_IAEF1		BIT(2)
+/* _RISAF_HWCFGR register fields */
+#define _RISAF_HWCFGR_CFG1_SHIFT	U(0)
+#define _RISAF_HWCFGR_CFG1_MASK		GENMASK_32(7, 0)
+#define _RISAF_HWCFGR_CFG2_SHIFT	U(8)
+#define _RISAF_HWCFGR_CFG2_MASK		GENMASK_32(15, 8)
+#define _RISAF_HWCFGR_CFG3_SHIFT	U(16)
+#define _RISAF_HWCFGR_CFG3_MASK		GENMASK_32(23, 16)
+#define _RISAF_HWCFGR_CFG4_SHIFT	U(24)
+#define _RISAF_HWCFGR_CFG4_MASK		GENMASK_32(31, 24)
+/* _RISAF_VERR register fields */
+#define _RISAF_VERR_MINREV_SHIFT	U(0)
+#define _RISAF_VERR_MINREV_MASK		GENMASK_32(3, 0)
+#define _RISAF_VERR_MAJREV_SHIFT	U(4)
+#define _RISAF_VERR_MAJREV_MASK		GENMASK_32(7, 4)
+
+/* RISAF region registers (base relative) */
+#define _RISAF_REG_BASE			U(0x40)
+#define _RISAF_REG_SIZE			U(0x40)
+#define _RISAF_REG(n)			(_RISAF_REG_BASE + \
+					 (((n) - 1) * _RISAF_REG_SIZE))
+#define _RISAF_REG_CFGR_OFFSET		U(0x0)
+#define _RISAF_REG_CFGR(n)		(_RISAF_REG(n) + _RISAF_REG_CFGR_OFFSET)
+#define _RISAF_REG_STARTR_OFFSET	U(0x4)
+#define _RISAF_REG_STARTR(n)		(_RISAF_REG(n) + \
+					 _RISAF_REG_STARTR_OFFSET)
+#define _RISAF_REG_ENDR_OFFSET		U(0x8)
+#define _RISAF_REG_ENDR(n)		(_RISAF_REG(n) + _RISAF_REG_ENDR_OFFSET)
+#define _RISAF_REG_CIDCFGR_OFFSET	U(0xC)
+#define _RISAF_REG_CIDCFGR(n)		(_RISAF_REG(n) + \
+					 _RISAF_REG_CIDCFGR_OFFSET)
+
+/* RISAF region register field description */
+/* _RISAF_REG_CFGR(n) register fields */
+#define _RISAF_REG_CFGR_BREN_SHIFT	U(0)
+#define _RISAF_REG_CFGR_BREN		BIT(_RISAF_REG_CFGR_BREN_SHIFT)
+#define _RISAF_REG_CFGR_SEC_SHIFT	U(8)
+#define _RISAF_REG_CFGR_SEC		BIT(_RISAF_REG_CFGR_SEC_SHIFT)
+#define _RISAF_REG_CFGR_ENC_SHIFT	U(15)
+#define _RISAF_REG_CFGR_ENC		BIT(_RISAF_REG_CFGR_ENC_SHIFT)
+#define _RISAF_REG_CFGR_PRIVC_SHIFT	U(16)
+#define _RISAF_REG_CFGR_PRIVC_MASK	GENMASK_32(23, 16)
+#define _RISAF_REG_CFGR_ALL_MASK	(_RISAF_REG_CFGR_BREN | \
+					 _RISAF_REG_CFGR_SEC | \
+					 _RISAF_REG_CFGR_ENC | \
+					 _RISAF_REG_CFGR_PRIVC_MASK)
+
+/* _RISAF_REG_CIDCFGR(n) register fields */
+#define _RISAF_REG_CIDCFGR_RDENC_SHIFT	U(0)
+#define _RISAF_REG_CIDCFGR_RDENC_MASK	GENMASK_32(7, 0)
+#define _RISAF_REG_CIDCFGR_WRENC_SHIFT	U(16)
+#define _RISAF_REG_CIDCFGR_WRENC_MASK	GENMASK_32(23, 16)
+#define _RISAF_REG_CIDCFGR_ALL_MASK	(_RISAF_REG_CIDCFGR_RDENC_MASK | \
+					 _RISAF_REG_CIDCFGR_WRENC_MASK)
+#define _RISAF_REG_READ_OK(reg, cid) \
+	((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_RDENC_SHIFT))
+#define _RISAF_REG_WRITE_OK(reg, cid)	\
+	((reg) & BIT((cid) + _RISAF_REG_CIDCFGR_WRENC_SHIFT))
+
+#define _RISAF_GET_REGION_ID(cfg)	((cfg) & DT_RISAF_REG_ID_MASK)
+
+#define _RISAF_NB_CID_SUPPORTED		U(8)
+
+/**
+ * struct stm32_risaf_region - RISAF memory region
+ *
+ * @addr: Region base address.
+ * @len: Length of the memory region.
+ * @cfg: Region configuration.
+ */
+struct stm32_risaf_region {
+	paddr_t addr;
+	size_t len;
+	uint32_t cfg;
+};
+
+/**
+ * struct stm32_risaf_pdata - RISAF platform data
+ *
+ * @base: Base address of the RISAF instance.
+ * @clock: Clock of the RISAF.
+ * @regions: Number of memory regions, defined by the device tree configuration.
+ * @risaf_name: Name of the RISAF instance
+ * @nregions: Number of memory regions found in the device tree.
+ * @conf_lock: State whether the RISAF configuration is locked.
+ * @mem_base: Base address of the memory range covered by the RISAF instance.
+ * @mem_size: Size of the memory range covered by the RISAF instance.
+ * @enc_supported: If true, the RISAF instance supports encryption of the memory
+ * regions.
+ */
+struct stm32_risaf_pdata {
+	struct io_pa_va base;
+	struct clk *clock;
+	struct stm32_risaf_region *regions;
+	char risaf_name[20];
+	unsigned int nregions;
+	unsigned int conf_lock;
+	paddr_t mem_base;
+	size_t mem_size;
+	bool enc_supported;
+};
+
+/**
+ * struct stm32_risaf_ddata - RISAF driver data
+ *
+ * @mask_regions: Number of address bits to match when determining access to a
+ * base region or subregion (WIDTH).
+ * @max_base_regions: Number of subdivision of the memory range (A.K.A memory
+ * regions) supported by the RISAF instance.
+ * @granularity: Length of the smallest possible region size.
+ */
+struct stm32_risaf_ddata {
+	uint32_t mask_regions;
+	uint32_t max_base_regions;
+	uint32_t granularity;
+};
+
+struct stm32_risaf_instance {
+	struct stm32_risaf_pdata pdata;
+	struct stm32_risaf_ddata *ddata;
+
+	SLIST_ENTRY(stm32_risaf_instance) link;
+};
+
+struct stm32_risaf_version {
+	uint32_t major;
+	uint32_t minor;
+	uint32_t ip_id;
+	uint32_t size_id;
+};
+
+/**
+ * struct stm32_risaf_compat_data  - Describes RISAF associated data
+ * for compatible list.
+ *
+ * @supported_encryption:	identify RISAF encryption capabilities.
+ */
+struct stm32_risaf_compat_data {
+	bool supported_encryption;
+};
+
+static bool is_tdcid;
+
+static const struct stm32_risaf_compat_data stm32_risaf_compat = {
+	.supported_encryption = false,
+};
+
+static const struct stm32_risaf_compat_data stm32_risaf_enc_compat = {
+	.supported_encryption = true,
+};
+
+static SLIST_HEAD(, stm32_risaf_instance) risaf_list =
+		SLIST_HEAD_INITIALIZER(risaf_list);
+
+static vaddr_t risaf_base(struct stm32_risaf_instance *risaf)
+{
+	return io_pa_or_va_secure(&risaf->pdata.base, 1);
+}
+
+static uint32_t stm32_risaf_get_region_config(uint32_t cfg)
+{
+	return SHIFT_U32((cfg & DT_RISAF_EN_MASK) >> DT_RISAF_EN_SHIFT,
+			 _RISAF_REG_CFGR_BREN_SHIFT) |
+	       SHIFT_U32((cfg & DT_RISAF_SEC_MASK) >> DT_RISAF_SEC_SHIFT,
+			 _RISAF_REG_CFGR_SEC_SHIFT) |
+	       SHIFT_U32((cfg & DT_RISAF_ENC_MASK) >> (DT_RISAF_ENC_SHIFT + 1),
+			 _RISAF_REG_CFGR_ENC_SHIFT) |
+	       SHIFT_U32((cfg & DT_RISAF_PRIV_MASK) >> DT_RISAF_PRIV_SHIFT,
+			 _RISAF_REG_CFGR_PRIVC_SHIFT);
+}
+
+static uint32_t stm32_risaf_get_region_cid_config(uint32_t cfg)
+{
+	return SHIFT_U32((cfg & DT_RISAF_WRITE_MASK) >> DT_RISAF_WRITE_SHIFT,
+			 _RISAF_REG_CIDCFGR_WRENC_SHIFT) |
+	       SHIFT_U32((cfg & DT_RISAF_READ_MASK) >> DT_RISAF_READ_SHIFT,
+			 _RISAF_REG_CIDCFGR_RDENC_SHIFT);
+}
+
+void stm32_risaf_clear_illegal_access_flags(void)
+{
+	struct stm32_risaf_instance *risaf = NULL;
+
+	SLIST_FOREACH(risaf, &risaf_list, link) {
+		vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
+
+		if (!io_read32(base + _RISAF_IASR))
+			continue;
+
+		io_write32(base + _RISAF_IACR, _RISAF_IACR_CAEF |
+			   _RISAF_IACR_IAEF0 | _RISAF_IACR_IAEF1);
+	}
+}
+
+void stm32_risaf_print_erroneous_data(void)
+{
+	struct stm32_risaf_instance *risaf = NULL;
+
+	if (!IS_ENABLED(CFG_TEE_CORE_DEBUG))
+		return;
+
+	SLIST_FOREACH(risaf, &risaf_list, link) {
+		vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
+
+		/* Check if faulty address on this RISAF */
+		if (!io_read32(base + _RISAF_IASR))
+			continue;
+
+		IMSG("\n\nDUMPING DATA FOR %s\n\n", risaf->pdata.risaf_name);
+		IMSG("=====================================================");
+		IMSG("Status register (IAESR0): %#"PRIx32,
+		     io_read32(base + _RISAF_IAESR0));
+
+		/* Reserved if dual port feature not available */
+		if (io_read32(base + _RISAF_IAESR1))
+			IMSG("Status register Dual Port (IAESR1) %#"PRIx32,
+			     io_read32(base + _RISAF_IAESR1));
+
+		IMSG("-----------------------------------------------------");
+		if (virt_to_phys((void *)base) == RISAF4_BASE) {
+			IMSG("Faulty address (IADDR0): %#"PRIxPA,
+			     risaf->pdata.mem_base +
+			     io_read32(base + _RISAF_IADDR0));
+
+			/* Reserved if dual port feature not available */
+			if (io_read32(base + _RISAF_IADDR1))
+				IMSG("Dual port faulty address (IADDR1): %#"PRIxPA,
+				     risaf->pdata.mem_base +
+				     io_read32(base + _RISAF_IADDR1));
+		} else {
+			IMSG("Faulty address (IADDR0): %#"PRIx32,
+			     io_read32(base + _RISAF_IADDR0));
+
+			/* Reserved if dual port feature not available */
+			if (io_read32(base + _RISAF_IADDR1))
+				IMSG("Dual port faulty address (IADDR1): %#"PRIx32,
+				     io_read32(base + _RISAF_IADDR1));
+		}
+
+		IMSG("=====================================================\n");
+	};
+}
+
+static __maybe_unused
+bool risaf_is_hw_encryption_enabled(struct stm32_risaf_instance *risaf)
+{
+	return (io_read32(risaf_base(risaf) + _RISAF_SR) &
+		_RISAF_SR_ENCDIS) != _RISAF_SR_ENCDIS;
+}
+
+static TEE_Result
+risaf_check_region_boundaries(struct stm32_risaf_instance *risaf,
+			      struct stm32_risaf_region *region)
+{
+	if (!core_is_buffer_inside(region->addr, region->len,
+				   risaf->pdata.mem_base,
+				   risaf->pdata.mem_size)) {
+		EMSG("Region %#"PRIxPA"..%#"PRIxPA" outside RISAF area %#"PRIxPA"...%#"PRIxPA,
+		     region->addr, region->addr + region->len - 1,
+		     risaf->pdata.mem_base,
+		     risaf->pdata.mem_base + risaf->pdata.mem_size - 1);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	if (!risaf->ddata->granularity ||
+	    (region->addr % risaf->ddata->granularity) ||
+	    (region->len % risaf->ddata->granularity)) {
+		EMSG("RISAF %#"PRIxPA": start/end address granularity not respected",
+		     risaf->pdata.base.pa);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+risaf_check_overlap(struct stm32_risaf_instance *risaf __maybe_unused,
+		    struct stm32_risaf_region *region, unsigned int index)
+{
+	unsigned int i = 0;
+
+	for (i = 0; i < index; i++) {
+		/* Skip region if there's no configuration */
+		if (!region[i].cfg)
+			continue;
+
+		if (core_is_buffer_intersect(region[index].addr,
+					     region[index].len,
+					     region[i].addr,
+					     region[i].len)) {
+			EMSG("RISAF %#"PRIxPA": Regions %u and %u overlap",
+			     risaf->pdata.base.pa, index, i);
+			return TEE_ERROR_GENERIC;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result risaf_configure_region(struct stm32_risaf_instance *risaf,
+					 uint32_t region_id, uint32_t cfg,
+					 uint32_t cid_cfg, paddr_t saddr,
+					 paddr_t eaddr)
+{
+	uint32_t mask = risaf->ddata->mask_regions;
+	vaddr_t base = risaf_base(risaf);
+
+	if (cfg & _RISAF_REG_CFGR_ENC) {
+		if (!risaf->pdata.enc_supported) {
+			EMSG("RISAF %#"PRIxPA": encryption feature error",
+			     risaf->pdata.base.pa);
+			return TEE_ERROR_GENERIC;
+		}
+
+		if ((cfg & _RISAF_REG_CFGR_SEC) != _RISAF_REG_CFGR_SEC) {
+			EMSG("RISAF %#"PRIxPA": encryption on non-secure area",
+			     risaf->pdata.base.pa);
+			return TEE_ERROR_GENERIC;
+		}
+	}
+
+	io_clrbits32(base + _RISAF_REG_CFGR(region_id), _RISAF_REG_CFGR_BREN);
+
+	io_clrsetbits32(base + _RISAF_REG_STARTR(region_id), mask,
+			(saddr - risaf->pdata.mem_base) & mask);
+	io_clrsetbits32(base + _RISAF_REG_ENDR(region_id), mask,
+			(eaddr - risaf->pdata.mem_base) & mask);
+	io_clrsetbits32(base + _RISAF_REG_CIDCFGR(region_id),
+			_RISAF_REG_CIDCFGR_ALL_MASK,
+			cid_cfg & _RISAF_REG_CIDCFGR_ALL_MASK);
+
+	io_clrsetbits32(base + _RISAF_REG_CFGR(region_id),
+			_RISAF_REG_CFGR_ALL_MASK,
+			cfg & _RISAF_REG_CFGR_ALL_MASK);
+
+	DMSG("RISAF %#"PRIxPA": region %02"PRIu32" - start %#"PRIxPA
+	     "- end %#"PRIxPA" - cfg %#08"PRIx32" - cidcfg %#08"PRIx32,
+	     risaf->pdata.base.pa, region_id,
+	     risaf->pdata.mem_base +
+	     io_read32(base + _RISAF_REG_STARTR(region_id)),
+	     risaf->pdata.mem_base +
+	     io_read32(base + _RISAF_REG_ENDR(region_id)),
+	     io_read32(base + _RISAF_REG_CFGR(region_id)),
+	     io_read32(base + _RISAF_REG_CIDCFGR(region_id)));
+
+	return TEE_SUCCESS;
+}
+
+static void risaf_print_version(struct stm32_risaf_instance *risaf)
+{
+	vaddr_t base = risaf_base(risaf);
+	struct stm32_risaf_version __maybe_unused version = {
+		.major = (io_read32(base + _RISAF_VERR) &
+			  _RISAF_VERR_MAJREV_MASK) >> _RISAF_VERR_MAJREV_SHIFT,
+		.minor = (io_read32(base + _RISAF_VERR) &
+			  _RISAF_VERR_MINREV_MASK) >> _RISAF_VERR_MINREV_SHIFT,
+		.ip_id = io_read32(base + _RISAF_IPIDR),
+		.size_id = io_read32(base + _RISAF_SIDR)
+	};
+
+	DMSG("RISAF %#"PRIxPA" version %"PRIu32".%"PRIu32", ip%#"PRIx32" size%#"PRIx32,
+	     risaf->pdata.base.pa, version.major, version.minor, version.ip_id,
+	     version.size_id);
+}
+
+static __maybe_unused
+void stm32_risaf_lock(struct stm32_risaf_instance *risaf)
+{
+	assert(risaf);
+
+	io_setbits32(risaf_base(risaf) + _RISAF_CR, _RISAF_CR_GLOCK);
+}
+
+static __maybe_unused
+void stm32_risaf_is_locked(struct stm32_risaf_instance *risaf, bool *state)
+{
+	assert(risaf);
+
+	*state = (io_read32(risaf_base(risaf) + _RISAF_CR) &
+		  _RISAF_CR_GLOCK) == _RISAF_CR_GLOCK;
+}
+
+static TEE_Result stm32_risaf_init_ddata(struct stm32_risaf_instance *risaf)
+{
+	vaddr_t base = risaf_base(risaf);
+	uint32_t granularity = 0;
+	uint32_t mask_lsb = 0;
+	uint32_t mask_msb = 0;
+	uint32_t hwcfgr = 0;
+
+	risaf->ddata = calloc(1, sizeof(*risaf->ddata));
+	if (!risaf->ddata)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	/* Get address mask depending on RISAF instance HW configuration */
+	hwcfgr =  io_read32(base + _RISAF_HWCFGR);
+	mask_lsb = (hwcfgr & _RISAF_HWCFGR_CFG3_MASK) >>
+		   _RISAF_HWCFGR_CFG3_SHIFT;
+	mask_msb = mask_lsb + ((hwcfgr & _RISAF_HWCFGR_CFG4_MASK) >>
+			       _RISAF_HWCFGR_CFG4_SHIFT) - 1U;
+	risaf->ddata->mask_regions = GENMASK_32(mask_msb, mask_lsb);
+	risaf->ddata->max_base_regions = (hwcfgr & _RISAF_HWCFGR_CFG1_MASK) >>
+					 _RISAF_HWCFGR_CFG1_SHIFT;
+
+	/* Get IP region granularity */
+	granularity = io_read32(risaf_base(risaf) + _RISAF_HWCFGR);
+	granularity = BIT((granularity & _RISAF_HWCFGR_CFG3_MASK) >>
+			  _RISAF_HWCFGR_CFG3_SHIFT);
+	risaf->ddata->granularity = granularity;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_risaf_pm_resume(struct stm32_risaf_instance *risaf)
+{
+	struct stm32_risaf_region *regions = risaf->pdata.regions;
+	size_t i = 0;
+
+	for (i = 0; i < risaf->pdata.nregions; i++) {
+		uint32_t id = _RISAF_GET_REGION_ID(regions[i].cfg);
+		paddr_t start_addr = 0;
+		paddr_t end_addr = 0;
+		uint32_t cid_cfg = 0;
+		uint32_t cfg = 0;
+
+		if (!id)
+			continue;
+
+		cfg = stm32_risaf_get_region_config(regions[i].cfg);
+		cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg);
+		start_addr = regions[i].addr;
+		end_addr = start_addr + regions[i].len - 1U;
+		if (risaf_configure_region(risaf, id, cfg, cid_cfg,
+					   start_addr, end_addr))
+			panic();
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_risaf_pm_suspend(struct stm32_risaf_instance *risaf)
+{
+	vaddr_t base = io_pa_or_va_secure(&risaf->pdata.base, 1);
+	size_t i = 0;
+
+	for (i = 0; i < risaf->pdata.nregions; i++) {
+		uint32_t id = _RISAF_GET_REGION_ID(risaf->pdata.regions[i].cfg);
+		struct stm32_risaf_region *region = risaf->pdata.regions + i;
+		paddr_t start_addr = 0;
+		paddr_t end_addr = 0;
+		uint32_t cid_cfg = 0;
+		uint32_t priv = 0;
+		uint32_t rden = 0;
+		uint32_t wren = 0;
+		uint32_t cfg = 0;
+		uint32_t enc = 0;
+		uint32_t sec = 0;
+		uint32_t en = 0;
+
+		/* Skip region not defined in DT, not configured in probe */
+		if (!id)
+			continue;
+
+		cfg = io_read32(base + _RISAF_REG_CFGR(id));
+		en = cfg & _RISAF_REG_CFGR_BREN;
+		sec = (cfg & _RISAF_REG_CFGR_SEC) >> _RISAF_REG_CFGR_SEC_SHIFT;
+		enc = (cfg & _RISAF_REG_CFGR_ENC) >> _RISAF_REG_CFGR_ENC_SHIFT;
+		priv = (cfg & _RISAF_REG_CFGR_PRIVC_MASK) >>
+		       _RISAF_REG_CFGR_PRIVC_SHIFT;
+
+		cid_cfg = io_read32(base + _RISAF_REG_CIDCFGR(id));
+		rden = cid_cfg & _RISAF_REG_CIDCFGR_RDENC_MASK;
+		wren = (cid_cfg & _RISAF_REG_CIDCFGR_WRENC_MASK) >>
+		       _RISAF_REG_CIDCFGR_WRENC_SHIFT;
+
+		region->cfg = id | SHIFT_U32(en, DT_RISAF_EN_SHIFT) |
+			      SHIFT_U32(sec, DT_RISAF_SEC_SHIFT) |
+			      SHIFT_U32(enc, DT_RISAF_ENC_SHIFT + 1) |
+			      SHIFT_U32(priv, DT_RISAF_PRIV_SHIFT) |
+			      SHIFT_U32(rden, DT_RISAF_READ_SHIFT) |
+			      SHIFT_U32(wren, DT_RISAF_WRITE_SHIFT);
+		start_addr = io_read32(base + _RISAF_REG_STARTR(id));
+		end_addr = io_read32(base + _RISAF_REG_ENDR(id));
+		region->addr = start_addr + risaf->pdata.mem_base;
+		region->len = end_addr - start_addr + 1;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+stm32_risaf_pm(enum pm_op op, unsigned int pm_hint,
+	       const struct pm_callback_handle *pm_handle)
+{
+	struct stm32_risaf_instance *risaf = pm_handle->handle;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	assert(risaf);
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME)
+		res = stm32_risaf_pm_resume(risaf);
+	else
+		res = stm32_risaf_pm_suspend(risaf);
+
+	return res;
+}
+
+static TEE_Result stm32_risaf_probe(const void *fdt, int node,
+				    const void *compat_data)
+{
+	const struct stm32_risaf_compat_data *compat = compat_data;
+	struct stm32_risaf_instance *risaf = NULL;
+	struct stm32_risaf_region *regions = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info dt_info = { };
+	const fdt32_t *conf_list = NULL;
+	const fdt64_t *cuint = NULL;
+	unsigned int nregions = 0;
+	unsigned int i = 0;
+	int len = 0;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	if (!is_tdcid)
+		return TEE_SUCCESS;
+
+	risaf = calloc(1, sizeof(*risaf));
+	if (!risaf)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	fdt_fill_device_info(fdt, &dt_info, node);
+	if (dt_info.reg == DT_INFO_INVALID_REG ||
+	    dt_info.reg_size == DT_INFO_INVALID_REG_SIZE) {
+		free(risaf);
+		return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	risaf->pdata.base.pa = dt_info.reg;
+	io_pa_or_va_secure(&risaf->pdata.base, dt_info.reg_size);
+
+	risaf->pdata.enc_supported = compat->supported_encryption;
+
+	res = clk_dt_get_by_index(fdt, node, 0, &risaf->pdata.clock);
+	if (!risaf->pdata.clock)
+		goto err;
+
+	conf_list = fdt_getprop(fdt, node, "memory-region", &len);
+	if (!conf_list) {
+		DMSG("RISAF %#"PRIxPA": No configuration in DT, use default",
+		     risaf->pdata.base.pa);
+		free(risaf);
+		return TEE_SUCCESS;
+	}
+
+	nregions = (unsigned int)len / sizeof(uint32_t);
+
+	/* Silently allow unexpected truncated names */
+	strncpy(risaf->pdata.risaf_name, fdt_get_name(fdt, node, NULL),
+		sizeof(risaf->pdata.risaf_name) - 1);
+
+	res = clk_enable(risaf->pdata.clock);
+	if (res)
+		goto err;
+
+	res = stm32_risaf_init_ddata(risaf);
+	if (res)
+		goto err_clk;
+
+	risaf_print_version(risaf);
+
+	cuint = fdt_getprop(fdt, node, "st,mem-map", &len);
+	if (!cuint || (size_t)len != sizeof(*cuint) * 2)
+		panic();
+
+	risaf->pdata.mem_base = (paddr_t)fdt64_to_cpu(*cuint);
+	risaf->pdata.mem_size = (size_t)fdt64_to_cpu(*(cuint + 1));
+
+	regions = calloc(nregions, sizeof(*regions));
+	if (nregions && !regions) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto err_ddata;
+	}
+
+	DMSG("RISAF %#"PRIxPA" memory range: %#"PRIxPA" - %#"PRIxPA,
+	     risaf->pdata.base.pa, risaf->pdata.mem_base,
+	     risaf->pdata.mem_base + risaf->pdata.mem_size - 1);
+
+	for (i = 0; i < nregions; i++) {
+		const fdt32_t *prop = NULL;
+		paddr_t start_addr = 0;
+		paddr_t end_addr = 0;
+		uint32_t cid_cfg = 0;
+		uint32_t phandle = 0;
+		uint32_t cfg = 0;
+		uint32_t id = 0;
+		int pnode = 0;
+
+		phandle = fdt32_to_cpu(*(conf_list + i));
+		pnode = fdt_node_offset_by_phandle(fdt, phandle);
+		if (pnode < 0)
+			continue;
+
+		if (fdt_reg_info(fdt, pnode, &regions[i].addr,
+				 &regions[i].len)) {
+			EMSG("Invalid config in node %s",
+			     fdt_get_name(fdt, pnode, NULL));
+			panic();
+		}
+
+		if (!regions[i].len)
+			continue;
+
+		/*
+		 * The secure bootloader is in charge of configuring RISAF
+		 * related to OP-TEE secure memory. Therefore, skip OP-TEE
+		 * region so that RISAF configuration cannot interfere with
+		 * OP-TEE execution flow.
+		 */
+		if (regions[i].addr == TZDRAM_BASE &&
+		    regions[i].len == TZDRAM_SIZE) {
+			continue;
+		}
+
+		prop = fdt_getprop(fdt, pnode, "st,protreg", NULL);
+		if (!prop)
+			continue;
+
+		regions[i].cfg = fdt32_to_cpu(*prop);
+
+		if (risaf_check_region_boundaries(risaf, &regions[i]) ||
+		    risaf_check_overlap(risaf, regions, i))
+			panic();
+
+		id = _RISAF_GET_REGION_ID(regions[i].cfg);
+		assert(id < risaf->ddata->max_base_regions);
+
+		cfg = stm32_risaf_get_region_config(regions[i].cfg);
+
+		cid_cfg = stm32_risaf_get_region_cid_config(regions[i].cfg);
+
+		start_addr = regions[i].addr;
+		end_addr = start_addr + regions[i].len - 1U;
+
+		if (risaf_configure_region(risaf, id, cfg, cid_cfg,
+					   start_addr, end_addr))
+			panic();
+	}
+
+	risaf->pdata.regions = regions;
+	risaf->pdata.nregions = nregions;
+
+	SLIST_INSERT_HEAD(&risaf_list, risaf, link);
+
+	register_pm_core_service_cb(stm32_risaf_pm, risaf, "stm32-risaf");
+
+	return TEE_SUCCESS;
+
+err_ddata:
+	free(risaf->ddata);
+err_clk:
+	clk_disable(risaf->pdata.clock);
+err:
+	free(risaf);
+	return res;
+}
+
+static const struct dt_device_match risaf_match_table[] = {
+	{
+		.compatible = "st,stm32mp25-risaf",
+		.compat_data = &stm32_risaf_compat,
+	},
+	{
+		.compatible = "st,stm32mp25-risaf-enc",
+		.compat_data = &stm32_risaf_enc_compat,
+	},
+	{ }
+};
+
+DEFINE_DT_DRIVER(risaf_dt_driver) = {
+	.name = "stm32-risaf",
+	.match_table = risaf_match_table,
+	.probe = stm32_risaf_probe,
+};
diff --git a/core/drivers/firewall/stm32_serc.c b/core/drivers/firewall/stm32_serc.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f3bf09abcd29abc62341c86d5da2c954a94e8b6
--- /dev/null
+++ b/core/drivers/firewall/stm32_serc.c
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <kernel/interrupt.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <tee_api_defines.h>
+#include <trace.h>
+#include <util.h>
+
+/* SERC offset register */
+#define _SERC_IER0		U(0x000)
+#define _SERC_ISR0		U(0x040)
+#define _SERC_ICR0		U(0x080)
+#define _SERC_ENABLE		U(0x100)
+
+#define _SERC_HWCFGR		U(0x3F0)
+#define _SERC_VERR		U(0x3F4)
+
+/* SERC_ENABLE register fields */
+#define _SERC_ENABLE_SERFEN	BIT(0)
+
+/* SERC_HWCFGR register fields */
+#define _SERC_HWCFGR_CFG1_MASK	GENMASK_32(7, 0)
+#define _SERC_HWCFGR_CFG1_SHIFT	U(0)
+#define _SERC_HWCFGR_CFG2_MASK	GENMASK_32(18, 16)
+#define _SERC_HWCFGR_CFG2_SHIFT	U(16)
+
+/* SERC_VERR register fields */
+#define _SERC_VERR_MINREV_MASK	GENMASK_32(3, 0)
+#define _SERC_VERR_MINREV_SHIFT	U(0)
+#define _SERC_VERR_MAJREV_MASK	GENMASK_32(7, 4)
+#define _SERC_VERR_MAJREV_SHIFT	U(4)
+
+/* Periph id per register */
+#define _PERIPH_IDS_PER_REG	U(32)
+
+#define _SERC_FLD_PREP(field, value)	(SHIFT_U32((value), \
+						   (field ## _SHIFT)) & \
+					 (field ## _MASK))
+#define _SERC_FLD_GET(field, value)	(((uint32_t)(value) & \
+					  (field ## _MASK)) >> \
+					 (field ## _SHIFT))
+
+#define SERC_EXCEPT_MSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG + \
+				_PERIPH_IDS_PER_REG - 1)
+#define SERC_EXCEPT_LSB_BIT(x) ((x) * _PERIPH_IDS_PER_REG)
+
+/**
+ * struct serc_driver_data - Hardware information on the SERC peripheral
+ *
+ * @version: Peripheral version number
+ * @num_ilac: Number of SERC lines
+ */
+struct serc_driver_data {
+	uint32_t version;
+	uint8_t num_ilac;
+};
+
+/**
+ * struct stm32_serc_platdata - Platform data for the SERC driver
+ *
+ * @irq_chip: Reference to the SERC's IRQ chip
+ * @clock: Reference on the SERC clock
+ * @base: Base address of the SERC peripheral
+ * @irq: ID of the SERC interrupt
+ */
+struct stm32_serc_platdata {
+	struct itr_chip *irq_chip;
+	struct clk *clock;
+	vaddr_t base;
+	size_t irq;
+};
+
+/**
+ * struct serc_device - SERC device private data
+ * @pdata: Platform data read from the DT
+ * @ddata: Device data read from the hardware
+ * @itr: Interrupt handler reference
+ */
+struct serc_device {
+	struct stm32_serc_platdata pdata;
+	struct serc_driver_data *ddata;
+	struct itr_handler *itr;
+};
+
+static struct serc_device serc_dev;
+
+static void stm32_serc_get_hwdata(void)
+{
+	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
+	struct serc_driver_data *ddata = serc_dev.ddata;
+	vaddr_t base = pdata->base;
+	uint32_t regval = 0;
+
+	regval = io_read32(base + _SERC_HWCFGR);
+
+	ddata->num_ilac = _SERC_FLD_GET(_SERC_HWCFGR_CFG1, regval);
+
+	ddata->version = io_read32(base + _SERC_VERR);
+
+	DMSG("SERC version %"PRIu32".%"PRIu32,
+	     _SERC_FLD_GET(_SERC_VERR_MAJREV, ddata->version),
+	     _SERC_FLD_GET(_SERC_VERR_MINREV, ddata->version));
+
+	DMSG("HW cap: num ilac:[%"PRIu8"]", ddata->num_ilac);
+}
+
+static TEE_Result stm32_serc_parse_fdt(const void *fdt, int node)
+{
+	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info dt_info = { };
+	struct io_pa_va base = { };
+
+	fdt_fill_device_info(fdt, &dt_info, node);
+	if (dt_info.reg == DT_INFO_INVALID_REG)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	res = interrupt_dt_get(fdt, node, &pdata->irq_chip, &pdata->irq);
+	if (res)
+		return res;
+
+	base.pa = dt_info.reg;
+	pdata->base = io_pa_or_va_secure(&base, dt_info.reg_size);
+
+	return clk_dt_get_by_index(fdt, node, 0, &pdata->clock);
+}
+
+static void stm32_serc_handle_ilac(void)
+{
+	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
+	struct serc_driver_data *ddata = serc_dev.ddata;
+	unsigned int nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
+	vaddr_t base = pdata->base;
+	unsigned int i = 0;
+	uint32_t isr = 0;
+
+	for (i = 0; i < nreg; i++) {
+		uint32_t offset = sizeof(uint32_t) * i;
+		unsigned int j = 0;
+
+		isr = io_read32(base + _SERC_ISR0 + offset);
+		isr &= io_read32(base + _SERC_IER0 + offset);
+
+		if (!isr)
+			continue;
+
+		EMSG("SERC exceptions [%d:%d]: %#"PRIx32,
+		     SERC_EXCEPT_MSB_BIT(i), SERC_EXCEPT_LSB_BIT(i), isr);
+
+		for (j = 0; j < _PERIPH_IDS_PER_REG; j++) {
+			EMSG("SERC exception ID: %d",
+			     SERC_EXCEPT_LSB_BIT(i) + __builtin_ffs(isr) - 1);
+
+			io_write32(base + _SERC_ICR0 + offset,
+				   BIT(__builtin_ffs(isr) - 1));
+
+			isr = io_read32(base + _SERC_ISR0 + offset);
+			isr &= io_read32(base + _SERC_IER0 + offset);
+
+			if (!isr)
+				break;
+		}
+	}
+
+	stm32_rif_access_violation_action();
+	if (IS_ENABLED(CFG_STM32_PANIC_ON_SERC_EVENT))
+		panic();
+}
+
+static enum itr_return stm32_serc_itr(struct itr_handler *h __unused)
+{
+	stm32_serc_handle_ilac();
+
+	return ITRR_HANDLED;
+}
+
+static void stm32_serc_setup(void)
+{
+	struct stm32_serc_platdata *pdata = &serc_dev.pdata;
+	struct serc_driver_data *ddata = serc_dev.ddata;
+	vaddr_t base = serc_dev.pdata.base;
+	uint32_t nreg = DIV_ROUND_UP(ddata->num_ilac, _PERIPH_IDS_PER_REG);
+	uint32_t i = 0;
+
+	io_setbits32(pdata->base + _SERC_ENABLE, _SERC_ENABLE_SERFEN);
+
+	for (i = 0; i < nreg; i++) {
+		vaddr_t reg_ofst = base + sizeof(uint32_t) * i;
+
+		/* Clear status flags */
+		io_write32(reg_ofst + _SERC_ICR0, ~0x0);
+		/* Enable all peripherals of nreg */
+		io_write32(reg_ofst + _SERC_IER0, ~0x0);
+	}
+}
+
+static TEE_Result probe_serc_device(const void *fdt, int node)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = stm32_serc_parse_fdt(fdt, node);
+	if (res)
+		return res;
+
+	/* Unbalanced clock enable to have the SERC running */
+	if (clk_enable(serc_dev.pdata.clock))
+		panic();
+
+	stm32_serc_get_hwdata();
+	stm32_serc_setup();
+
+	res = interrupt_alloc_add_handler(serc_dev.pdata.irq_chip,
+					  serc_dev.pdata.irq, stm32_serc_itr,
+					  ITRF_TRIGGER_LEVEL, NULL,
+					  &serc_dev.itr);
+	if (res)
+		panic();
+
+	interrupt_enable(serc_dev.pdata.irq_chip, serc_dev.itr->it);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_serc_pm(enum pm_op op, unsigned int pm_hint,
+				const struct pm_callback_handle *hdl __unused)
+{
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME) {
+		if (clk_enable(serc_dev.pdata.clock))
+			panic();
+		stm32_serc_setup();
+	} else {
+		clk_disable(serc_dev.pdata.clock);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_serc_probe(const void *fdt, int node,
+				   const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	serc_dev.ddata = calloc(1, sizeof(*serc_dev.ddata));
+	if (!serc_dev.ddata)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = probe_serc_device(fdt, node);
+	if (res) {
+		free(serc_dev.ddata);
+		return res;
+	}
+
+	register_pm_core_service_cb(stm32_serc_pm, NULL, "stm32-serc");
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match stm32_serc_match_table[] = {
+	{ .compatible = "st,stm32mp25-serc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_serc_dt_driver) = {
+	.name = "stm32-serc",
+	.match_table = stm32_serc_match_table,
+	.probe = stm32_serc_probe,
+};
diff --git a/core/drivers/firewall/sub.mk b/core/drivers/firewall/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..dbdf0a8dd4c74fad57f47ebf452327567827639d
--- /dev/null
+++ b/core/drivers/firewall/sub.mk
@@ -0,0 +1,9 @@
+srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c
+srcs-$(CFG_STM32_IAC) += stm32_iac.c
+srcs-$(CFG_STM32_RIF) += stm32_rif.c
+srcs-$(CFG_STM32_RIFSC) += stm32_rifsc.c
+srcs-$(CFG_STM32_SERC) += stm32_serc.c
+srcs-$(CFG_STM32_RISAB) += stm32_risab.c
+srcs-$(CFG_STM32_RISAF) += stm32_risaf.c
+
+srcs-$(CFG_DRIVERS_FIREWALL) += firewall.c
diff --git a/core/drivers/gic.c b/core/drivers/gic.c
index e751ae4e5c56c9840297c996cd0f66d963aebcc7..0913da6ec895013fe7042933da5d30a3158bb31f 100644
--- a/core/drivers/gic.c
+++ b/core/drivers/gic.c
@@ -1,15 +1,16 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2016-2017, 2023 Linaro Limited
+ * Copyright (c) 2016-2017, 2023-2024 Linaro Limited
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 
 #include <arm.h>
 #include <assert.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <compiler.h>
 #include <config.h>
 #include <drivers/gic.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <initcall.h>
 #include <io.h>
 #include <keep.h>
 #include <kernel/dt.h>
@@ -69,6 +70,12 @@
 #define GICR_IGRPMODR0		(GICR_SGI_BASE_OFFSET + 0xD00)
 #define GICR_ICENABLER0		(GICR_SGI_BASE_OFFSET + 0x180)
 #define GICR_ICPENDR0		(GICR_SGI_BASE_OFFSET + 0x280)
+#define GICR_ISENABLER0		(GICR_SGI_BASE_OFFSET + 0x100)
+#define GICR_ICFGR0		(GICR_SGI_BASE_OFFSET + 0xC00)
+#define GICR_ICFGR1		(GICR_SGI_BASE_OFFSET + 0xC04)
+#define GICR_IPRIORITYR(n)	(GICR_SGI_BASE_OFFSET + 0x400 + (n) * 4)
+
+#define GICR_CTLR_RWP		BIT32(3)
 
 #define GICR_TYPER_LAST		BIT64(4)
 #define GICR_TYPER_AFF3_SHIFT	56
@@ -125,9 +132,11 @@ struct gic_data {
 	size_t max_it;
 	uint32_t per_cpu_group_status;
 	uint32_t per_cpu_group_modifier;
+	uint32_t per_cpu_enable;
 	struct itr_chip chip;
 };
 
+static bool gic_primary_done __nex_bss;
 static struct gic_data gic_data __nex_bss;
 
 static void gic_op_add(struct itr_chip *chip, size_t it, uint32_t type,
@@ -210,7 +219,21 @@ out:
 	return ret;
 }
 
-static void gicv3_sync_sgi_config(struct gic_data *gd)
+static void gicr_wait_for_pending_write(vaddr_t gicr_base)
+{
+	/*
+	 * Wait for changes to
+	 * - GICR_ICENABLER0
+	 * - GICR_CTLR.DPG1S
+	 * - GICR_CTLR.DPG1NS
+	 * - GICR_CTLR.DPG0
+	 * to be visible to all agents in the system.
+	 */
+	while (io_read32(gicr_base + GICR_CTLR) & GICR_CTLR_RWP)
+		;
+}
+
+static void gicv3_sync_redist_config(struct gic_data *gd)
 {
 	vaddr_t gicr_base = get_gicr_base(gd);
 	bool need_sync = false;
@@ -227,13 +250,13 @@ static void gicv3_sync_sgi_config(struct gic_data *gd)
 
 	grp0 = io_read32(gicr_base + GICR_IGROUPR0);
 	gmod0 = io_read32(gicr_base + GICR_IGRPMODR0);
-	for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) {
+	for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) {
 		/* Ignore matching bits */
 		if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)) &&
 		    !(BIT32(n) & (gmod0 ^ gd->per_cpu_group_modifier)))
 			continue;
 		/*
-		 * SGI-n differs from primary CPU configuration,
+		 * SGI/PPI-n differs from primary CPU configuration,
 		 * let's sync up.
 		 */
 		need_sync = true;
@@ -241,6 +264,9 @@ static void gicv3_sync_sgi_config(struct gic_data *gd)
 		/* Disable interrupt */
 		io_write32(gicr_base + GICR_ICENABLER0, BIT32(n));
 
+		/* Wait for the write to GICR_ICENABLER0 to propagate */
+		gicr_wait_for_pending_write(gicr_base);
+
 		/* Make interrupt non-pending */
 		io_write32(gicr_base + GICR_ICPENDR0, BIT32(n));
 
@@ -257,22 +283,23 @@ static void gicv3_sync_sgi_config(struct gic_data *gd)
 	if (need_sync) {
 		io_write32(gicr_base + GICR_IGROUPR0, grp0);
 		io_write32(gicr_base + GICR_IGRPMODR0, gmod0);
+		io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable);
 	}
 }
 
-static void gic_legacy_sync_sgi_config(struct gic_data *gd)
+static void gic_legacy_sync_dist_config(struct gic_data *gd)
 {
 	bool need_sync = false;
 	uint32_t grp0 = 0;
 	size_t n = 0;
 
 	grp0 = io_read32(gd->gicd_base + GICD_IGROUPR(0));
-	for (n = GIC_SGI_SEC_BASE; n <= GIC_SGI_SEC_MAX; n++) {
+	for (n = GIC_SGI_SEC_BASE; n < GIC_SPI_BASE; n++) {
 		/* Ignore matching bits */
 		if (!(BIT32(n) & (grp0 ^ gd->per_cpu_group_status)))
 			continue;
 		/*
-		 * SGI-n differs from primary CPU configuration,
+		 * SGI/PPI-n differs from primary CPU configuration,
 		 * let's sync up.
 		 */
 		need_sync = true;
@@ -289,8 +316,11 @@ static void gic_legacy_sync_sgi_config(struct gic_data *gd)
 			grp0 &= ~BIT32(n);
 	}
 
-	if (need_sync)
+	if (need_sync) {
 		io_write32(gd->gicd_base + GICD_IGROUPR(0), grp0);
+		io_write32(gd->gicd_base + GICD_ISENABLER(0),
+			   gd->per_cpu_enable);
+	}
 }
 
 static void init_gic_per_cpu(struct gic_data *gd)
@@ -327,12 +357,12 @@ void gic_init_per_cpu(void)
 	if (IS_ENABLED(CFG_WITH_ARM_TRUSTED_FW)) {
 		/*
 		 * GIC is already initialized by TF-A, we only need to
-		 * handle eventual SGI configuration changes.
+		 * handle eventual SGI or PPI configuration changes.
 		 */
 		if (affinity_routing_is_enabled(gd))
-			gicv3_sync_sgi_config(gd);
+			gicv3_sync_redist_config(gd);
 		else
-			gic_legacy_sync_sgi_config(gd);
+			gic_legacy_sync_dist_config(gd);
 	} else {
 		/*
 		 * Non-TF-A case where all CPU specific configuration
@@ -364,6 +394,9 @@ void gic_init_donate_sgi_to_ns(size_t it)
 		/* Disable interrupt */
 		io_write32(gicr_base + GICR_ICENABLER0, BIT32(it));
 
+		/* Wait for the write to GICR_ICENABLER0 to propagate */
+		gicr_wait_for_pending_write(gicr_base);
+
 		/* Make interrupt non-pending */
 		io_write32(gicr_base + GICR_ICPENDR0, BIT32(it));
 
@@ -475,7 +508,7 @@ static void gic_init_base_addr(paddr_t gicc_base_pa, paddr_t gicd_base_pa,
 	vers &= GICD_PIDR2_ARCHREV_MASK;
 
 	if (IS_ENABLED(CFG_ARM_GICV3)) {
-		assert(vers == 3);
+		assert(vers == 4 || vers == 3);
 	} else {
 		assert(vers == 2 || vers == 1);
 		gicc_base = core_mmu_get_va(gicc_base_pa, MEM_AREA_IO_SEC,
@@ -861,10 +894,40 @@ static void gic_op_add(struct itr_chip *chip, size_t it,
 	if (it > gd->max_it)
 		panic();
 
-	gic_it_add(gd, it);
-	/* Set the CPU mask to deliver interrupts to any online core */
-	gic_it_set_cpu_mask(gd, it, 0xff);
-	gic_it_set_prio(gd, it, 0x1);
+	if (it < GIC_SPI_BASE) {
+		if (gic_primary_done)
+			panic("Cannot add SGI or PPI after boot");
+
+		/* Assign it to Secure Group 1, G1S */
+		gd->per_cpu_group_modifier |= BIT32(it);
+		gd->per_cpu_group_status &= ~BIT32(it);
+	}
+
+	if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) {
+		vaddr_t gicr_base = get_gicr_base(gd);
+
+		if (!gicr_base)
+			panic("GICR_BASE missing");
+
+		/* Disable interrupt */
+		io_write32(gicr_base + GICR_ICENABLER0, BIT32(it));
+
+		/* Wait for the write to GICR_ICENABLER0 to propagate */
+		gicr_wait_for_pending_write(gicr_base);
+
+		/* Make interrupt non-pending */
+		io_write32(gicr_base + GICR_ICPENDR0, BIT32(it));
+
+		/* Make it to Secure */
+		io_write32(gicr_base + GICR_IGROUPR0, gd->per_cpu_group_status);
+		io_write32(gicr_base + GICR_IGRPMODR0,
+			   gd->per_cpu_group_modifier);
+	} else {
+		gic_it_add(gd, it);
+		/* Set the CPU mask to deliver interrupts to any online core */
+		gic_it_set_cpu_mask(gd, it, 0xff);
+		gic_it_set_prio(gd, it, 0x1);
+	}
 }
 
 static void gic_op_enable(struct itr_chip *chip, size_t it)
@@ -876,7 +939,22 @@ static void gic_op_enable(struct itr_chip *chip, size_t it)
 	if (it > gd->max_it)
 		panic();
 
-	gic_it_enable(gd, it);
+	if (it < GIC_SPI_BASE)
+		gd->per_cpu_enable |= BIT(it);
+
+	if (it < GIC_SPI_BASE && affinity_routing_is_enabled(gd)) {
+		vaddr_t gicr_base = get_gicr_base(gd);
+
+		if (!gicr_base)
+			panic("GICR_BASE missing");
+
+		/* Assigned to G1S */
+		assert(gd->per_cpu_group_modifier & BIT(it) &&
+		       !(gd->per_cpu_group_status & BIT(it)));
+		io_write32(gicr_base + GICR_ISENABLER0, gd->per_cpu_enable);
+	} else {
+		gic_it_enable(gd, it);
+	}
 }
 
 static void gic_op_disable(struct itr_chip *chip, size_t it)
@@ -991,3 +1069,11 @@ DEFINE_DT_DRIVER(gic_dt_driver) = {
 	.probe = gic_probe,
 };
 #endif /*CFG_DT*/
+
+static TEE_Result gic_set_primary_done(void)
+{
+	gic_primary_done = true;
+	return TEE_SUCCESS;
+}
+
+nex_release_init_resource(gic_set_primary_done);
diff --git a/core/drivers/gpio/gpio.c b/core/drivers/gpio/gpio.c
index 457599ecd1464e1090c3bbd2c00dbfdf7c3558d0..bcdb91cc8ed4bbd960f7bbe1a21c4ce2a1beb3ee 100644
--- a/core/drivers/gpio/gpio.c
+++ b/core/drivers/gpio/gpio.c
@@ -7,7 +7,6 @@
 #include <libfdt.h>
 #include <stdio.h>
 #include <tee_api_defines.h>
-#include <tee_api_defines_extensions.h>
 #include <tee_api_types.h>
 #include <util.h>
 
diff --git a/core/drivers/hfic.c b/core/drivers/hfic.c
index 109941014cba1c10f7e4b460b536f641eec87dc7..08e729381b5855c75d61a8d3ef3b2190d7d12fe0 100644
--- a/core/drivers/hfic.c
+++ b/core/drivers/hfic.c
@@ -7,28 +7,52 @@
 #include <compiler.h>
 #include <config.h>
 #include <drivers/hfic.h>
-#include <hafnium.h>
 #include <kernel/interrupt.h>
 #include <kernel/panic.h>
 #include <kernel/thread.h>
 
+/*
+ * For documentation of the paravirtualized interface see:
+ * https://hafnium.readthedocs.io/en/latest/design/secure-partition-manager.html#paravirtualized-interfaces
+ */
+
+#define HF_INTERRUPT_ENABLE	0xff03
+#define HF_INTERRUPT_GET	0xff04
+#define HF_INTERRUPT_DEACTIVATE	0xff08
+#define HF_INTERRUPT_RECONFIGURE 0xff09
+
+#define HF_INVALID_INTID	0xffffffff
+#define HF_MANAGED_EXIT_INTID	4
+
+#define HF_INTERRUPT_TYPE_IRQ	0
+#define HF_INTERRUPT_TYPE_FIQ	1
+#define HF_ENABLE		1
+#define HF_DISABLE		0
+
+#define HF_INT_RECONFIGURE_STATUS 2
+
 struct hfic_data {
 	struct itr_chip chip;
 };
 
 static struct hfic_data hfic_data __nex_bss;
 
-static void hfic_op_add(struct itr_chip *chip __unused, size_t it __unused,
+static void hfic_op_add(struct itr_chip *chip __unused, size_t it,
 			uint32_t type __unused, uint32_t prio __unused)
 {
+	uint32_t res __maybe_unused = 0;
+
+	res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE,
+			 HF_INTERRUPT_TYPE_IRQ);
+	assert(!res);
 }
 
 static void hfic_op_enable(struct itr_chip *chip __unused, size_t it)
 {
 	uint32_t res __maybe_unused = 0;
 
-	res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE,
-			 HF_INTERRUPT_TYPE_IRQ);
+	res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it,
+			 HF_INT_RECONFIGURE_STATUS, HF_ENABLE);
 	assert(!res);
 }
 
@@ -36,8 +60,8 @@ static void hfic_op_disable(struct itr_chip *chip __unused, size_t it)
 {
 	uint32_t res __maybe_unused = 0;
 
-	res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_DISABLE,
-			 HF_INTERRUPT_TYPE_IRQ);
+	res = thread_hvc(HF_INTERRUPT_RECONFIGURE, it,
+			 HF_INT_RECONFIGURE_STATUS, HF_DISABLE);
 	assert(!res);
 }
 
diff --git a/core/drivers/hisi_trng.c b/core/drivers/hisi_trng.c
index 3d865e40a85ccac675ddebe6db0bcb2a63c64d19..59c066f1e46bfbf882b63c6d06ff70abb60f648d 100644
--- a/core/drivers/hisi_trng.c
+++ b/core/drivers/hisi_trng.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: BSD-2-Clause
 /* Copyright (c) 2023 HiSilicon Limited. */
 
 #include <initcall.h>
diff --git a/core/drivers/i2c/atmel_i2c.c b/core/drivers/i2c/atmel_i2c.c
index df44f3120f1cfe4054fcc9fb33335ae23cc0ecde..f7b74ae62608d0998f67cd9b40fed721c23ee6c4 100644
--- a/core/drivers/i2c/atmel_i2c.c
+++ b/core/drivers/i2c/atmel_i2c.c
@@ -284,7 +284,7 @@ static TEE_Result atmel_i2c_get_dt_i2c(struct dt_pargs *args, void *data,
 	struct i2c_dev *i2c_dev = NULL;
 	struct i2c_ctrl *i2c_ctrl = data;
 
-	i2c_dev = i2c_create_dev(i2c_ctrl, args->fdt, args->phandle_node);
+	i2c_dev = i2c_create_dev(i2c_ctrl, args->fdt, args->consumer_node);
 	if (!i2c_dev)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
diff --git a/core/drivers/imx/dcp/dcp.c b/core/drivers/imx/dcp/dcp.c
index 34324b9031a2ffe4549b1b08f0e24eaddc14d279..7e09e40bb0bb0123e981ec891575d56f6a4ece2e 100644
--- a/core/drivers/imx/dcp/dcp.c
+++ b/core/drivers/imx/dcp/dcp.c
@@ -299,8 +299,7 @@ TEE_Result dcp_cmac(struct dcp_cipher_init *init, uint8_t *input,
 		goto out;
 
 	/* Get number of block */
-	nb_blocks = ROUNDUP(input_size, DCP_AES128_BLOCK_SIZE) /
-		    DCP_AES128_BLOCK_SIZE;
+	nb_blocks = ROUNDUP_DIV(input_size, DCP_AES128_BLOCK_SIZE);
 
 	block_complete = nb_blocks && !(input_size % DCP_AES128_BLOCK_SIZE);
 	if (nb_blocks == 0)
diff --git a/core/drivers/imx/mu/sub.mk b/core/drivers/imx/mu/sub.mk
index 368c22c31c0dd8cfb80b24f0a8cae3f7baf5b5ee..c64f5fed8b71d4f8ac8c28449aaa2419843f2c8a 100644
--- a/core/drivers/imx/mu/sub.mk
+++ b/core/drivers/imx/mu/sub.mk
@@ -1,5 +1,5 @@
 srcs-y += imx_mu.c
-srcs-$(call cfg-one-enabled,CFG_MX8ULP CFG_MX93) += imx_mu_8ulp.c
+srcs-$(call cfg-one-enabled,CFG_MX8ULP CFG_MX93 CFG_MX91) += imx_mu_8ulp.c
 ifeq ($(filter y, $(CFG_MX8QM) $(CFG_MX8QX) $(CFG_MX8DXL)),y)
 srcs-y += imx_mu_8q.c
 endif
diff --git a/core/drivers/imx_csu.c b/core/drivers/imx_csu.c
index fc06697ef82fd674e02a7a71f4c580adea7b6b95..c693b9afea1eecd77cce6891cadffe31f418cb65 100644
--- a/core/drivers/imx_csu.c
+++ b/core/drivers/imx_csu.c
@@ -72,11 +72,12 @@ const struct csu_setting csu_setting_imx7ds[] = {
 	{(-1), 0},
 };
 
-/* Set all masters to non-secure except the Cortex-A7 */
+/* Set all masters to non-secure except the Cortex-A cores */
+const struct csu_sa_setting csu_sa_imx6 = { 0x15554554, 0x2aaa8aaa };
 const struct csu_sa_setting csu_sa_imx6ul = { 0x10554550, 0x20aa8aa2 };
 const struct csu_sa_setting csu_sa_imx7ds = { 0x15554554, 0x2aaa8aaa };
 
-const struct csu_config csu_imx6 = { NULL, csu_setting_imx6 };
+const struct csu_config csu_imx6 = { &csu_sa_imx6, csu_setting_imx6 };
 const struct csu_config csu_imx6ul = { &csu_sa_imx6ul, csu_setting_imx6ul };
 const struct csu_config csu_imx6ull = { NULL, csu_setting_imx6ull };
 const struct csu_config csu_imx6sl = { NULL, csu_setting_imx6sl };
diff --git a/core/drivers/imx_ele.c b/core/drivers/imx_ele.c
index bfa2f193c7c81c9d02ac7dc7e54df903602830e8..2ea1aff1f1cea850d26ebb9209120adbba3aee59 100644
--- a/core/drivers/imx_ele.c
+++ b/core/drivers/imx_ele.c
@@ -43,7 +43,7 @@
 #if defined(CFG_MX8ULP)
 #define ELE_MU_DID 0x7
 #define CACHELINE_SIZE 64
-#elif defined(CFG_MX93)
+#elif defined(CFG_MX93) || defined(CFG_MX91)
 #define ELE_MU_DID 0x3
 #define CACHELINE_SIZE 64
 #else
@@ -493,7 +493,7 @@ err:
 	panic("Fail to get the device UID");
 }
 
-#if defined(CFG_MX93)
+#if defined(CFG_MX93) || defined(CFG_MX91)
 TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
@@ -556,4 +556,4 @@ out:
 
 	return TEE_SUCCESS;
 }
-#endif /* CFG_MX93 */
+#endif /* CFG_MX93 || CFG_MX91 */
diff --git a/core/drivers/microchip_pit.c b/core/drivers/microchip_pit.c
new file mode 100644
index 0000000000000000000000000000000000000000..1056ea4e5d04b7141c5bbfb017be2a19adfc132e
--- /dev/null
+++ b/core/drivers/microchip_pit.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Microchip
+ */
+
+#include <assert.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <kernel/dt_driver.h>
+#include <string.h>
+
+#define MCHP_PIT64B_FREQ		UL(5000000)	/* 5 MHz */
+
+static TEE_Result microchip_pit_probe(const void *fdt, int node,
+				      const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct clk *parent = NULL;
+	struct clk *pclk = NULL;
+	struct clk *gclk = NULL;
+	size_t i = 0;
+
+	res = clk_dt_get_by_name(fdt, node, "pclk", &pclk);
+	if (res)
+		return res;
+
+	res = clk_dt_get_by_name(fdt, node, "gclk", &gclk);
+	if (res)
+		return res;
+
+	res = clk_enable(pclk);
+	if (res)
+		panic();
+
+	while (1) {
+		parent = clk_get_parent_by_index(gclk, i++);
+		if (!parent)
+			panic();
+		if (!memcmp("syspll", clk_get_name(parent),
+			    sizeof("syspll") - 1))
+			break;
+	}
+
+	res = clk_set_parent(gclk, parent);
+	if (res)
+		panic();
+
+	res = clk_set_rate(gclk, MCHP_PIT64B_FREQ);
+	if (res)
+		panic();
+
+	return clk_enable(gclk);
+}
+
+static const struct dt_device_match microchip_pit_match_table[] = {
+	{ .compatible = "microchip,sama7g5-pit64b" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(microchip_pit_dt_driver) = {
+	.name = "microchip_pit",
+	.type = DT_DRIVER_NOTYPE,
+	.match_table = microchip_pit_match_table,
+	.probe = microchip_pit_probe,
+};
diff --git a/core/drivers/nvmem/atmel_sfc.c b/core/drivers/nvmem/atmel_sfc.c
index e034aa706201e2bb3ad0a7dbf9e05f653e61db46..9b337e4bf2a11cfe857d5e82e2ddd629e008154f 100644
--- a/core/drivers/nvmem/atmel_sfc.c
+++ b/core/drivers/nvmem/atmel_sfc.c
@@ -8,7 +8,7 @@
 #include <kernel/dt_driver.h>
 #include <malloc.h>
 #include <matrix.h>
-#include <sama5d2.h>
+#include <platform_config.h>
 #include <string.h>
 #include <tee_api_defines.h>
 #include <tee_api_types.h>
@@ -32,6 +32,9 @@ static TEE_Result atmel_sfc_read_cell(struct nvmem_cell *cell, uint8_t *data)
 {
 	struct atmel_sfc *atmel_sfc = cell->drv_data;
 
+	if (cell->offset + cell->len > ATMEL_SFC_CELLS_8)
+		return TEE_ERROR_GENERIC;
+
 	memcpy(data, &atmel_sfc->fuses[cell->offset], cell->len);
 
 	return TEE_SUCCESS;
diff --git a/core/drivers/nvmem/nvmem.c b/core/drivers/nvmem/nvmem.c
index 7d30c2c166d69c10862625a24a6880bc7dc9a88b..94d3be4168d99d51a1bdfbbf9229f2a0167d0d4f 100644
--- a/core/drivers/nvmem/nvmem.c
+++ b/core/drivers/nvmem/nvmem.c
@@ -10,20 +10,9 @@
 TEE_Result nvmem_cell_parse_dt(const void *fdt, int nodeoffset,
 			       struct nvmem_cell *cell)
 {
-	size_t buf_len = 0;
-	paddr_t offset = 0;
-
-	buf_len = fdt_reg_size(fdt, nodeoffset);
-	if (buf_len == DT_INFO_INVALID_REG_SIZE)
-		return TEE_ERROR_GENERIC;
-
-	offset = fdt_reg_base_address(fdt, nodeoffset);
-	if (offset == DT_INFO_INVALID_REG)
+	if (fdt_reg_info(fdt, nodeoffset, &cell->offset, &cell->len))
 		return TEE_ERROR_GENERIC;
 
-	cell->len = buf_len;
-	cell->offset = offset;
-
 	return TEE_SUCCESS;
 }
 
diff --git a/core/drivers/nvmem/nvmem_die_id.c b/core/drivers/nvmem/nvmem_die_id.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4aa588b888c40ed0a853b41ab316de97441824d
--- /dev/null
+++ b/core/drivers/nvmem/nvmem_die_id.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, Microchip
+ */
+
+#include <drivers/nvmem.h>
+#include <io.h>
+#include <kernel/dt.h>
+#include <kernel/huk_subkey.h>
+#include <kernel/tee_common_otp.h>
+#include <malloc.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+
+static uint8_t *die_id;
+static size_t die_id_len;
+
+int tee_otp_get_die_id(uint8_t *buffer, size_t len)
+{
+	if (!die_id) {
+		if (huk_subkey_derive(HUK_SUBKEY_DIE_ID, NULL, 0, buffer, len))
+			return -1;
+		return 0;
+	}
+
+	memcpy(buffer, die_id, MIN(die_id_len, len));
+
+	return 0;
+}
+
+static TEE_Result nvmem_die_id_probe(const void *fdt, int node,
+				     const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct nvmem_cell *cell = NULL;
+	uint8_t *data = NULL;
+
+	res = nvmem_get_cell_by_name(fdt, node, "die_id", &cell);
+	if (res)
+		return res;
+
+	res = nvmem_cell_malloc_and_read(cell, &data);
+	if (!res) {
+		die_id = data;
+		die_id_len = cell->len;
+	}
+
+	nvmem_put_cell(cell);
+
+	return res;
+}
+
+static const struct dt_device_match nvmem_die_id_match_table[] = {
+	{ .compatible = "optee,nvmem-die-id" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(nvmem_die_id_dt_driver) = {
+	.name = "nvmem_die_id_key",
+	.type = DT_DRIVER_NVMEM,
+	.match_table = nvmem_die_id_match_table,
+	.probe = nvmem_die_id_probe,
+};
diff --git a/core/drivers/nvmem/nvmem_huk.c b/core/drivers/nvmem/nvmem_huk.c
new file mode 100644
index 0000000000000000000000000000000000000000..af5f9ab9a6c9098c29cad3844a198c5df6c2907c
--- /dev/null
+++ b/core/drivers/nvmem/nvmem_huk.c
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, Microchip
+ */
+
+#include <drivers/nvmem.h>
+#include <io.h>
+#include <kernel/dt.h>
+#include <kernel/huk_subkey.h>
+#include <kernel/tee_common_otp.h>
+#include <libfdt.h>
+#include <malloc.h>
+#include <tee_api_defines.h>
+#include <tee_api_types.h>
+#include <trace.h>
+#include <types_ext.h>
+
+static uint8_t *huk;
+
+TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
+{
+	if (!huk) {
+		EMSG("no HUK");
+		return TEE_ERROR_GENERIC;
+	}
+
+	memcpy(hwkey->data, huk, HW_UNIQUE_KEY_LENGTH);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result nvmem_huk_probe(const void *fdt, int node,
+				  const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct nvmem_cell *cell = NULL;
+	uint8_t *data = NULL;
+
+	res = nvmem_get_cell_by_name(fdt, node, "hw_unique_key", &cell);
+	if (res)
+		return res;
+
+	if (cell->len < HW_UNIQUE_KEY_LENGTH) {
+		EMSG("cell %s is too small", fdt_get_name(fdt, node, NULL));
+		nvmem_put_cell(cell);
+		return TEE_ERROR_GENERIC;
+	}
+
+	if (cell->len > HW_UNIQUE_KEY_LENGTH)
+		IMSG("nvmem_huk: HUK truncated from %zu to %u bytes",
+		     cell->len, HW_UNIQUE_KEY_LENGTH);
+
+	res = nvmem_cell_malloc_and_read(cell, &data);
+	if (!res)
+		huk = data;
+
+	nvmem_put_cell(cell);
+
+	return res;
+}
+
+static const struct dt_device_match nvmem_huk_match_table[] = {
+	{ .compatible = "optee,nvmem-huk" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(nvmem_huk_dt_driver) = {
+	.name = "nvmem_huk",
+	.type = DT_DRIVER_NVMEM,
+	.match_table = nvmem_huk_match_table,
+	.probe = nvmem_huk_probe,
+};
diff --git a/core/drivers/nvmem/sub.mk b/core/drivers/nvmem/sub.mk
index cec703b14ffb8e49c21ae4e282197c72ede540e9..dd5e1f63fa1a8b3a6b608b588028a95eadcf2dee 100644
--- a/core/drivers/nvmem/sub.mk
+++ b/core/drivers/nvmem/sub.mk
@@ -1,2 +1,4 @@
 srcs-y += nvmem.c
 srcs-$(CFG_ATMEL_SFC) += atmel_sfc.c
+srcs-$(CFG_NVMEM_DIE_ID) += nvmem_die_id.c
+srcs-$(CFG_NVMEM_HUK) += nvmem_huk.c
diff --git a/core/drivers/openedges_omc.c b/core/drivers/openedges_omc.c
new file mode 100644
index 0000000000000000000000000000000000000000..53a524fc19c62e18a37df1396225bfd249f18373
--- /dev/null
+++ b/core/drivers/openedges_omc.c
@@ -0,0 +1,238 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ *
+ * Driver for the Orbit Memory Controller.
+ * https://www.openedges.com/memorycontroller
+ */
+
+#include <assert.h>
+#include <drivers/openedges_omc.h>
+#include <io.h>
+#include <kernel/panic.h>
+#include <trace.h>
+#include <util.h>
+
+#define ACTION_OFF              U(0x1004)
+
+#define INT_STATUS              U(0x1010)
+#define INT_CLEAR               U(0x1014)
+#define FAIL_ADDRESS_LOW_OFF    U(0x1020)
+#define FAIL_ADDRESS_HIGH_OFF   U(0x1024)
+#define FAIL_CONTROL_OFF        U(0x1028)
+#define FAIL_ID_OFF             U(0x102c)
+#define FAIL_DIRECTION_OFF(d)   (U(0x20) * (d))
+
+#define REGION_COUNT		U(17)
+#define REGION_BASE_LOW_OFF     U(0x1100)
+#define REGION_BASE_HIGH_OFF    U(0x1104)
+#define REGION_TOP_LOW_OFF      U(0x1108)
+#define REGION_TOP_HIGH_OFF     U(0x110c)
+#define REGION_ATTRIBUTES_OFF   U(0x1110)
+#define REGION_ID_ACCESS_OFF    U(0x1114)
+#define REGION_NUM_OFF(region)  (U(0x20) * (region))
+
+#define ADDRESS_CTRL0_OFF       U(0x1f00)
+#define ADDRESS_CTRL1_OFF       U(0x1f04)
+#define REGION0_START_OFF       U(0x1f10)
+#define REGION0_END_OFF         U(0x1f14)
+#define REGION0_CFG_OFF         U(0x1f18)
+#define REGION1_START_OFF       U(0x1f20)
+#define REGION1_END_OFF         U(0x1f24)
+#define REGION1_CFG_OFF         U(0x1f28)
+#define CHIP0_SIZE_OFF          U(0x1f30)
+#define CHIP1_SIZE_OFF          U(0x1f34)
+
+#define INT_TYPE_READ           U(0)
+#define INT_TYPE_WRITE          U(1)
+#define INT_TYPE_MAX            U(2)
+
+#define INT_STATUS_OVERLAP      BIT(16)
+#define INT_STATUS_OVERRUN      BIT(8)
+#define INT_STATUS_STATUS       BIT(0)
+#define INT_STATUS_MASK         (INT_STATUS_OVERLAP | INT_STATUS_OVERRUN | \
+				 INT_STATUS_STATUS)
+
+#define INT_CLEAR_CLEAR_SHIFT   U(0)
+#define INT_CLEAR_CLEAR_MASK    U(0x1)
+
+#define FAIL_CONTROL_NONSECURE  BIT(21)
+#define FAIL_CONTROL_PRIVILEGED BIT(20)
+
+#define FAIL_ID_AID_SHIFT       U(8)
+#define FAIL_ID_AID_MASK        GENMASK_32(27, 8)
+#define FAIL_ID_MID_SHIFT       U(0)
+#define FAIL_ID_MID_MASK        GENMASK_32(7, 0)
+
+#define REG_ATTR_S_WR_EN        BIT(31)
+#define REG_ATTR_S_RD_EN        BIT(30)
+#define REG_ATTR_FILTER_EN      BIT(0)
+
+struct omc_instance {
+	vaddr_t base;
+	uint32_t size;
+	uint8_t num_filters;
+};
+
+static struct omc_instance tzc;
+
+static void omc_write32(uint8_t filter, uint32_t offs, uint32_t val)
+{
+	vaddr_t filter_offs = filter * tzc.size;
+
+	io_write32(tzc.base + filter_offs + offs, val);
+}
+
+static uint32_t omc_read32(uint8_t filter, uint32_t offs)
+{
+	vaddr_t filter_offs = filter * tzc.size;
+
+	return io_read32(tzc.base + filter_offs + offs);
+}
+
+static void omc_write64(uint8_t filter, uint32_t offs, uint64_t val)
+{
+	vaddr_t filter_offs = filter * tzc.size;
+
+	io_write64(tzc.base + filter_offs + offs, val);
+}
+
+static uint64_t omc_read64(uint8_t filter, uint32_t offs)
+{
+	vaddr_t filter_offs = filter * tzc.size;
+
+	return io_read64(tzc.base + filter_offs + offs);
+}
+
+static void omc_write_region_base(uint8_t filter, uint32_t region, uint64_t val)
+{
+	omc_write64(filter, REGION_BASE_LOW_OFF + REGION_NUM_OFF(region), val);
+}
+
+static void omc_write_region_top(uint8_t filter, uint32_t region, uint64_t val)
+{
+	omc_write64(filter, REGION_TOP_LOW_OFF + REGION_NUM_OFF(region), val);
+}
+
+static void omc_write_region_attributes(uint8_t filter, uint32_t region,
+					uint32_t val)
+{
+	omc_write32(filter, REGION_ATTRIBUTES_OFF + REGION_NUM_OFF(region),
+		    val);
+}
+
+static void omc_write_region_id_access(uint8_t filter, uint32_t region,
+				       uint32_t val)
+{
+	omc_write32(filter, REGION_ID_ACCESS_OFF + REGION_NUM_OFF(region), val);
+}
+
+static uint64_t omc_read_start_address(uint8_t filter)
+{
+	return SHIFT_U64(omc_read32(filter, REGION0_START_OFF), 8);
+}
+
+void omc_init(vaddr_t base, uint32_t size, uint8_t num)
+{
+	assert(base);
+
+	tzc.base = base;
+	tzc.size = size;
+	tzc.num_filters = num;
+}
+
+void omc_configure_region(uint8_t region, const struct omc_region_config *cfg)
+{
+	uint8_t filter = 0;
+	uint32_t attr = 0;
+	uint64_t start_addr = 0;
+
+	if (!tzc.base)
+		panic("tzc.base is not registered");
+	else if (!cfg)
+		panic("cfg is null");
+	else if (cfg->filters >> tzc.num_filters)
+		panic("cfg->filters is overflowed");
+	else if (region >= REGION_COUNT)
+		panic("region is overflowed");
+	else if ((cfg->base | (cfg->top + 1)) & 0xFFF)
+		panic("region base or (top + 1) is not 4KB aligned");
+
+	for (filter = 0; filter < tzc.num_filters; filter++) {
+		if (cfg->flags & OMC_FLAG_RELATIVE_ADDR)
+			start_addr = omc_read_start_address(filter);
+		else
+			start_addr = 0;
+
+		omc_write_region_base(filter, region, start_addr + cfg->base);
+		omc_write_region_top(filter, region, start_addr + cfg->top);
+
+		/* Assign the region to a filter and set secure attributes */
+		attr = REG_ATTR_S_WR_EN | REG_ATTR_S_RD_EN;
+		if (cfg->filters & BIT(filter))
+			attr |= REG_ATTR_FILTER_EN;
+		omc_write_region_attributes(filter, region, attr);
+
+		omc_write_region_id_access(filter, region,
+					   cfg->ns_device_access);
+	}
+}
+
+void omc_set_action(enum omc_action action)
+{
+	uint8_t filter = 0;
+
+	if (!tzc.base)
+		panic("tzc.base is null");
+
+	for (filter = 0; filter < tzc.num_filters; filter++)
+		omc_write32(filter, ACTION_OFF, (uint32_t)action);
+}
+
+void omc_fail_dump(uint8_t filter)
+{
+	uint64_t __maybe_unused addr = 0;
+	uint32_t status = 0;
+	uint32_t __maybe_unused ctrl = 0;
+	uint32_t __maybe_unused nsaid = 0;
+	uint32_t direction = 0;
+
+	for (direction = INT_TYPE_READ; direction < INT_TYPE_MAX; direction++) {
+		status = omc_read32(filter,
+				    INT_STATUS + FAIL_DIRECTION_OFF(direction));
+		if (!(status & INT_STATUS_MASK))
+			continue;
+
+		if (status & INT_STATUS_OVERLAP)
+			EMSG("Overlap violation on filter %"PRIu8, filter);
+
+		if (status & INT_STATUS_OVERRUN)
+			EMSG("Overrun violation on filter %"PRIu8, filter);
+
+		if (status & INT_STATUS_STATUS)
+			EMSG("Permission violation on filter %"PRIu8, filter);
+
+		ctrl = omc_read32(filter, FAIL_CONTROL_OFF +
+				FAIL_DIRECTION_OFF(direction));
+		addr = omc_read64(filter, FAIL_ADDRESS_LOW_OFF +
+				FAIL_DIRECTION_OFF(direction));
+		nsaid = omc_read32(filter, FAIL_ID_OFF +
+				FAIL_DIRECTION_OFF(direction));
+		EMSG("Violation @%#"PRIx64
+		     ", %ssecure %sprivileged %s, MID %#"PRIx32", AID %#"PRIx32,
+		     addr,
+		     (ctrl & FAIL_CONTROL_NONSECURE) ? "non-" : "",
+		     (ctrl & FAIL_CONTROL_PRIVILEGED) ? "" : "un",
+		     (direction == INT_TYPE_WRITE) ? "write" : "read",
+		     (nsaid & FAIL_ID_MID_MASK) >> FAIL_ID_MID_SHIFT,
+		     (nsaid & FAIL_ID_AID_MASK) >> FAIL_ID_AID_SHIFT);
+	}
+}
+
+void omc_int_clear(uint8_t filter)
+{
+	if (!tzc.base)
+		panic("tzc.base is null");
+
+	omc_write32(filter, INT_CLEAR, BIT(0));
+}
diff --git a/core/drivers/pinctrl/atmel_pio.c b/core/drivers/pinctrl/atmel_pio.c
index 98b181f66ec50e6b034a05f3cd8d8e2bde14ea57..320d5279a1992a03ef56c31bc3b8eabc4a686481 100644
--- a/core/drivers/pinctrl/atmel_pio.c
+++ b/core/drivers/pinctrl/atmel_pio.c
@@ -178,8 +178,11 @@ static void pio_init_hw(struct atmel_pio *pio)
 		pio_write(pio, PIO_SIONR(PIO_GROUP_COUNT), GENMASK_32(31, 0));
 }
 
+/* Non-null reference for compat data */
+static const uint8_t has_pioe;
+
 static TEE_Result pio_node_probe(const void *fdt, int node,
-				 const void *compat_data __unused)
+				 const void *compat_data)
 {
 	size_t size = 0;
 	struct clk *clk = NULL;
@@ -209,6 +212,9 @@ static TEE_Result pio_node_probe(const void *fdt, int node,
 	matrix_configure_periph_secure(AT91C_ID_PIOC);
 	matrix_configure_periph_secure(AT91C_ID_PIOD);
 
+	if (compat_data == &has_pioe)
+		matrix_configure_periph_secure(AT91C_ID_PIOD + 1);
+
 	pio_init_hw(pio);
 
 	res = pinctrl_register_provider(fdt, node, pio_pinctrl_dt_get, pio);
@@ -227,6 +233,10 @@ free_pio:
 
 static const struct dt_device_match atmel_pio_match_table[] = {
 	{ .compatible = "atmel,sama5d2-pinctrl" },
+	{
+		.compatible = "microchip,sama7g5-pinctrl",
+		.compat_data = &has_pioe,
+	},
 	{ }
 };
 
diff --git a/core/drivers/pl011.c b/core/drivers/pl011.c
index 0fc03d674513d053ec275e499082aa90740adb01..da16392fffdb923b4d7101fa7cf5bb8d7b029ab8 100644
--- a/core/drivers/pl011.c
+++ b/core/drivers/pl011.c
@@ -5,9 +5,11 @@
 #include <assert.h>
 #include <drivers/pl011.h>
 #include <io.h>
+#include <util.h>
 #include <keep.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
+#include <kernel/spinlock.h>
 #include <stdlib.h>
 #include <trace.h>
 #include <types_ext.h>
@@ -127,11 +129,27 @@ static void pl011_putc(struct serial_chip *chip, int ch)
 	io_write32(base + UART_DR, ch);
 }
 
+static void pl011_rx_intr_enable(struct serial_chip *chip)
+{
+	vaddr_t base = chip_to_base(chip);
+
+	io_write32(base + UART_IMSC, UART_IMSC_RXIM);
+}
+
+static void pl011_rx_intr_disable(struct serial_chip *chip)
+{
+	vaddr_t base = chip_to_base(chip);
+
+	io_write32(base + UART_IMSC, 0);
+}
+
 static const struct serial_ops pl011_ops = {
 	.flush = pl011_flush,
 	.getchar = pl011_getchar,
 	.have_rx_data = pl011_have_rx_data,
 	.putc = pl011_putc,
+	.rx_intr_enable = pl011_rx_intr_enable,
+	.rx_intr_disable = pl011_rx_intr_disable,
 };
 DECLARE_KEEP_PAGER(pl011_ops);
 
@@ -160,8 +178,8 @@ void pl011_init(struct pl011_data *pd, paddr_t pbase, uint32_t uart_clk,
 	/* Configure TX to 8 bits, 1 stop bit, no parity, fifo disabled. */
 	io_write32(base + UART_LCR_H, UART_LCRH_WLEN_8);
 
-	/* Enable interrupts for receive and receive timeout */
-	io_write32(base + UART_IMSC, UART_IMSC_RXIM | UART_IMSC_RTIM);
+	/* Enable receive interrupt */
+	io_write32(base + UART_IMSC, UART_IMSC_RXIM);
 
 	/* Enable UART and RX/TX */
 	io_write32(base + UART_CR, UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE);
diff --git a/core/drivers/pm/sam/at91_pm.c b/core/drivers/pm/sam/at91_pm.c
index 86fb0497c02047c5f614b4bc6f82d936c6caadb4..fd9eb456d54bd29bc60f0f604d9d8e26b6ea1758 100644
--- a/core/drivers/pm/sam/at91_pm.c
+++ b/core/drivers/pm/sam/at91_pm.c
@@ -12,6 +12,7 @@
 #include <kernel/boot.h>
 #include <kernel/dt.h>
 #include <kernel/pm.h>
+#include <kernel/tlb_helpers.h>
 #include <libfdt.h>
 #include <matrix.h>
 #include <mm/core_memprot.h>
@@ -107,8 +108,8 @@ void atmel_pm_cpu_idle(void)
 	io_write32(soc_pm.ramc + AT91_DDRSDRC_LPR, saved_lpr0);
 }
 
-static void at91_sama5d2_config_shdwc_ws(vaddr_t shdwc, uint32_t *mode,
-					 uint32_t *polarity)
+static void at91_sam_config_shdwc_ws(vaddr_t shdwc, uint32_t *mode,
+				     uint32_t *polarity)
 {
 	uint32_t val = 0;
 
@@ -118,11 +119,11 @@ static void at91_sama5d2_config_shdwc_ws(vaddr_t shdwc, uint32_t *mode,
 	*polarity |= (val >> AT91_SHDW_WKUPT_SHIFT) & AT91_SHDW_WKUPT_MASK;
 }
 
-static int at91_sama5d2_config_pmc_ws(vaddr_t pmc, uint32_t mode,
-				      uint32_t polarity)
+static int at91_sam_config_pmc_ws(vaddr_t pmc, uint32_t mode, uint32_t polarity)
 {
 	io_write32(pmc + AT91_PMC_FSMR, mode);
-	io_write32(pmc + AT91_PMC_FSPR, polarity);
+	if (IS_ENABLED(CFG_SAMA5D2))
+		io_write32(pmc + AT91_PMC_FSPR, polarity);
 
 	return 0;
 }
@@ -138,6 +139,8 @@ static const struct wakeup_source_info ws_info[] = {
 	{ .pmc_fsmr_bit = AT91_PMC_RTCAL,	.shdwc_mr_bit = BIT(17) },
 	{ .pmc_fsmr_bit = AT91_PMC_USBAL },
 	{ .pmc_fsmr_bit = AT91_PMC_SDMMC_CD },
+	{ .pmc_fsmr_bit = AT91_PMC_RTTAL },
+	{ .pmc_fsmr_bit = AT91_PMC_RXLP_MCE },
 };
 
 struct wakeup_src {
@@ -145,7 +148,8 @@ struct wakeup_src {
 	const struct wakeup_source_info *info;
 };
 
-static const struct wakeup_src sama5d2_ws_ids[] = {
+static const struct wakeup_src sam_ws_ids[] = {
+#ifdef CFG_SAMA5D2
 	{ .compatible = "atmel,sama5d2-gem",		.info = &ws_info[0] },
 	{ .compatible = "atmel,at91rm9200-rtc",		.info = &ws_info[1] },
 	{ .compatible = "atmel,sama5d3-udc",		.info = &ws_info[2] },
@@ -154,6 +158,16 @@ static const struct wakeup_src sama5d2_ws_ids[] = {
 	{ .compatible = "atmel,at91sam9g45-ehci",	.info = &ws_info[2] },
 	{ .compatible = "usb-ehci",			.info = &ws_info[2] },
 	{ .compatible = "atmel,sama5d2-sdhci",		.info = &ws_info[3] }
+#endif
+#ifdef CFG_SAMA7G5
+	{ .compatible = "microchip,sama7g5-rtc",	.info = &ws_info[1] },
+	{ .compatible = "microchip,sama7g5-ohci",	.info = &ws_info[2] },
+	{ .compatible = "usb-ohci",			.info = &ws_info[2] },
+	{ .compatible = "atmel,at91sam9g45-ehci",	.info = &ws_info[2] },
+	{ .compatible = "usb-ehci",			.info = &ws_info[2] },
+	{ .compatible = "microchip,sama7g5-sdhci",	.info = &ws_info[3] },
+	{ .compatible = "microchip,sama7g5-rtt",	.info = &ws_info[4] },
+#endif
 };
 
 static bool dev_is_wakeup_source(const void *fdt, int node)
@@ -176,13 +190,13 @@ static int at91_pm_config_ws_ulp1(bool set)
 		return TEE_SUCCESS;
 	}
 
-	at91_sama5d2_config_shdwc_ws(soc_pm.shdwc, &mode, &polarity);
+	at91_sam_config_shdwc_ws(soc_pm.shdwc, &mode, &polarity);
 
 	val = io_read32(soc_pm.shdwc + AT91_SHDW_MR);
 
 	/* Loop through defined wakeup sources. */
-	for (src = 0; src < ARRAY_SIZE(sama5d2_ws_ids); src++) {
-		wsrc = &sama5d2_ws_ids[src];
+	for (src = 0; src < ARRAY_SIZE(sam_ws_ids); src++) {
+		wsrc = &sam_ws_ids[src];
 		wsi = wsrc->info;
 
 		node = fdt_node_offset_by_compatible(soc_pm.fdt, -1,
@@ -209,7 +223,7 @@ next_node:
 		return TEE_ERROR_BAD_STATE;
 	}
 
-	at91_sama5d2_config_pmc_ws(soc_pm.pmc, mode, polarity);
+	at91_sam_config_pmc_ws(soc_pm.pmc, mode, polarity);
 
 	return TEE_SUCCESS;
 }
@@ -231,8 +245,8 @@ static bool at91_pm_verify_clocks(void)
 		return false;
 	}
 
-	/* PCK0..PCK3 must be disabled, or configured to use clk32k */
-	for (i = 0; i < 4; i++) {
+	/* PCK0..PCKx must be disabled, or configured to use clk32k */
+	for (i = 0; i < AT91_PMC_PCK_COUNT; i++) {
 		uint32_t css = 0;
 
 		if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
@@ -266,6 +280,21 @@ static TEE_Result at91_write_backup_data(void)
 	return TEE_SUCCESS;
 }
 
+static void at91_pm_change_state(enum pm_op op)
+{
+	int type = 0;
+	uint32_t hint = 0;
+
+	if (soc_pm.mode == AT91_PM_STANDBY)
+		type = PM_SUSPEND_STANDBY;
+	else
+		type = PM_SUSPEND_TO_MEM;
+
+	hint = SHIFT_U32(type, PM_HINT_SUSPEND_TYPE_SHIFT);
+
+	pm_change_state(op, hint);
+}
+
 static TEE_Result at91_enter_backup(void)
 {
 	int ret = -1;
@@ -275,7 +304,7 @@ static TEE_Result at91_enter_backup(void)
 	if (res)
 		return res;
 
-	pm_change_state(PM_OP_SUSPEND, 0);
+	at91_pm_change_state(PM_OP_SUSPEND);
 	ret = sm_pm_cpu_suspend((uint32_t)&soc_pm,
 				(void *)at91_suspend_sram_fn);
 	if (ret < 0) {
@@ -285,7 +314,7 @@ static TEE_Result at91_enter_backup(void)
 		res = TEE_SUCCESS;
 	}
 
-	pm_change_state(PM_OP_RESUME, 0);
+	at91_pm_change_state(PM_OP_RESUME);
 	if (res)
 		return res;
 
@@ -298,6 +327,7 @@ static TEE_Result at91_enter_backup(void)
 TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t sctlr = 0;
 
 	DMSG("Entering suspend mode %d", soc_pm.mode);
 
@@ -311,6 +341,19 @@ TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec)
 
 	sm_save_unbanked_regs(&nsec->ub_regs);
 
+	/*
+	 * In order to run code for low-power out of SRAM without abort,
+	 * configure regions with write permission with not forced to
+	 * XN (Execute-never) attribute.
+	 */
+	if (IS_ENABLED(CFG_HWSUPP_MEM_PERM_WXN)) {
+		sctlr = read_sctlr();
+		if (sctlr & SCTLR_WXN) {
+			write_sctlr(sctlr & ~SCTLR_WXN);
+			tlbi_all();
+		}
+	}
+
 	if (soc_pm.mode == AT91_PM_BACKUP) {
 		res = at91_enter_backup();
 	} else {
@@ -318,6 +361,14 @@ TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec)
 		res = TEE_SUCCESS;
 	}
 
+	/* Restore the XN attribute */
+	if (IS_ENABLED(CFG_HWSUPP_MEM_PERM_WXN)) {
+		if (sctlr & SCTLR_WXN) {
+			write_sctlr(sctlr);
+			tlbi_all();
+		}
+	}
+
 	if (soc_pm.mode == AT91_PM_ULP1)
 		at91_pm_config_ws_ulp1(false);
 
@@ -337,21 +388,49 @@ TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec)
 
 static TEE_Result at91_pm_dt_dram_init(const void *fdt)
 {
+	const struct {
+		const char *compatible;
+		vaddr_t *address;
+	} dram_map[] = {
+#ifdef CFG_SAMA5D2
+		{
+			.compatible = "atmel,sama5d3-ddramc",
+			.address = &soc_pm.ramc,
+		},
+#endif
+#ifdef CFG_SAMA7G5
+		{
+			.compatible = "microchip,sama7g5-uddrc",
+			.address = &soc_pm.ramc,
+		},
+		{
+			.compatible = "microchip,sama7g5-ddr3phy",
+			.address = &soc_pm.ramc_phy,
+		},
+#endif
+	};
+	uint32_t i = 0;
 	int node = -1;
 	size_t size = 0;
 
-	node = fdt_node_offset_by_compatible(fdt, -1, "atmel,sama5d3-ddramc");
-	if (node < 0)
-		return TEE_ERROR_ITEM_NOT_FOUND;
+	for (i = 0; i < ARRAY_SIZE(dram_map); i++) {
+		node = fdt_node_offset_by_compatible(fdt, -1,
+						     dram_map[i].compatible);
 
-	if (dt_map_dev(fdt, node, &soc_pm.ramc, &size, DT_MAP_AUTO) < 0)
-		return TEE_ERROR_GENERIC;
+		if (node < 0)
+			return TEE_ERROR_ITEM_NOT_FOUND;
+
+		if (dt_map_dev(fdt, node,
+			       dram_map[i].address, &size, DT_MAP_AUTO) < 0)
+			return TEE_ERROR_GENERIC;
+	}
 
 	return TEE_SUCCESS;
 }
 
 static TEE_Result at91_pm_backup_init(const void *fdt)
 {
+	enum dt_map_dev_directive mapping = DT_MAP_AUTO;
 	int node = -1;
 	size_t size = 0;
 
@@ -359,11 +438,16 @@ static TEE_Result at91_pm_backup_init(const void *fdt)
 	if (node < 0)
 		return TEE_ERROR_ITEM_NOT_FOUND;
 
-	if (dt_map_dev(fdt, node, &soc_pm.sfrbu, &size, DT_MAP_AUTO) < 0)
+	if (IS_ENABLED(CFG_SAMA7G5))
+		mapping = DT_MAP_SECURE;
+
+	if (dt_map_dev(fdt, node, &soc_pm.sfrbu, &size, mapping) < 0)
 		return TEE_ERROR_GENERIC;
 
 	if (fdt_get_status(fdt, node) == DT_STATUS_OK_SEC)
-		matrix_configure_periph_secure(AT91C_ID_SFRBU);
+		/* for SAMA7G5 SFRBU is always secured, no need to configre */
+		if (!IS_ENABLED(CFG_SAMA7G5))
+			matrix_configure_periph_secure(AT91C_ID_SFRBU);
 
 	return TEE_SUCCESS;
 }
@@ -388,8 +472,13 @@ static TEE_Result at91_pm_sram_init(const void *fdt)
 
 	at91_suspend_sram_pbase = virt_to_phys((void *)at91_suspend_sram_base);
 
-	/* Map the secure ram suspend code to be executable */
-	at91_suspend_sram_fn = core_mmu_add_mapping(MEM_AREA_TEE_RAM,
+	/*
+	 * Map the secure ram suspend code with the memory area type
+	 * "MEM_AREA_TEE_COHERENT" to make it non-cacheable.
+	 * Mapping with memory area type "MEM_AREA_TEE_RAM" would enable
+	 * cacheable attribute and might cause abort in some cases.
+	 */
+	at91_suspend_sram_fn = core_mmu_add_mapping(MEM_AREA_TEE_COHERENT,
 						    at91_suspend_sram_pbase,
 						    suspend_sz);
 	if (!at91_suspend_sram_fn) {
@@ -444,7 +533,7 @@ static TEE_Result at91_securam_init(const void *fdt)
 	return TEE_SUCCESS;
 }
 
-static TEE_Result sama5d2_pm_init_all(const void *fdt, vaddr_t shdwc)
+static TEE_Result sam_pm_init_all(const void *fdt, vaddr_t shdwc)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 
@@ -475,10 +564,10 @@ static TEE_Result sama5d2_pm_init_all(const void *fdt, vaddr_t shdwc)
 	return TEE_SUCCESS;
 }
 
-TEE_Result sama5d2_pm_init(const void *fdt, vaddr_t shdwc)
+TEE_Result sam_pm_init(const void *fdt, vaddr_t shdwc)
 {
-	if (sama5d2_pm_init_all(fdt, shdwc))
-		panic("Failed to setup PM for sama5d2");
+	if (sam_pm_init_all(fdt, shdwc))
+		panic("Failed to setup PM for this MPU");
 
 	return TEE_SUCCESS;
 }
diff --git a/core/drivers/pm/sam/at91_pm.h b/core/drivers/pm/sam/at91_pm.h
index 47b2d72c00cd104b4b500754341e3db91ff704d5..a78ee05153ba8eceedd2863ac160d5fe1eeecea4 100644
--- a/core/drivers/pm/sam/at91_pm.h
+++ b/core/drivers/pm/sam/at91_pm.h
@@ -26,6 +26,7 @@ struct at91_pm_data {
 	vaddr_t sfrbu;
 	vaddr_t pmc;
 	vaddr_t ramc;
+	vaddr_t ramc_phy;
 	unsigned int mode;
 	const void *fdt;
 };
diff --git a/core/drivers/pm/sam/pm-defines.c b/core/drivers/pm/sam/pm-defines.c
index 94e31b8a4a3e522fbcb549deac306b36d76c2239..6d96e2b3e7532dd19725f0ccdceb4e98471663ec 100644
--- a/core/drivers/pm/sam/pm-defines.c
+++ b/core/drivers/pm/sam/pm-defines.c
@@ -12,6 +12,8 @@ DEFINES
 {
 	DEFINE(PM_DATA_PMC,		offsetof(struct at91_pm_data, pmc));
 	DEFINE(PM_DATA_RAMC0,		offsetof(struct at91_pm_data, ramc));
+	DEFINE(PM_DATA_RAMC_PHY,	offsetof(struct at91_pm_data,
+						 ramc_phy));
 	DEFINE(PM_DATA_MODE,		offsetof(struct at91_pm_data, mode));
 	DEFINE(PM_DATA_SHDWC,		offsetof(struct at91_pm_data, shdwc));
 	DEFINE(PM_DATA_SFRBU,		offsetof(struct at91_pm_data, sfrbu));
diff --git a/core/drivers/pm/sam/pm_suspend.S b/core/drivers/pm/sam/pm_suspend.S
index 9367d2345e8afedd720bf365b209df8b9b5c4da6..08cef1121858e0b847c07ed0c98ffd550f482360 100644
--- a/core/drivers/pm/sam/pm_suspend.S
+++ b/core/drivers/pm/sam/pm_suspend.S
@@ -10,7 +10,11 @@
 #include <arm32_macros.S>
 #include <asm.S>
 #include <at91_pmc.h>
+#ifdef CFG_SAMA7G5
+#include <drivers/sam/sama7-ddr.h>
+#else
 #include <drivers/sam/at91_ddr.h>
+#endif
 #include <generated/pm-defines.h>
 
 #include "at91_pm.h"
@@ -25,11 +29,23 @@ tmp3	.req	r6
 
 /*
  * Wait until master clock is ready (after switching master clock source)
+ * @r_mckid:	register holding master clock identifier
+ *
+ * Side effects: overwrites tmp1
  */
-.macro wait_mckrdy
+.macro wait_mckrdy r_mckid
+#ifdef CFG_SAMA7G5
+	cmp	\r_mckid, #0
+	beq	1f
+2:	ldr	tmp1, [pmc, #AT91_PMC_SR]
+	tst	tmp1, #AT91_PMC_MCKXRDY
+	beq	2b
+	b	3f
+#endif
 1:	ldr	tmp1, [pmc, #AT91_PMC_SR]
 	tst	tmp1, #AT91_PMC_MCKRDY
 	beq	1b
+3:
 .endm
 
 /*
@@ -68,6 +84,221 @@ tmp3	.req	r6
 
 .arm
 
+#ifdef CFG_SAMA7G5
+/*
+ * Enable self-refresh
+ *
+ * Side effects: overwrites tmp1, tmp2, tmp3
+ */
+.macro at91_sramc_self_refresh_ena
+	dsb
+
+	ldr	tmp2, .sramc_base
+
+	/* Disable all AXI ports. */
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_0]
+	bic	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_0]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_1]
+	bic	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_1]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_2]
+	bic	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_2]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_3]
+	bic	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_3]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_4]
+	bic	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_4]
+
+sr_ena_1:
+	/* Wait for all ports to disable. */
+	ldr	tmp1, [tmp2, #UDDRC_PSTAT]
+	ldr	tmp3, =UDDRC_PSTAT_ALL_PORTS
+	tst	tmp1, tmp3
+	bne	sr_ena_1
+
+	/* Switch to self-refresh. */
+	ldr	tmp1, [tmp2, #UDDRC_PWRCTL]
+	orr	tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
+	str	tmp1, [tmp2, #UDDRC_PWRCTL]
+
+sr_ena_2:
+	/* Wait for self-refresh enter. */
+	ldr	tmp1, [tmp2, #UDDRC_STAT]
+	bic	tmp1, tmp1, #~UDDRC_STAT_SELFREF_TYPE_MSK
+	cmp	tmp1, #UDDRC_STAT_SELFREF_TYPE_SW
+	bne	sr_ena_2
+
+	ldr	tmp2, .sramc_phy_base
+
+	/* Disable DX DLLs for non-backup modes. */
+	ldr	tmp1, .pm_mode
+	cmp	tmp1, #AT91_PM_BACKUP
+	beq	sr_ena_3
+
+	/* Do not soft reset the AC DLL. */
+	ldr	tmp1, [tmp2, #DDR3PHY_ACDLLCR]
+	bic	tmp1, tmp1, #DDR3PHY_ACDLLCR_DLLSRST
+	str	tmp1, [tmp2, #DDR3PHY_ACDLLCR]
+
+	/* Disable DX DLLs. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
+	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+	str	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
+
+	ldr	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
+	orr	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+	str	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
+
+sr_ena_3:
+	/* Power down DDR PHY data receivers. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DXCCR]
+	orr	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+	str	tmp1, [tmp2, #DDR3PHY_DXCCR]
+
+	/* Power down ADDR/CMD IO. */
+	ldr	tmp1, [tmp2, #DDR3PHY_ACIOCR]
+	orr	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+	orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+	orr	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+	str	tmp1, [tmp2, #DDR3PHY_ACIOCR]
+
+	/* Power down ODT. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DSGCR]
+	orr	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+	str	tmp1, [tmp2, #DDR3PHY_DSGCR]
+.endm
+
+/*
+ * Disable self-refresh
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
+.macro at91_sramc_self_refresh_dis
+	ldr	tmp2, .sramc_phy_base
+
+	/* Power up DDR PHY data receivers. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DXCCR]
+	bic	tmp1, tmp1, #DDR3PHY_DXCCR_DXPDR
+	str	tmp1, [tmp2, #DDR3PHY_DXCCR]
+
+	/* Power up the output of CK and CS pins. */
+	ldr	tmp1, [tmp2, #DDR3PHY_ACIOCR]
+	bic	tmp1, tmp1, #DDR3PHY_ACIORC_ACPDD
+	bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CKPDD_CK0
+	bic	tmp1, tmp1, #DDR3PHY_ACIOCR_CSPDD_CS0
+	str	tmp1, [tmp2, #DDR3PHY_ACIOCR]
+
+	/* Power up ODT. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DSGCR]
+	bic	tmp1, tmp1, #DDR3PHY_DSGCR_ODTPDD_ODT0
+	str	tmp1, [tmp2, #DDR3PHY_DSGCR]
+
+	/* Enable DX DLLs. */
+	ldr	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
+	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+	str	tmp1, [tmp2, #DDR3PHY_DX0DLLCR]
+
+	ldr	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
+	bic	tmp1, tmp1, #DDR3PHY_DXDLLCR_DLLDIS
+	str	tmp1, [tmp2, #DDR3PHY_DX1DLLCR]
+
+	ldr	tmp2, .sramc_base
+
+	/* Enable quasi-dynamic programming. */
+	mov	tmp1, #0
+	str	tmp1, [tmp2, #UDDRC_SWCTRL]
+
+	/* De-assert SDRAM initialization. */
+	ldr	tmp1, [tmp2, #UDDRC_DFIMISC]
+	bic	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+	str	tmp1, [tmp2, #UDDRC_DFIMISC]
+
+	/* Quasi-dynamic programming done. */
+	mov	tmp1, #UDDRC_SWCTRL_SW_DONE
+	str	tmp1, [tmp2, #UDDRC_SWCTRL]
+
+sr_dis_1:
+	ldr	tmp1, [tmp2, #UDDRC_SWSTAT]
+	tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+	beq	sr_dis_1
+
+	ldr	tmp2, .sramc_phy_base
+
+	/* DLL soft-reset + DLL lock wait + ITM reset */
+	mov	tmp1, #(DDR3PHY_PIR_INIT | DDR3PHY_PIR_DLLSRST | \
+			DDR3PHY_PIR_DLLLOCK | DDR3PHY_PIR_ITMSRST)
+	str	tmp1, [tmp2, #DDR3PHY_PIR]
+
+sr_dis_4:
+	/* Wait for it. */
+	ldr	tmp1, [tmp2, #DDR3PHY_PGSR]
+	tst	tmp1, #DDR3PHY_PGSR_IDONE
+	beq	sr_dis_4
+
+	ldr	tmp2, .sramc_base
+
+	/* Enable quasi-dynamic programming. */
+	mov	tmp1, #0
+	str	tmp1, [tmp2, #UDDRC_SWCTRL]
+
+	/* Assert PHY init complete enable signal. */
+	ldr	tmp1, [tmp2, #UDDRC_DFIMISC]
+	orr	tmp1, tmp1, #UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN
+	str	tmp1, [tmp2, #UDDRC_DFIMISC]
+
+	/* Programming is done. Set sw_done. */
+	mov	tmp1, #UDDRC_SWCTRL_SW_DONE
+	str	tmp1, [tmp2, #UDDRC_SWCTRL]
+
+sr_dis_5:
+	/* Wait for it. */
+	ldr	tmp1, [tmp2, #UDDRC_SWSTAT]
+	tst	tmp1, #UDDRC_SWSTAT_SW_DONE_ACK
+	beq	sr_dis_5
+
+	/* Trigger self-refresh exit. */
+	ldr	tmp1, [tmp2, #UDDRC_PWRCTL]
+	bic	tmp1, tmp1, #UDDRC_PWRCTL_SELFREF_SW
+	str	tmp1, [tmp2, #UDDRC_PWRCTL]
+
+sr_dis_6:
+	/* Wait for self-refresh exit done. */
+	ldr	tmp1, [tmp2, #UDDRC_STAT]
+	bic	tmp1, tmp1, #~UDDRC_STAT_OPMODE_MSK
+	cmp	tmp1, #UDDRC_STAT_OPMODE_NORMAL
+	bne	sr_dis_6
+
+	/* Enable all AXI ports. */
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_0]
+	orr	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_0]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_1]
+	orr	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_1]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_2]
+	orr	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_2]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_3]
+	orr	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_3]
+
+	ldr	tmp1, [tmp2, #UDDRC_PCTRL_4]
+	orr	tmp1, tmp1, #0x1
+	str	tmp1, [tmp2, #UDDRC_PCTRL_4]
+
+	dsb
+.endm
+#endif
 
 #define SUSPEND_FUNC(__name) \
 __name:
@@ -96,10 +327,28 @@ SUSPEND_FUNC(at91_pm_suspend_in_sram)
 	mov	tmp1, #0
 	mcr	p15, 0, tmp1, c7, c10, 4
 
+	write_tlbiall
+	isb
+
+	/*
+	 * ldrne below are here to preload their address in the TLB as access
+	 * to RAM may be limited while in self-refresh.
+	 */
 	ldr	tmp1, [r0, #PM_DATA_PMC]
 	str	tmp1, .pmc_base
+	cmp	tmp1, #0
+	ldrne	tmp2, [tmp1, #0]
+
 	ldr	tmp1, [r0, #PM_DATA_RAMC0]
 	str	tmp1, .sramc_base
+	cmp	tmp1, #0
+	ldrne	tmp2, [tmp1, #0]
+
+	ldr	tmp1, [r0, #PM_DATA_RAMC_PHY]
+	str	tmp1, .sramc_phy_base
+	cmp	tmp1, #0
+	ldrne	tmp2, [tmp1, #0]
+
 	ldr	tmp1, [r0, #PM_DATA_MODE]
 	str	tmp1, .pm_mode
 	/* Both ldrne below are here to preload their address in the TLB */
@@ -113,8 +362,13 @@ SUSPEND_FUNC(at91_pm_suspend_in_sram)
 	ldrne	tmp2, [tmp1, #0x10]
 
 	/* Active the self-refresh mode */
+#ifdef CFG_SAMA5D2
 	mov	r0, #SRAMC_SELF_FRESH_ACTIVE
 	bl	at91_sramc_self_refresh
+#endif
+#ifdef CFG_SAMA7G5
+	at91_sramc_self_refresh_ena
+#endif
 
 	ldr	r0, .pm_mode
 	cmp	r0, #AT91_PM_STANDBY
@@ -137,8 +391,13 @@ backup_mode:
 
 exit_suspend:
 	/* Exit the self-refresh mode */
+#ifdef CFG_SAMA5D2
 	mov	r0, #SRAMC_SELF_FRESH_EXIT
 	bl	at91_sramc_self_refresh
+#endif
+#ifdef CFG_SAMA7G5
+	at91_sramc_self_refresh_dis
+#endif
 
 	/* Restore registers, and return */
 	ldmfd	sp!, {r4 - r12, pc}
@@ -151,7 +410,8 @@ SUSPEND_FUNC(at91_backup_mode)
 	bic	tmp1, tmp1, #AT91_PMC_CSS
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
 
 	/*BUMEN*/
 	ldr	r0, .sfrbu
@@ -162,9 +422,33 @@ SUSPEND_FUNC(at91_backup_mode)
 	ldr	r0, .shdwc
 	mov	tmp1, #0xA5000000
 	add	tmp1, tmp1, #0x1
+#ifdef CFG_SAMA7G5
+	/* LPM Pad Enable: The LPM pad is set high */
+	orr	tmp1, tmp1, #0x200000
+#endif
 	str	tmp1, [r0, #0]
 SUSPEND_END_FUNC(at91_backup_mode)
 
+/*
+ * Set LPM
+ * @ena: 0 - disable LPM
+ *	 1 - enable LPM
+ *
+ * Side effects: overwrites tmp1, tmp3
+ */
+.macro at91_set_lpm ena
+#ifdef CFG_SAMA7G5
+	mov	tmp1, #\ena
+	cmp	tmp1, #1
+	movne	tmp3, #0x400000 /* LPM Pad Disable: The LPM pad is set low */
+	moveq	tmp3, #0x200000 /* LPM Pad Enable: The LPM pad is set high */
+	add	tmp3, #0xA5000000
+	ldr	tmp1, .shdwc
+	cmp	tmp1, #0
+	strne	tmp3, [tmp1]
+#endif
+.endm
+
 .macro at91_pm_ulp0_mode
 	ldr	pmc, .pmc_base
 	ldr	tmp2, .pm_mode
@@ -178,7 +462,9 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	bic	tmp1, tmp1, #AT91_PMC_PRES
 	orr	tmp1, tmp1, #AT91_PMC_PRES_64
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
-	wait_mckrdy
+
+	mov	tmp3, #0
+	wait_mckrdy tmp3
 	b	1f
 
 0:
@@ -192,7 +478,7 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	ldr	tmp1, [pmc, #AT91_PMC_SR]
 	str	tmp1, .saved_osc_status
 	tst	tmp1, #AT91_PMC_MOSCRCS
-	bne	1f
+	bne	7f
 
 	/* Turn off RC oscillator */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
@@ -206,20 +492,27 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	tst	tmp1, #AT91_PMC_MOSCRCS
 	bne	2b
 
+	/* Enable LPM. */
+7:	at91_set_lpm 1
+
 	/* Wait for interrupt */
 1:	at91_cpu_idle
 
 	/* Check if ULP0 fast variant has been requested. */
 	cmp	tmp2, #AT91_PM_ULP0_FAST
-	bne	5f
+	bne	8f
 
 	/* Set lowest prescaler for fast resume. */
 	ldr	tmp1, [pmc, #AT91_PMC_MCKR]
 	bic	tmp1, tmp1, #AT91_PMC_PRES
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
-	wait_mckrdy
+
+	mov	tmp3, #0
+	wait_mckrdy tmp3
 	b	6f
 
+8:	at91_set_lpm 0
+
 5:	/* Restore RC oscillator state */
 	ldr	tmp1, .saved_osc_status
 	tst	tmp1, #AT91_PMC_MOSCRCS
@@ -294,7 +587,11 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
+
+	/* Enable LPM */
+	at91_set_lpm 1
 
 	/* Enter the ULP1 mode by set WAITMODE bit in CKGR_MOR */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
@@ -307,7 +604,11 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	nop
 	nop
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
+
+	/* Disable LPM. */
+	at91_set_lpm 0
 
 	/* Enable the crystal oscillator */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
@@ -323,7 +624,8 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	bic	tmp1, tmp1, #AT91_PMC_CSS
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
 
 	/* Switch main clock source to crystal oscillator */
 	ldr	tmp1, [pmc, #AT91_CKGR_MOR]
@@ -340,7 +642,7 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	orr	tmp1, tmp1, #AT91_PMC_CSS_MAIN
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	wait_mckrdy tmp3
 
 	/* Restore RC oscillator state */
 	ldr	tmp1, .saved_osc_status
@@ -362,7 +664,59 @@ SUSPEND_END_FUNC(at91_backup_mode)
 3:
 .endm
 
+/*
+ * Save PLLA setting and disable it
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
 .macro at91_plla_disable
+#ifdef CFG_SAMA7G5
+	/* Save PLLA settings */
+	ldr	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
+	bic	tmp2, tmp2, #AT91_PMC_PLL_UPDT_ID
+	str	tmp2, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* save div */
+	mov	tmp1, #0
+	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL0]
+	bic	tmp2, tmp2, #0xffffff00
+	orr	tmp1, tmp1, tmp2
+
+	/* save mul */
+	ldr	tmp2, [pmc, #AT91_PMC_PLL_CTRL1]
+	bic	tmp2, tmp2, #0xffffff
+	orr	tmp1, tmp1, tmp2
+	str	tmp1, .saved_pllar
+
+	/* step 2 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* step 3 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
+	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
+	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+
+	/* step 4 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* step 5 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+	bic	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
+	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+
+	/* step 6 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+#else
 	/* Save PLLA setting and disable it */
 	ldr	tmp1, [pmc, #AT91_CKGR_PLLAR]
 	str	tmp1, .saved_pllar
@@ -371,10 +725,62 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	mov	tmp1, #AT91_PMC_PLLCOUNT
 	orr	tmp1, tmp1, #(1 << 29)		/* bit 29 always set */
 	str	tmp1, [pmc, #AT91_CKGR_PLLAR]
+#endif
 2:
 .endm
 
+/*
+ * Enable PLLA with the saved setting
+ *
+ * Side effects: overwrites tmp1, tmp2
+ */
 .macro at91_plla_enable
+#ifdef CFG_SAMA7G5
+	/* step 1 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* step 2 */
+	ldr	tmp1, =AT91_PMC_PLL_ACR_DEFAULT_PLLA
+	str	tmp1, [pmc, #AT91_PMC_PLL_ACR]
+
+	/* step 3 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
+	ldr	tmp2, .saved_pllar
+	bic	tmp2, tmp2, #0xffffff
+	orr	tmp1, tmp1, tmp2
+	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL1]
+
+	/* step 4 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* step 5 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENLOCK
+	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLL
+	orr	tmp1, tmp1, #AT91_PMC_PLL_CTRL0_ENPLLCK
+	bic	tmp1, tmp1, #0xff
+	ldr	tmp2, .saved_pllar
+	bic	tmp2, tmp2, #0xffffff00
+	orr	tmp1, tmp1, tmp2
+	str	tmp1, [pmc, #AT91_PMC_PLL_CTRL0]
+
+	/* step 6 */
+	ldr	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+	orr	tmp1, tmp1, #AT91_PMC_PLL_UPDT_UPDATE
+	bic	tmp1, tmp1, #AT91_PMC_PLL_UPDT_ID
+	str	tmp1, [pmc, #AT91_PMC_PLL_UPDT]
+
+	/* step 7 */
+3:	ldr	tmp1, [pmc, #AT91_PMC_PLL_ISR0]
+	tst	tmp1, #0x1
+	beq	3b
+#else
 	ldr	tmp2, .saved_pllar
 
 	/* Restore PLLA setting */
@@ -390,9 +796,98 @@ SUSPEND_END_FUNC(at91_backup_mode)
 	tst	tmp1, #AT91_PMC_LOCKA
 	beq	1b
 2:
+#endif
 .endm
 
+#ifdef CFG_SAMA7G5
+/*
+ * at91_mckx_ps_enable:	save MCK1..4 settings and switch it to main clock
+ *
+ * Side effects: overwrites tmp1, tmp2, tmp3
+ */
+.macro at91_mckx_ps_enable
+	ldr	pmc, .pmc_base
+
+	/* There are 4 MCKs we need to handle: MCK1..4 */
+	mov	tmp1, #1
+e_loop:
+	/* Write MCK ID to retrieve the settings */
+	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
+	ldr	tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+	cmp	tmp1, #1
+	streq	tmp2, .saved_mck1
+	cmp	tmp1, #2
+	streq	tmp2, .saved_mck2
+	cmp	tmp1, #3
+	streq	tmp2, .saved_mck3
+	cmp	tmp1, #4
+	streq	tmp2, .saved_mck4
+
+	/* Use CSS=MD_SLOW_CLK and DIV=64. */
+	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MASK
+	bic	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV_MASK
+	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CSS_MD_SLCK
+	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_DIV64
+	orr	tmp2, tmp2, #AT91_PMC_MCR_V2_CMD
+	str	tmp2, [pmc, #AT91_PMC_MCR_V2]
+
+	mov	tmp2, tmp1
+	wait_mckrdy tmp1
+	mov	tmp1, tmp2
+
+	add	tmp1, tmp1, #1
+	cmp	tmp1, #5
+	bne	e_loop
+.endm
+
+/*
+ * at91_mckx_ps_restore: restore MCK1..4 settings
+ *
+ * Side effects: overwrites tmp1, tmp2, tmp3
+ */
+.macro at91_mckx_ps_restore
+	ldr	pmc, .pmc_base
+
+	/* There are 4 MCKs we need to handle: MCK1..4 */
+	mov	tmp1, #1
+	ldr	tmp2, .saved_mck1
+r_loop:
+	cmp	tmp1, #2
+	ldreq	tmp2, .saved_mck2
+	cmp	tmp1, #3
+	ldreq	tmp2, .saved_mck3
+	cmp	tmp1, #4
+	ldreq	tmp2, .saved_mck4
+
+	/* Write MCK ID to retrieve the settings */
+	str	tmp1, [pmc, #AT91_PMC_MCR_V2]
+	ldr	tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+	/* We need to restore CSS and DIV. */
+	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_CSS_MASK
+	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_DIV_MASK
+	orr	tmp3, tmp3, tmp2
+	bic	tmp3, tmp3, #AT91_PMC_MCR_V2_ID_MASK
+	orr	tmp3, tmp3, tmp1
+	orr	tmp3, tmp3, #AT91_PMC_MCR_V2_CMD
+	str	tmp3, [pmc, #AT91_PMC_MCR_V2]
+
+	mov	tmp2, tmp1
+	wait_mckrdy tmp1
+	mov	tmp1, tmp2
+
+	add	tmp1, tmp1, #1
+	cmp	tmp1, #5
+	bne	r_loop
+.endm
+#endif
+
 SUSPEND_FUNC(at91_ulp_mode)
+#ifdef CFG_SAMA7G5
+	at91_mckx_ps_enable
+#endif
+
 	ldr	pmc, .pmc_base
 	ldr	tmp3, .pm_mode
 
@@ -412,10 +907,12 @@ SUSPEND_FUNC(at91_ulp_mode)
 save_mck:
 	str	tmp1, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
 
 	at91_plla_disable
 
+	ldr	tmp3, .pm_mode
 	cmp	tmp3, #AT91_PM_ULP1
 	beq	ulp1_mode
 
@@ -437,11 +934,17 @@ ulp_exit:
 	ldr	tmp2, .saved_mckr
 	str	tmp2, [pmc, #AT91_PMC_MCKR]
 
-	wait_mckrdy
+	mov	tmp3, #0
+	wait_mckrdy tmp3
+
+#ifdef CFG_SAMA7G5
+	at91_mckx_ps_restore
+#endif
 
 	mov	pc, lr
 SUSPEND_END_FUNC(at91_ulp_mode)
 
+#ifdef CFG_SAMA5D2
 /*
  * void at91_sramc_self_refresh(unsigned int is_active)
  *
@@ -491,11 +994,14 @@ ddrc_exit_sf:
 exit_sramc_sf:
 	mov	pc, lr
 SUSPEND_END_FUNC(at91_sramc_self_refresh)
+#endif
 
 .pmc_base:
 	.word 0
 .sramc_base:
 	.word 0
+.sramc_phy_base:
+	.word 0
 .shdwc:
 	.word 0
 .sfrbu:
@@ -512,6 +1018,16 @@ SUSPEND_END_FUNC(at91_sramc_self_refresh)
 	.word 0
 .saved_osc_status:
 	.word 0
+#ifdef CFG_SAMA7G5
+.saved_mck1:
+	.word 0
+.saved_mck2:
+	.word 0
+.saved_mck3:
+	.word 0
+.saved_mck4:
+	.word 0
+#endif
 
 .global at91_pm_suspend_in_sram_sz
 at91_pm_suspend_in_sram_sz:
diff --git a/core/drivers/regulator/regulator.c b/core/drivers/regulator/regulator.c
index 4691913062b6dd41ab797afeeab6bb53cbc01b51..61edba7240edcc1fc7187bb090b7696dda6d278f 100644
--- a/core/drivers/regulator/regulator.c
+++ b/core/drivers/regulator/regulator.c
@@ -11,7 +11,7 @@
 #include <keep.h>
 #include <kernel/boot.h>
 #include <kernel/delay.h>
-#include <kernel/mutex.h>
+#include <kernel/mutex_pm_aware.h>
 #include <kernel/panic.h>
 #include <kernel/pm.h>
 #include <kernel/tee_time.h>
@@ -26,32 +26,15 @@
 static SLIST_HEAD(, regulator) regulator_device_list =
 	SLIST_HEAD_INITIALIZER(regulator);
 
+/* Access protection mutex complying the power state transitions context */
 static void lock_regulator(struct regulator *regulator)
 {
-	/*
-	 * Regulator operation may occur at runtime and during specific
-	 * system power transition: power off, PM suspend and resume.
-	 * These operate upon fastcall entries, under PSCI services
-	 * execution, where non-secure world is not operational. In these
-	 * cases we cannot take a mutex and will expect the mutex is
-	 * unlocked.
-	 */
-	if (thread_get_id_may_fail() == THREAD_ID_INVALID) {
-		assert(!regulator->lock.state);
-		return;
-	}
-
-	mutex_lock(&regulator->lock);
+	mutex_pm_aware_lock(&regulator->mutex);
 }
 
 static void unlock_regulator(struct regulator *regulator)
 {
-	if (thread_get_id_may_fail() == THREAD_ID_INVALID) {
-		/* Path for PM sequences when with local Monitor */
-		return;
-	}
-
-	mutex_unlock(&regulator->lock);
+	mutex_pm_aware_unlock(&regulator->mutex);
 }
 
 static TEE_Result set_state(struct regulator *regulator, bool on_not_off)
@@ -181,9 +164,27 @@ bool regulator_is_enabled(struct regulator *regulator)
 	return !res && enabled;
 }
 
+int regulator_get_voltage(struct regulator *regulator)
+{
+	TEE_Result res = TEE_SUCCESS;
+	int level_uv = regulator->min_uv;
+
+	if (regulator->ops->get_voltage) {
+		res = regulator->ops->get_voltage(regulator, &level_uv);
+		if (res) {
+			EMSG("%s get_voltage failed with %#"PRIx32,
+			     regulator_name(regulator), res);
+			level_uv = 0;
+		}
+	}
+
+	return level_uv;
+}
+
 TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
+	int cur_uv = 0;
 
 	assert(regulator);
 	FMSG("%s %duV", regulator_name(regulator), level_uv);
@@ -191,7 +192,8 @@ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv)
 	if (level_uv < regulator->min_uv || level_uv > regulator->max_uv)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (level_uv == regulator->cur_uv)
+	cur_uv = regulator_get_voltage(regulator);
+	if (level_uv == cur_uv)
 		return TEE_SUCCESS;
 
 	if (!regulator->ops->set_voltage)
@@ -207,8 +209,6 @@ TEE_Result regulator_set_voltage(struct regulator *regulator, int level_uv)
 		return res;
 	}
 
-	regulator->cur_uv = level_uv;
-
 	return TEE_SUCCESS;
 }
 
@@ -216,26 +216,30 @@ TEE_Result regulator_supported_voltages(struct regulator *regulator,
 					struct regulator_voltages_desc **desc,
 					const int **levels)
 {
-	assert(regulator && desc && levels);
+	TEE_Result res = TEE_ERROR_NOT_SUPPORTED;
 
-	if (regulator->ops->supported_voltages) {
-		TEE_Result res = TEE_ERROR_GENERIC;
+	assert(regulator && desc && levels);
 
+	if (regulator->ops->supported_voltages)
 		res = regulator->ops->supported_voltages(regulator, desc,
 							 levels);
-		if (res != TEE_ERROR_NOT_SUPPORTED)
-			return res;
-	} else {
+	if (res == TEE_ERROR_NOT_SUPPORTED) {
 		*desc = &regulator->voltages_fallback.desc;
 		*levels = regulator->voltages_fallback.levels;
+	} else if (res) {
+		return res;
 	}
 
-	assert(((*desc)->type == VOLTAGE_TYPE_FULL_LIST &&
-		(*levels)[0] >= regulator->min_uv && (*desc)->num_levels &&
-		(*levels)[(*desc)->num_levels - 1] <= regulator->max_uv) ||
-	       ((*desc)->type == VOLTAGE_TYPE_INCREMENT &&
-		(*levels)[0] >= regulator->min_uv &&
-		(*levels)[1] <= regulator->max_uv));
+	if ((*desc)->type == VOLTAGE_TYPE_FULL_LIST) {
+		assert((*desc)->num_levels);
+		assert((*levels)[0] >= regulator->min_uv);
+		assert((*levels)[(*desc)->num_levels - 1] <= regulator->max_uv);
+	} else if ((*desc)->type == VOLTAGE_TYPE_INCREMENT) {
+		assert((*levels)[0] >= regulator->min_uv);
+		assert((*levels)[1] <= regulator->max_uv);
+	} else {
+		assert(0);
+	}
 
 	return TEE_SUCCESS;
 }
@@ -251,19 +255,14 @@ TEE_Result regulator_register(struct regulator *regulator)
 	    regulator->flags & ~REGULATOR_FLAGS_MASK)
 		return TEE_ERROR_BAD_PARAMETERS;
 
+	mutex_pm_aware_init(&regulator->mutex);
+
 	regulator_get_range(regulator, &min_uv, &max_uv);
 	if (min_uv > max_uv)
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	/* Sanitize regulator effective level */
-	if (regulator->ops->get_voltage) {
-		res = regulator->ops->get_voltage(regulator, &uv);
-		if (res)
-			return res;
-	} else {
-		uv = min_uv;
-	}
-	regulator->cur_uv = uv;
+	uv = regulator_get_voltage(regulator);
 
 	if (uv < min_uv || uv > max_uv) {
 		res = regulator_set_voltage(regulator, min_uv);
@@ -311,7 +310,8 @@ static TEE_Result regulator_core_cleanup(void)
 		}
 	}
 
-	regulator_print_tree();
+	if (TRACE_LEVEL >= TRACE_DEBUG)
+		regulator_print_tree();
 
 	return TEE_SUCCESS;
 }
@@ -448,7 +448,7 @@ out:
 	if (!msg)
 		snprintf(msg_end - 4, 4, "...");
 
-	DMSG("%s", msg_buf);
+	IMSG("%s", msg_buf);
 }
 
 static void print_tree(void)
@@ -487,10 +487,10 @@ static void print_tree(void)
 void regulator_print_tree(void)
 {
 	if (IS_ENABLED(CFG_DRIVERS_REGULATOR_PRINT_TREE) &&
-	    TRACE_LEVEL >= TRACE_DEBUG) {
-		DMSG("Regulator tree summary");
+	    TRACE_LEVEL >= TRACE_INFO) {
+		IMSG("Regulator tree summary");
 		if (SLIST_EMPTY(&regulator_device_list))
-			DMSG("-- No registered regulator");
+			IMSG("-- No registered regulator");
 		else
 			print_tree();
 	}
diff --git a/core/drivers/regulator/regulator_gpio.c b/core/drivers/regulator/regulator_gpio.c
index a5fa4c28ebbfe32ff477eb3d993bc418037ed5d1..e48d585729c301540ddbf9e2889264c36ea4691b 100644
--- a/core/drivers/regulator/regulator_gpio.c
+++ b/core/drivers/regulator/regulator_gpio.c
@@ -20,14 +20,16 @@ static_assert(GPIO_LEVEL_HIGH == 1 && GPIO_LEVEL_LOW == 0);
  * @enable_gpio: GPIO for the enable state of the regulator or NULL if always on
  * @enable_delay: Time (in microsecond) for the regulator to get enabled
  * @voltage_gpio: GPIO for the voltage level selection
+ * @levels_desc: Supported voltage levels description
  * @voltage_levels_uv: 2 cells array supported voltage levels, increasing order
- * @voltage_level_high: True if higher voltage level relates to active high GPIO
+ * @voltage_level_high: True if higher voltage level relates to GPIO state 1
  */
 struct regulator_gpio {
 	struct regulator regulator;
 	struct gpio *enable_gpio;
 	unsigned int enable_delay;
 	struct gpio *voltage_gpio;
+	struct regulator_voltages_desc levels_desc;
 	int voltage_levels_uv[2];
 	bool voltage_level_high;
 };
@@ -72,14 +74,20 @@ static TEE_Result regulator_gpio_set_voltage(struct regulator *regulator,
 					     int level_uv)
 {
 	struct regulator_gpio *regu = regulator_priv(regulator);
+	enum gpio_level value = GPIO_LEVEL_LOW;
 
 	if (level_uv == regu->voltage_levels_uv[0])
-		gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_LOW);
+		value = GPIO_LEVEL_LOW;
 	else if (level_uv == regu->voltage_levels_uv[1])
-		gpio_set_value(regu->voltage_gpio, GPIO_LEVEL_HIGH);
+		value = GPIO_LEVEL_HIGH;
 	else
 		return TEE_ERROR_BAD_PARAMETERS;
 
+	if (!regu->voltage_level_high)
+		value = !value;
+
+	gpio_set_value(regu->voltage_gpio, value);
+
 	return TEE_SUCCESS;
 }
 
@@ -87,8 +95,24 @@ static TEE_Result regulator_gpio_read_voltage(struct regulator *regulator,
 					      int *level_uv)
 {
 	struct regulator_gpio *regu = regulator_priv(regulator);
+	enum gpio_level value = gpio_get_value(regu->voltage_gpio);
 
-	*level_uv = regu->voltage_levels_uv[gpio_get_value(regu->voltage_gpio)];
+	if (!regu->voltage_level_high)
+		value = !value;
+
+	*level_uv = regu->voltage_levels_uv[value];
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result regulator_gpio_voltages(struct regulator *regulator,
+					  struct regulator_voltages_desc **desc,
+					  const int **levels)
+{
+	struct regulator_gpio *regu = regulator_priv(regulator);
+
+	*desc = &regu->levels_desc;
+	*levels = regu->voltage_levels_uv;
 
 	return TEE_SUCCESS;
 }
@@ -98,6 +122,7 @@ static const struct regulator_ops regulator_gpio_ops = {
 	.get_state = regulator_gpio_read_state,
 	.set_voltage = regulator_gpio_set_voltage,
 	.get_voltage = regulator_gpio_read_voltage,
+	.supported_voltages = regulator_gpio_voltages,
 };
 
 static TEE_Result get_enable_gpio(const void *fdt, int node,
@@ -146,6 +171,8 @@ static TEE_Result get_voltage_level_gpio(const void *fdt, int node,
 	const fdt32_t *cuint = NULL;
 	struct gpio *gpio = NULL;
 	void *gpio_ref = &gpio;
+	int level0 = 0;
+	int level1 = 0;
 	int len = 0;
 
 	res = dt_driver_device_from_node_idx_prop("gpios", fdt, node, 0,
@@ -175,13 +202,25 @@ static TEE_Result get_voltage_level_gpio(const void *fdt, int node,
 
 	if (fdt32_to_cpu(*(cuint + 1))) {
 		assert(!fdt32_to_cpu(*(cuint + 3)));
-		regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint + 2));
-		regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint));
+		level1 = fdt32_to_cpu(*(cuint));
+		level0 = fdt32_to_cpu(*(cuint + 2));
 	} else {
 		assert(fdt32_to_cpu(*(cuint + 3)) == 1);
-		regu->voltage_levels_uv[0] = fdt32_to_cpu(*(cuint));
-		regu->voltage_levels_uv[1] = fdt32_to_cpu(*(cuint + 2));
+		level0 = fdt32_to_cpu(*(cuint));
+		level1 = fdt32_to_cpu(*(cuint + 2));
+	}
+
+	/* Get the 2 supported levels in increasing order */
+	regu->levels_desc.type = VOLTAGE_TYPE_FULL_LIST;
+	regu->levels_desc.num_levels = 2;
+	if (level0 < level1) {
+		regu->voltage_levels_uv[0] = level0;
+		regu->voltage_levels_uv[1] = level1;
 		regu->voltage_level_high = true;
+	} else {
+		regu->voltage_levels_uv[0] = level1;
+		regu->voltage_levels_uv[1] = level0;
+		regu->voltage_level_high = false;
 	}
 
 	gpio_set_direction(gpio, GPIO_DIR_OUT);
diff --git a/core/drivers/regulator/stm32_vrefbuf.c b/core/drivers/regulator/stm32_vrefbuf.c
index 18ccb099b014239954bccd8fb0e2dd77f85f1c7b..c206eea36008f077816c99851cc19d9ff2fe9349 100644
--- a/core/drivers/regulator/stm32_vrefbuf.c
+++ b/core/drivers/regulator/stm32_vrefbuf.c
@@ -343,10 +343,7 @@ static TEE_Result stm32_vrefbuf_regulator_probe(const void *fdt, int node,
 	if (!regu_name)
 		panic();
 
-	reg_base = fdt_reg_base_address(fdt, node);
-	reg_size = fdt_reg_size(fdt, node);
-	if (reg_base == DT_INFO_INVALID_REG ||
-	    reg_size == DT_INFO_INVALID_REG_SIZE)
+	if (fdt_reg_info(fdt, node, &reg_base, &reg_size))
 		panic();
 
 	vr->base = (vaddr_t)phys_to_virt(reg_base, MEM_AREA_IO_SEC, reg_size);
diff --git a/core/drivers/regulator/stm32mp13_regulator_iod.c b/core/drivers/regulator/stm32mp13_regulator_iod.c
index a678d51468dc46d4f15c1dccfd9de07027c57332..32dd13256bc0a8f00027ef3add59b04b36b49e0c 100644
--- a/core/drivers/regulator/stm32mp13_regulator_iod.c
+++ b/core/drivers/regulator/stm32mp13_regulator_iod.c
@@ -13,6 +13,7 @@
 #include <io.h>
 #include <kernel/boot.h>
 #include <kernel/dt.h>
+#include <kernel/dt_driver.h>
 #include <kernel/panic.h>
 #include <kernel/pm.h>
 #include <libfdt.h>
diff --git a/core/drivers/remoteproc/stm32_remoteproc.c b/core/drivers/remoteproc/stm32_remoteproc.c
index e4cd6c8b10ec00eb76530f8cfdd4622f8c6ca986..989faa24531ebcc49f0cf465879a137a9d98e07d 100644
--- a/core/drivers/remoteproc/stm32_remoteproc.c
+++ b/core/drivers/remoteproc/stm32_remoteproc.c
@@ -7,12 +7,16 @@
 #include <config.h>
 #include <drivers/rstctrl.h>
 #include <drivers/stm32_remoteproc.h>
+#ifdef CFG_STM32MP15
+#include <drivers/stm32mp1_rcc.h>
+#endif
 #include <kernel/cache_helpers.h>
 #include <kernel/dt_driver.h>
 #include <kernel/tee_misc.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
+#include <stm32_util.h>
 
 #define TIMEOUT_US_1MS	U(1000)
 
@@ -39,6 +43,7 @@ struct stm32_rproc_mem {
  * @regions:	memory regions used
  * @mcu_rst:	remote processor reset control
  * @hold_boot:	remote processor hold boot control
+ * @ns_loading: True if supports non-secure firmware loading, false otherwise
  */
 struct stm32_rproc_instance {
 	const struct stm32_rproc_compat_data *cdata;
@@ -47,6 +52,7 @@ struct stm32_rproc_instance {
 	struct stm32_rproc_mem *regions;
 	struct rstctrl *mcu_rst;
 	struct rstctrl *hold_boot;
+	bool ns_loading;
 };
 
 /**
@@ -72,6 +78,16 @@ void *stm32_rproc_get(uint32_t rproc_id)
 	return rproc;
 }
 
+bool stm32_rproc_is_secure(uint32_t rproc_id)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+
+	if (rproc)
+		return !rproc->cdata->ns_loading;
+
+	return false;
+}
+
 TEE_Result stm32_rproc_start(uint32_t rproc_id)
 {
 	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
@@ -283,14 +299,22 @@ static TEE_Result stm32_rproc_parse_mems(struct stm32_rproc_instance *rproc,
 			goto err;
 		}
 
-		regions[i].addr = fdt_reg_base_address(fdt, pnode);
-		regions[i].size = fdt_reg_size(fdt, pnode);
-
-		if (regions[i].addr <= 0 || regions[i].size <= 0) {
+		if (fdt_reg_info(fdt, pnode, &regions[i].addr,
+				 &regions[i].size)) {
 			res = TEE_ERROR_GENERIC;
 			goto err;
 		}
 
+#if defined(CFG_STM32MP15)
+		if (stm32mp1_ram_intersect_pager_ram(regions[i].addr,
+						     regions[i].size)) {
+			EMSG("Region %#"PRIxPA"..%#"PRIxPA" intersects pager secure memory",
+			     regions[i].addr,
+			     regions[i].addr + regions[i].size);
+			return TEE_ERROR_GENERIC;
+		}
+#endif
+
 		res = stm32_rproc_get_dma_range(&regions[i], fdt, node);
 		if (res)
 			goto err;
@@ -315,6 +339,35 @@ err:
 	return res;
 }
 
+TEE_Result stm32_rproc_clean_up_memories(uint32_t rproc_id)
+{
+	struct stm32_rproc_instance *rproc = stm32_rproc_get(rproc_id);
+	struct stm32_rproc_mem *mems = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+	void *va = NULL;
+	size_t size = 0;
+	paddr_t pa = 0;
+
+	if (!rproc)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	mems = rproc->regions;
+	for (i = 0; i < rproc->n_regions; i++) {
+		pa = mems[i].addr;
+		size = mems[i].size;
+		res = stm32_rproc_map(rproc_id, pa, size, &va);
+		if (res)
+			break;
+		memset(va, 0, size);
+		res = stm32_rproc_unmap(rproc_id, va, size);
+		if (res)
+			break;
+	}
+
+	return res;
+}
+
 static void stm32_rproc_cleanup(struct stm32_rproc_instance *rproc)
 {
 	free(rproc->regions);
@@ -352,6 +405,14 @@ static TEE_Result stm32_rproc_probe(const void *fdt, int node,
 			goto err;
 	}
 
+	if (!stm32_rcc_is_secure()) {
+		IMSG("WARNING: insecure rproc isolation, RCC is not secure");
+		if (!IS_ENABLED(CFG_INSECURE))
+			panic();
+	} else {
+		stm32_rcc_set_mckprot(true);
+	}
+
 	/*
 	 * The memory management should be enhance with firewall
 	 * mechanism to map the memory in secure area for the firmware
@@ -371,6 +432,7 @@ err:
 
 static const struct stm32_rproc_compat_data stm32_rproc_m4_compat = {
 	.rproc_id = STM32_M4_RPROC_ID,
+	.ns_loading = false,
 };
 
 static const struct dt_device_match stm32_rproc_match_table[] = {
diff --git a/core/drivers/riscv_zkr_rng.c b/core/drivers/riscv_zkr_rng.c
new file mode 100644
index 0000000000000000000000000000000000000000..cfc70bb14a0313b9f6c370801d4452e0e7d8257e
--- /dev/null
+++ b/core/drivers/riscv_zkr_rng.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+
+#include <crypto/crypto.h>
+#include <encoding.h>
+#include <kernel/delay.h>
+#include <kernel/panic.h>
+#include <riscv.h>
+#include <rng_support.h>
+#include <tee/tee_cryp_utl.h>
+
+#define RNG_TIMEOUT_US	1000000
+
+static bool __must_check seed_get_random_u16(uint16_t *val)
+{
+	uint64_t timeout = timeout_init_us(RNG_TIMEOUT_US);
+	uint32_t seed = 0;
+	uint32_t opst = 0;
+
+	do {
+		/*
+		 * The seed register must be accessed using CSR
+		 * read-write instructions. The write operation
+		 * is ignored and serves to indicate polling and
+		 * flushing.
+		 */
+		seed = swap_csr(CSR_SEED, 0);
+		opst = seed & SEED_OPST;
+
+		switch (opst) {
+		case SEED_OPST_ES16:
+			*val = seed & SEED_ENTROPY;
+			return true;
+		case SEED_OPST_DEAD:
+			/* Unrecoverable self-test error */
+			return false;
+		case SEED_OPST_BIST:
+		case SEED_OPST_WAIT:
+		default:
+			riscv_cpu_pause();
+		}
+	} while (!timeout_elapsed(timeout));
+
+	/* Consider timeout case due to normal world scheduler */
+	seed = swap_csr(CSR_SEED, 0);
+	if ((seed & SEED_OPST) == SEED_OPST_ES16) {
+		*val = seed & SEED_ENTROPY;
+		return true;
+	}
+
+	EMSG("Failed to produce a sufficient amount of entropy");
+
+	return false;
+}
+
+TEE_Result hw_get_random_bytes(void *buf, size_t len)
+{
+	uint8_t *ptr = buf;
+	uint16_t seed = 0;
+
+	while (len > 0) {
+		if (!seed_get_random_u16(&seed))
+			return TEE_ERROR_ACCESS_DENIED;
+		*ptr++ = seed & 0xff;
+		len--;
+		if (len > 0) {
+			*ptr++ = seed >> 8;
+			len--;
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+void plat_rng_init(void)
+{
+	if (!riscv_detect_csr_seed())
+		panic("RISC-V Zkr is not supported or unavailable in S-mode");
+}
diff --git a/core/drivers/rstctrl/stm32_rstctrl.c b/core/drivers/rstctrl/stm32_rstctrl.c
index 50ff4ec883fd544282ac4f3cf0750a93d9f25216..bcde0019f81c316cc3499745c2775f6c73c3d0ce 100644
--- a/core/drivers/rstctrl/stm32_rstctrl.c
+++ b/core/drivers/rstctrl/stm32_rstctrl.c
@@ -5,148 +5,16 @@
  */
 
 #include <drivers/rstctrl.h>
-#include <drivers/stm32mp_dt_bindings.h>
-#include <drivers/stm32mp1_rcc.h>
-#include <io.h>
-#include <kernel/delay.h>
-#include <kernel/dt.h>
-#include <kernel/dt_driver.h>
-#include <kernel/panic.h>
 #include <mm/core_memprot.h>
 #include <stm32_util.h>
 
-#define RESET_ID_MASK		GENMASK_32(31, 5)
-#define RESET_ID_SHIFT		5
-#define RESET_BIT_POS_MASK	GENMASK_32(4, 0)
-#define RESET_OFFSET_MAX	1024
+#include "stm32_rstctrl.h"
 
-/* Exposed rstctrl instance */
-struct stm32_rstline {
-	unsigned int id;
-	struct rstctrl rstctrl;
-	SLIST_ENTRY(stm32_rstline) link;
-};
+static struct stm32_reset_data *stm32_reset_pdata;
 
 static SLIST_HEAD(, stm32_rstline) stm32_rst_list =
 	SLIST_HEAD_INITIALIZER(stm32_rst_list);
 
-static size_t reset_id2reg_offset(unsigned int id)
-{
-	size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT;
-
-	assert(offset < RESET_OFFSET_MAX);
-	return offset * sizeof(uint32_t);
-}
-
-static uint8_t reset_id2reg_bit_pos(unsigned int reset_id)
-{
-	uint8_t pos = reset_id & RESET_BIT_POS_MASK;
-
-	assert(pos < 32);
-	return pos;
-}
-
-static struct stm32_rstline *to_rstline(struct rstctrl *rstctrl)
-{
-	assert(rstctrl);
-
-	return container_of(rstctrl, struct stm32_rstline, rstctrl);
-}
-
-static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us)
-{
-	unsigned int id = to_rstline(rstctrl)->id;
-	vaddr_t rcc_base = stm32_rcc_base();
-	uint32_t bit_mask = 0;
-	size_t offset = 0;
-
-#ifdef CFG_STM32MP15
-	switch (id) {
-	case MCU_HOLD_BOOT_R:
-		/*
-		 * The RCC_MP_GCR is a read/write register.
-		 * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
-		 */
-		io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
-
-		return TEE_SUCCESS;
-	case MCU_R:
-		/* MCU reset can only be written */
-		to_us = 0;
-		break;
-	default:
-		break;
-	}
-#endif
-
-	offset = reset_id2reg_offset(id);
-	bit_mask = BIT(reset_id2reg_bit_pos(id));
-
-	io_write32(rcc_base + offset, bit_mask);
-
-	if (to_us) {
-		uint64_t timeout_ref = timeout_init_us(to_us);
-
-		while (!(io_read32(rcc_base + offset) & bit_mask))
-			if (timeout_elapsed(timeout_ref))
-				break;
-
-		if (!(io_read32(rcc_base + offset) & bit_mask))
-			return TEE_ERROR_SECURITY;
-	}
-
-	return TEE_SUCCESS;
-}
-
-static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us)
-{
-	unsigned int id = to_rstline(rstctrl)->id;
-	vaddr_t rcc_base = stm32_rcc_base();
-	uint32_t bit_mask = 0;
-	size_t offset = 0;
-
-#ifdef CFG_STM32MP15
-	switch (id) {
-	case MCU_HOLD_BOOT_R:
-		/*
-		 * The RCC_MP_GCR is a read/write register.
-		 * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
-		 */
-		io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
-
-		return TEE_SUCCESS;
-	case MCU_R:
-		/* MCU reset deasserts by its own */
-		return TEE_SUCCESS;
-	default:
-		break;
-	}
-#endif
-
-	offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET;
-	bit_mask = BIT(reset_id2reg_bit_pos(id));
-
-	io_write32(rcc_base + offset, bit_mask);
-
-	if (to_us) {
-		uint64_t timeout_ref = timeout_init_us(to_us);
-
-		while ((io_read32(rcc_base + offset) & bit_mask))
-			if (timeout_elapsed(timeout_ref))
-				break;
-
-		if (io_read32(rcc_base + offset) & bit_mask)
-			return TEE_ERROR_SECURITY;
-	}
-
-	return TEE_SUCCESS;
-}
-
-static struct rstctrl_ops stm32_rstctrl_ops = {
-	.assert_level = reset_assert,
-	.deassert_level = reset_deassert,
-};
-
 static struct stm32_rstline *find_rstctrl_device(unsigned int control_id)
 {
 	struct stm32_rstline *stm32_rstline = NULL;
@@ -158,7 +26,9 @@ static struct stm32_rstline *find_rstctrl_device(unsigned int control_id)
 	return stm32_rstline;
 }
 
-static struct stm32_rstline *find_or_allocate_rstline(unsigned int binding_id)
+static struct
+stm32_rstline *find_or_allocate_rstline(unsigned int binding_id,
+					const struct stm32_reset_data *pdata)
 {
 	struct stm32_rstline *stm32_rstline = find_rstctrl_device(binding_id);
 
@@ -167,24 +37,37 @@ static struct stm32_rstline *find_or_allocate_rstline(unsigned int binding_id)
 
 	stm32_rstline = calloc(1, sizeof(*stm32_rstline));
 	if (stm32_rstline) {
-		stm32_rstline->rstctrl.ops = &stm32_rstctrl_ops;
+		assert(pdata->get_rstctrl_ops);
+
 		stm32_rstline->id = binding_id;
+		stm32_rstline->data = pdata;
+		stm32_rstline->rstctrl.ops = pdata->get_rstctrl_ops(binding_id);
+
 		SLIST_INSERT_HEAD(&stm32_rst_list, stm32_rstline, link);
 	}
 
 	return stm32_rstline;
 }
 
+struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl)
+{
+	assert(rstctrl);
+
+	return container_of(rstctrl, struct stm32_rstline, rstctrl);
+}
+
 struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id)
 {
-	struct stm32_rstline *rstline = find_or_allocate_rstline(binding_id);
+	struct stm32_rstline *rstline = NULL;
+
+	rstline = find_or_allocate_rstline(binding_id, stm32_reset_pdata);
 
 	assert(rstline);
 	return &rstline->rstctrl;
 }
 
 static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
-					void *priv_data __unused,
+					void *priv_data,
 					struct rstctrl **out_device)
 {
 	struct stm32_rstline *stm32_rstline = NULL;
@@ -195,7 +78,7 @@ static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
 
 	control_id = arg->args[0];
 
-	stm32_rstline = find_or_allocate_rstline(control_id);
+	stm32_rstline = find_or_allocate_rstline(control_id, priv_data);
 	if (!stm32_rstline)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
@@ -204,12 +87,12 @@ static TEE_Result stm32_rstctrl_get_dev(struct dt_pargs *arg,
 	return TEE_SUCCESS;
 }
 
-static TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
-					       const void *compat_data __unused)
+TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
+					const void *compat_data)
 {
 	struct dt_node_info info = { };
 
-	assert(rstctrl_ops_is_valid(&stm32_rstctrl_ops));
+	stm32_reset_pdata = (struct stm32_reset_data *)compat_data;
 
 	fdt_fill_device_info(fdt, &info, offs);
 
@@ -217,19 +100,5 @@ static TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
 	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
 
 	return rstctrl_register_provider(fdt, offs, stm32_rstctrl_get_dev,
-					 NULL);
+					 stm32_reset_pdata);
 }
-
-static const struct dt_device_match stm32_rstctrl_match_table[] = {
-	{ .compatible = "st,stm32mp1-rcc" },
-	{ .compatible = "st,stm32mp1-rcc-secure" },
-	{ .compatible = "st,stm32mp13-rcc" },
-	{ }
-};
-
-DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = {
-	.name = "stm32_rstctrl",
-	.type = DT_DRIVER_RSTCTRL,
-	.match_table = stm32_rstctrl_match_table,
-	.probe = stm32_rstctrl_provider_probe,
-};
diff --git a/core/drivers/rstctrl/stm32_rstctrl.h b/core/drivers/rstctrl/stm32_rstctrl.h
new file mode 100644
index 0000000000000000000000000000000000000000..a6ca6c442371ed4c45db612ea864e46982d0997b
--- /dev/null
+++ b/core/drivers/rstctrl/stm32_rstctrl.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+
+#include <drivers/rstctrl.h>
+#include <stdbool.h>
+#include <sys/queue.h>
+
+/*
+ * struct stm32_reset_cfg - Reset line controller data
+ * @offset: Byte offset in reset controller IOMEM
+ * @bit_index: Bit position of reset line control at IOMEM @offset
+ * @set_clr: True is @offset is an atomic SET/CLR register, false otherwise
+ * @inverted: True is reset line is asserted at level 0, false otherwise
+ * @no_deassert: True is reset line cannot be deasserted, false otherwise
+ * @no_timeout: True if reset state cannot be read back for timeout detection
+ */
+struct stm32_reset_cfg {
+	unsigned int offset;
+	unsigned int bit_index;
+	bool set_clr;
+	bool inverted;
+	bool no_deassert;
+	bool no_timeout;
+};
+
+/*
+ * struct stm32_reset_data - Reset controller platform data
+ * @nb_lines: Number of reset lines
+ * @rst_lines: Table of reset lines
+ * @get_rstctrl_ops: Handler to retrieve the controller operation handlers
+ */
+struct stm32_reset_data {
+	unsigned int nb_lines;
+	const struct stm32_reset_cfg **rst_lines;
+	const struct rstctrl_ops * (*get_rstctrl_ops)(unsigned int id);
+};
+
+/*
+ * struct stm32_rstline - Exposed rstctrl instance
+ * @id: Identifier used in the device tree bindings
+ * @rstctrl: Related reset controller instance
+ * @link: Reference in reset controller list
+ */
+struct stm32_rstline {
+	unsigned int id;
+	struct rstctrl rstctrl;
+	const struct stm32_reset_data *data;
+	SLIST_ENTRY(stm32_rstline) link;
+};
+
+struct stm32_rstline *to_stm32_rstline(struct rstctrl *rstctrl);
+
+TEE_Result stm32_rstctrl_provider_probe(const void *fdt, int offs,
+					const void *compat_data);
diff --git a/core/drivers/rstctrl/stm32mp1_rstctrl.c b/core/drivers/rstctrl/stm32mp1_rstctrl.c
new file mode 100644
index 0000000000000000000000000000000000000000..ec5ef9f6520ee8e065c6a94b8e42b7dba119cb1e
--- /dev/null
+++ b/core/drivers/rstctrl/stm32mp1_rstctrl.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2022, Linaro Limited
+ * Copyright (c) 2018-2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <drivers/rstctrl.h>
+#include <drivers/stm32mp1_rcc.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <io.h>
+#include <keep.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <stm32_util.h>
+
+#include "stm32_rstctrl.h"
+
+#define RESET_ID_MASK		GENMASK_32(31, 5)
+#define RESET_ID_SHIFT		U(5)
+#define RESET_BIT_POS_MASK	GENMASK_32(4, 0)
+#define RESET_OFFSET_MAX	U(1024)
+
+static size_t reset_id2reg_offset(unsigned int id)
+{
+	size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT;
+
+	assert(offset < RESET_OFFSET_MAX);
+	return offset * sizeof(uint32_t);
+}
+
+static uint32_t reset_id2reg_bit_pos(unsigned int reset_id)
+{
+	uint32_t pos = reset_id & RESET_BIT_POS_MASK;
+
+	assert(pos < 32);
+	return pos;
+}
+
+static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us)
+{
+	unsigned int id = to_stm32_rstline(rstctrl)->id;
+	vaddr_t rcc_base = stm32_rcc_base();
+	uint32_t bit_mask = 0;
+	size_t offset = 0;
+
+#ifdef CFG_STM32MP15
+	switch (id) {
+	case MCU_HOLD_BOOT_R:
+		/*
+		 * The RCC_MP_GCR is a read/write register.
+		 * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
+		 */
+		io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+
+		return TEE_SUCCESS;
+	case MCU_R:
+		/* MCU reset can only be written */
+		to_us = 0;
+		break;
+	default:
+		break;
+	}
+#endif
+
+	offset = reset_id2reg_offset(id);
+	bit_mask = BIT(reset_id2reg_bit_pos(id));
+
+	io_write32(rcc_base + offset, bit_mask);
+
+	if (to_us) {
+		uint32_t value = 0;
+
+		if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value,
+					   value & bit_mask, 0, to_us))
+			return TEE_ERROR_GENERIC;
+	} else {
+		/* Make sure the above write is performed */
+		dsb();
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us)
+{
+	unsigned int id = to_stm32_rstline(rstctrl)->id;
+	vaddr_t rcc_base = stm32_rcc_base();
+	uint32_t bit_mask = 0;
+	size_t offset = 0;
+
+#ifdef CFG_STM32MP15
+	switch (id) {
+	case MCU_HOLD_BOOT_R:
+		/*
+		 * The RCC_MP_GCR is a read/write register.
+		 * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
+		 */
+		io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
+
+		return TEE_SUCCESS;
+	case MCU_R:
+		/* MCU reset deasserts by its own */
+		return TEE_SUCCESS;
+	default:
+		break;
+	}
+#endif
+
+	offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET;
+	bit_mask = BIT(reset_id2reg_bit_pos(id));
+
+	io_write32(rcc_base + offset, bit_mask);
+
+	if (to_us) {
+		uint32_t value = 0;
+
+		if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value,
+					   !(value & bit_mask), 0, to_us))
+			return TEE_ERROR_GENERIC;
+	} else {
+		/* Make sure the above write is performed */
+		dsb();
+	}
+
+	return TEE_SUCCESS;
+}
+
+static const struct rstctrl_ops stm32_rstctrl_ops = {
+	.assert_level = reset_assert,
+	.deassert_level = reset_deassert,
+};
+DECLARE_KEEP_PAGER(stm32_rstctrl_ops);
+
+static const struct rstctrl_ops *stm32_reset_get_ops(unsigned int id __unused)
+{
+	return &stm32_rstctrl_ops;
+}
+
+static const struct stm32_reset_data stm32mp1_reset_data = {
+	.get_rstctrl_ops = stm32_reset_get_ops
+};
+DECLARE_KEEP_PAGER(stm32mp1_reset_data);
+
+static const struct dt_device_match stm32_rstctrl_match_table[] = {
+	{
+		.compatible = "st,stm32mp1-rcc",
+		.compat_data = &stm32mp1_reset_data,
+	},
+	{
+		.compatible = "st,stm32mp1-rcc-secure",
+		.compat_data = &stm32mp1_reset_data,
+	},
+	{
+		.compatible = "st,stm32mp13-rcc",
+		.compat_data = &stm32mp1_reset_data,
+	},
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = {
+	.name = "stm32_rstctrl",
+	.type = DT_DRIVER_RSTCTRL,
+	.match_table = stm32_rstctrl_match_table,
+	.probe = stm32_rstctrl_provider_probe,
+};
diff --git a/core/drivers/rstctrl/stm32mp25_rstctrl.c b/core/drivers/rstctrl/stm32mp25_rstctrl.c
new file mode 100644
index 0000000000000000000000000000000000000000..f16314e0d4d7fefc544549bf4990b92fe8c0ec95
--- /dev/null
+++ b/core/drivers/rstctrl/stm32mp25_rstctrl.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <drivers/rstctrl.h>
+#include <drivers/stm32_shared_io.h>
+#include <drivers/stm32mp25_rcc.h>
+#include <drivers/stm32mp_dt_bindings.h>
+#include <io.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <stm32_util.h>
+
+#include "stm32_rstctrl.h"
+
+static TEE_Result stm32_reset_update(struct rstctrl *rstctrl, bool status,
+				     unsigned int to_us)
+{
+	unsigned int id = to_stm32_rstline(rstctrl)->id;
+	const struct stm32_reset_data *data = NULL;
+	const struct stm32_reset_cfg *rst_line = NULL;
+	vaddr_t address = stm32_rcc_base();
+	uint32_t bit_mask = 0;
+	uint32_t value = 0;
+
+	data = to_stm32_rstline(rstctrl)->data;
+
+	rst_line = data->rst_lines[id];
+	if (!rst_line)
+		return TEE_SUCCESS;
+
+	address += rst_line->offset;
+	bit_mask = BIT(rst_line->bit_index);
+
+	if (!status && rst_line->no_deassert)
+		return TEE_SUCCESS;
+
+	status = rst_line->inverted ^ status;
+
+	if (status) {
+		if (rst_line->set_clr)
+			io_write32(address, bit_mask);
+		else
+			io_setbits32_stm32shregs(address, bit_mask);
+	} else {
+		if (rst_line->set_clr)
+			io_write32(address + RCC_MP_ENCLRR_OFFSET, bit_mask);
+		else
+			io_clrbits32_stm32shregs(address, bit_mask);
+	}
+
+	if (to_us && !rst_line->no_timeout) {
+		if (IO_READ32_POLL_TIMEOUT(address, value,
+					   ((value & bit_mask) == bit_mask) ==
+					   status, 0, to_us))
+			return TEE_ERROR_GENERIC;
+	} else {
+		/* Make sure the above write is performed */
+		dsb();
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_reset_assert(struct rstctrl *rstctrl,
+				     unsigned int to_us)
+{
+	return stm32_reset_update(rstctrl, true, to_us);
+}
+
+static TEE_Result stm32_reset_deassert(struct rstctrl *rstctrl,
+				       unsigned int to_us)
+{
+	return stm32_reset_update(rstctrl, false, to_us);
+}
+
+static const struct rstctrl_ops stm32_rstctrl_ops = {
+	.assert_level = stm32_reset_assert,
+	.deassert_level = stm32_reset_deassert,
+};
+
+#define STM32_RESET(id, _offset, _bit_index, _set_clr, _inverted, _no_deassert,\
+		    _no_timeout)\
+	[(id)] = &(struct stm32_reset_cfg){\
+		.offset		= (_offset),\
+		.bit_index	= (_bit_index),\
+		.set_clr	= (_set_clr),\
+		.inverted	= (_inverted),\
+		.no_deassert	= (_no_deassert),\
+		.no_timeout	= (_no_timeout),\
+	}
+
+#define RST(id, _offset, _bit_index)\
+	STM32_RESET((id), (_offset), (_bit_index), false, false, false, false)
+
+#define RST_SETR(id, _offset, _bit_index)\
+	STM32_RESET((id), (_offset), (_bit_index), true, false, false, false)
+
+#define RST_INV(id, _offset, _bit_index)\
+	STM32_RESET((id), (_offset), (_bit_index), false, true, false, false)
+
+#define RST_SETR_NO_DEASSERT(id, _offset, _bit_index)\
+	STM32_RESET((id), (_offset), (_bit_index), false, false, true, false)
+
+#define RST_SETR_NO_DEASSERT_TIMEOUT(id, _offset, _bit_index)\
+	STM32_RESET((id), (_offset), (_bit_index), false, false, true, true)
+
+static
+const struct stm32_reset_cfg *stm32mp25_reset_cfg[STM32MP25_LAST_RESET] = {
+	RST(TIM1_R,		RCC_TIM1CFGR,		0),
+	RST(TIM2_R,		RCC_TIM2CFGR,		0),
+	RST(TIM3_R,		RCC_TIM3CFGR,		0),
+	RST(TIM4_R,		RCC_TIM4CFGR,		0),
+	RST(TIM5_R,		RCC_TIM5CFGR,		0),
+	RST(TIM6_R,		RCC_TIM6CFGR,		0),
+	RST(TIM7_R,		RCC_TIM7CFGR,		0),
+	RST(TIM8_R,		RCC_TIM8CFGR,		0),
+	RST(TIM10_R,		RCC_TIM10CFGR,		0),
+	RST(TIM11_R,		RCC_TIM11CFGR,		0),
+	RST(TIM12_R,		RCC_TIM12CFGR,		0),
+	RST(TIM13_R,		RCC_TIM13CFGR,		0),
+	RST(TIM14_R,		RCC_TIM14CFGR,		0),
+	RST(TIM15_R,		RCC_TIM15CFGR,		0),
+	RST(TIM16_R,		RCC_TIM16CFGR,		0),
+	RST(TIM17_R,		RCC_TIM17CFGR,		0),
+	RST(TIM20_R,		RCC_TIM20CFGR,		0),
+	RST(LPTIM1_R,		RCC_LPTIM1CFGR,		0),
+	RST(LPTIM2_R,		RCC_LPTIM2CFGR,		0),
+	RST(LPTIM3_R,		RCC_LPTIM3CFGR,		0),
+	RST(LPTIM4_R,		RCC_LPTIM4CFGR,		0),
+	RST(LPTIM5_R,		RCC_LPTIM5CFGR,		0),
+	RST(SPI1_R,		RCC_SPI1CFGR,		0),
+	RST(SPI2_R,		RCC_SPI2CFGR,		0),
+	RST(SPI3_R,		RCC_SPI3CFGR,		0),
+	RST(SPI4_R,		RCC_SPI4CFGR,		0),
+	RST(SPI5_R,		RCC_SPI5CFGR,		0),
+	RST(SPI6_R,		RCC_SPI6CFGR,		0),
+	RST(SPI7_R,		RCC_SPI7CFGR,		0),
+	RST(SPI8_R,		RCC_SPI8CFGR,		0),
+	RST(SPDIFRX_R,		RCC_SPDIFRXCFGR,	0),
+	RST(USART1_R,		RCC_USART1CFGR,		0),
+	RST(USART2_R,		RCC_USART2CFGR,		0),
+	RST(USART3_R,		RCC_USART3CFGR,		0),
+	RST(UART4_R,		RCC_UART4CFGR,		0),
+	RST(UART5_R,		RCC_UART5CFGR,		0),
+	RST(USART6_R,		RCC_USART6CFGR,		0),
+	RST(UART7_R,		RCC_UART7CFGR,		0),
+	RST(UART8_R,		RCC_UART8CFGR,		0),
+	RST(UART9_R,		RCC_UART9CFGR,		0),
+	RST(LPUART1_R,		RCC_LPUART1CFGR,	0),
+	RST(IS2M_R,		RCC_IS2MCFGR,		0),
+	RST(I2C1_R,		RCC_I2C1CFGR,		0),
+	RST(I2C2_R,		RCC_I2C2CFGR,		0),
+	RST(I2C3_R,		RCC_I2C3CFGR,		0),
+	RST(I2C4_R,		RCC_I2C4CFGR,		0),
+	RST(I2C5_R,		RCC_I2C5CFGR,		0),
+	RST(I2C6_R,		RCC_I2C6CFGR,		0),
+	RST(I2C7_R,		RCC_I2C7CFGR,		0),
+	RST(I2C8_R,		RCC_I2C8CFGR,		0),
+	RST(SAI1_R,		RCC_SAI1CFGR,		0),
+	RST(SAI2_R,		RCC_SAI2CFGR,		0),
+	RST(SAI3_R,		RCC_SAI3CFGR,		0),
+	RST(SAI4_R,		RCC_SAI4CFGR,		0),
+	RST(MDF1_R,		RCC_MDF1CFGR,		0),
+	RST(MDF2_R,		RCC_ADF1CFGR,		0),
+	RST(FDCAN_R,		RCC_FDCANCFGR,		0),
+	RST(HDP_R,		RCC_HDPCFGR,		0),
+	RST(ADC12_R,		RCC_ADC12CFGR,		0),
+	RST(ADC3_R,		RCC_ADC3CFGR,		0),
+	RST(ETH1_R,		RCC_ETH1CFGR,		0),
+	RST(ETH2_R,		RCC_ETH2CFGR,		0),
+	RST(USB2_R,		RCC_USB2CFGR,		0),
+	RST(USB2PHY1_R,		RCC_USB2PHY1CFGR,	0),
+	RST(USB2PHY2_R,		RCC_USB2PHY2CFGR,	0),
+	RST(USB3DR_R,		RCC_USB3DRCFGR,		0),
+	RST(USB3PCIEPHY_R,	RCC_USB3PCIEPHYCFGR,	0),
+	RST(USBTC_R,		RCC_USBTCCFGR,		0),
+	RST(ETHSW_R,		RCC_ETHSWCFGR,		0),
+	RST(SDMMC1_R,		RCC_SDMMC1CFGR,		0),
+	RST(SDMMC1DLL_R,	RCC_SDMMC1CFGR,		16),
+	RST(SDMMC2_R,		RCC_SDMMC2CFGR,		0),
+	RST(SDMMC2DLL_R,	RCC_SDMMC2CFGR,		16),
+	RST(SDMMC3_R,		RCC_SDMMC3CFGR,		0),
+	RST(SDMMC3DLL_R,	RCC_SDMMC3CFGR,		16),
+	RST(GPU_R,		RCC_GPUCFGR,		0),
+	RST(LTDC_R,		RCC_LTDCCFGR,		0),
+	RST(DSI_R,		RCC_DSICFGR,		0),
+	RST(LVDS_R,		RCC_LVDSCFGR,		0),
+	RST(CSI_R,		RCC_CSICFGR,		0),
+	RST(DCMIPP_R,		RCC_DCMIPPCFGR,		0),
+	RST(CCI_R,		RCC_CCICFGR,		0),
+	RST(VDEC_R,		RCC_VDECCFGR,		0),
+	RST(VENC_R,		RCC_VENCCFGR,		0),
+	RST(WWDG1_R,		RCC_WWDG1CFGR,		0),
+	RST(WWDG2_R,		RCC_WWDG2CFGR,		0),
+	RST(VREF_R,		RCC_VREFCFGR,		0),
+	RST(DTS_R,		RCC_DTSCFGR,		0),
+	RST(CRC_R,		RCC_CRCCFGR,		0),
+	RST(SERC_R,		RCC_SERCCFGR,		0),
+	RST(OSPIIOM_R,		RCC_OSPIIOMCFGR,	0),
+	RST(I3C1_R,		RCC_I3C1CFGR,		0),
+	RST(I3C2_R,		RCC_I3C2CFGR,		0),
+	RST(I3C3_R,		RCC_I3C3CFGR,		0),
+	RST(I3C4_R,		RCC_I3C4CFGR,		0),
+	RST(RNG_R,		RCC_RNGCFGR,		0),
+	RST(PKA_R,		RCC_PKACFGR,		0),
+	RST(SAES_R,		RCC_SAESCFGR,		0),
+	RST(HASH_R,		RCC_HASHCFGR,		0),
+	RST(CRYP1_R,		RCC_CRYP1CFGR,		0),
+	RST(CRYP2_R,		RCC_CRYP2CFGR,		0),
+	RST(PCIE_R,		RCC_PCIECFGR,		0),
+	RST(OSPI1_R,		RCC_OSPI1CFGR,		0),
+	RST(OSPI1DLL_R,		RCC_OSPI1CFGR,		16),
+	RST(OSPI2_R,		RCC_OSPI2CFGR,		0),
+	RST(OSPI2DLL_R,		RCC_OSPI2CFGR,		16),
+	RST(DBG_R,		RCC_DBGCFGR,		12),
+
+	RST_SETR(IWDG2_KER_R,	RCC_IWDGC1CFGSETR,	18),
+	RST_SETR(IWDG4_KER_R,	RCC_IWDGC2CFGSETR,	18),
+	RST_SETR(IWDG1_SYS_R,	RCC_IWDGC1CFGSETR,	0),
+	RST_SETR(IWDG2_SYS_R,	RCC_IWDGC1CFGSETR,	2),
+	RST_SETR(IWDG3_SYS_R,	RCC_IWDGC2CFGSETR,	0),
+	RST_SETR(IWDG4_SYS_R,	RCC_IWDGC2CFGSETR,	2),
+
+	RST_INV(C2_HOLDBOOT_R,	RCC_CPUBOOTCR,		0),
+	RST_INV(C1_HOLDBOOT_R,	RCC_CPUBOOTCR,		1),
+
+	RST_SETR_NO_DEASSERT_TIMEOUT(C1_R,	RCC_C1RSTCSETR,		0),
+	RST_SETR_NO_DEASSERT_TIMEOUT(C1P1POR_R,	RCC_C1P1RSTCSETR,	0),
+	RST_SETR_NO_DEASSERT_TIMEOUT(C1P1_R,	RCC_C1P1RSTCSETR,	1),
+	RST_SETR_NO_DEASSERT_TIMEOUT(C2_R,	RCC_C2RSTCSETR,		0),
+	RST_SETR_NO_DEASSERT_TIMEOUT(SYS_R,	RCC_GRSTCSETR,		0),
+
+	/*
+	 * Don't manage reset lines of RIF aware resources
+	 * DDRCP_R, DDRCAPB_R, DDRPHYCAPB_R, DDRCFG_R, DDR_R,
+	 * IPCC1_R, IPCC2_R,
+	 * HPDMA1_R, HPDMA2_R, HPDMA3_R, LPDMA_R,
+	 * GPIOA_R, GPIOB_R, GPIOC_R, GPIOD_R,
+	 * GPIOE_R, GPIOF_R, GPIOG_R, GPIOH_R,
+	 * GPIOI_R, GPIOJ_R, GPIOK_R, GPIOZ_R,
+	 * HSEM_R,
+	 * FMC_R,
+	 */
+};
+
+static const struct rstctrl_ops *stm32_reset_get_ops(unsigned int id __unused)
+{
+	return &stm32_rstctrl_ops;
+}
+
+static const struct stm32_reset_data stm32mp25_reset_data = {
+	.nb_lines = ARRAY_SIZE(stm32mp25_reset_cfg),
+	.rst_lines = stm32mp25_reset_cfg,
+	.get_rstctrl_ops = stm32_reset_get_ops,
+};
+
+static const struct dt_device_match stm32_rstctrl_match_table[] = {
+	{
+		.compatible = "st,stm32mp25-rcc",
+		.compat_data = &stm32mp25_reset_data,
+	},
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = {
+	.name = "stm32_rstctrl",
+	.type = DT_DRIVER_RSTCTRL,
+	.match_table = stm32_rstctrl_match_table,
+	.probe = stm32_rstctrl_provider_probe,
+};
diff --git a/core/drivers/rstctrl/sub.mk b/core/drivers/rstctrl/sub.mk
index 0466b621f8d7237fc0661baf6644784d50499abd..78c037261cb8b47bf9f586071de34235645c4a46 100644
--- a/core/drivers/rstctrl/sub.mk
+++ b/core/drivers/rstctrl/sub.mk
@@ -1,2 +1,4 @@
 srcs-y += rstctrl.c
 srcs-$(CFG_STM32_RSTCTRL) += stm32_rstctrl.c
+srcs-$(CFG_STM32MP1_RSTCTRL) += stm32mp1_rstctrl.c
+srcs-$(CFG_STM32MP25_RSTCTRL) += stm32mp25_rstctrl.c
diff --git a/core/drivers/scmi-msg/clock.c b/core/drivers/scmi-msg/clock.c
index dce76fa90cf2075cb3395ed855a8af98ba9bdf57..ac30570e4b1554724038a71cd13601ba8ebd3698 100644
--- a/core/drivers/scmi-msg/clock.c
+++ b/core/drivers/scmi-msg/clock.c
@@ -321,7 +321,7 @@ static void scmi_clock_describe_rates(struct scmi_msg *msg)
 		}
 
 		out_count = rate_index - in_args->rate_index;
-		remaining = nb_rates - in_args->rate_index;
+		remaining = nb_rates - rate_index;
 		p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(out_count, remaining);
 	} else if (status == SCMI_NOT_SUPPORTED) {
 		unsigned long triplet[3] = { 0, 0, 0 };
diff --git a/core/drivers/scmi-msg/clock_generic.c b/core/drivers/scmi-msg/clock_generic.c
index 1b2d1e6cf24baea47db304c548dcb5c90d8fff88..bd08cb0218bb75d687d41b432975cc6a884dee6c 100644
--- a/core/drivers/scmi-msg/clock_generic.c
+++ b/core/drivers/scmi-msg/clock_generic.c
@@ -82,16 +82,20 @@ int32_t plat_scmi_clock_rates_array(unsigned int channel_id,
 				    unsigned long *rates,
 				    size_t *nb_elts)
 {
+	TEE_Result res = TEE_ERROR_GENERIC;
 	struct scmi_clk *clk = NULL;
 
 	clk = clk_scmi_get_by_id(channel_id, scmi_id);
 	if (!clk)
 		return SCMI_DENIED;
 
-	if (clk_get_rates_array(clk->clk, start_index, rates, nb_elts))
+	res = clk_get_rates_array(clk->clk, start_index, rates, nb_elts);
+	if (res == TEE_SUCCESS)
+		return SCMI_SUCCESS;
+	else if (res == TEE_ERROR_NOT_SUPPORTED)
+		return SCMI_NOT_SUPPORTED;
+	else
 		return SCMI_GENERIC_ERROR;
-
-	return SCMI_SUCCESS;
 }
 
 unsigned long plat_scmi_clock_get_rate(unsigned int channel_id,
diff --git a/core/drivers/scmi-msg/smt.c b/core/drivers/scmi-msg/smt.c
index 880212befbc67c48fe50fca6f0848f684ba986d5..8067f66c5a3c6ed2819cbf95c3d5b8fb228db700 100644
--- a/core/drivers/scmi-msg/smt.c
+++ b/core/drivers/scmi-msg/smt.c
@@ -97,7 +97,7 @@ void scmi_entry_smt(unsigned int channel_id, uint32_t *payload_buf)
 			  sizeof(smt_hdr->message_header);
 
 	if (in_payload_size > SCMI_SEC_PAYLOAD_SIZE) {
-		DMSG("SCMI payload too big %u", in_payload_size);
+		DMSG("SCMI payload too big %zu", in_payload_size);
 		goto out;
 	}
 
diff --git a/core/drivers/scmi-msg/voltage_domain.h b/core/drivers/scmi-msg/voltage_domain.h
index be53cb6ffd704c59530c9bc154216184f4b92269..167dab12a7a9876e6118ebbda970485ba35ae356 100644
--- a/core/drivers/scmi-msg/voltage_domain.h
+++ b/core/drivers/scmi-msg/voltage_domain.h
@@ -12,7 +12,7 @@
 
 #include "common.h"
 
-#define SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN	0x30000
+#define SCMI_PROTOCOL_VERSION_VOLTAGE_DOMAIN	0x20000
 
 /*
  * Identifiers of the SCMI Clock Management Protocol commands
diff --git a/core/drivers/semihosting_console.c b/core/drivers/semihosting_console.c
new file mode 100644
index 0000000000000000000000000000000000000000..18072c1e1148e5746288ddf8818f40ebecb4b498
--- /dev/null
+++ b/core/drivers/semihosting_console.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+
+#include <compiler.h>
+#include <console.h>
+#include <drivers/semihosting_console.h>
+#include <drivers/serial.h>
+#include <kernel/semihosting.h>
+#include <util.h>
+
+/*
+ * struct semihosting_console_data - Structure for semihosting console driver
+ * @chip - General structure for each serial chip
+ * @fd - Handle of the file at @file_path when semihosting_console_init() is
+ *       called, or -1 if using the semihosting console
+ */
+struct semihosting_console_data {
+	struct serial_chip chip;
+	int fd;
+};
+
+static struct semihosting_console_data sh_console_data __nex_bss;
+
+static void semihosting_console_putc(struct serial_chip *chip __unused, int ch)
+{
+	semihosting_sys_writec(ch);
+}
+
+static int semihosting_console_getchar(struct serial_chip *chip __unused)
+{
+	return semihosting_sys_readc();
+}
+
+static const struct serial_ops semihosting_console_ops = {
+	.putc = semihosting_console_putc,
+	.getchar = semihosting_console_getchar,
+};
+DECLARE_KEEP_PAGER(semihosting_console_ops);
+
+static void semihosting_console_fd_putc(struct serial_chip *chip __unused,
+					int ch)
+{
+	if (sh_console_data.fd >= 0)
+		semihosting_write(sh_console_data.fd, &ch, 1);
+}
+
+static const struct serial_ops semihosting_console_fd_ops = {
+	.putc = semihosting_console_fd_putc,
+};
+DECLARE_KEEP_PAGER(semihosting_console_fd_ops);
+
+void semihosting_console_init(const char *file_path)
+{
+	if (file_path) {
+		/* Output log to given file on the semihosting host system. */
+		sh_console_data.chip.ops = &semihosting_console_fd_ops;
+		sh_console_data.fd =
+			semihosting_open(file_path, O_RDWR | O_CREAT | O_TRUNC);
+	} else {
+		/* Output log to semihosting host debug console. */
+		sh_console_data.chip.ops = &semihosting_console_ops;
+		sh_console_data.fd = -1;
+	}
+
+	register_serial_console(&sh_console_data.chip);
+}
diff --git a/core/drivers/stm32_bsec.c b/core/drivers/stm32_bsec.c
index 4a879699041185085b685b724572dc76e445b76f..81768cf3997b396dc500489ed03c3f2996ca1195 100644
--- a/core/drivers/stm32_bsec.c
+++ b/core/drivers/stm32_bsec.c
@@ -736,17 +736,14 @@ static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node)
 		panic();
 
 	fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) {
-		unsigned int reg_offset = 0;
-		unsigned int reg_size = 0;
+		paddr_t reg_offset = 0;
+		size_t reg_size = 0;
 		unsigned int otp_id = 0;
 		unsigned int i = 0;
 		size_t size = 0;
 
-		reg_offset = fdt_reg_base_address(fdt, bsec_subnode);
-		reg_size = fdt_reg_size(fdt, bsec_subnode);
-
-		assert(reg_offset != DT_INFO_INVALID_REG &&
-		       reg_size != DT_INFO_INVALID_REG_SIZE);
+		if (fdt_reg_info(fdt, bsec_subnode, &reg_offset, &reg_size))
+			panic();
 
 		otp_id = reg_offset / sizeof(uint32_t);
 
@@ -837,8 +834,8 @@ static void save_dt_nvmem_layout(void *fdt, int bsec_node)
 		panic();
 
 	fdt_for_each_subnode(node, fdt, bsec_node) {
-		unsigned int reg_offset = 0;
-		unsigned int reg_length = 0;
+		paddr_t reg_offset = 0;
+		size_t reg_length = 0;
 		const char *string = NULL;
 		const char *s = NULL;
 		int len = 0;
@@ -852,11 +849,7 @@ static void save_dt_nvmem_layout(void *fdt, int bsec_node)
 		layout_cell->phandle = fdt_get_phandle(fdt, node);
 		assert(layout_cell->phandle != (uint32_t)-1);
 
-		reg_offset = fdt_reg_base_address(fdt, node);
-		reg_length = fdt_reg_size(fdt, node);
-
-		if (reg_offset == DT_INFO_INVALID_REG ||
-		    reg_length == DT_INFO_INVALID_REG_SIZE) {
+		if (fdt_reg_info(fdt, node, &reg_offset, &reg_length)) {
 			DMSG("Malformed nvmem %s: ignored", string);
 			continue;
 		}
diff --git a/core/drivers/stm32_etzpc.c b/core/drivers/stm32_etzpc.c
deleted file mode 100644
index 19c7d708ec18041918485108f67661223fa17d9c..0000000000000000000000000000000000000000
--- a/core/drivers/stm32_etzpc.c
+++ /dev/null
@@ -1,348 +0,0 @@
-// SPDX-License-Identifier: BSD-3-Clause
-/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
- * Copyright (c) 2017-2019, STMicroelectronics
- */
-
-/*
- * STM32 ETPZC acts as a firewall on stm32mp SoC peripheral interfaces and
- * internal memories. The driver expects a single instance of the controller
- * in the platform.
- *
- * The driver API is defined in header file stm32_etzpc.h.
- *
- * Driver registers a PM callback for restoration of the access permissions
- * when it resumes.
- */
-
-#include <assert.h>
-#include <drivers/stm32_etzpc.h>
-#include <initcall.h>
-#include <io.h>
-#include <keep.h>
-#include <kernel/boot.h>
-#include <kernel/dt.h>
-#include <kernel/dt_driver.h>
-#include <kernel/panic.h>
-#include <kernel/pm.h>
-#include <libfdt.h>
-#include <mm/core_memprot.h>
-#include <util.h>
-
-/* Devicetree compatibility */
-#define ETZPC_COMPAT			"st,stm32-etzpc"
-
-/* ID Registers */
-#define ETZPC_TZMA0_SIZE		0x000U
-#define ETZPC_DECPROT0			0x010U
-#define ETZPC_DECPROT_LOCK0		0x030U
-#define ETZPC_HWCFGR			0x3F0U
-#define ETZPC_VERR			0x3F4U
-
-/* ID Registers fields */
-#define ETZPC_TZMA0_SIZE_LOCK		BIT(31)
-#define ETZPC_DECPROT0_MASK		GENMASK_32(1, 0)
-#define ETZPC_HWCFGR_NUM_TZMA_MASK	GENMASK_32(7, 0)
-#define ETZPC_HWCFGR_NUM_TZMA_SHIFT	0
-#define ETZPC_HWCFGR_NUM_PER_SEC_MASK	GENMASK_32(15, 8)
-#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT	8
-#define ETZPC_HWCFGR_NUM_AHB_SEC_MASK	GENMASK_32(23, 16)
-#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT	16
-#define ETZPC_HWCFGR_CHUNCKS1N4_MASK	GENMASK_32(31, 24)
-#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT	24
-
-#define DECPROT_SHIFT			1
-#define IDS_PER_DECPROT_REGS		16U
-#define IDS_PER_DECPROT_LOCK_REGS	32U
-
-/*
- * Implementation uses uint8_t to store each securable DECPROT configuration
- * and uint16_t to store each securable TZMA configuration. When resuming
- * from deep suspend, the DECPROT configurations are restored.
- */
-#define PERIPH_PM_LOCK_BIT		BIT(7)
-#define PERIPH_PM_ATTR_MASK		GENMASK_32(2, 0)
-#define TZMA_PM_LOCK_BIT		BIT(15)
-#define TZMA_PM_VALUE_MASK		GENMASK_32(9, 0)
-
-/*
- * @base - iobase for interface base address
- * @num_tzma - number of TZMA zone, read from the hardware
- * @num_ahb_sec - number of securable AHB master zone, read from the hardware
- * @num_per_sec - number of securable AHB & APB periphs, read from the hardware
- * @periph_cfg - Backup for restoring DECPROT when resuming (PERIH_PM_*)
- * @tzma_cfg - Backup for restoring TZMA when resuming (TZMA_PM_*)
- */
-struct etzpc_instance {
-	struct io_pa_va base;
-	unsigned int num_tzma;
-	unsigned int num_per_sec;
-	unsigned int num_ahb_sec;
-	uint8_t *periph_cfg;
-	uint16_t *tzma_cfg;
-};
-
-/* Only 1 instance of the ETZPC is expected per platform */
-static struct etzpc_instance etzpc_dev;
-
-static vaddr_t etzpc_base(void)
-{
-	return io_pa_or_va_secure(&etzpc_dev.base, 1);
-}
-
-static bool __maybe_unused valid_decprot_id(unsigned int id)
-{
-	return id < etzpc_dev.num_per_sec;
-}
-
-static bool __maybe_unused valid_tzma_id(unsigned int id)
-{
-	return id < etzpc_dev.num_tzma;
-}
-
-void etzpc_configure_decprot(uint32_t decprot_id,
-			     enum etzpc_decprot_attributes decprot_attr)
-{
-	size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
-	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
-	uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK;
-	vaddr_t base = etzpc_base();
-
-	assert(valid_decprot_id(decprot_id));
-
-	io_clrsetbits32(base + ETZPC_DECPROT0 + offset,
-			ETZPC_DECPROT0_MASK << shift,
-			masked_decprot << shift);
-
-	/* Save for PM */
-	assert((decprot_attr & ~PERIPH_PM_ATTR_MASK) == 0);
-	COMPILE_TIME_ASSERT(ETZPC_DECPROT_MAX <= UINT8_MAX);
-
-	etzpc_dev.periph_cfg[decprot_id] &= ~PERIPH_PM_ATTR_MASK;
-	etzpc_dev.periph_cfg[decprot_id] |= (uint8_t)decprot_attr;
-}
-
-enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id)
-{
-	size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS);
-	uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT;
-	vaddr_t base = etzpc_base();
-	uint32_t value = 0;
-
-	assert(valid_decprot_id(decprot_id));
-
-	value = (io_read32(base + ETZPC_DECPROT0 + offset) >> shift) &
-		ETZPC_DECPROT0_MASK;
-
-	return (enum etzpc_decprot_attributes)value;
-}
-
-void etzpc_lock_decprot(uint32_t decprot_id)
-{
-	size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
-	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
-	vaddr_t base = etzpc_base();
-
-	assert(valid_decprot_id(decprot_id));
-
-	io_write32(base + offset + ETZPC_DECPROT_LOCK0, mask);
-
-	/* Save for PM */
-	etzpc_dev.periph_cfg[decprot_id] |= PERIPH_PM_LOCK_BIT;
-}
-
-bool etzpc_get_lock_decprot(uint32_t decprot_id)
-{
-	size_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS);
-	uint32_t mask = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS);
-	vaddr_t base = etzpc_base();
-
-	assert(valid_decprot_id(decprot_id));
-
-	return io_read32(base + offset + ETZPC_DECPROT_LOCK0) & mask;
-}
-
-void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value)
-{
-	size_t offset = sizeof(uint32_t) * tzma_id;
-	vaddr_t base = etzpc_base();
-
-	assert(valid_tzma_id(tzma_id));
-
-	io_write32(base + ETZPC_TZMA0_SIZE + offset, tzma_value);
-
-	/* Save for PM */
-	assert((tzma_value & ~TZMA_PM_VALUE_MASK) == 0);
-	etzpc_dev.tzma_cfg[tzma_id] &= ~TZMA_PM_VALUE_MASK;
-	etzpc_dev.tzma_cfg[tzma_id] |= tzma_value;
-}
-
-uint16_t etzpc_get_tzma(uint32_t tzma_id)
-{
-	size_t offset = sizeof(uint32_t) * tzma_id;
-	vaddr_t base = etzpc_base();
-
-	assert(valid_tzma_id(tzma_id));
-
-	return io_read32(base + ETZPC_TZMA0_SIZE + offset);
-}
-
-void etzpc_lock_tzma(uint32_t tzma_id)
-{
-	size_t offset = sizeof(uint32_t) * tzma_id;
-	vaddr_t base = etzpc_base();
-
-	assert(valid_tzma_id(tzma_id));
-
-	io_setbits32(base + ETZPC_TZMA0_SIZE + offset, ETZPC_TZMA0_SIZE_LOCK);
-
-	/* Save for PM */
-	etzpc_dev.tzma_cfg[tzma_id] |= TZMA_PM_LOCK_BIT;
-}
-
-bool etzpc_get_lock_tzma(uint32_t tzma_id)
-{
-	size_t offset = sizeof(uint32_t) * tzma_id;
-	vaddr_t base = etzpc_base();
-
-	assert(valid_tzma_id(tzma_id));
-
-	return io_read32(base + ETZPC_TZMA0_SIZE + offset) &
-	       ETZPC_TZMA0_SIZE_LOCK;
-}
-
-static TEE_Result etzpc_pm(enum pm_op op, unsigned int pm_hint __unused,
-			  const struct pm_callback_handle *pm_handle)
-{
-	struct etzpc_instance *dev = NULL;
-	unsigned int n = 0;
-
-	if (op != PM_OP_RESUME)
-		return TEE_SUCCESS;
-
-	dev = (struct etzpc_instance *)PM_CALLBACK_GET_HANDLE(pm_handle);
-
-	for (n = 0; n < dev->num_per_sec; n++) {
-		unsigned int attr = dev->periph_cfg[n] & PERIPH_PM_ATTR_MASK;
-
-		etzpc_configure_decprot(n, (enum etzpc_decprot_attributes)attr);
-
-		if (dev->periph_cfg[n] & PERIPH_PM_LOCK_BIT)
-			etzpc_lock_decprot(n);
-	}
-
-	for (n = 0; n < dev->num_tzma; n++) {
-		uint16_t value = dev->tzma_cfg[n] & TZMA_PM_VALUE_MASK;
-
-		etzpc_configure_tzma(n, value);
-
-		if (dev->tzma_cfg[n] & TZMA_PM_LOCK_BIT)
-			etzpc_lock_tzma(n);
-	}
-
-	return TEE_SUCCESS;
-}
-DECLARE_KEEP_PAGER(etzpc_pm);
-
-static void init_pm(struct etzpc_instance *dev)
-{
-	unsigned int n = 0;
-
-	dev->periph_cfg = calloc(dev->num_per_sec, sizeof(*dev->periph_cfg));
-	dev->tzma_cfg = calloc(dev->num_tzma, sizeof(*dev->tzma_cfg));
-	if (!dev->periph_cfg || !dev->tzma_cfg)
-		panic();
-
-	for (n = 0; n < dev->num_per_sec; n++) {
-		dev->periph_cfg[n] = (uint8_t)etzpc_get_decprot(n);
-		if (etzpc_get_lock_decprot(n))
-			dev->periph_cfg[n] |= PERIPH_PM_LOCK_BIT;
-	}
-
-	for (n = 0; n < dev->num_tzma; n++) {
-		dev->tzma_cfg[n] = (uint8_t)etzpc_get_tzma(n);
-		if (etzpc_get_lock_tzma(n))
-			dev->tzma_cfg[n] |= TZMA_PM_LOCK_BIT;
-	}
-
-	register_pm_core_service_cb(etzpc_pm, dev, "stm32-etzpc");
-}
-
-struct etzpc_hwcfg {
-	unsigned int num_tzma;
-	unsigned int num_per_sec;
-	unsigned int num_ahb_sec;
-	unsigned int chunk_size;
-};
-
-static void get_hwcfg(struct etzpc_hwcfg *hwcfg)
-{
-	uint32_t reg = io_read32(etzpc_base() + ETZPC_HWCFGR);
-
-	hwcfg->num_tzma = (reg & ETZPC_HWCFGR_NUM_TZMA_MASK) >>
-			  ETZPC_HWCFGR_NUM_TZMA_SHIFT;
-	hwcfg->num_per_sec = (reg & ETZPC_HWCFGR_NUM_PER_SEC_MASK) >>
-			     ETZPC_HWCFGR_NUM_PER_SEC_SHIFT;
-	hwcfg->num_ahb_sec = (reg & ETZPC_HWCFGR_NUM_AHB_SEC_MASK) >>
-			     ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT;
-	hwcfg->chunk_size = (reg & ETZPC_HWCFGR_CHUNCKS1N4_MASK) >>
-			    ETZPC_HWCFGR_CHUNCKS1N4_SHIFT;
-}
-
-static void init_device_from_hw_config(struct etzpc_instance *dev,
-				       paddr_t pbase)
-{
-	struct etzpc_hwcfg hwcfg = { };
-
-	assert(!dev->base.pa && cpu_mmu_enabled());
-	dev->base.pa = pbase;
-	dev->base.va = (vaddr_t)phys_to_virt(dev->base.pa, MEM_AREA_IO_SEC, 1);
-	assert(etzpc_base());
-
-	get_hwcfg(&hwcfg);
-	dev->num_tzma = hwcfg.num_tzma;
-	dev->num_per_sec = hwcfg.num_per_sec;
-	dev->num_ahb_sec = hwcfg.num_ahb_sec;
-
-	DMSG("ETZPC revison 0x02%" PRIu8 ", per_sec %u, ahb_sec %u, tzma %u",
-	     io_read8(etzpc_base() + ETZPC_VERR),
-	     hwcfg.num_per_sec, hwcfg.num_ahb_sec, hwcfg.num_tzma);
-
-	init_pm(dev);
-}
-
-static TEE_Result stm32_etzpc_probe(const void *fdt, int node,
-				    const void *compat_data __unused)
-{
-	TEE_Result res = TEE_ERROR_GENERIC;
-	paddr_t pbase = 0;
-	int subnode = 0;
-
-	pbase = fdt_reg_base_address(fdt, node);
-	if (pbase == DT_INFO_INVALID_REG)
-		panic();
-
-	init_device_from_hw_config(&etzpc_dev, pbase);
-
-	fdt_for_each_subnode(subnode, fdt, node) {
-		res = dt_driver_maybe_add_probe_node(fdt, subnode);
-		if (res) {
-			EMSG("Failed to add node %s to probe list: %#"PRIx32,
-			     fdt_get_name(fdt, subnode, NULL), res);
-			panic();
-		}
-	}
-
-	return TEE_SUCCESS;
-}
-
-static const struct dt_device_match etzpc_match_table[] = {
-	{ .compatible = "st,stm32-etzpc" },
-	{ }
-};
-
-DEFINE_DT_DRIVER(etzpc_dt_driver) = {
-	.name = "stm32-etzpc",
-	.match_table = etzpc_match_table,
-	.probe = stm32_etzpc_probe,
-};
diff --git a/core/drivers/stm32_fmc.c b/core/drivers/stm32_fmc.c
new file mode 100644
index 0000000000000000000000000000000000000000..89a554437f52c9ce4ba698f1e104e9cc486bed23
--- /dev/null
+++ b/core/drivers/stm32_fmc.c
@@ -0,0 +1,510 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <config.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_gpio.h>
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#define _FMC_CFGR			U(0x020)
+#define _FMC_SECCFGR			U(0x300)
+#define _FMC_PRIVCFGR			U(0x304)
+#define _FMC_RCFGLOCKR			U(0x308)
+#define _FMC_CIDCFGR(x)			(U(0x30C) + U(0x8) * (x))
+#define _FMC_SEMCR(x)			(U(0x310) + U(0x8) * (x))
+/*
+ * CFGR register bitfields
+ */
+#define _FMC_CFGR_CLKDIV_MASK		GENMASK_32(19, 16)
+#define _FMC_CFGR_CLKDIV_SHIFT		U(16)
+#define _FMC_CFGR_CCLKEN		BIT(20)
+#define _FMC_CFGR_ENABLE		BIT(31)
+
+/*
+ * CIDCFGR register bitfields
+ */
+#define _FMC_CIDCFGR_SEMWL_MASK		GENMASK_32(23, 16)
+#define _FMC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
+#define _FMC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
+					 _CIDCFGR_SEMEN |	 \
+					 _FMC_CIDCFGR_SCID_MASK |\
+					 _FMC_CIDCFGR_SEMWL_MASK)
+
+/*
+ * PRIVCFGR register bitfields
+ */
+#define _FMC_PRIVCFGR_MASK		GENMASK_32(5, 0)
+
+/*
+ * RCFGLOCKR register bitfields
+ */
+#define _FMC_RCFGLOCKR_MASK		GENMASK_32(5, 0)
+
+/*
+ * SECCFGR register bitfields
+ */
+#define _FMC_SECCFGR_EN			BIT(0)
+#define _FMC_SECCFGR_MASK		GENMASK_32(5, 0)
+
+/*
+ * SEMCR register bitfields
+ */
+#define _FMC_SEMCR_SCID_MASK		GENMASK_32(7, 5)
+#define _FMC_SEMCR_SCID_SHIFT		U(5)
+
+/*
+ * Miscellaneous
+ */
+
+#define FMC_RIF_CONTROLLERS		U(6)
+
+#define FMC_NSEC_PER_SEC		UL(1000000000)
+
+struct fmc_pdata {
+	struct clk *fmc_clock;
+	struct pinctrl_state *pinctrl_d;
+	struct pinctrl_state *pinctrl_s;
+	struct rif_conf_data *conf_data;
+	unsigned int nb_controller;
+	vaddr_t base;
+	uint32_t clk_period_ns;
+	bool is_tdcid;
+	bool cclken;
+};
+
+static struct fmc_pdata *fmc_d;
+
+static bool fmc_controller_is_secure(uint8_t controller)
+{
+	return io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(controller);
+}
+
+static TEE_Result handle_available_semaphores(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t cidcfgr = 0;
+	unsigned int i = 0;
+
+	for (i = 0; i < FMC_RIF_CONTROLLERS; i++) {
+		if (!(BIT(i) & fmc_d->conf_data->access_mask[0]))
+			continue;
+
+		cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i));
+
+		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+			continue;
+
+		if (!(io_read32(fmc_d->base + _FMC_SECCFGR) & BIT(i))) {
+			res = stm32_rif_release_semaphore(fmc_d->base +
+							  _FMC_SEMCR(i),
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot release semaphore for resource %u",
+				     i);
+				return res;
+			}
+		} else {
+			res = stm32_rif_acquire_semaphore(fmc_d->base +
+							  _FMC_SEMCR(i),
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot acquire semaphore for resource %u",
+				     i);
+				return res;
+			}
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result apply_rif_config(void)
+{
+	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
+	unsigned int i = 0;
+
+	if (!fmc_d->conf_data)
+		return TEE_SUCCESS;
+
+	res = clk_enable(fmc_d->fmc_clock);
+	if (res)
+		panic("Cannot access FMC clock");
+
+	if (fmc_d->is_tdcid) {
+		for (i = 0; i < FMC_RIF_CONTROLLERS; i++) {
+			if (!(BIT(i) & fmc_d->conf_data->access_mask[0]))
+				continue;
+			/*
+			 * When TDCID, OP-TEE should be the one to set the CID
+			 * filtering configuration. Clearing previous
+			 * configuration prevents undesired events during the
+			 * only legitimate configuration.
+			 */
+			io_clrbits32(fmc_d->base + _FMC_CIDCFGR(i),
+				     _FMC_CIDCFGR_CONF_MASK);
+		}
+	} else {
+		res = handle_available_semaphores();
+		if (res)
+			panic();
+	}
+
+	/* Security and privilege RIF configuration */
+	io_clrsetbits32(fmc_d->base + _FMC_PRIVCFGR, _FMC_PRIVCFGR_MASK,
+			fmc_d->conf_data->priv_conf[0]);
+	io_clrsetbits32(fmc_d->base + _FMC_SECCFGR, _FMC_SECCFGR_MASK,
+			fmc_d->conf_data->sec_conf[0]);
+
+	if (!fmc_d->is_tdcid)
+		goto out;
+
+	for (i = 0; i < FMC_RIF_CONTROLLERS; i++) {
+		if (!(BIT(i) & fmc_d->conf_data->access_mask[0]))
+			continue;
+
+		io_clrsetbits32(fmc_d->base + _FMC_CIDCFGR(i),
+				_FMC_CIDCFGR_CONF_MASK,
+				fmc_d->conf_data->cid_confs[i]);
+	}
+
+	/*
+	 * Lock RIF configuration if configured. This cannot be undone until
+	 * next reset.
+	 */
+	io_setbits32(fmc_d->base + _FMC_RCFGLOCKR,
+		     fmc_d->conf_data->lock_conf[0]);
+
+	res = handle_available_semaphores();
+	if (res)
+		panic();
+out:
+	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
+		/* Check that RIF config are applied, panic otherwise */
+		if ((io_read32(fmc_d->base + _FMC_PRIVCFGR) &
+		     fmc_d->conf_data->access_mask[0]) !=
+		    fmc_d->conf_data->priv_conf[0]) {
+			EMSG("FMC controller priv conf is incorrect");
+			panic();
+		}
+
+		if ((io_read32(fmc_d->base + _FMC_SECCFGR) &
+		     fmc_d->conf_data->access_mask[0]) !=
+		    fmc_d->conf_data->sec_conf[0]) {
+			EMSG("FMC controller sec conf is incorrect");
+			panic();
+		}
+	}
+
+	/* Disable the clock to allow RCC RIF re-configuration on this clock */
+	clk_disable(fmc_d->fmc_clock);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result parse_dt(const void *fdt, int node)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info info = { };
+	const fdt32_t *cuint = NULL;
+	struct io_pa_va addr = { };
+	unsigned int i = 0;
+	int ctrl_node = 0;
+	int lenp = 0;
+
+	fdt_fill_device_info(fdt, &info, node);
+	assert(info.reg != DT_INFO_INVALID_REG &&
+	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
+
+	addr.pa = info.reg;
+	fmc_d->base = io_pa_or_va(&addr, info.reg_size);
+
+	res = clk_dt_get_by_index(fdt, node, 0, &fmc_d->fmc_clock);
+	if (res)
+		return res;
+
+	res = pinctrl_get_state_by_name(fdt, node, "default",
+					&fmc_d->pinctrl_d);
+	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
+		return res;
+
+	res = pinctrl_get_state_by_name(fdt, node, "sleep",
+					&fmc_d->pinctrl_s);
+	if (res && res != TEE_ERROR_ITEM_NOT_FOUND)
+		return res;
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (!cuint) {
+		DMSG("No RIF configuration available");
+		goto skip_rif;
+	}
+
+	fmc_d->conf_data = calloc(1, sizeof(*fmc_d->conf_data));
+	if (!fmc_d->conf_data)
+		panic();
+
+	fmc_d->nb_controller = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(fmc_d->nb_controller <= FMC_RIF_CONTROLLERS);
+
+	fmc_d->conf_data->cid_confs = calloc(FMC_RIF_CONTROLLERS,
+					     sizeof(uint32_t));
+	fmc_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
+	fmc_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
+	fmc_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t));
+	fmc_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
+	if (!fmc_d->conf_data->cid_confs || !fmc_d->conf_data->sec_conf ||
+	    !fmc_d->conf_data->priv_conf || !fmc_d->conf_data->access_mask)
+		panic("Missing memory capacity for FMC RIF configuration");
+
+	for (i = 0; i < fmc_d->nb_controller; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), fmc_d->conf_data,
+				    FMC_RIF_CONTROLLERS);
+
+skip_rif:
+	fdt_for_each_subnode(ctrl_node, fdt, node) {
+		int status = fdt_get_status(fdt, ctrl_node);
+		uint32_t bank = 0;
+
+		if (status == DT_STATUS_DISABLED)
+			continue;
+
+		if (fdt_read_uint32(fdt, ctrl_node, "reg", &bank) < 0)
+			return TEE_ERROR_BAD_PARAMETERS;
+
+		if (bank != 0)
+			continue;
+
+		if (fdt_getprop(fdt, ctrl_node,
+				"st,fmc2-ebi-cs-cclk-enable", NULL))
+			fmc_d->cclken = true;
+
+		if (!fmc_d->cclken)
+			continue;
+
+		if (fdt_read_uint32(fdt, ctrl_node,
+				    "st,fmc2-ebi-cs-clk-period-ns",
+				    &fmc_d->clk_period_ns) < 0)
+			return TEE_ERROR_BAD_PARAMETERS;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result __maybe_unused check_fmc_rif_conf(void)
+{
+	unsigned int i = 0;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = clk_enable(fmc_d->fmc_clock);
+	if (res)
+		panic("Cannot access FMC clock");
+
+	if (fmc_controller_is_secure(0)) {
+		res = TEE_SUCCESS;
+		goto end;
+	}
+
+	for (i = 1; i < fmc_d->nb_controller; i++) {
+		uint32_t cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(i));
+		uint32_t semcr = io_read32(fmc_d->base + _FMC_SEMCR(i));
+
+		/* Check if a controller is secure */
+		if (fmc_controller_is_secure(i)) {
+			res = TEE_ERROR_BAD_STATE;
+			goto end;
+		}
+
+		/*
+		 * Check if a controller is shared with incorrect CID
+		 * (!= RIF_CID1)
+		 */
+		res = stm32_rif_check_access(cidcfgr, semcr, MAX_CID_SUPPORTED,
+					     RIF_CID1);
+		if (res)
+			break;
+	}
+
+end:
+	clk_disable(fmc_d->fmc_clock);
+
+	return res;
+}
+
+static void configure_fmc(void)
+{
+	uint32_t cidcfgr = 0;
+	uint32_t semcr = 0;
+
+	if (clk_enable(fmc_d->fmc_clock))
+		panic("Cannot access FMC clock");
+
+	semcr = io_read32(fmc_d->base + _FMC_SEMCR(0));
+	cidcfgr = io_read32(fmc_d->base + _FMC_CIDCFGR(0));
+
+	/*
+	 * If OP-TEE doesn't have access to the controller 0,
+	 * then we don't want to try to enable the FMC.
+	 */
+	if (stm32_rif_check_access(cidcfgr, semcr, MAX_CID_SUPPORTED, RIF_CID1))
+		goto end;
+
+	/* Check controller 0 access */
+	if (!fmc_controller_is_secure(0)) {
+		DMSG("Controller 0 non-secure, FMC not enabled");
+		goto end;
+	}
+
+	if (cidcfgr & _CIDCFGR_SEMEN &&
+	    stm32_rif_acquire_semaphore(fmc_d->base + _FMC_SEMCR(0),
+					MAX_CID_SUPPORTED))
+		panic("Couldn't acquire controller 0 semaphore");
+
+	if (fmc_d->pinctrl_d && pinctrl_apply_state(fmc_d->pinctrl_d))
+		panic("Could not apply FMC pinctrl");
+
+	if (fmc_d->cclken) {
+		unsigned long hclk = clk_get_rate(fmc_d->fmc_clock);
+		unsigned long hclkp = FMC_NSEC_PER_SEC / (hclk / 1000);
+		unsigned long timing = DIV_ROUND_UP(fmc_d->clk_period_ns * 1000,
+						    hclkp);
+		uint32_t clk_div = SHIFT_U32(1, _FMC_CFGR_CLKDIV_SHIFT);
+
+		if (timing > 1) {
+			timing--;
+			if (timing >
+			    _FMC_CFGR_CLKDIV_MASK >> _FMC_CFGR_CLKDIV_SHIFT)
+				clk_div = _FMC_CFGR_CLKDIV_MASK;
+			else
+				clk_div = SHIFT_U32(timing,
+						    _FMC_CFGR_CLKDIV_SHIFT);
+		}
+
+		io_clrsetbits32(fmc_d->base + _FMC_CFGR,
+				_FMC_CFGR_CLKDIV_MASK | _FMC_CFGR_CCLKEN,
+				clk_div | _FMC_CFGR_CCLKEN);
+	}
+
+	/* Set the FMC enable BIT */
+	io_setbits32(fmc_d->base + _FMC_CFGR, _FMC_CFGR_ENABLE);
+
+end:
+	clk_disable(fmc_d->fmc_clock);
+}
+
+static void fmc_setup(void)
+{
+	if (apply_rif_config())
+		panic("Failed to apply rif_config");
+
+	/* Sanity check for FMC RIF config */
+	assert(!check_fmc_rif_conf());
+
+	configure_fmc();
+}
+
+static void fmc_suspend(void)
+{
+	unsigned int i = 0;
+
+	if (clk_enable(fmc_d->fmc_clock))
+		panic("Cannot access FMC clock");
+
+	if (fmc_controller_is_secure(0) && fmc_d->pinctrl_s &&
+	    pinctrl_apply_state(fmc_d->pinctrl_s))
+		panic();
+
+	for (i = 0; i < FMC_RIF_CONTROLLERS; i++)
+		fmc_d->conf_data->cid_confs[i] =
+			io_read32(fmc_d->base + _FMC_CIDCFGR(i)) &
+			_FMC_CIDCFGR_CONF_MASK;
+
+	fmc_d->conf_data->priv_conf[0] =
+		io_read32(fmc_d->base + _FMC_PRIVCFGR) & _FMC_PRIVCFGR_MASK;
+	fmc_d->conf_data->sec_conf[0] =
+		io_read32(fmc_d->base + _FMC_SECCFGR) & _FMC_SECCFGR_MASK;
+	fmc_d->conf_data->lock_conf[0] =
+		io_read32(fmc_d->base + _FMC_RCFGLOCKR) & _FMC_RCFGLOCKR_MASK;
+	fmc_d->conf_data->access_mask[0] =
+		GENMASK_32(FMC_RIF_CONTROLLERS - 1, 0);
+
+	clk_disable(fmc_d->fmc_clock);
+}
+
+static TEE_Result fmc_pm(enum pm_op op, unsigned int pm_hint,
+			 const struct pm_callback_handle *pm_handle __unused)
+{
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME)
+		fmc_setup();
+	else
+		fmc_suspend();
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result fmc_probe(const void *fdt, int node,
+			    const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	fmc_d = calloc(1, sizeof(*fmc_d));
+	if (!fmc_d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = stm32_rifsc_check_tdcid(&fmc_d->is_tdcid);
+	if (res) {
+		free(fmc_d);
+		return res;
+	}
+
+	res = parse_dt(fdt, node);
+	if (res)
+		goto err;
+
+	fmc_setup();
+
+	register_pm_core_service_cb(fmc_pm, NULL, "stm32-fmc");
+
+	return TEE_SUCCESS;
+err:
+	/* Free all allocated resources */
+	if (fmc_d->conf_data) {
+		free(fmc_d->conf_data->access_mask);
+		free(fmc_d->conf_data->cid_confs);
+		free(fmc_d->conf_data->priv_conf);
+		free(fmc_d->conf_data->sec_conf);
+	}
+	free(fmc_d->conf_data);
+	free(fmc_d);
+
+	return res;
+}
+
+static const struct dt_device_match stm32_fmc_match_table[] = {
+	{ .compatible = "st,stm32mp25-fmc2-ebi" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_fmc_dt_driver) = {
+	.name = "stm32_fmc",
+	.match_table = stm32_fmc_match_table,
+	.probe = fmc_probe,
+};
diff --git a/core/drivers/stm32_gpio.c b/core/drivers/stm32_gpio.c
index 40f1ccb71768cc206fd6b0f2cedf268dcd563595..cebb9344c5e29dfe561df770dd0f4ccf9ba8bb37 100644
--- a/core/drivers/stm32_gpio.c
+++ b/core/drivers/stm32_gpio.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2017-2023, STMicroelectronics
+ * Copyright (c) 2017-2024, STMicroelectronics
  *
  * STM32 GPIO driver is used as pin controller for stm32mp SoCs.
  */
@@ -9,14 +9,18 @@
 #include <compiler.h>
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
+#include <drivers/firewall.h>
 #include <drivers/gpio.h>
 #include <drivers/pinctrl.h>
 #include <drivers/stm32_gpio.h>
+#include <drivers/stm32_rif.h>
 #include <dt-bindings/gpio/stm32mp_gpio.h>
+#include <dt-bindings/pinctrl/stm32-pinfunc.h>
 #include <io.h>
 #include <kernel/dt.h>
 #include <kernel/boot.h>
 #include <kernel/panic.h>
+#include <kernel/pm.h>
 #include <kernel/spinlock.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
@@ -43,9 +47,42 @@
 #define GPIO_AFRL_OFFSET	U(0x20)
 #define GPIO_AFRH_OFFSET	U(0x24)
 #define GPIO_SECR_OFFSET	U(0x30)
+#define GPIO_PRIVCFGR_OFFSET	U(0x34)
+#define GPIO_RCFGLOCKR_OFFSET	U(0x38)
+#define GPIO_CIDCFGR(x)		(U(0x50) + U(0x8) * (x))
+#define GPIO_SEMCR(x)		(U(0x54) + U(0x8) * (x))
 
 #define GPIO_ALT_LOWER_LIMIT	U(0x8)
 
+/*
+ * CIDCFGR register bitfields
+ */
+#define GPIO_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
+#define GPIO_CIDCFGR_SCID_MASK	GENMASK_32(6, 4)
+#define GPIO_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN | _CIDCFGR_SEMEN |	\
+				 GPIO_CIDCFGR_SCID_MASK |		\
+				 GPIO_CIDCFGR_SEMWL_MASK)
+
+/*
+ * PRIVCFGR register bitfields
+ */
+#define GPIO_PRIVCFGR_MASK	GENMASK_32(15, 0)
+
+/*
+ * SECCFGR register bitfields
+ */
+#define GPIO_SECCFGR_MASK	GENMASK_32(15, 0)
+
+/*
+ * RCFGLOCKR register bitfields
+ */
+#define GPIO_RCFGLOCKR_MASK	GENMASK_32(15, 0)
+
+/*
+ * SEMCR register bitfields
+ */
+#define GPIO_SEMCR_SCID_M	GENMASK_32(6, 4)
+
 #define GPIO_MODE_MASK		GENMASK_32(1, 0)
 #define GPIO_OSPEED_MASK	GENMASK_32(1, 0)
 #define GPIO_PUPD_PULL_MASK	GENMASK_32(1, 0)
@@ -79,6 +116,8 @@
 #define GPIO_OD_LEVEL_LOW	U(0x0)
 #define GPIO_OD_LEVEL_HIGH	U(0x1)
 
+#define GPIO_MAX_CID_SUPPORTED	U(3)
+
 /*
  * GPIO configuration description structured as single 16bit word
  * for efficient save/restore when GPIO pin suspends or resumes.
@@ -89,6 +128,7 @@
  * @pupd: One of GPIO_PUPD_*
  * @od: One of GPIO_OD_*
  * @af: Alternate function numerical ID between 0 and 15
+ * @nsec: Hint on expected secure state of the pin: 0 if secure, 1 otherwise
  */
 struct gpio_cfg {
 	uint16_t mode:		2;
@@ -97,6 +137,7 @@ struct gpio_cfg {
 	uint16_t pupd:		2;
 	uint16_t od:		1;
 	uint16_t af:		4;
+	uint16_t nsec:		1;
 };
 
 /*
@@ -131,7 +172,11 @@ struct stm32_pinctrl_array {
  * @ngpios: number of GPIOs.
  * @bank_id: Id of the bank.
  * @lock: lock protecting the GPIO bank access.
- * @sec_support: True if bank supports pin security protection, otherwise false
+ * @rif_cfg: RIF configuration data
+ * @seccfgr: non-RIF bank secure configuration data
+ * @sec_support: True if bank supports pin security protection, else false
+ * @ready: True if configuration is applied, else false
+ * @is_tdcid: True if OP-TEE runs as Trusted Domain CID
  * @link: Link in bank list
  */
 struct stm32_gpio_bank {
@@ -141,19 +186,37 @@ struct stm32_gpio_bank {
 	unsigned int ngpios;
 	unsigned int bank_id;
 	unsigned int lock;
+	struct rif_conf_data *rif_cfg;
+	uint32_t seccfgr;
 	bool sec_support;
+	bool ready;
+	bool is_tdcid;
 	STAILQ_ENTRY(stm32_gpio_bank) link;
 };
 
+/*
+ * struct stm32_gpio_pm_state - Consumed GPIO for PM purpose
+ * @gpio_pinctrl: Reference and configuration state for a consumed GPIO
+ * @level: GPIO level
+ * @link: Link in consumed GPIO list
+ */
+struct stm32_gpio_pm_state {
+	struct stm32_pinctrl gpio_pinctrl;
+	uint8_t level;
+	SLIST_ENTRY(stm32_gpio_pm_state) link;
+};
+
 /**
  * Compatibility information of supported banks
  *
  * @gpioz: True if bank is a GPIOZ bank
  * @secure_control: Identify GPIO security bank capability.
+ * @secure_extended: Identify RIF presence.
  */
 struct bank_compat {
 	bool gpioz;
 	bool secure_control;
+	bool secure_extended;
 };
 
 static unsigned int gpio_lock;
@@ -161,6 +224,8 @@ static unsigned int gpio_lock;
 static STAILQ_HEAD(, stm32_gpio_bank) bank_list =
 		STAILQ_HEAD_INITIALIZER(bank_list);
 
+static SLIST_HEAD(, stm32_gpio_pm_state) consumed_gpios_head;
+
 static bool is_stm32_gpio_chip(struct gpio_chip *chip);
 
 static struct stm32_gpio_bank *gpio_chip_to_bank(struct gpio_chip *chip)
@@ -277,11 +342,40 @@ static void stm32_gpio_set_direction(struct gpio_chip *chip,
 	clk_disable(bank->clock);
 }
 
-static void stm32_gpio_put_gpio(struct gpio_chip *chip __maybe_unused,
-				struct gpio *gpio)
+/* Forward reference to the PM callback handler for consumed GPIOs */
+static TEE_Result consumed_gpios_pm(enum pm_op op, unsigned int pm_hint,
+				    const struct pm_callback_handle *pm_hdl);
+
+/* Forward reference to RIF semaphore release helper function */
+static void release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank,
+					      unsigned int pin);
+
+static void stm32_gpio_put_gpio(struct gpio_chip *chip, struct gpio *gpio)
 {
+	struct stm32_gpio_bank *bank = gpio_chip_to_bank(chip);
+	struct stm32_gpio_pm_state *tstate = NULL;
+	struct stm32_gpio_pm_state *state = NULL;
+	uint32_t exceptions = 0;
+
 	assert(is_stm32_gpio_chip(chip));
-	free(gpio);
+
+	exceptions = cpu_spin_lock_xsave(&gpio_lock);
+
+	SLIST_FOREACH_SAFE(state, &consumed_gpios_head, link, tstate) {
+		if (state->gpio_pinctrl.bank == bank->bank_id &&
+		    state->gpio_pinctrl.pin == gpio->pin) {
+			SLIST_REMOVE(&consumed_gpios_head, state,
+				     stm32_gpio_pm_state, link);
+			unregister_pm_driver_cb(consumed_gpios_pm, state);
+			release_rif_semaphore_if_acquired(bank, gpio->pin);
+			free(state);
+			free(gpio);
+			break;
+		}
+	}
+	assert(state);
+
+	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
 }
 
 static const struct gpio_ops stm32_gpio_ops = {
@@ -308,9 +402,136 @@ static struct stm32_gpio_bank *stm32_gpio_get_bank(unsigned int bank_id)
 	panic();
 }
 
+#if defined(CFG_STM32_RIF)
+static bool pin_is_accessible(struct stm32_gpio_bank *bank, unsigned int pin)
+{
+	bool accessible = false;
+	uint32_t cidcfgr = 0;
+
+	if (!bank->rif_cfg)
+		return true;
+
+	if (clk_enable(bank->clock))
+		panic();
+
+	cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(pin));
+
+	if (!(cidcfgr & _CIDCFGR_CFEN)) {
+		/* Resource can be accessed when CID filtering is disabled */
+		accessible = true;
+	} else if (stm32_rif_scid_ok(cidcfgr, GPIO_CIDCFGR_SCID_MASK,
+				     RIF_CID1)) {
+		/* Resource can be accessed if CID1 is statically allowed */
+		accessible = true;
+	} else if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1)) {
+		/* CID1 is allowed to request the semaphore */
+		accessible = true;
+	}
+
+	clk_disable(bank->clock);
+
+	return accessible;
+}
+
+static TEE_Result acquire_rif_semaphore_if_needed(struct stm32_gpio_bank *bank,
+						  unsigned int pin)
+{
+	TEE_Result res = TEE_SUCCESS;
+	uint32_t cidcfgr = 0;
+
+	if (!bank->rif_cfg)
+		return TEE_SUCCESS;
+
+	res = clk_enable(bank->clock);
+	if (res)
+		return res;
+
+	cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(pin));
+
+	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+		res = stm32_rif_acquire_semaphore(bank->base + GPIO_SEMCR(pin),
+						  GPIO_MAX_CID_SUPPORTED);
+
+	clk_disable(bank->clock);
+
+	return res;
+}
+
+static uint32_t semaphore_current_cid(struct stm32_gpio_bank *bank,
+				      unsigned int pin)
+{
+	return (io_read32(bank->base + GPIO_SEMCR(pin)) >>
+		_CIDCFGR_SCID_SHIFT) &
+		GENMASK_32(GPIO_MAX_CID_SUPPORTED - 1, 0);
+}
+
+static void release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank,
+					      unsigned int pin)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t cidcfgr = 0;
+
+	if (!bank->rif_cfg)
+		return;
+
+	res = clk_enable(bank->clock);
+	if (res)
+		panic();
+
+	cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(pin));
+
+	if (stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1) &&
+	    semaphore_current_cid(bank, pin) == RIF_CID1) {
+		res = stm32_rif_release_semaphore(bank->base + GPIO_SEMCR(pin),
+						  GPIO_MAX_CID_SUPPORTED);
+		if (res) {
+			EMSG("Failed to release GPIO %c%u semaphore",
+			     bank->bank_id + 'A', pin);
+			panic();
+		}
+	}
+
+	clk_disable(bank->clock);
+}
+#else
+static bool pin_is_accessible(struct stm32_gpio_bank *bank __unused,
+			      unsigned int pin __unused)
+{
+	return true;
+}
+
+static TEE_Result
+acquire_rif_semaphore_if_needed(struct stm32_gpio_bank *bank __unused,
+				unsigned int pin __unused)
+{
+	return TEE_SUCCESS;
+}
+
+static void
+release_rif_semaphore_if_acquired(struct stm32_gpio_bank *bank __unused,
+				  unsigned int pin __unused)
+{
+}
+#endif /*CFG_STM32_RIF*/
+
+static bool pin_is_secure(struct stm32_gpio_bank *bank, unsigned int pin)
+{
+	bool secure = false;
+
+	if (bank->rif_cfg || bank->sec_support) {
+		if (clk_enable(bank->clock))
+			panic();
+
+		secure = io_read32(bank->base + GPIO_SECR_OFFSET) & BIT(pin);
+
+		clk_disable(bank->clock);
+	}
+
+	return secure;
+}
+
 /* Save to output @cfg the current GPIO (@bank_id/@pin) configuration */
-static void __maybe_unused get_gpio_cfg(uint32_t bank_id, uint32_t pin,
-					struct gpio_cfg *cfg)
+static void get_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg)
 {
 	struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id);
 
@@ -398,8 +619,10 @@ static void set_gpio_cfg(uint32_t bank_id, uint32_t pin, struct gpio_cfg *cfg)
 
 /* Count pins described in the DT node and get related data if possible */
 static int get_pinctrl_from_fdt(const void *fdt, int node,
+				int consumer_node __maybe_unused,
 				struct stm32_pinctrl *pinctrl, size_t count)
 {
+	struct stm32_gpio_bank *bank_ref = NULL;
 	const fdt32_t *cuint = NULL;
 	const fdt32_t *slewrate = NULL;
 	int len = 0;
@@ -407,6 +630,7 @@ static int get_pinctrl_from_fdt(const void *fdt, int node,
 	uint32_t speed = GPIO_OSPEED_LOW;
 	uint32_t pull = GPIO_PUPD_NO_PULL;
 	size_t found = 0;
+	bool do_panic = false;
 
 	cuint = fdt_getprop(fdt, node, "pinmux", &len);
 	if (!cuint)
@@ -429,6 +653,7 @@ static int get_pinctrl_from_fdt(const void *fdt, int node,
 		uint32_t alternate = 0;
 		uint32_t odata = 0;
 		bool opendrain = false;
+		bool pin_non_secure = true;
 
 		pincfg = fdt32_to_cpu(*cuint);
 		cuint++;
@@ -439,6 +664,8 @@ static int get_pinctrl_from_fdt(const void *fdt, int node,
 
 		mode = pincfg & DT_GPIO_MODE_MASK;
 
+		pin_non_secure = pincfg & STM32_PIN_NSEC;
+
 		switch (mode) {
 		case 0:
 			mode = GPIO_MODE_INPUT;
@@ -499,27 +726,70 @@ static int get_pinctrl_from_fdt(const void *fdt, int node,
 			ref->cfg.pupd = pull;
 			ref->cfg.od = odata;
 			ref->cfg.af = alternate;
+			ref->cfg.nsec = pin_non_secure;
+
+			bank_ref = stm32_gpio_get_bank(bank);
+
+			if (pin >= bank_ref->ngpios) {
+				EMSG("node %s requests pin %c%u that does not exist",
+				     fdt_get_name(fdt, consumer_node, NULL),
+				     bank + 'A', pin);
+				do_panic = true;
+			}
 		}
 
 		found++;
 	}
 
+	if (do_panic)
+		panic();
+
 	return (int)found;
 }
 
+static TEE_Result consumed_gpios_pm(enum pm_op op,
+				    unsigned int pm_hint __unused,
+				    const struct pm_callback_handle *pm_hdl)
+{
+	struct stm32_gpio_pm_state *handle = pm_hdl->handle;
+	unsigned int bank_id = handle->gpio_pinctrl.bank;
+	unsigned int pin = handle->gpio_pinctrl.pin;
+	struct gpio_chip *chip = &stm32_gpio_get_bank(bank_id)->gpio_chip;
+
+	if (op == PM_OP_RESUME) {
+		set_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg);
+		if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT)
+			stm32_gpio_set_level(chip, pin, handle->level);
+	} else {
+		get_gpio_cfg(bank_id, pin, &handle->gpio_pinctrl.cfg);
+		if (handle->gpio_pinctrl.cfg.mode == GPIO_MODE_OUTPUT)
+			handle->level = stm32_gpio_get_level(chip, pin);
+	}
+
+	return TEE_SUCCESS;
+}
+DECLARE_KEEP_PAGER(consumed_gpios_pm);
+
 static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data,
 				    struct gpio **out_gpio)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
+	const char *consumer_name __maybe_unused = NULL;
+	struct stm32_gpio_pm_state *reg_state = NULL;
+	struct stm32_gpio_pm_state *state = NULL;
 	struct stm32_gpio_bank *bank = data;
 	struct gpio *gpio = NULL;
 	unsigned int shift_1b = 0;
 	unsigned int shift_2b = 0;
+	bool gpio_secure = true;
 	uint32_t exceptions = 0;
 	uint32_t otype = 0;
 	uint32_t pupd = 0;
 	uint32_t mode = 0;
 
+	consumer_name = fdt_get_name(pargs->fdt, pargs->consumer_node,
+				     NULL);
+
 	res = gpio_dt_alloc_pin(pargs, &gpio);
 	if (res)
 		return res;
@@ -530,6 +800,61 @@ static TEE_Result stm32_gpio_get_dt(struct dt_pargs *pargs, void *data,
 		return TEE_ERROR_GENERIC;
 	}
 
+	if (gpio->dt_flags & GPIO_STM32_NSEC)
+		gpio_secure = false;
+
+	state = calloc(1, sizeof(*state));
+	if (!state) {
+		free(gpio);
+		return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	SLIST_FOREACH(reg_state, &consumed_gpios_head, link) {
+		if (reg_state->gpio_pinctrl.bank == bank->bank_id &&
+		    reg_state->gpio_pinctrl.pin == gpio->pin) {
+			EMSG("node %s: GPIO %c%u is used by another device",
+			     consumer_name, bank->bank_id + 'A', gpio->pin);
+			free(state);
+			free(gpio);
+			return TEE_ERROR_GENERIC;
+		}
+	}
+
+	if (!pin_is_accessible(bank, gpio->pin)) {
+		EMSG("node %s requests pin on GPIO %c%u which access is denied",
+		     consumer_name, bank->bank_id + 'A', gpio->pin);
+		panic();
+	}
+
+	res = acquire_rif_semaphore_if_needed(bank, gpio->pin);
+	if (res) {
+		EMSG("Failed to acquire GPIO %c%u semaphore for node %s",
+		     bank->bank_id + 'A', gpio->pin, consumer_name);
+		return res;
+	}
+
+	if (gpio_secure && !(bank->rif_cfg || bank->sec_support)) {
+		EMSG("node %s requests secure GPIO %c%u that cannot be secured",
+		     consumer_name, bank->bank_id + 'A', gpio->pin);
+		panic();
+	}
+
+	if (gpio_secure != pin_is_secure(bank, gpio->pin)) {
+		IMSG("WARNING: node %s requests %s GPIO %c%u but pin is %s. Check st,protreg in GPIO bank node %s",
+		     consumer_name, gpio_secure ? "secure" : "non-secure",
+		     bank->bank_id + 'A', gpio->pin,
+		     pin_is_secure(bank, gpio->pin) ? "secure" : "non-secure",
+		     fdt_get_name(pargs->fdt, pargs->phandle_node, NULL));
+		if (!IS_ENABLED(CFG_INSECURE))
+			panic();
+	}
+
+	state->gpio_pinctrl.pin = gpio->pin;
+	state->gpio_pinctrl.bank = bank->bank_id;
+	SLIST_INSERT_HEAD(&consumed_gpios_head, state, link);
+
+	register_pm_driver_cb(consumed_gpios_pm, state, "stm32-gpio-state");
+
 	shift_1b = gpio->pin;
 	shift_2b = SHIFT_U32(gpio->pin, 1);
 
@@ -606,6 +931,258 @@ static bool bank_is_registered(const void *fdt, int node)
 	return false;
 }
 
+#ifdef CFG_STM32_RIF
+static TEE_Result handle_available_semaphores(struct stm32_gpio_bank *bank,
+					      uint32_t gpios_mask)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t cidcfgr = 0;
+	unsigned int i = 0;
+
+	for (i = 0 ; i < bank->ngpios; i++) {
+		if (!(BIT(i) & gpios_mask))
+			continue;
+
+		cidcfgr = io_read32(bank->base + GPIO_CIDCFGR(i));
+
+		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+			continue;
+
+		if (!(io_read32(bank->base + GPIO_SECR_OFFSET) & BIT(i))) {
+			res = stm32_rif_release_semaphore(bank->base +
+							  GPIO_SEMCR(i),
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot release semaphore for resource %u",
+				     i);
+				return res;
+			}
+		} else {
+			res = stm32_rif_acquire_semaphore(bank->base +
+							  GPIO_SEMCR(i),
+							  MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot acquire semaphore for resource %u",
+				     i);
+				return res;
+			}
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank,
+				   uint32_t gpios_mask)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+
+	if (!bank->rif_cfg)
+		return TEE_SUCCESS;
+
+	if (clk_enable(bank->clock))
+		panic();
+
+	if (bank->is_tdcid) {
+		for (i = 0; i < bank->ngpios; i++) {
+			if (!(BIT(i) & gpios_mask))
+				continue;
+
+			/*
+			 * When TDCID, OP-TEE should be the one to set the CID
+			 * filtering configuration. Clearing previous
+			 * configuration prevents undesired events during the
+			 * only legitimate configuration.
+			 */
+			io_clrbits32(bank->base + GPIO_CIDCFGR(i),
+				     GPIO_CIDCFGR_CONF_MASK);
+		}
+	} else {
+		res = handle_available_semaphores(bank, gpios_mask);
+		if (res)
+			panic();
+	}
+
+	/* Security and privilege RIF configuration */
+	io_mask32(bank->base + GPIO_PRIVCFGR_OFFSET,
+		  bank->rif_cfg->priv_conf[0], gpios_mask);
+	io_mask32(bank->base + GPIO_SECR_OFFSET,
+		  bank->rif_cfg->sec_conf[0], gpios_mask);
+
+	if (!bank->is_tdcid) {
+		res = TEE_SUCCESS;
+		goto out;
+	}
+
+	for (i = 0; i < bank->ngpios; i++) {
+		if (!(BIT(i) & gpios_mask))
+			continue;
+
+		io_clrsetbits32(bank->base + GPIO_CIDCFGR(i),
+				GPIO_CIDCFGR_CONF_MASK,
+				bank->rif_cfg->cid_confs[i]);
+	}
+
+	/*
+	 * Lock RIF configuration if configured. This cannot be undone until
+	 * next reset.
+	 */
+	io_setbits32(bank->base + GPIO_RCFGLOCKR_OFFSET,
+		     bank->rif_cfg->lock_conf[0]);
+
+	res = handle_available_semaphores(bank, gpios_mask);
+	if (res)
+		panic();
+
+out:
+	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
+		/* Check that RIF config are applied, panic otherwise */
+		if ((io_read32(bank->base + GPIO_PRIVCFGR_OFFSET) &
+		     gpios_mask) !=
+		    (bank->rif_cfg->priv_conf[0] & gpios_mask)) {
+			EMSG("GPIO bank%c priv conf is incorrect",
+			     'A' + bank->bank_id);
+			panic();
+		}
+
+		if ((io_read32(bank->base + GPIO_SECR_OFFSET) & gpios_mask) !=
+		    (bank->rif_cfg->sec_conf[0] & gpios_mask)) {
+			EMSG("GPIO bank %c sec conf is incorrect",
+			     'A' + bank->bank_id);
+			panic();
+		}
+	}
+
+	clk_disable(bank->clock);
+
+	return res;
+}
+#else /* CFG_STM32_RIF */
+static TEE_Result apply_rif_config(struct stm32_gpio_bank *bank __unused,
+				   uint32_t gpios_mask __unused)
+{
+	return TEE_SUCCESS;
+}
+#endif /* CFG_STM32_RIF */
+
+/* Forward reference to stm32_gpio_set_conf_sec() defined below */
+static void stm32_gpio_set_conf_sec(struct stm32_gpio_bank *bank);
+
+static TEE_Result stm32_gpio_fw_configure(struct firewall_query *firewall)
+{
+	struct stm32_gpio_bank *bank = firewall->ctrl->priv;
+	uint32_t firewall_arg = 0;
+	uint32_t gpios_mask = 0;
+	bool secure = true;
+
+	assert(bank->sec_support);
+
+	if (firewall->arg_count != 1)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	firewall_arg = firewall->args[0];
+
+	if (bank->rif_cfg) {
+		gpios_mask = BIT(RIF_CHANNEL_ID(firewall_arg));
+
+		/* We're about to change a specific GPIO config */
+		bank->rif_cfg->access_mask[0] |= gpios_mask;
+
+		/*
+		 * Update bank RIF config with firewall configuration data
+		 * and apply it.
+		 */
+		stm32_rif_parse_cfg(firewall_arg, bank->rif_cfg,
+				    bank->ngpios);
+		return apply_rif_config(bank, gpios_mask);
+	}
+
+	/*
+	 * Non RIF GPIO banks use a single cell as a bit mask (bits 0 to 15)
+	 * to define the a group of GPIO pins (one or several) to configure
+	 * for that bank, and GPIO_STM32_NSEC bit flag to set if these pins
+	 * are non-secure (flag set) or non-secure (flag cleared).
+	 */
+	gpios_mask = firewall_arg & GENMASK_32(15, 0);
+
+	secure = !(firewall_arg & GPIO_STM32_NSEC);
+
+	if (gpios_mask & ~GENMASK_32(bank->ngpios, 0)) {
+		EMSG("Invalid bitmask %#"PRIx32" for GPIO bank %c",
+		     gpios_mask, 'A' + bank->bank_id);
+		return TEE_ERROR_GENERIC;
+	}
+
+	/* Update bank secure register configuration data and apply it */
+	if (secure)
+		bank->seccfgr |= gpios_mask;
+	else
+		bank->seccfgr &= ~gpios_mask;
+
+	stm32_gpio_set_conf_sec(bank);
+
+	return TEE_SUCCESS;
+}
+
+static const struct firewall_controller_ops stm32_gpio_firewall_ops = {
+	.set_conf = stm32_gpio_fw_configure,
+};
+
+static void stm32_gpio_save_rif_config(struct stm32_gpio_bank *bank)
+{
+	size_t i = 0;
+
+	for (i = 0; i < bank->ngpios; i++)
+		bank->rif_cfg->cid_confs[i] = io_read32(bank->base +
+							 GPIO_CIDCFGR(i));
+
+	bank->rif_cfg->priv_conf[0] = io_read32(bank->base +
+						GPIO_PRIVCFGR_OFFSET);
+	bank->rif_cfg->sec_conf[0] = io_read32(bank->base +
+					       GPIO_SECR_OFFSET);
+	bank->rif_cfg->lock_conf[0] = io_read32(bank->base +
+						GPIO_RCFGLOCKR_OFFSET);
+}
+
+static void stm32_parse_gpio_rif_conf(struct stm32_gpio_bank *bank,
+				      const void *fdt, int node)
+{
+	unsigned int i = 0;
+	unsigned int nb_rif_conf = 0;
+	int lenp = 0;
+	const fdt32_t *cuint = NULL;
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (!cuint) {
+		DMSG("No RIF configuration available");
+		return;
+	}
+
+	bank->rif_cfg = calloc(1, sizeof(*bank->rif_cfg));
+	if (!bank->rif_cfg)
+		panic();
+
+	bank->rif_cfg->sec_conf = calloc(1, sizeof(uint32_t));
+	if (!bank->rif_cfg->sec_conf)
+		panic();
+
+	nb_rif_conf = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(nb_rif_conf <= bank->ngpios);
+
+	bank->rif_cfg->cid_confs = calloc(bank->ngpios, sizeof(uint32_t));
+	bank->rif_cfg->priv_conf = calloc(1, sizeof(uint32_t));
+	bank->rif_cfg->lock_conf = calloc(1, sizeof(uint32_t));
+	bank->rif_cfg->access_mask = calloc(1, sizeof(uint32_t));
+	if (!bank->rif_cfg->cid_confs || !bank->rif_cfg->access_mask ||
+	    !bank->rif_cfg->priv_conf || !bank->rif_cfg->lock_conf)
+		panic("Missing memory capacity for GPIOS RIF configuration");
+
+	for (i = 0; i < nb_rif_conf; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), bank->rif_cfg,
+				    bank->ngpios);
+}
+
 /* Get GPIO bank information from the DT */
 static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node,
 				     const void *compat_data,
@@ -634,30 +1211,28 @@ static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node,
 	if (!bank)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
+	if (compat->secure_extended) {
+		res = stm32_rifsc_check_tdcid(&bank->is_tdcid);
+		if (res) {
+			free(bank);
+			return res;
+		}
+	}
+
 	/*
 	 * Do not rely *only* on the "reg" property to get the address,
 	 * but consider also the "ranges" translation property
 	 */
-	pa = fdt_reg_base_address(fdt, node);
-	if (pa == DT_INFO_INVALID_REG)
-		panic("missing reg property");
+	if (fdt_reg_info(fdt, node, &pa, &blen))
+		panic("missing reg or reg size property");
 
 	pa_va.pa = pa + range_offset;
 
-	blen = fdt_reg_size(fdt, node);
-	if (blen == DT_INFO_INVALID_REG_SIZE)
-		panic("missing reg size property");
-
 	DMSG("Bank name %s", fdt_get_name(fdt, node, NULL));
 	bank->bank_id = dt_get_bank_id(fdt, node);
 	bank->clock = clk;
 	bank->gpio_chip.ops = &stm32_gpio_ops;
 	bank->sec_support = compat->secure_control;
-	if (bank->sec_support)
-		bank->base = io_pa_or_va_secure(&pa_va, blen);
-	else
-		bank->base = io_pa_or_va_nsec(&pa_va, blen);
-	assert(bank->base);
 
 	/* Parse gpio-ranges with its 4 parameters */
 	cuint = fdt_getprop(fdt, node, "gpio-ranges", &len);
@@ -673,22 +1248,65 @@ static TEE_Result dt_stm32_gpio_bank(const void *fdt, int node,
 		cuint += 4;
 	}
 
-	if (compat->gpioz)
-		stm32mp_register_gpioz_pin_count(bank->ngpios);
+	if (compat->secure_extended) {
+		/* RIF configuration */
+		bank->base = io_pa_or_va_secure(&pa_va, blen);
+
+		stm32_parse_gpio_rif_conf(bank, fdt, node);
+	} else if (bank->sec_support) {
+		/* Secure configuration */
+		bank->base = io_pa_or_va_secure(&pa_va, blen);
+		cuint = fdt_getprop(fdt, node, "st,protreg", NULL);
+		if (cuint)
+			bank->seccfgr = fdt32_to_cpu(*cuint);
+		else
+			DMSG("GPIO bank %c assigned to non-secure",
+			     bank->bank_id + 'A');
+	} else {
+		bank->base = io_pa_or_va_nsec(&pa_va, blen);
+	}
 
 	*out_bank = bank;
+
 	return TEE_SUCCESS;
 }
 
-static void set_bank_gpio_non_secure(struct stm32_gpio_bank *bank)
+static TEE_Result stm32_gpio_firewall_register(const void *fdt, int node,
+					       struct stm32_gpio_bank *bank)
 {
-	unsigned int pin = 0;
+	struct firewall_controller *controller = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	char bank_name[] = "gpio-bank-X";
+	char *name = NULL;
+
+	if (!IS_ENABLED(CFG_DRIVERS_FIREWALL) ||
+	    !bank->sec_support)
+		return TEE_SUCCESS;
+
+	controller = calloc(1, sizeof(*controller));
+	if (!controller)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	bank_name[sizeof(bank_name) - 2] = 'A' + bank->bank_id;
+	name = strdup(bank_name);
+
+	controller->name = name;
+	controller->priv = bank;
+	controller->ops = &stm32_gpio_firewall_ops;
+
+	if (!controller->name)
+		EMSG("Warning: out of memory to store bank name");
+
+	res = firewall_dt_controller_register(fdt, node, controller);
+	if (res) {
+		free(name);
+		free(controller);
+	}
 
-	for (pin = 0; pin < bank->ngpios; pin++)
-		stm32_gpio_set_secure_cfg(bank->bank_id, pin, false);
+	return res;
 }
 
-/* Parse a pinctrl node to register and configure the GPIO banks it describes */
+/* Parse a pinctrl node to register the GPIO banks it describes */
 static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 					const void *compat_data)
 {
@@ -732,32 +1350,11 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 			if (res)
 				panic();
 
-			STAILQ_INSERT_TAIL(&bank_list, bank, link);
+			res = stm32_gpio_firewall_register(fdt, b_node, bank);
+			if (res)
+				panic();
 
-			DMSG("Registered GPIO bank %c (%d pins) @%#"PRIxVA,
-			     bank->bank_id + 'A', bank->ngpios, bank->base);
-
-			assert(bank->ngpios <= GPIO_PIN_MAX + 1);
-
-			if (bank->sec_support) {
-				uint32_t seccfgr = 0;
-				unsigned int i = 0;
-				int lenp = 0;
-
-				cuint = fdt_getprop(fdt, b_node, "st,protreg",
-						    &lenp);
-				if (!cuint) {
-					set_bank_gpio_non_secure(bank);
-					continue;
-				}
-
-				seccfgr = fdt32_to_cpu(*cuint);
-				for (i = 0; i < bank->ngpios; i++)
-					stm32_gpio_set_secure_cfg(bank->bank_id,
-								  i,
-								  seccfgr &
-								  TZPROT(i));
-			}
+			STAILQ_INSERT_TAIL(&bank_list, bank, link);
 		} else {
 			if (len != -FDT_ERR_NOTFOUND)
 				panic();
@@ -767,34 +1364,60 @@ static TEE_Result dt_stm32_gpio_pinctrl(const void *fdt, int node,
 	return TEE_SUCCESS;
 }
 
-void stm32_gpio_set_secure_cfg(unsigned int bank_id, unsigned int pin,
-			       bool secure)
-{
-	struct stm32_gpio_bank *bank = stm32_gpio_get_bank(bank_id);
-	uint32_t exceptions = 0;
-
-	if (clk_enable(bank->clock))
-		panic();
-	exceptions = cpu_spin_lock_xsave(&gpio_lock);
-
-	if (secure)
-		io_setbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin));
-	else
-		io_clrbits32(bank->base + GPIO_SECR_OFFSET, BIT(pin));
-
-	FMSG("Set secure GPIO: bank %c pin %u", bank->bank_id + 'A', pin);
-
-	cpu_spin_unlock_xrestore(&gpio_lock, exceptions);
-	clk_disable(bank->clock);
-}
-
 #ifdef CFG_DRIVERS_PINCTRL
 static TEE_Result stm32_pinctrl_conf_apply(struct pinconf *conf)
 {
 	struct stm32_pinctrl_array *ref = conf->priv;
 	struct stm32_pinctrl *p = ref->pinctrl;
+	struct stm32_gpio_bank *bank = NULL;
+	TEE_Result res = TEE_ERROR_GENERIC;
 	size_t pin_count = ref->count;
 	size_t n = 0;
+	bool error = false;
+
+	for (n = 0; n < pin_count; n++) {
+		bank = stm32_gpio_get_bank(p[n].bank);
+
+		if (!pin_is_accessible(bank, p[n].pin)) {
+			EMSG("Apply pinctrl for pin %c%u that cannot be accessed",
+			     p[n].bank + 'A', p[n].pin);
+			error = true;
+			continue;
+		}
+
+		res = acquire_rif_semaphore_if_needed(bank, p[n].pin);
+		if (res) {
+			EMSG("Failed to acquire GPIO %c%u semaphore",
+			     bank->bank_id + 'A', p[n].pin);
+			error = true;
+			continue;
+		}
+
+		if (p[n].cfg.nsec == !pin_is_secure(bank, p[n].pin))
+			continue;
+
+		if (IS_ENABLED(CFG_INSECURE)) {
+			IMSG("WARNING: apply pinctrl for %ssecure pin %c%u that is %ssecure",
+			     p[n].cfg.nsec ? "non-" : "",
+			     p[n].bank + 'A', p[n].pin,
+			     pin_is_secure(bank, p[n].pin) ? "" : "non-");
+		} else {
+			EMSG("Apply pinctrl for %ssecure pin %c%u that is %ssecure",
+			     p[n].cfg.nsec ? "non-" : "",
+			     p[n].bank + 'A', p[n].pin,
+			     pin_is_secure(bank, p[n].pin) ? "" : "non-");
+			error = true;
+		}
+	}
+
+	if (error) {
+		for (n = 0; n < pin_count; n++) {
+			bank = stm32_gpio_get_bank(p[n].bank);
+			release_rif_semaphore_if_acquired(bank, p[n].pin);
+		}
+
+		return TEE_ERROR_SECURITY;
+	}
 
 	for (n = 0; n < pin_count; n++)
 		set_gpio_cfg(p[n].bank, p[n].pin, &p[n].cfg);
@@ -851,29 +1474,6 @@ out:
 	*count = pin_count;
 }
 
-void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure)
-{
-	size_t conf_index = 0;
-
-	if (!pinctrl)
-		return;
-
-	for (conf_index = 0; conf_index < pinctrl->conf_count; conf_index++) {
-		struct pinconf *pinconf = pinctrl->confs[conf_index];
-		struct stm32_pinctrl_array *ref = pinconf->priv;
-		struct stm32_pinctrl *pc = NULL;
-		size_t n = 0;
-
-		for (n = 0; n < ref->count; n++) {
-			if (pinconf->ops != &stm32_pinctrl_ops)
-				continue;
-
-			pc = ref->pinctrl + n;
-			stm32_gpio_set_secure_cfg(pc->bank, pc->pin, secure);
-		}
-	}
-}
-
 /* Allocate and return a pinctrl configuration from a DT reference */
 static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs,
 				       void *data __unused,
@@ -917,7 +1517,9 @@ static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs,
 	fdt_for_each_subnode(pinmux_node, fdt, pinctrl_node) {
 		int found = 0;
 
-		found = get_pinctrl_from_fdt(fdt, pinmux_node, pinctrl + count,
+		found = get_pinctrl_from_fdt(fdt, pinmux_node,
+					     pargs->consumer_node,
+					     pinctrl + count,
 					     pin_count - count);
 		if (found <= 0 && found > ((int)pin_count - count)) {
 			/* We can't recover from an error here so let's panic */
@@ -933,9 +1535,139 @@ static TEE_Result stm32_pinctrl_dt_get(struct dt_pargs *pargs,
 }
 #endif /*CFG_DRIVERS_PINCTRL*/
 
+static void stm32_gpio_get_conf_sec(struct stm32_gpio_bank *bank)
+{
+	if (bank->sec_support) {
+		clk_enable(bank->clock);
+		bank->seccfgr = io_read32(bank->base + GPIO_SECR_OFFSET);
+		clk_disable(bank->clock);
+	}
+}
+
+static void stm32_gpio_set_conf_sec(struct stm32_gpio_bank *bank)
+{
+	if (bank->sec_support) {
+		clk_enable(bank->clock);
+		io_write32(bank->base + GPIO_SECR_OFFSET, bank->seccfgr);
+		clk_disable(bank->clock);
+	}
+}
+
+static TEE_Result stm32_gpio_sec_config_resume(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct stm32_gpio_bank *bank = NULL;
+
+	STAILQ_FOREACH(bank, &bank_list, link) {
+		if (bank->rif_cfg) {
+			if (!bank->is_tdcid)
+				continue;
+
+			bank->rif_cfg->access_mask[0] = GENMASK_32(bank->ngpios,
+								   0);
+
+			res = apply_rif_config(bank,
+					       bank->rif_cfg->access_mask[0]);
+			if (res) {
+				EMSG("Failed to set GPIO bank %c RIF config",
+				     'A' + bank->bank_id);
+				return res;
+			}
+		} else {
+			stm32_gpio_set_conf_sec(bank);
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_gpio_sec_config_suspend(void)
+{
+	struct stm32_gpio_bank *bank = NULL;
+
+	STAILQ_FOREACH(bank, &bank_list, link) {
+		if (bank->rif_cfg) {
+			if (bank->is_tdcid)
+				stm32_gpio_save_rif_config(bank);
+		} else {
+			stm32_gpio_get_conf_sec(bank);
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result
+stm32_gpio_sec_config_pm(enum pm_op op, unsigned int pm_hint,
+			 const struct pm_callback_handle *hdl __unused)
+{
+	TEE_Result ret = TEE_ERROR_GENERIC;
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT))
+		return TEE_SUCCESS;
+
+	if (op == PM_OP_RESUME)
+		ret = stm32_gpio_sec_config_resume();
+	else
+		ret = stm32_gpio_sec_config_suspend();
+
+	return ret;
+}
+DECLARE_KEEP_PAGER(stm32_gpio_sec_config_pm);
+
+/*
+ * Several pinctrl nodes can be probed. Their bank will be put in the unique
+ * bank_list. To avoid multiple configuration set for a bank when looping
+ * over each bank in the bank list, ready is set to true when a bank is
+ * configured. Therefore, during other bank probes, the configuration won't
+ * be set again.
+ */
+static TEE_Result apply_sec_cfg(void)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct stm32_gpio_bank *bank = NULL;
+	unsigned int pin = 0;
+
+	STAILQ_FOREACH(bank, &bank_list, link) {
+		if (bank->ready)
+			continue;
+
+		if (bank->rif_cfg) {
+			res = apply_rif_config(bank,
+					       bank->rif_cfg->access_mask[0]);
+			if (res) {
+				EMSG("Failed to set GPIO bank %c RIF config",
+				     'A' + bank->bank_id);
+				STAILQ_REMOVE(&bank_list, bank, stm32_gpio_bank,
+					      link);
+				free(bank);
+				return res;
+			}
+
+			/*
+			 * Semaphores for pinctrl and GPIO are taken when
+			 * these are used (pinctrl state applied, GPIO
+			 * consumed) or when an explicit firewall configuration
+			 * is requested through the firewall framework.
+			 * Therefore release here the taken semaphores.
+			 */
+			for (pin = 0; pin < bank->ngpios; pin++)
+				release_rif_semaphore_if_acquired(bank, pin);
+
+		} else {
+			stm32_gpio_set_conf_sec(bank);
+		}
+
+		bank->ready = true;
+	}
+
+	return TEE_SUCCESS;
+}
+
 static TEE_Result stm32_pinctrl_probe(const void *fdt, int node,
 				      const void *compat_data)
 {
+	static bool pm_register;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
 	/* Register GPIO banks described in this pin control node */
@@ -943,11 +1675,26 @@ static TEE_Result stm32_pinctrl_probe(const void *fdt, int node,
 	if (res)
 		return res;
 
+	if (STAILQ_EMPTY(&bank_list))
+		DMSG("no gpio bank for that driver");
+	else if (apply_sec_cfg())
+		panic();
+
+	if (!pm_register) {
+		/*
+		 * Register to PM once for all probed banks to restore
+		 * their secure configuration.
+		 */
+		register_pm_driver_cb(stm32_gpio_sec_config_pm, NULL,
+				      "stm32-gpio-secure-config");
+		pm_register = true;
+	}
+
 #ifdef CFG_DRIVERS_PINCTRL
 	res = pinctrl_register_provider(fdt, node, stm32_pinctrl_dt_get,
 					(void *)compat_data);
 	if (res)
-		return res;
+		panic();
 #endif
 
 	return TEE_SUCCESS;
@@ -958,12 +1705,14 @@ static const struct dt_device_match stm32_pinctrl_match_table[] = {
 		.compatible = "st,stm32mp135-pinctrl",
 		.compat_data = &(struct bank_compat){
 			.secure_control = true,
+			.secure_extended = false,
 		},
 	},
 	{
 		.compatible = "st,stm32mp157-pinctrl",
 		.compat_data = &(struct bank_compat){
 			.secure_control = false,
+			.secure_extended = false,
 		},
 	},
 	{
@@ -971,6 +1720,22 @@ static const struct dt_device_match stm32_pinctrl_match_table[] = {
 		.compat_data = &(struct bank_compat){
 			.gpioz = true,
 			.secure_control = true,
+			.secure_extended = false,
+		},
+	},
+	{
+		.compatible = "st,stm32mp257-pinctrl",
+		.compat_data = &(struct bank_compat){
+			.secure_control = true,
+			.secure_extended = true,
+		},
+	},
+	{
+		.compatible = "st,stm32mp257-z-pinctrl",
+		.compat_data = &(struct bank_compat){
+			.gpioz = true,
+			.secure_control = true,
+			.secure_extended = true,
 		},
 	},
 	{ }
diff --git a/core/drivers/stm32_hpdma.c b/core/drivers/stm32_hpdma.c
new file mode 100644
index 0000000000000000000000000000000000000000..a4a77c614332e7c17f0d0bf7bbf03f8e32860040
--- /dev/null
+++ b/core/drivers/stm32_hpdma.c
@@ -0,0 +1,368 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <config.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_gpio.h>
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#define _HPDMA_SECCFGR			U(0x000)
+#define _HPDMA_PRIVCFGR			U(0x004)
+#define _HPDMA_RCFGLOCKR		U(0x008)
+#define _HPDMA_CIDCFGR(x)		(U(0x054) + U(0x080) * (x))
+#define _HPDMA_SEMCR(x)			(U(0x058) + U(0x080) * (x))
+
+/*
+ * CFGR register bitfields
+ */
+#define _HPDMA_CFGR_ENABLE		BIT(31)
+
+/*
+ * CIDCFGR register bitfields
+ */
+#define _HPDMA_CIDCFGR_SEMWL_MASK	GENMASK_32(23, 16)
+#define _HPDMA_CIDCFGR_SCID_MASK	GENMASK_32(5, 4)
+#define _HPDMA_CIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
+					 _CIDCFGR_SEMEN |	 \
+					 _HPDMA_CIDCFGR_SCID_MASK |\
+					 _HPDMA_CIDCFGR_SEMWL_MASK)
+
+/*
+ * PRIVCFGR register bitfields
+ */
+#define _HPDMA_PRIVCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * RCFGLOCKR register bitfields
+ */
+#define _HPDMA_RCFGLOCKR_MASK		GENMASK_32(15, 0)
+
+/*
+ * SECCFGR register bitfields
+ */
+#define _HPDMA_SECCFGR_EN		BIT(0)
+#define _HPDMA_SECCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * SEMCR register bitfields
+ */
+#define _HPDMA_SEMCR_SCID_MASK		GENMASK_32(5, 4)
+#define _HPDMA_SEMCR_SCID_SHIFT		U(4)
+
+/*
+ * Miscellaneous
+ */
+
+#define HPDMA_RIF_CHANNELS		U(16)
+
+#define HPDMA_NB_MAX_CID_SUPPORTED	U(3)
+
+struct hpdma_pdata {
+	struct clk *hpdma_clock;
+	struct rif_conf_data *conf_data;
+	unsigned int nb_channels;
+	vaddr_t base;
+
+	SLIST_ENTRY(hpdma_pdata) link;
+};
+
+static SLIST_HEAD(, hpdma_pdata) hpdma_list =
+		SLIST_HEAD_INITIALIZER(hpdma_list);
+
+static TEE_Result handle_available_semaphores(struct hpdma_pdata *hpdma_d)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint32_t cidcfgr = 0;
+	unsigned int i = 0;
+
+	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
+		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
+			continue;
+
+		cidcfgr = io_read32(hpdma_d->base + _HPDMA_CIDCFGR(i));
+
+		if (!stm32_rif_semaphore_enabled_and_ok(cidcfgr, RIF_CID1))
+			continue;
+
+		if (!(io_read32(hpdma_d->base + _HPDMA_SECCFGR) & BIT(i))) {
+			res =
+			stm32_rif_release_semaphore(hpdma_d->base +
+						    _HPDMA_SEMCR(i),
+						    HPDMA_NB_MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot release semaphore for resource %u",
+				     i);
+				return res;
+			}
+		} else {
+			res =
+			stm32_rif_acquire_semaphore(hpdma_d->base +
+						    _HPDMA_SEMCR(i),
+						    HPDMA_NB_MAX_CID_SUPPORTED);
+			if (res) {
+				EMSG("Cannot acquire semaphore for resource %u",
+				     i);
+				return res;
+			}
+		}
+	}
+
+	return TEE_SUCCESS;
+}
+
+/* This function expects HPDMA bus clock is enabled */
+static TEE_Result apply_rif_config(struct hpdma_pdata *hpdma_d, bool is_tdcid)
+{
+	TEE_Result res = TEE_ERROR_ACCESS_DENIED;
+	unsigned int i = 0;
+
+	if (!hpdma_d->conf_data)
+		return TEE_SUCCESS;
+
+	if (is_tdcid) {
+		for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
+			if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
+				continue;
+			/*
+			 * When TDCID, OP-TEE should be the one to set the CID
+			 * filtering configuration. Clearing previous
+			 * configuration prevents undesired events during the
+			 * only legitimate configuration.
+			 */
+			io_clrbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
+				     _HPDMA_CIDCFGR_CONF_MASK);
+		}
+	} else {
+		res = handle_available_semaphores(hpdma_d);
+		if (res)
+			panic();
+	}
+
+	/* Security and privilege RIF configuration */
+	io_clrsetbits32(hpdma_d->base + _HPDMA_PRIVCFGR, _HPDMA_PRIVCFGR_MASK &
+			hpdma_d->conf_data->access_mask[0],
+			hpdma_d->conf_data->priv_conf[0]);
+	io_clrsetbits32(hpdma_d->base + _HPDMA_SECCFGR, _HPDMA_SECCFGR_MASK &
+			hpdma_d->conf_data->access_mask[0],
+			hpdma_d->conf_data->sec_conf[0]);
+
+	/* Skip CID/semaphore configuration if not in TDCID state. */
+	if (!is_tdcid)
+		goto end;
+
+	for (i = 0; i < HPDMA_RIF_CHANNELS; i++) {
+		if (!(BIT(i) & hpdma_d->conf_data->access_mask[0]))
+			continue;
+
+		io_clrsetbits32(hpdma_d->base + _HPDMA_CIDCFGR(i),
+				_HPDMA_CIDCFGR_CONF_MASK,
+				hpdma_d->conf_data->cid_confs[i]);
+	}
+
+	/*
+	 * Lock RIF configuration if configured. This cannot be undone until
+	 * next reset.
+	 */
+	io_setbits32(hpdma_d->base + _HPDMA_RCFGLOCKR,
+		     hpdma_d->conf_data->lock_conf[0]);
+
+	res = handle_available_semaphores(hpdma_d);
+	if (res)
+		panic();
+
+end:
+	if (IS_ENABLED(CFG_TEE_CORE_DEBUG)) {
+		/* Check that RIF config are applied, panic otherwise */
+		if ((io_read32(hpdma_d->base + _HPDMA_PRIVCFGR) &
+		     hpdma_d->conf_data->access_mask[0]) !=
+		    hpdma_d->conf_data->priv_conf[0])
+			panic("HPDMA channel priv conf is incorrect");
+
+		if ((io_read32(hpdma_d->base + _HPDMA_SECCFGR) &
+		     hpdma_d->conf_data->access_mask[0]) !=
+		    hpdma_d->conf_data->sec_conf[0])
+			panic("HPDMA channel sec conf is incorrect");
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result parse_dt(const void *fdt, int node,
+			   struct hpdma_pdata *hpdma_d)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+	int lenp = 0;
+	const fdt32_t *cuint = NULL;
+	struct dt_node_info info = { };
+	struct io_pa_va addr = { };
+
+	fdt_fill_device_info(fdt, &info, node);
+	assert(info.reg != DT_INFO_INVALID_REG &&
+	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
+
+	addr.pa = info.reg;
+	hpdma_d->base = io_pa_or_va_secure(&addr, info.reg_size);
+
+	/* Gate the IP */
+	res = clk_dt_get_by_index(fdt, node, 0, &hpdma_d->hpdma_clock);
+	if (res)
+		return res;
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (!cuint) {
+		DMSG("No RIF configuration available");
+		return TEE_SUCCESS;
+	}
+
+	hpdma_d->conf_data = calloc(1, sizeof(*hpdma_d->conf_data));
+	if (!hpdma_d->conf_data)
+		panic();
+
+	hpdma_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(hpdma_d->nb_channels <= HPDMA_RIF_CHANNELS);
+
+	hpdma_d->conf_data->cid_confs = calloc(HPDMA_RIF_CHANNELS,
+					       sizeof(uint32_t));
+	hpdma_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
+	hpdma_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
+	hpdma_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
+	hpdma_d->conf_data->lock_conf = calloc(1, sizeof(uint32_t));
+	if (!hpdma_d->conf_data->cid_confs || !hpdma_d->conf_data->sec_conf ||
+	    !hpdma_d->conf_data->priv_conf ||
+	    !hpdma_d->conf_data->access_mask || !hpdma_d->conf_data->lock_conf)
+		panic("Missing memory capacity for HPDMA RIF configuration");
+
+	for (i = 0; i < hpdma_d->nb_channels; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), hpdma_d->conf_data,
+				    HPDMA_RIF_CHANNELS);
+
+	return TEE_SUCCESS;
+}
+
+static void stm32_hpdma_pm_resume(struct hpdma_pdata *hpdma)
+{
+	if (apply_rif_config(hpdma, true))
+		panic("Failed to resume HPDMA");
+}
+
+static void stm32_hpdma_pm_suspend(struct hpdma_pdata *hpdma)
+{
+	size_t i = 0;
+
+	for (i = 0; i < HPDMA_RIF_CHANNELS; i++)
+		hpdma->conf_data->cid_confs[i] = io_read32(hpdma->base +
+							  _HPDMA_CIDCFGR(i)) &
+						_HPDMA_CIDCFGR_CONF_MASK;
+
+	hpdma->conf_data->priv_conf[0] = io_read32(hpdma->base +
+						  _HPDMA_PRIVCFGR) &
+					_HPDMA_PRIVCFGR_MASK;
+	hpdma->conf_data->sec_conf[0] = io_read32(hpdma->base +
+						 _HPDMA_SECCFGR) &
+				       _HPDMA_SECCFGR_MASK;
+	hpdma->conf_data->lock_conf[0] = io_read32(hpdma->base +
+						  _HPDMA_RCFGLOCKR) &
+					_HPDMA_RCFGLOCKR_MASK;
+
+	/*
+	 * The access mask is modified to restore the conf for all
+	 * resources.
+	 */
+	hpdma->conf_data->access_mask[0] = GENMASK_32(HPDMA_RIF_CHANNELS - 1,
+						      0);
+}
+
+static TEE_Result
+stm32_hpdma_pm(enum pm_op op, unsigned int pm_hint,
+	       const struct pm_callback_handle *pm_handle)
+{
+	struct hpdma_pdata *hpdma = pm_handle->handle;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool is_tdcid = false;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		panic();
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !is_tdcid)
+		return TEE_SUCCESS;
+
+	res = clk_enable(hpdma->hpdma_clock);
+	if (res)
+		return res;
+
+	if (op == PM_OP_RESUME)
+		stm32_hpdma_pm_resume(hpdma);
+	else
+		stm32_hpdma_pm_suspend(hpdma);
+
+	clk_disable(hpdma->hpdma_clock);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_hpdma_probe(const void *fdt, int node,
+				    const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct hpdma_pdata *hpdma_d = NULL;
+	bool is_tdcid = false;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	hpdma_d = calloc(1, sizeof(*hpdma_d));
+	if (!hpdma_d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = parse_dt(fdt, node, hpdma_d);
+	if (res) {
+		free(hpdma_d);
+		return res;
+	}
+
+	if (clk_enable(hpdma_d->hpdma_clock))
+		panic("Cannot access hpdma clock");
+
+	res = apply_rif_config(hpdma_d, is_tdcid);
+	if (res)
+		panic("Failed to apply RIF config");
+
+	clk_disable(hpdma_d->hpdma_clock);
+
+	SLIST_INSERT_HEAD(&hpdma_list, hpdma_d, link);
+
+	register_pm_core_service_cb(stm32_hpdma_pm, hpdma_d, "stm32-hpdma");
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match stm32_hpdma_match_table[] = {
+	{ .compatible = "st,stm32-dma3" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_hpdma_dt_driver) = {
+	.name = "st,stm32-hpdma",
+	.match_table = stm32_hpdma_match_table,
+	.probe = stm32_hpdma_probe,
+};
diff --git a/core/drivers/stm32_hsem.c b/core/drivers/stm32_hsem.c
new file mode 100644
index 0000000000000000000000000000000000000000..115c05aebb1a90106b1968ac19e44a5c26072dd3
--- /dev/null
+++ b/core/drivers/stm32_hsem.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <config.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#define HSEM_SECCFGR			U(0x200)
+#define HSEM_PRIVCFGR			U(0x210)
+#define HSEM_CnCIDCFGR(x)		(U(0x220) + U(0x004) * ((x) - 1))
+#define HSEM_GpCIDCFGR(x)		(U(0x240) + U(0x004) * (x))
+
+/*
+ * CnCIDCFGR register bitfields
+ */
+#define HSEM_CnCIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
+					 HSEM_CnCIDCFGR_SCID_MASK)
+#define HSEM_CnCIDCFGR_SCID_MASK	GENMASK_32(6, 4)
+
+/*
+ * GpCIDCFGR register bitfields
+ */
+#define HSEM_GpCIDCFGR_SEM_WLIST_C_MASK	GENMASK_32(18, 16)
+#define HSEM_GpCIDCFGR_SEM_WLIST_SHIFT	U(16)
+#define HSEM_GpCIDCFGR_CONF_MASK	(_CIDCFGR_CFEN |	 \
+					 HSEM_GpCIDCFGR_SEM_WLIST_C_MASK)
+
+/*
+ * PRIVCFGR register bitfields
+ */
+#define HSEM_PRIVCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * SECCFGR register bitfields
+ */
+#define HSEM_SECCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * Miscellaneous
+ */
+#define HSEM_NB_PROC			U(3)
+#define HSEM_NB_SEM_GROUPS		U(4)
+#define HSEM_NB_SEM_PER_GROUP		U(4)
+
+#define HSEM_RIF_RESOURCES		U(16)
+
+struct hsem_pdata {
+	struct clk *hsem_clock;
+	struct rif_conf_data conf_data;
+	unsigned int nb_channels;
+	vaddr_t base;
+	uint32_t *rif_proc_conf;
+};
+
+static struct hsem_pdata *hsem_d;
+
+static void apply_rif_config(bool is_tdcid)
+{
+	unsigned int i = 0;
+	unsigned int j = 0;
+
+	/*
+	 * When TDCID, OP-TEE should be the one to set the CID filtering
+	 * configuration. Clearing previous configuration prevents
+	 * undesired events during the only legitimate configuration.
+	 */
+	if (is_tdcid) {
+		for (i = 0; i < HSEM_NB_PROC; i++)
+			io_clrbits32(hsem_d->base + HSEM_CnCIDCFGR(i + 1),
+				     HSEM_CnCIDCFGR_CONF_MASK);
+
+		/* Clean HSEM groups configuration registers */
+		for (i = 0; i < HSEM_NB_SEM_GROUPS; i++)
+			io_clrbits32(hsem_d->base + HSEM_GpCIDCFGR(i),
+				     HSEM_GpCIDCFGR_CONF_MASK);
+	}
+
+	/* Security and privilege RIF configuration */
+	io_clrsetbits32(hsem_d->base + HSEM_SECCFGR,
+			HSEM_SECCFGR_MASK & hsem_d->conf_data.access_mask[0],
+			hsem_d->conf_data.sec_conf[0]);
+	io_clrsetbits32(hsem_d->base + HSEM_PRIVCFGR,
+			HSEM_PRIVCFGR_MASK & hsem_d->conf_data.access_mask[0],
+			hsem_d->conf_data.priv_conf[0]);
+
+	if (!is_tdcid)
+		return;
+
+	/* Configure HSEM processors configuration registers */
+	for (i = 0; i < HSEM_NB_PROC; i++) {
+		/*
+		 * If a processor CID configuration is present, enable it.
+		 * Else, nothing to do.
+		 */
+		if (!hsem_d->rif_proc_conf[i])
+			continue;
+
+		io_clrsetbits32(hsem_d->base + HSEM_CnCIDCFGR(i + 1),
+				HSEM_CnCIDCFGR_CONF_MASK,
+				_CIDCFGR_CFEN | hsem_d->rif_proc_conf[i]);
+	}
+
+	/*
+	 * Configure HSEM groups configuration registers
+	 * If one semaphore is configured, all semaphores of its group
+	 * must be configured too and MUST have the same RIF
+	 * configuration.
+	 */
+	for (i = 0; i < HSEM_NB_SEM_GROUPS; i++) {
+		unsigned int grp_idx = i * HSEM_NB_SEM_PER_GROUP;
+		uint32_t group_cid_value = hsem_d->conf_data.cid_confs[grp_idx];
+		unsigned int sem_wlist_c = 0;
+		bool cid_found = false;
+
+		/*
+		 * HSEM resources in the same group must have the same CID
+		 * filtering configuration. Else it is inconsistent.
+		 */
+		for (j = 0; j < HSEM_NB_SEM_PER_GROUP; j++)
+			if (hsem_d->conf_data.cid_confs[j + grp_idx] !=
+			    group_cid_value)
+				panic("Inconsistent HSEM RIF group config");
+
+		/* If CID filtering is disabled, do nothing */
+		if (!(group_cid_value & _CIDCFGR_CFEN))
+			continue;
+
+		/*
+		 * Check if configured CIDs correspond to a processor's
+		 * CID in HSEM_CnCIDCFGR registers.
+		 */
+		for (j = 0; j < HSEM_NB_PROC; j++) {
+			uint32_t proc_cid = hsem_d->rif_proc_conf[j] >>
+					    _CIDCFGR_SCID_SHIFT;
+
+			assert(proc_cid <= MAX_CID_SUPPORTED);
+			if (BIT(proc_cid + _CIDCFGR_SEMWL_SHIFT) &
+			    group_cid_value) {
+				sem_wlist_c |=
+					BIT(j + HSEM_GpCIDCFGR_SEM_WLIST_SHIFT);
+				cid_found = true;
+			}
+		}
+		if (!cid_found)
+			panic("Unknown HSEM processor CID");
+
+		io_clrsetbits32(hsem_d->base + HSEM_GpCIDCFGR(i),
+				HSEM_GpCIDCFGR_CONF_MASK,
+				_CIDCFGR_CFEN | sem_wlist_c);
+	}
+}
+
+static TEE_Result parse_dt(const void *fdt, int node)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	unsigned int i = 0;
+	int lenp = 0;
+	const fdt32_t *cuint = NULL;
+	struct dt_node_info info = { };
+	struct io_pa_va addr = { };
+
+	fdt_fill_device_info(fdt, &info, node);
+	assert(info.reg != DT_INFO_INVALID_REG &&
+	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
+
+	addr.pa = info.reg;
+	hsem_d->base = io_pa_or_va_secure(&addr, info.reg_size);
+
+	/* Gate the IP */
+	res = clk_dt_get_by_index(fdt, node, 0, &hsem_d->hsem_clock);
+	if (res)
+		return res;
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (!cuint)
+		panic("No RIF configuration available");
+
+	hsem_d->nb_channels = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(hsem_d->nb_channels <= HSEM_RIF_RESOURCES);
+
+	hsem_d->rif_proc_conf = calloc(HSEM_NB_PROC, sizeof(uint32_t));
+	assert(hsem_d->rif_proc_conf);
+	hsem_d->conf_data.cid_confs = calloc(HSEM_RIF_RESOURCES,
+					     sizeof(uint32_t));
+	hsem_d->conf_data.sec_conf = calloc(1, sizeof(uint32_t));
+	hsem_d->conf_data.priv_conf = calloc(1, sizeof(uint32_t));
+	hsem_d->conf_data.access_mask = calloc(1, sizeof(uint32_t));
+	assert(hsem_d->conf_data.cid_confs && hsem_d->conf_data.sec_conf &&
+	       hsem_d->conf_data.priv_conf && hsem_d->conf_data.access_mask);
+
+	for (i = 0; i < hsem_d->nb_channels; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), &hsem_d->conf_data,
+				    HSEM_RIF_RESOURCES);
+
+	cuint = fdt_getprop(fdt, node, "st,proccid", &lenp);
+	if (!cuint)
+		panic("No RIF proc configuration available");
+
+	lenp = (unsigned int)(lenp / sizeof(uint32_t));
+	/*
+	 * There should be maximum (HSEM_NB_PROC * 2) property argument.
+	 * First argument for a processor is its number, the second is its CID.
+	 */
+	assert((unsigned int)lenp <= (HSEM_NB_PROC * 2));
+
+	for (i = 0; i < (unsigned int)lenp / 2; i++) {
+		unsigned int pos = fdt32_to_cpu(cuint[i * 2]) - 1;
+		unsigned int cid_value = fdt32_to_cpu(cuint[(i * 2) + 1]);
+
+		hsem_d->rif_proc_conf[pos] = SHIFT_U32(cid_value,
+						       _CIDCFGR_SCID_SHIFT);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_hsem_probe(const void *fdt, int node,
+				   const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	bool is_tdcid = false;
+
+	res = stm32_rifsc_check_tdcid(&is_tdcid);
+	if (res)
+		return res;
+
+	hsem_d = calloc(1, sizeof(*hsem_d));
+	if (!hsem_d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = parse_dt(fdt, node);
+	if (res) {
+		free(hsem_d);
+		return res;
+	}
+
+	res = clk_enable(hsem_d->hsem_clock);
+	if (res)
+		panic("Cannot access HSEM clock");
+
+	apply_rif_config(is_tdcid);
+
+	clk_disable(hsem_d->hsem_clock);
+
+	return TEE_SUCCESS;
+}
+
+static const struct dt_device_match stm32_hsem_match_table[] = {
+	{ .compatible = "st,stm32mp25-hsem" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_hsem_dt_driver) = {
+	.name = "st,stm32-hsem",
+	.match_table = stm32_hsem_match_table,
+	.probe = stm32_hsem_probe,
+};
diff --git a/core/drivers/stm32_i2c.c b/core/drivers/stm32_i2c.c
index 563dfc94664833b7be36e9e6924f44adc778d0c8..e3ca041e14bbe041581ee6d786d46c9cc5ac3288 100644
--- a/core/drivers/stm32_i2c.c
+++ b/core/drivers/stm32_i2c.c
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 /*
- * Copyright (c) 2017-2019, STMicroelectronics
+ * Copyright (c) 2017-2024, STMicroelectronics
  *
  * The driver API is defined in header file stm32_i2c.h.
  *
@@ -16,10 +16,11 @@
 #include <drivers/stm32_gpio.h>
 #include <drivers/stm32_i2c.h>
 #include <io.h>
+#include <kernel/boot.h>
 #include <kernel/delay.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
-#include <kernel/boot.h>
+#include <kernel/mutex_pm_aware.h>
 #include <kernel/panic.h>
 #include <libfdt.h>
 #include <stdbool.h>
@@ -657,18 +658,12 @@ static int i2c_setup_timing(struct i2c_handle_s *hi2c,
  * Configure I2C Analog noise filter.
  * @hi2c: I2C handle structure
  * @analog_filter_on: True if enabling analog filter, false otherwise
- * Return 0 on success or a negative value
  */
-static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
-				    bool analog_filter_on)
+static void i2c_config_analog_filter(struct i2c_handle_s *hi2c,
+				     bool analog_filter_on)
 {
 	vaddr_t base = get_base(hi2c);
 
-	if (hi2c->i2c_state != I2C_STATE_READY)
-		return -1;
-
-	hi2c->i2c_state = I2C_STATE_BUSY;
-
 	/* Disable the selected I2C peripheral */
 	io_clrbits32(base + I2C_CR1, I2C_CR1_PE);
 
@@ -681,10 +676,6 @@ static int i2c_config_analog_filter(struct i2c_handle_s *hi2c,
 
 	/* Enable the selected I2C peripheral */
 	io_setbits32(base + I2C_CR1, I2C_CR1_PE);
-
-	hi2c->i2c_state = I2C_STATE_READY;
-
-	return 0;
 }
 
 TEE_Result stm32_i2c_get_setup_from_fdt(void *fdt, int node,
@@ -763,6 +754,8 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c,
 	vaddr_t base = 0;
 	uint32_t val = 0;
 
+	mutex_pm_aware_init(&hi2c->mu);
+
 	rc = i2c_setup_timing(hi2c, init_data, &timing);
 	if (rc)
 		return rc;
@@ -824,16 +817,14 @@ int stm32_i2c_init(struct i2c_handle_s *hi2c,
 	hi2c->i2c_err = I2C_ERROR_NONE;
 	hi2c->i2c_state = I2C_STATE_READY;
 
-	rc = i2c_config_analog_filter(hi2c, init_data->analog_filter);
-	if (rc)
-		DMSG("I2C analog filter error %d", rc);
-
-	if (IS_ENABLED(CFG_STM32MP13))
-		stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true);
+	i2c_config_analog_filter(hi2c, init_data->analog_filter);
 
 	clk_disable(hi2c->clock);
 
-	return rc;
+	if (hi2c->pinctrl && pinctrl_apply_state(hi2c->pinctrl))
+		return -1;
+
+	return 0;
 }
 
 /* I2C transmit (TX) data register flush sequence */
@@ -1080,11 +1071,15 @@ static int do_write(struct i2c_handle_s *hi2c, struct i2c_request *request,
 	if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM)
 		return -1;
 
-	if (hi2c->i2c_state != I2C_STATE_READY)
+	if (!p_data || !size)
 		return -1;
 
-	if (!p_data || !size)
+	mutex_pm_aware_lock(&hi2c->mu);
+
+	if (hi2c->i2c_state != I2C_STATE_READY) {
+		mutex_pm_aware_unlock(&hi2c->mu);
 		return -1;
+	}
 
 	clk_enable(hi2c->clock);
 
@@ -1174,6 +1169,7 @@ static int do_write(struct i2c_handle_s *hi2c, struct i2c_request *request,
 
 bail:
 	clk_disable(hi2c->clock);
+	mutex_pm_aware_unlock(&hi2c->mu);
 
 	return rc;
 }
@@ -1216,8 +1212,12 @@ int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr,
 	uint8_t *p_buff = p_data;
 	uint32_t event_mask = 0;
 
-	if (hi2c->i2c_state != I2C_STATE_READY || !p_data)
+	mutex_pm_aware_lock(&hi2c->mu);
+
+	if (hi2c->i2c_state != I2C_STATE_READY || !p_data) {
+		mutex_pm_aware_unlock(&hi2c->mu);
 		return -1;
+	}
 
 	clk_enable(hi2c->clock);
 
@@ -1277,6 +1277,7 @@ int stm32_i2c_read_write_membyte(struct i2c_handle_s *hi2c, uint16_t dev_addr,
 
 bail:
 	clk_disable(hi2c->clock);
+	mutex_pm_aware_unlock(&hi2c->mu);
 
 	return rc;
 }
@@ -1303,11 +1304,15 @@ static int do_read(struct i2c_handle_s *hi2c, struct i2c_request *request,
 	if (request->mode != I2C_MODE_MASTER && request->mode != I2C_MODE_MEM)
 		return -1;
 
-	if (hi2c->i2c_state != I2C_STATE_READY)
+	if (!p_data || !size)
 		return -1;
 
-	if (!p_data || !size)
+	mutex_pm_aware_lock(&hi2c->mu);
+
+	if (hi2c->i2c_state != I2C_STATE_READY) {
+		mutex_pm_aware_unlock(&hi2c->mu);
 		return -1;
+	}
 
 	clk_enable(hi2c->clock);
 
@@ -1392,6 +1397,7 @@ static int do_read(struct i2c_handle_s *hi2c, struct i2c_request *request,
 
 bail:
 	clk_disable(hi2c->clock);
+	mutex_pm_aware_unlock(&hi2c->mu);
 
 	return rc;
 }
@@ -1473,8 +1479,12 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr,
 	unsigned int i2c_trials = 0U;
 	bool rc = false;
 
-	if (hi2c->i2c_state != I2C_STATE_READY)
+	mutex_pm_aware_lock(&hi2c->mu);
+
+	if (hi2c->i2c_state != I2C_STATE_READY) {
+		mutex_pm_aware_unlock(&hi2c->mu);
 		return rc;
+	}
 
 	clk_enable(hi2c->clock);
 
@@ -1549,6 +1559,7 @@ bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint32_t dev_addr,
 
 bail:
 	clk_disable(hi2c->clock);
+	mutex_pm_aware_unlock(&hi2c->mu);
 
 	return rc;
 }
@@ -1572,9 +1583,6 @@ void stm32_i2c_resume(struct i2c_handle_s *hi2c)
 
 	restore_cfg(hi2c, &hi2c->sec_cfg);
 
-	if (IS_ENABLED(CFG_STM32MP13))
-		stm32_pinctrl_set_secure_cfg(hi2c->pinctrl, true);
-
 	hi2c->i2c_state = I2C_STATE_READY;
 }
 
@@ -1600,7 +1608,7 @@ static TEE_Result stm32_get_i2c_dev(struct dt_pargs *args, void *data,
 	struct stm32_i2c_dev *stm32_i2c_dev = NULL;
 	paddr_t addr = 0;
 
-	addr = fdt_reg_base_address(args->fdt, args->phandle_node);
+	addr = fdt_reg_base_address(args->fdt, args->consumer_node);
 	if (addr == DT_INFO_INVALID_REG) {
 		DMSG("Can't get device I2C address");
 		return TEE_ERROR_GENERIC;
@@ -1654,8 +1662,7 @@ static TEE_Result stm32_i2c_probe(const void *fdt, int node,
 	init_data.analog_filter = true;
 	init_data.digital_filter_coef = 0;
 
-	res = stm32_i2c_init(i2c_handle_p, &init_data);
-	if (res)
+	if (stm32_i2c_init(i2c_handle_p, &init_data))
 		panic("Couldn't initialise I2C");
 
 	res = i2c_register_provider(fdt, node, stm32_get_i2c_dev, i2c_handle_p);
diff --git a/core/drivers/stm32_ipcc.c b/core/drivers/stm32_ipcc.c
new file mode 100644
index 0000000000000000000000000000000000000000..61ba0ea3754997415687186187d9a1d6d6158755
--- /dev/null
+++ b/core/drivers/stm32_ipcc.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#include <arm.h>
+#include <config.h>
+#include <drivers/clk.h>
+#include <drivers/clk_dt.h>
+#include <drivers/stm32_rif.h>
+#include <io.h>
+#include <kernel/boot.h>
+#include <kernel/delay.h>
+#include <kernel/dt.h>
+#include <kernel/dt_driver.h>
+#include <kernel/panic.h>
+#include <kernel/pm.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stm32_util.h>
+#include <trace.h>
+
+#define IPCC_C1SECCFGR			U(0x80)
+#define IPCC_C1PRIVCFGR			U(0x84)
+#define IPCC_C1CIDCFGR			U(0x88)
+#define IPCC_C2SECCFGR			U(0x90)
+#define IPCC_C2PRIVCFGR			U(0x94)
+#define IPCC_C2CIDCFGR			U(0x98)
+#define IPCC_HWCFGR			U(0x3F0)
+
+/*
+ * CIDCFGR register bitfields
+ */
+#define IPCC_CIDCFGR_CFEN		BIT(0)
+#define IPCC_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
+#define IPCC_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
+					 IPCC_CIDCFGR_SCID_MASK)
+
+/*
+ * PRIVCFGR register bitfields
+ */
+#define IPCC_PRIVCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * SECCFGR register bitfields
+ */
+#define IPCC_SECCFGR_MASK		GENMASK_32(15, 0)
+
+/*
+ * IPCC_HWCFGR register bitfields
+ */
+#define IPCC_HWCFGR_CHAN_MASK		GENMASK_32(7, 0)
+
+/*
+ * Miscellaneous
+ */
+#define IPCC_NB_MAX_RIF_CHAN		U(16)
+
+struct ipcc_pdata {
+	/*
+	 * An IPCC has nb_channels_cfg channel configuration for its
+	 * (nb_channels_cfg / 2) bi-directionnal channels
+	 */
+	unsigned int nb_channels_cfg;
+	struct clk *ipcc_clock;
+	vaddr_t base;
+	struct rif_conf_data *conf_data;
+	bool is_tdcid;
+
+	STAILQ_ENTRY(ipcc_pdata) link;
+};
+
+static STAILQ_HEAD(, ipcc_pdata) ipcc_list =
+		STAILQ_HEAD_INITIALIZER(ipcc_list);
+
+/* This function expects IPCC bus clock is enabled */
+static void apply_rif_config(struct ipcc_pdata *ipcc_d)
+{
+	bool proc1_cidfilt = false;
+	bool proc2_cidfilt = false;
+	uint32_t priv_proc_1 = 0;
+	uint32_t priv_proc_2 = 0;
+	uint32_t sec_proc_1 = 0;
+	uint32_t sec_proc_2 = 0;
+	unsigned int cid1 = 0;
+	unsigned int cid2 = 0;
+	unsigned int i = 0;
+	bool is_cid_configured = false;
+
+	if (!ipcc_d->conf_data)
+		return;
+
+	/*
+	 * Check that the number of channel supported by hardware
+	 * is coherent with the config
+	 */
+	assert((io_read32(ipcc_d->base + IPCC_HWCFGR) &
+			  IPCC_HWCFGR_CHAN_MASK) >=
+	       ipcc_d->nb_channels_cfg / 2);
+
+	/*
+	 * When TDCID, OP-TEE should be the one to set the CID filtering
+	 * configuration. Clearing previous configuration prevents
+	 * undesired events during the only legitimate configuration.
+	 */
+	if (ipcc_d->is_tdcid) {
+		/* IPCC Processor 1 */
+		io_clrbits32(ipcc_d->base + IPCC_C1CIDCFGR,
+			     IPCC_CIDCFGR_CONF_MASK);
+
+		/* IPCC Processor 2 */
+		io_clrbits32(ipcc_d->base + IPCC_C2CIDCFGR,
+			     IPCC_CIDCFGR_CONF_MASK);
+	}
+
+	cid1 = io_read32(ipcc_d->base + IPCC_C1CIDCFGR) &
+	       IPCC_CIDCFGR_SCID_MASK;
+	cid2 = io_read32(ipcc_d->base + IPCC_C2CIDCFGR) &
+	       IPCC_CIDCFGR_SCID_MASK;
+
+	proc1_cidfilt = io_read32(ipcc_d->base + IPCC_C1CIDCFGR) &
+		       IPCC_CIDCFGR_CFEN;
+	proc2_cidfilt = io_read32(ipcc_d->base + IPCC_C2CIDCFGR) &
+		       IPCC_CIDCFGR_CFEN;
+
+	/* Split the sec and priv configuration for IPCC processor 1 and 2 */
+	sec_proc_1 = ipcc_d->conf_data->sec_conf[0] &
+		     GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0);
+	priv_proc_1 = ipcc_d->conf_data->priv_conf[0] &
+		      GENMASK_32(IPCC_NB_MAX_RIF_CHAN - 1, 0);
+
+	sec_proc_2 = (ipcc_d->conf_data->sec_conf[0] &
+		      GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1,
+				 IPCC_NB_MAX_RIF_CHAN)) >>
+		     IPCC_NB_MAX_RIF_CHAN;
+	priv_proc_2 = (ipcc_d->conf_data->priv_conf[0] &
+		       GENMASK_32((IPCC_NB_MAX_RIF_CHAN * 2) - 1,
+				  IPCC_NB_MAX_RIF_CHAN)) >>
+		      IPCC_NB_MAX_RIF_CHAN;
+
+	/* Security and privilege RIF configuration */
+	if (!proc1_cidfilt || cid1 == RIF_CID1) {
+		io_clrsetbits32(ipcc_d->base + IPCC_C1PRIVCFGR,
+				IPCC_PRIVCFGR_MASK, priv_proc_1);
+		io_clrsetbits32(ipcc_d->base + IPCC_C1SECCFGR,
+				IPCC_SECCFGR_MASK, sec_proc_1);
+	}
+	if (!proc2_cidfilt || cid2 == RIF_CID1) {
+		io_clrsetbits32(ipcc_d->base + IPCC_C2PRIVCFGR,
+				IPCC_PRIVCFGR_MASK, priv_proc_2);
+		io_clrsetbits32(ipcc_d->base + IPCC_C2SECCFGR,
+				IPCC_SECCFGR_MASK, sec_proc_2);
+	}
+
+	/*
+	 * Evaluate RIF CID filtering configuration before setting it.
+	 * Parsed configuration must have consistency. If CID filtering
+	 * is enabled for an IPCC channel, then it must be the case for all
+	 * channels of this processor. This is a configuration check.
+	 */
+	for (i = 0; i < IPCC_NB_MAX_RIF_CHAN; i++) {
+		if (!(BIT(i) & ipcc_d->conf_data->access_mask[0]))
+			continue;
+
+		if (!is_cid_configured &&
+		    (BIT(0) & ipcc_d->conf_data->cid_confs[i])) {
+			is_cid_configured = true;
+			if (i > 0)
+				panic("Inconsistent IPCC CID filtering RIF configuration");
+		}
+
+		if (is_cid_configured &&
+		    !(BIT(0) & ipcc_d->conf_data->cid_confs[i]))
+			panic("Inconsistent IPCC CID filtering RIF configuration");
+	}
+
+	/* IPCC processor 1 CID filtering configuration */
+	if (!ipcc_d->is_tdcid)
+		return;
+
+	io_clrsetbits32(ipcc_d->base + IPCC_C1CIDCFGR,
+			IPCC_CIDCFGR_CONF_MASK,
+			ipcc_d->conf_data->cid_confs[0]);
+
+	/*
+	 * Reset this field to evaluate CID filtering configuration
+	 * for processor 2
+	 */
+	is_cid_configured = false;
+
+	for (i = IPCC_NB_MAX_RIF_CHAN; i < IPCC_NB_MAX_RIF_CHAN * 2; i++) {
+		if (!(BIT(i) & ipcc_d->conf_data->access_mask[0]))
+			continue;
+
+		if (!is_cid_configured &&
+		    (BIT(0) & ipcc_d->conf_data->cid_confs[i])) {
+			is_cid_configured = true;
+			if (i > IPCC_NB_MAX_RIF_CHAN)
+				panic("Inconsistent IPCC CID filtering RIF configuration");
+		}
+
+		if (is_cid_configured &&
+		    !(BIT(0) & ipcc_d->conf_data->cid_confs[i]))
+			panic("Inconsistent IPCC CID filtering RIF configuration");
+	}
+
+	/* IPCC Processor 2 CID filtering configuration */
+	io_clrsetbits32(ipcc_d->base + IPCC_C2CIDCFGR,
+			IPCC_CIDCFGR_CONF_MASK,
+			ipcc_d->conf_data->cid_confs[IPCC_NB_MAX_RIF_CHAN]);
+}
+
+static void stm32_ipcc_pm_resume(struct ipcc_pdata *ipcc)
+{
+	apply_rif_config(ipcc);
+}
+
+static void stm32_ipcc_pm_suspend(struct ipcc_pdata *ipcc __unused)
+{
+	/*
+	 * Do nothing because IPCC forbids RIF configuration read if CID
+	 * filtering is enabled. We'll simply restore the device tree RIF
+	 * configuration.
+	 */
+}
+
+static TEE_Result
+stm32_ipcc_pm(enum pm_op op, unsigned int pm_hint,
+	      const struct pm_callback_handle *pm_handle)
+{
+	struct ipcc_pdata *ipcc = pm_handle->handle;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (!PM_HINT_IS_STATE(pm_hint, CONTEXT) || !ipcc->is_tdcid)
+		return TEE_SUCCESS;
+
+	res = clk_enable(ipcc->ipcc_clock);
+	if (res)
+		return res;
+
+	if (op == PM_OP_RESUME)
+		stm32_ipcc_pm_resume(ipcc);
+	else
+		stm32_ipcc_pm_suspend(ipcc);
+
+	clk_disable(ipcc->ipcc_clock);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result parse_dt(const void *fdt, int node, struct ipcc_pdata *ipcc_d)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct dt_node_info info = { };
+	const fdt32_t *cuint = NULL;
+	struct io_pa_va addr = { };
+	unsigned int i = 0;
+	int lenp = 0;
+
+	fdt_fill_device_info(fdt, &info, node);
+	assert(info.reg != DT_INFO_INVALID_REG &&
+	       info.reg_size != DT_INFO_INVALID_REG_SIZE);
+
+	addr.pa = info.reg;
+	ipcc_d->base = io_pa_or_va_secure(&addr, info.reg_size);
+	assert(ipcc_d->base);
+
+	/* Gate the IP */
+	res = clk_dt_get_by_index(fdt, node, 0, &ipcc_d->ipcc_clock);
+	if (res)
+		return res;
+
+	cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+	if (!cuint) {
+		DMSG("No RIF configuration available");
+		return TEE_SUCCESS;
+	}
+
+	ipcc_d->conf_data = calloc(1, sizeof(*ipcc_d->conf_data));
+	if (!ipcc_d->conf_data)
+		panic();
+
+	ipcc_d->nb_channels_cfg = (unsigned int)(lenp / sizeof(uint32_t));
+	assert(ipcc_d->nb_channels_cfg <= (IPCC_NB_MAX_RIF_CHAN * 2));
+
+	ipcc_d->conf_data->cid_confs = calloc(IPCC_NB_MAX_RIF_CHAN * 2,
+					      sizeof(uint32_t));
+	ipcc_d->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
+	ipcc_d->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
+	ipcc_d->conf_data->access_mask = calloc(1, sizeof(uint32_t));
+	if (!ipcc_d->conf_data->cid_confs || !ipcc_d->conf_data->sec_conf ||
+	    !ipcc_d->conf_data->priv_conf || !ipcc_d->conf_data->access_mask)
+		panic("Missing memory capacity for ipcc RIF configuration");
+
+	for (i = 0; i < ipcc_d->nb_channels_cfg; i++)
+		stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]), ipcc_d->conf_data,
+				    IPCC_NB_MAX_RIF_CHAN * 2);
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_ipcc_probe(const void *fdt, int node,
+				   const void *compat_data __unused)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	struct ipcc_pdata *ipcc_d = NULL;
+
+	ipcc_d = calloc(1, sizeof(*ipcc_d));
+	if (!ipcc_d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	res = stm32_rifsc_check_tdcid(&ipcc_d->is_tdcid);
+	if (res)
+		goto err;
+
+	res = parse_dt(fdt, node, ipcc_d);
+	if (res)
+		goto err;
+
+	res = clk_enable(ipcc_d->ipcc_clock);
+	if (res)
+		panic("Cannot access IPCC clock");
+
+	apply_rif_config(ipcc_d);
+
+	clk_disable(ipcc_d->ipcc_clock);
+
+	STAILQ_INSERT_TAIL(&ipcc_list, ipcc_d, link);
+
+	register_pm_core_service_cb(stm32_ipcc_pm, ipcc_d, "stm32-ipcc");
+
+	return TEE_SUCCESS;
+
+err:
+	/* Free all allocated resources */
+	if (ipcc_d->conf_data) {
+		free(ipcc_d->conf_data->access_mask);
+		free(ipcc_d->conf_data->cid_confs);
+		free(ipcc_d->conf_data->priv_conf);
+		free(ipcc_d->conf_data->sec_conf);
+	}
+	free(ipcc_d->conf_data);
+	free(ipcc_d);
+
+	return res;
+}
+
+static const struct dt_device_match stm32_ipcc_match_table[] = {
+	{ .compatible = "st,stm32mp25-ipcc" },
+	{ }
+};
+
+DEFINE_DT_DRIVER(stm32_ipcc_dt_driver) = {
+	.name = "st,stm32mp-ipcc",
+	.match_table = stm32_ipcc_match_table,
+	.probe = stm32_ipcc_probe,
+};
diff --git a/core/drivers/stm32_iwdg.c b/core/drivers/stm32_iwdg.c
index c7b7ae86bc43433e5f1b92a556cee88e117b2cc9..4f91ce0812dbb2c35f4ccb7143e5292ed9ee533d 100644
--- a/core/drivers/stm32_iwdg.c
+++ b/core/drivers/stm32_iwdg.c
@@ -61,14 +61,12 @@
  * IWDG_FLAGS_HW_ENABLED                Watchdog is enabled by BootROM
  * IWDG_FLAGS_DISABLE_ON_STOP           Watchdog is freezed in SoC STOP mode
  * IWDG_FLAGS_DISABLE_ON_STANDBY        Watchdog is freezed in SoC STANDBY mode
- * IWDG_FLAGS_NON_SECURE                Instance is assigned to non-secure world
  * IWDG_FLAGS_ENABLED			Watchdog has been enabled
  */
 #define IWDG_FLAGS_HW_ENABLED			BIT(0)
 #define IWDG_FLAGS_DISABLE_ON_STOP		BIT(1)
 #define IWDG_FLAGS_DISABLE_ON_STANDBY		BIT(2)
-#define IWDG_FLAGS_NON_SECURE			BIT(3)
-#define IWDG_FLAGS_ENABLED			BIT(4)
+#define IWDG_FLAGS_ENABLED			BIT(3)
 
 /*
  * IWDG watch instance data
@@ -78,7 +76,6 @@
  * @flags - Property flags for the IWDG instance
  * @timeout - Watchdog elaspure timeout
  * @wdt_chip - Wathcdog chip instance
- * @link - Link in registered watchdog instance list
  */
 struct stm32_iwdg_device {
 	struct io_pa_va base;
@@ -87,22 +84,13 @@ struct stm32_iwdg_device {
 	uint32_t flags;
 	unsigned long timeout;
 	struct wdt_chip wdt_chip;
-	SLIST_ENTRY(stm32_iwdg_device) link;
 };
 
-static SLIST_HEAD(iwdg_dev_list_head, stm32_iwdg_device) iwdg_dev_list =
-	SLIST_HEAD_INITIALIZER(iwdg_dev_list_head);
-
 static vaddr_t get_base(struct stm32_iwdg_device *iwdg)
 {
 	return io_pa_or_va(&iwdg->base, 1);
 }
 
-static bool is_assigned_to_nsec(struct stm32_iwdg_device *iwdg)
-{
-	return iwdg->flags & IWDG_FLAGS_NON_SECURE;
-}
-
 static void iwdg_wdt_set_enabled(struct stm32_iwdg_device *iwdg)
 {
 	iwdg->flags |= IWDG_FLAGS_ENABLED;
@@ -268,17 +256,9 @@ static TEE_Result stm32_iwdg_parse_fdt(struct stm32_iwdg_device *iwdg,
 	if (res)
 		return res;
 
-	if (dt_info.status == DT_STATUS_OK_NSEC)
-		iwdg->flags |= IWDG_FLAGS_NON_SECURE;
-
 	/* Get IOMEM address */
 	iwdg->base.pa = dt_info.reg;
-
-	if (iwdg->flags & IWDG_FLAGS_NON_SECURE)
-		io_pa_or_va_nsec(&iwdg->base, dt_info.reg_size);
-	else
-		io_pa_or_va_secure(&iwdg->base, dt_info.reg_size);
-
+	io_pa_or_va_secure(&iwdg->base, dt_info.reg_size);
 	assert(iwdg->base.va);
 
 	/* Get and check timeout value */
@@ -355,28 +335,6 @@ static TEE_Result stm32_iwdg_setup(struct stm32_iwdg_device *iwdg,
 	return TEE_SUCCESS;
 }
 
-static TEE_Result stm32_iwdg_register(struct stm32_iwdg_device *iwdg)
-{
-	TEE_Result res = TEE_ERROR_GENERIC;
-
-	if (is_assigned_to_nsec(iwdg)) {
-		stm32mp_register_non_secure_periph_iomem(iwdg->base.pa);
-	} else {
-		stm32mp_register_secure_periph_iomem(iwdg->base.pa);
-
-		/* Expose watchdog runtime service only to secure IWDG */
-		iwdg->wdt_chip.ops = &stm32_iwdg_ops;
-
-		res = watchdog_register(&iwdg->wdt_chip);
-		if (res)
-			return res;
-	}
-
-	SLIST_INSERT_HEAD(&iwdg_dev_list, iwdg, link);
-
-	return TEE_SUCCESS;
-}
-
 static TEE_Result stm32_iwdg_probe(const void *fdt, int node,
 				   const void *compat_data __unused)
 {
@@ -389,16 +347,16 @@ static TEE_Result stm32_iwdg_probe(const void *fdt, int node,
 
 	res = stm32_iwdg_setup(iwdg, fdt, node);
 	if (res)
-		goto err;
+		goto out;
 
-	res = stm32_iwdg_register(iwdg);
-	if (res)
-		goto err;
+	iwdg->wdt_chip.ops = &stm32_iwdg_ops;
 
-	return TEE_SUCCESS;
+	res = watchdog_register(&iwdg->wdt_chip);
+
+out:
+	if (res)
+		free(iwdg);
 
-err:
-	free(iwdg);
 	return res;
 }
 
diff --git a/core/drivers/stm32_rng.c b/core/drivers/stm32_rng.c
index af234fa9a589ce5c64b9296499ae582a514e78a7..e1875e7ca547554e7efe5578be578bf8fcdd557c 100644
--- a/core/drivers/stm32_rng.c
+++ b/core/drivers/stm32_rng.c
@@ -1,12 +1,16 @@
 // SPDX-License-Identifier: BSD-3-Clause
 /*
- * Copyright (c) 2018-2023, STMicroelectronics
+ * Copyright (c) 2018-2024, STMicroelectronics
  */
 
 #include <assert.h>
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
 #include <drivers/rstctrl.h>
+#if defined(CFG_STM32MP15)
+#include <drivers/stm32_etzpc.h>
+#include <dt-bindings/firewall/stm32mp15-etzpc.h>
+#endif /* defined(CFG_STM32MP15) */
 #include <io.h>
 #include <kernel/delay.h>
 #include <kernel/dt.h>
@@ -26,13 +30,23 @@
 #define RNG_CR			U(0x00)
 #define RNG_SR			U(0x04)
 #define RNG_DR			U(0x08)
+#define RNG_NSCR		U(0x0C)
+#define RNG_HTCR		U(0x10)
+#define RNG_VERR		U(0x3F4)
 
 #define RNG_CR_RNGEN		BIT(2)
 #define RNG_CR_IE		BIT(3)
 #define RNG_CR_CED		BIT(5)
+#define RNG_CR_CONFIG1		GENMASK_32(11, 8)
+#define RNG_CR_NISTC		BIT(12)
+#define RNG_CR_POWER_OPTIM	BIT(13)
+#define RNG_CR_CONFIG2		GENMASK_32(15, 13)
 #define RNG_CR_CLKDIV		GENMASK_32(19, 16)
 #define RNG_CR_CLKDIV_SHIFT	U(16)
+#define RNG_CR_CONFIG3		GENMASK_32(25, 20)
 #define RNG_CR_CONDRST		BIT(30)
+#define RNG_CR_ENTROPY_SRC_MASK	(RNG_CR_CONFIG1 | RNG_CR_NISTC | \
+				 RNG_CR_CONFIG2 | RNG_CR_CONFIG3)
 
 #define RNG_SR_DRDY		BIT(0)
 #define RNG_SR_CECS		BIT(1)
@@ -40,6 +54,12 @@
 #define RNG_SR_CEIS		BIT(5)
 #define RNG_SR_SEIS		BIT(6)
 
+#define RNG_NSCR_MASK		GENMASK_32(17, 0)
+
+#define RNG_VERR_MINOR_MASK	GENMASK_32(3, 0)
+#define RNG_VERR_MAJOR_MASK	GENMASK_32(7, 4)
+#define RNG_VERR_MAJOR_SHIFT	U(4)
+
 #if TRACE_LEVEL > TRACE_DEBUG
 #define RNG_READY_TIMEOUT_US	U(100000)
 #else
@@ -49,26 +69,35 @@
 
 #define RNG_FIFO_BYTE_DEPTH	U(16)
 
-#define RNG_NIST_CONFIG_A	U(0x0F00D00)
-#define RNG_NIST_CONFIG_B	U(0x1801000)
-#define RNG_NIST_CONFIG_MASK	GENMASK_32(25, 8)
-
-#define RNG_MAX_NOISE_CLK_FREQ	U(3000000)
+#define RNG_CONFIG_MASK		(RNG_CR_ENTROPY_SRC_MASK | RNG_CR_CED | \
+				 RNG_CR_CLKDIV)
 
 struct stm32_rng_driver_data {
+	unsigned long max_noise_clk_freq;
+	unsigned long nb_clock;
+	uint32_t cr;
+	uint32_t nscr;
+	uint32_t htcr;
+	bool has_power_optim;
 	bool has_cond_reset;
 };
 
 struct stm32_rng_instance {
 	struct io_pa_va base;
 	struct clk *clock;
+	struct clk *bus_clock;
 	struct rstctrl *rstctrl;
 	const struct stm32_rng_driver_data *ddata;
 	unsigned int lock;
-	bool release_post_boot;
+	uint64_t error_to_ref;
+	uint32_t pm_cr;
+	uint32_t pm_health;
+	uint32_t pm_noise_ctrl;
+	uint32_t health_test_conf;
+	uint32_t noise_ctrl_conf;
+	uint32_t rng_config;
 	bool clock_error;
 	bool error_conceal;
-	uint64_t error_to_ref;
 };
 
 /* Expect at most a single RNG instance */
@@ -249,7 +278,7 @@ static uint32_t stm32_rng_clock_freq_restrain(void)
 	 * No need to handle the case when clock-div > 0xF as it is physically
 	 * impossible
 	 */
-	while ((clock_rate >> clock_div) > RNG_MAX_NOISE_CLK_FREQ)
+	while ((clock_rate >> clock_div) > dev->ddata->max_noise_clk_freq)
 		clock_div++;
 
 	DMSG("RNG clk rate : %lu", clk_get_rate(dev->clock) >> clock_div);
@@ -257,11 +286,48 @@ static uint32_t stm32_rng_clock_freq_restrain(void)
 	return clock_div;
 }
 
-static TEE_Result init_rng(void)
+static TEE_Result enable_rng_clock(void)
+{
+	TEE_Result res = clk_enable(stm32_rng->clock);
+
+	if (!res && stm32_rng->bus_clock) {
+		res = clk_enable(stm32_rng->bus_clock);
+		if (res)
+			clk_disable(stm32_rng->clock);
+	}
+
+	return res;
+}
+
+static void disable_rng_clock(void)
+{
+	clk_disable(stm32_rng->clock);
+	if (stm32_rng->bus_clock)
+		clk_disable(stm32_rng->bus_clock);
+}
+
+static TEE_Result stm32_rng_init(void)
 {
+	TEE_Result res = TEE_ERROR_GENERIC;
 	vaddr_t rng_base = get_base();
-	uint64_t timeout_ref = 0;
 	uint32_t cr_ced_mask = 0;
+	uint32_t value = 0;
+
+	res = enable_rng_clock();
+	if (res)
+		return res;
+
+	if (stm32_rng->rstctrl &&
+	    rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
+		res = TEE_ERROR_GENERIC;
+		goto out;
+	}
+
+	if (stm32_rng->rstctrl &&
+	    rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
+		res = TEE_ERROR_GENERIC;
+		goto out;
+	}
 
 	if (!stm32_rng->clock_error)
 		cr_ced_mask = RNG_CR_CED;
@@ -272,35 +338,66 @@ static TEE_Result init_rng(void)
 	if (stm32_rng->ddata->has_cond_reset) {
 		uint32_t clock_div = stm32_rng_clock_freq_restrain();
 
-		/* Update configuration fields */
-		io_clrsetbits32(rng_base + RNG_CR, RNG_NIST_CONFIG_MASK,
-				RNG_NIST_CONFIG_B | RNG_CR_CONDRST |
-				cr_ced_mask);
-		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CLKDIV,
-				clock_div << RNG_CR_CLKDIV_SHIFT);
+		/*
+		 * Keep default RNG configuration if none was specified.
+		 * 0 is an invalid value as it disables all entropy sources.
+		 */
+		if (!stm32_rng->rng_config)
+			stm32_rng->rng_config = io_read32(rng_base + RNG_CR) &
+						RNG_CR_ENTROPY_SRC_MASK;
+
+		/*
+		 * Configuration must be set in the same access that sets
+		 * RNG_CR_CONDRST bit. Otherwise, the configuration setting is
+		 * not taken into account. CONFIGLOCK bit is always cleared at
+		 * this stage.
+		 */
+		io_clrsetbits32(rng_base + RNG_CR, RNG_CONFIG_MASK,
+				stm32_rng->rng_config | RNG_CR_CONDRST |
+				cr_ced_mask |
+				SHIFT_U32(clock_div, RNG_CR_CLKDIV_SHIFT));
+
+		/*
+		 * Write health test and noise source control configuration
+		 * according to current RNG entropy source configuration
+		 */
+		if (stm32_rng->noise_ctrl_conf)
+			io_write32(rng_base + RNG_NSCR,
+				   stm32_rng->noise_ctrl_conf);
+
+		if (stm32_rng->health_test_conf)
+			io_write32(rng_base + RNG_HTCR,
+				   stm32_rng->health_test_conf);
 
 		io_clrsetbits32(rng_base + RNG_CR, RNG_CR_CONDRST,
 				RNG_CR_RNGEN);
 
-		timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
-		while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
-			if (timeout_elapsed(timeout_ref))
-				break;
-		if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
+		if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_CR, value,
+					   !(value & RNG_CR_CONDRST), 0,
+					   RNG_READY_TIMEOUT_US))
 			panic();
+
+		DMSG("RNG control register %#"PRIx32,
+		     io_read32(rng_base + RNG_CR));
+		DMSG("RNG noise source control register %#"PRIx32,
+		     io_read32(rng_base + RNG_NSCR));
+		DMSG("RNG health test register %#"PRIx32,
+		     io_read32(rng_base + RNG_HTCR));
 	} else {
 		io_setbits32(rng_base + RNG_CR, RNG_CR_RNGEN | cr_ced_mask);
 	}
 
-	timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
-	while (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
-		if (timeout_elapsed(timeout_ref))
-			break;
-
-	if (!(io_read32(rng_base + RNG_SR) & RNG_SR_DRDY))
+	if (IO_READ32_POLL_TIMEOUT(rng_base + RNG_SR, value,
+				   value & RNG_SR_DRDY, 0,
+				   RNG_READY_TIMEOUT_US))
 		return TEE_ERROR_GENERIC;
 
-	return TEE_SUCCESS;
+	res =  TEE_SUCCESS;
+
+out:
+	disable_rng_clock();
+
+	return res;
 }
 
 static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
@@ -318,7 +415,7 @@ static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
 		return TEE_ERROR_NOT_SUPPORTED;
 	}
 
-	rc = clk_enable(stm32_rng->clock);
+	rc = enable_rng_clock();
 	if (rc)
 		return rc;
 
@@ -359,17 +456,23 @@ static TEE_Result stm32_rng_read(uint8_t *out, size_t size)
 
 out:
 	assert(!rc || rc == TEE_ERROR_GENERIC);
-	clk_disable(stm32_rng->clock);
+	disable_rng_clock();
 
 	return rc;
 }
 
 #ifdef CFG_WITH_SOFTWARE_PRNG
-/* Override weak plat_rng_init with platform handler to seed PRNG */
+/* Override weak plat_rng_init with platform handler to attempt to seed PRNG */
 void plat_rng_init(void)
 {
 	uint8_t seed[RNG_FIFO_BYTE_DEPTH] = { };
 
+	if (!stm32_rng) {
+		__plat_rng_init();
+		DMSG("PRNG seeded without RNG");
+		return;
+	}
+
 	if (stm32_rng_read(seed, sizeof(seed)))
 		panic();
 
@@ -389,7 +492,7 @@ void plat_rng_init(void)
 }
 #endif
 
-static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
+static TEE_Result stm32_rng_pm_resume(void)
 {
 	vaddr_t base = get_base();
 
@@ -405,7 +508,11 @@ static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
 		 * not taken into account. CONFIGLOCK bit is always cleared in
 		 * this configuration.
 		 */
-		io_write32(base + RNG_CR, pm_cr | RNG_CR_CONDRST);
+		io_write32(base + RNG_CR, stm32_rng->pm_cr | RNG_CR_CONDRST);
+
+		/* Restore health test and noise control configuration */
+		io_write32(base + RNG_NSCR, stm32_rng->pm_noise_ctrl);
+		io_write32(base + RNG_HTCR, stm32_rng->pm_health);
 
 		io_clrsetbits32(base + RNG_CR, RNG_CR_CONDRST, RNG_CR_RNGEN);
 
@@ -416,7 +523,42 @@ static TEE_Result stm32_rng_pm_resume(uint32_t pm_cr)
 		if (io_read32(base + RNG_CR) & RNG_CR_CONDRST)
 			panic();
 	} else {
-		io_write32(base + RNG_CR, RNG_CR_RNGEN | pm_cr);
+		io_write32(base + RNG_CR, RNG_CR_RNGEN | stm32_rng->pm_cr);
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_rng_pm_suspend(void)
+{
+	vaddr_t rng_base = get_base();
+
+	stm32_rng->pm_cr = io_read32(rng_base + RNG_CR);
+
+	if (stm32_rng->ddata->has_cond_reset) {
+		stm32_rng->pm_health = io_read32(rng_base + RNG_HTCR);
+		stm32_rng->pm_noise_ctrl = io_read32(rng_base + RNG_NSCR);
+	}
+
+	if (stm32_rng->ddata->has_power_optim) {
+		uint64_t timeout_ref = 0;
+
+		/*
+		 * As per reference manual, it is recommended to set
+		 * RNG_CONFIG2[bit0] when RNG power consumption is critical.
+		 */
+		io_setbits32(rng_base + RNG_CR, RNG_CR_POWER_OPTIM |
+				RNG_CR_CONDRST);
+		io_clrbits32(rng_base + RNG_CR, RNG_CR_CONDRST);
+
+		timeout_ref = timeout_init_us(RNG_READY_TIMEOUT_US);
+		while (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
+			if (timeout_elapsed(timeout_ref))
+				break;
+		if (io_read32(rng_base + RNG_CR) & RNG_CR_CONDRST)
+			panic();
+	} else {
+		io_clrbits32(rng_base + RNG_CR, RNG_CR_RNGEN);
 	}
 
 	return TEE_SUCCESS;
@@ -426,21 +568,20 @@ static TEE_Result
 stm32_rng_pm(enum pm_op op, unsigned int pm_hint __unused,
 	     const struct pm_callback_handle *pm_handle __unused)
 {
-	static uint32_t pm_cr;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
 	assert(stm32_rng && (op == PM_OP_SUSPEND || op == PM_OP_RESUME));
 
-	res = clk_enable(stm32_rng->clock);
+	res = enable_rng_clock();
 	if (res)
 		return res;
 
-	if (op == PM_OP_SUSPEND)
-		pm_cr = io_read32(get_base() + RNG_CR);
+	if (op == PM_OP_RESUME)
+		res = stm32_rng_pm_resume();
 	else
-		res = stm32_rng_pm_resume(pm_cr);
+		res = stm32_rng_pm_suspend();
 
-	clk_disable(stm32_rng->clock);
+	disable_rng_clock();
 
 	return res;
 }
@@ -464,16 +605,32 @@ static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node)
 	if (res != TEE_SUCCESS && res != TEE_ERROR_ITEM_NOT_FOUND)
 		return res;
 
-	res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock);
-	if (res)
-		return res;
+	if (stm32_rng->ddata->nb_clock > 1) {
+		res = clk_dt_get_by_name(fdt, node, "rng_clk",
+					 &stm32_rng->clock);
+		if (res)
+			return res;
+
+		res = clk_dt_get_by_name(fdt, node, "rng_hclk",
+					 &stm32_rng->bus_clock);
+		if (res)
+			return res;
+	} else {
+		res = clk_dt_get_by_index(fdt, node, 0, &stm32_rng->clock);
+		if (res)
+			return res;
+	}
 
 	if (fdt_getprop(fdt, node, "clock-error-detect", NULL))
 		stm32_rng->clock_error = true;
 
-	/* Release device if not used at runtime or for pm transitions */
-	stm32_rng->release_post_boot = IS_ENABLED(CFG_WITH_SOFTWARE_PRNG) &&
-				       !IS_ENABLED(CFG_PM);
+	stm32_rng->rng_config = stm32_rng->ddata->cr;
+	if (stm32_rng->rng_config & ~RNG_CR_ENTROPY_SRC_MASK)
+		panic("Incorrect entropy source configuration");
+	stm32_rng->health_test_conf = stm32_rng->ddata->htcr;
+	stm32_rng->noise_ctrl_conf = stm32_rng->ddata->nscr;
+	if (stm32_rng->noise_ctrl_conf & ~RNG_NSCR_MASK)
+		panic("Incorrect noise source control configuration");
 
 	return TEE_SUCCESS;
 }
@@ -481,6 +638,7 @@ static TEE_Result stm32_rng_parse_fdt(const void *fdt, int node)
 static TEE_Result stm32_rng_probe(const void *fdt, int offs,
 				  const void *compat_data)
 {
+	unsigned int __maybe_unused version = 0;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
 	/* Expect a single RNG instance */
@@ -490,46 +648,38 @@ static TEE_Result stm32_rng_probe(const void *fdt, int offs,
 	if (!stm32_rng)
 		panic();
 
+	stm32_rng->ddata = compat_data;
+	assert(stm32_rng->ddata);
+
 	res = stm32_rng_parse_fdt(fdt, offs);
 	if (res)
 		goto err;
 
-	stm32_rng->ddata = compat_data;
-	assert(stm32_rng->ddata);
-
-	res = clk_enable(stm32_rng->clock);
+	res = enable_rng_clock();
 	if (res)
 		goto err;
 
-	if (stm32_rng->rstctrl &&
-	    rstctrl_assert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
-		res = TEE_ERROR_GENERIC;
-		goto err_clk;
-	}
+	version = io_read32(get_base() + RNG_VERR);
+	DMSG("RNG version Major %u, Minor %u",
+	     (version & RNG_VERR_MAJOR_MASK) >> RNG_VERR_MAJOR_SHIFT,
+	     version & RNG_VERR_MINOR_MASK);
 
-	if (stm32_rng->rstctrl &&
-	    rstctrl_deassert_to(stm32_rng->rstctrl, RNG_RESET_TIMEOUT_US)) {
-		res = TEE_ERROR_GENERIC;
-		goto err_clk;
-	}
+	disable_rng_clock();
 
-	res = init_rng();
+	res = stm32_rng_init();
 	if (res)
-		goto err_clk;
-
-	clk_disable(stm32_rng->clock);
+		goto err;
 
-	if (stm32_rng->release_post_boot)
-		stm32mp_register_non_secure_periph_iomem(stm32_rng->base.pa);
-	else
-		stm32mp_register_secure_periph_iomem(stm32_rng->base.pa);
+	/* Power management implementation expects both or none are set */
+	assert(stm32_rng->ddata->has_power_optim ==
+	       stm32_rng->ddata->has_cond_reset);
 
-	register_pm_core_service_cb(stm32_rng_pm, &stm32_rng, "rng-service");
+	if (!IS_ENABLED(CFG_WITH_SOFTWARE_PRNG))
+		register_pm_core_service_cb(stm32_rng_pm, &stm32_rng,
+					    "rng-service");
 
 	return TEE_SUCCESS;
 
-err_clk:
-	clk_disable(stm32_rng->clock);
 err:
 	free(stm32_rng);
 	stm32_rng = NULL;
@@ -538,17 +688,43 @@ err:
 }
 
 static const struct stm32_rng_driver_data mp13_data[] = {
-	{ .has_cond_reset = true },
+	{
+		.max_noise_clk_freq = U(48000000),
+		.nb_clock = 1,
+		.has_cond_reset = true,
+		.has_power_optim = true,
+		.cr = 0x00F00D00,
+		.nscr = 0x2B5BB,
+		.htcr = 0x969D,
+	},
 };
 
 static const struct stm32_rng_driver_data mp15_data[] = {
-	{ .has_cond_reset = false },
+	{
+		.max_noise_clk_freq = U(48000000),
+		.nb_clock = 1,
+		.has_cond_reset = false,
+		.has_power_optim = false,
+	},
 };
 DECLARE_KEEP_PAGER(mp15_data);
 
+static const struct stm32_rng_driver_data mp25_data[] = {
+	{
+		.max_noise_clk_freq = U(48000000),
+		.nb_clock = 2,
+		.has_cond_reset = true,
+		.has_power_optim = true,
+		.cr = 0x00F00D00,
+		.nscr = 0x2B5BB,
+		.htcr = 0x969D,
+	},
+};
+
 static const struct dt_device_match rng_match_table[] = {
 	{ .compatible = "st,stm32-rng", .compat_data = &mp15_data },
 	{ .compatible = "st,stm32mp13-rng", .compat_data = &mp13_data },
+	{ .compatible = "st,stm32mp25-rng", .compat_data = &mp25_data },
 	{ }
 };
 
@@ -560,7 +736,7 @@ DEFINE_DT_DRIVER(stm32_rng_dt_driver) = {
 
 static TEE_Result stm32_rng_release(void)
 {
-	if (stm32_rng && stm32_rng->release_post_boot) {
+	if (stm32_rng && IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)) {
 		DMSG("Release RNG driver");
 		free(stm32_rng);
 		stm32_rng = NULL;
diff --git a/core/drivers/stm32_tamp.c b/core/drivers/stm32_tamp.c
index 6a34bd15749c97224d902d0c09255bbccef5ca39..c489f3f88c9bde443d923ff052d4330201edcd89 100644
--- a/core/drivers/stm32_tamp.c
+++ b/core/drivers/stm32_tamp.c
@@ -5,7 +5,7 @@
 
 #include <drivers/clk.h>
 #include <drivers/clk_dt.h>
-#include <drivers/stm32_tamp.h>
+#include <drivers/stm32_rif.h>
 #include <io.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
@@ -35,6 +35,9 @@
 #define _TAMP_COUNT2R			0x44U
 #define _TAMP_OR			0x50U
 #define _TAMP_ERCFGR			0X54U
+#define _TAMP_BKPRIFR(x)		(0x70U + 0x4U * ((x) - 1U))
+#define _TAMP_CIDCFGR(x)		(0x80U + 0x4U * (x))
+#define _TAMP_BKPxR(x)			(0x100U + 0x4U * ((x) - 1U))
 #define _TAMP_HWCFGR2			0x3ECU
 #define _TAMP_HWCFGR1			0x3F0U
 #define _TAMP_VERR			0x3F4U
@@ -45,13 +48,19 @@
 #define _TAMP_SECCFGR_BKPRWSEC_MASK	GENMASK_32(7, 0)
 #define _TAMP_SECCFGR_BKPRWSEC_SHIFT	0U
 #define _TAMP_SECCFGR_CNT2SEC		BIT(14)
+#define _TAMP_SECCFGR_CNT2SEC_SHIFT	14U
 #define _TAMP_SECCFGR_CNT1SEC		BIT(15)
+#define _TAMP_SECCFGR_CNT1SEC_SHIFT	15U
 #define _TAMP_SECCFGR_BKPWSEC_MASK	GENMASK_32(23, 16)
 #define _TAMP_SECCFGR_BKPWSEC_SHIFT	16U
 #define _TAMP_SECCFGR_BHKLOCK		BIT(30)
 #define _TAMP_SECCFGR_TAMPSEC		BIT(31)
+#define _TAMP_SECCFGR_TAMPSEC_SHIFT	31U
 #define _TAMP_SECCFGR_BUT_BKP_MASK	(GENMASK_32(31, 30) | \
 					 GENMASK_32(15, 14))
+#define _TAMP_SECCFGR_RIF_TAMP_SEC	BIT(0)
+#define _TAMP_SECCFGR_RIF_COUNT_1	BIT(1)
+#define _TAMP_SECCFGR_RIF_COUNT_2	BIT(2)
 
 /* _TAMP_SMCR bit fields */
 #define _TAMP_SMCR_BKPRWDPROT_MASK	GENMASK_32(7, 0)
@@ -69,6 +78,9 @@
 #define _TAMP_PRIVCFG_TAMPPRIV		BIT(31)
 #define _TAMP_PRIVCFGR_MASK		(GENMASK_32(31, 29) | \
 					 GENMASK_32(15, 14))
+#define _TAMP_PRIVCFGR_RIF_TAMP_PRIV	BIT(0)
+#define _TAMP_PRIVCFGR_RIF_R1		BIT(1)
+#define _TAMP_PRIVCFGR_RIF_R2		BIT(2)
 
 /*
  * _TAMP_PRIVCFGR bit fields
@@ -98,66 +110,275 @@
 #define _TAMP_VERR_MAJREV		GENMASK_32(7, 4)
 
 /*
- * TAMP instance data
- * @base - IOMEM base address
- * @clock - TAMP clock
- * @it - TAMP interrupt number
- * @hwconf1 - Copy of TAMP HWCONF1 register content
- * @hwconf2 - Copy of TAMP HWCONF2 register content
- * @compat - Reference to compat data passed at driver initialization
+ * CIDCFGR register bitfields
  */
-struct stm32_tamp_instance {
-	struct io_pa_va base;
-	struct clk *clock;
-	int it;
-	uint32_t hwconf1;
-	uint32_t hwconf2;
-	struct stm32_tamp_compat *compat;
-};
+#define _TAMP_CIDCFGR_SCID_MASK		GENMASK_32(6, 4)
+#define _TAMP_CIDCFGR_CONF_MASK		(_CIDCFGR_CFEN |	 \
+					 _CIDCFGR_SEMEN |	 \
+					 _TAMP_CIDCFGR_SCID_MASK)
+
+/* _TAMP_BKPRIFR */
+#define _TAMP_BKPRIFR_1_MASK		GENMASK_32(7, 0)
+#define _TAMP_BKPRIFR_2_MASK		GENMASK_32(7, 0)
+#define _TAMP_BKPRIFR_3_MASK		(GENMASK_32(23, 16) | GENMASK_32(7, 0))
+#define _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT	16U
+
+/*
+ * RIF miscellaneous
+ */
+#define TAMP_NB_BKPR_ZONES		3U
+#define TAMP_RIF_RESOURCES		3U
+#define TAMP_RIF_OFFSET_CNT		4U
 
 /*
  * Compatibility capabilities
- * TAMP_HAS_REGISTER_SECCFG - Supports SECCFGR, otherwise supports SMCR register
+ * TAMP_HAS_REGISTER_SECCFGR - Supports SECCFGR, otherwise supports SMCR
+ * register
  * TAMP_HAS_REGISTER_PRIVCFG - Supports PRIVCFGR configuration register
+ * TAMP_HAS_RIF_SUPPORT - Supports RIF
  */
-#define TAMP_HAS_REGISTER_SECCFG	BIT(0)
+#define TAMP_HAS_REGISTER_SECCFGR	BIT(0)
 #define TAMP_HAS_REGISTER_PRIVCFGR	BIT(1)
+#define TAMP_HAS_RIF_SUPPORT		BIT(31)
 
-/*
- * @nb_monotonic_counter - Number of monotic counter supported
- * @tags - Bit flags TAMP_HAS_* for compatibily management
+/**
+ * struct stm32_tamp_compat - TAMP compatible data
+ * @nb_monotonic_counter: Number of monotic counter supported
+ * @tags: Bit flags TAMP_HAS_* for compatibility management
  */
 struct stm32_tamp_compat {
 	int nb_monotonic_counter;
 	uint32_t tags;
 };
 
+/*
+ * struct stm32_bkpregs_conf - Backup registers zone bounds
+ * @zone1_end - Number of backup registers in zone 1
+ * @zone2_end - Number of backup registers in zone 2 + zone 1
+ * @rif_offsets - RIF offsets used for CID compartments
+ *
+ * TAMP backup registers access permissions
+ *
+ * Zone 1: read/write in secure state, no access in non-secure state
+ * Zone 2: read/write in secure state, read-only in non-secure state
+ * Zone 3: read/write in secure state, read/write in non-secure state
+ *
+ * Protection zone 1
+ * If zone1_end == 0 no backup register are in zone 1.
+ * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1,
+ * with <x> = (@zone1_end - 1).
+ *
+ * Protection zone 2
+ * If zone2_end == 0 no backup register are in zone 2 and zone 1.
+ * Otherwise backup registers from TAMP_BKP<y>R to TAMP_BKP<z>R are in zone 2,
+ * with <y> = @zone1_end and <z> = (@zone2_end - 1).
+ *
+ * Protection zone 3
+ * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3,
+ * with <t> = (@zone2_end - 1).
+ *
+ * When RIF is supported, each zone can be subdivided to restrain accesses to
+ * some CIDs.
+ */
+struct stm32_bkpregs_conf {
+	uint32_t zone1_end;
+	uint32_t zone2_end;
+	uint32_t *rif_offsets;
+};
+
+/**
+ * struct stm32_tamp_platdata - TAMP platform data
+ * @base: IOMEM base address
+ * @bkpregs_conf: TAMP backup register configuration reference
+ * @compat: Reference to compat data passed at driver initialization
+ * @conf_data: RIF configuration data
+ * @clock: TAMP clock
+ * @nb_rif_resources: Number of RIF resources
+ * @it: TAMP interrupt number
+ * @is_tdcid: True if current processor is TDCID
+ */
+struct stm32_tamp_platdata {
+	struct io_pa_va base;
+	struct stm32_bkpregs_conf bkpregs_conf;
+	struct stm32_tamp_compat *compat;
+	struct rif_conf_data *conf_data;
+	struct clk *clock;
+	unsigned int nb_rif_resources;
+	int it;
+	bool is_tdcid;
+};
+
+/**
+ * struct stm32_tamp_instance - TAMP instance data
+ * @pdata: TAMP platform data
+ * @hwconf1: Copy of TAMP HWCONF1 register content
+ * @hwconf2: Copy of TAMP HWCONF2 register content
+ */
+struct stm32_tamp_instance {
+	struct stm32_tamp_platdata pdata;
+	uint32_t hwconf1;
+	uint32_t hwconf2;
+};
+
 /* Expects at most a single instance */
-static struct stm32_tamp_instance *stm32_tamp_device;
+static struct stm32_tamp_instance *stm32_tamp_dev;
+
+static void apply_rif_config(void)
+{
+	struct rif_conf_data *rif_conf = stm32_tamp_dev->pdata.conf_data;
+	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
+	uint32_t access_mask_priv_reg = 0;
+	uint32_t access_mask_sec_reg = 0;
+	uint32_t privcfgr = 0;
+	uint32_t seccfgr = 0;
+	unsigned int i = 0;
+
+	if (!stm32_tamp_dev->pdata.conf_data)
+		return;
+
+	/* Build access masks for _TAMP_PRIVCFGR and _TAMP_SECCFGR */
+	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
+		if (BIT(i) & rif_conf->access_mask[0]) {
+			switch (i) {
+			case 0:
+				access_mask_sec_reg |= _TAMP_SECCFGR_TAMPSEC;
+				access_mask_priv_reg |= _TAMP_PRIVCFG_TAMPPRIV;
+				break;
+			case 1:
+				access_mask_sec_reg |= _TAMP_SECCFGR_CNT1SEC;
+				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT1PRIV;
+				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPRWPRIV;
+				break;
+			case 2:
+				access_mask_sec_reg |= _TAMP_SECCFGR_CNT2SEC;
+				access_mask_priv_reg |= _TAMP_PRIVCFG_CNT2PRIV;
+				access_mask_priv_reg |= _TAMP_PRIVCFG_BKPWPRIV;
+				break;
+			default:
+				panic();
+			}
+		}
+	}
 
-TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf)
+	/*
+	 * When TDCID, OP-TEE should be the one to set the CID filtering
+	 * configuration. Clearing previous configuration prevents
+	 * undesired events during the only legitimate configuration.
+	 */
+	if (stm32_tamp_dev->pdata.is_tdcid) {
+		for (i = 0; i < TAMP_RIF_RESOURCES; i++)
+			if (BIT(i) & rif_conf->access_mask[0])
+				io_clrbits32(base + _TAMP_CIDCFGR(i),
+					     _TAMP_CIDCFGR_CONF_MASK);
+	}
+
+	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_TAMP_SEC)
+		seccfgr |= _TAMP_SECCFGR_TAMPSEC;
+	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_1)
+		seccfgr |= _TAMP_SECCFGR_CNT1SEC;
+	if (rif_conf->sec_conf[0] & _TAMP_SECCFGR_RIF_COUNT_2)
+		seccfgr |= _TAMP_SECCFGR_CNT2SEC;
+
+	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_TAMP_PRIV)
+		privcfgr |= _TAMP_PRIVCFG_TAMPPRIV;
+	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R1)
+		privcfgr |= _TAMP_PRIVCFG_CNT1PRIV | _TAMP_PRIVCFG_BKPRWPRIV;
+	if (rif_conf->priv_conf[0] & _TAMP_PRIVCFGR_RIF_R2)
+		privcfgr |= _TAMP_PRIVCFG_CNT2PRIV | _TAMP_PRIVCFG_BKPWPRIV;
+
+	/* Security and privilege RIF configuration */
+	io_clrsetbits32(base + _TAMP_PRIVCFGR, access_mask_priv_reg, privcfgr);
+	io_clrsetbits32(base + _TAMP_SECCFGR, access_mask_sec_reg, seccfgr);
+
+	if (!stm32_tamp_dev->pdata.is_tdcid)
+		return;
+
+	for (i = 0; i < TAMP_RIF_RESOURCES; i++) {
+		if (!(BIT(i) & rif_conf->access_mask[0]))
+			continue;
+
+		io_clrsetbits32(base + _TAMP_CIDCFGR(i),
+				_TAMP_CIDCFGR_CONF_MASK,
+				rif_conf->cid_confs[i]);
+	}
+}
+
+static TEE_Result stm32_tamp_apply_bkpr_rif_conf(void)
 {
-	struct stm32_tamp_instance *tamp = stm32_tamp_device;
+	struct stm32_bkpregs_conf *bkpregs_conf =
+			&stm32_tamp_dev->pdata.bkpregs_conf;
+	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
+	unsigned int i = 0;
+
+	if (!bkpregs_conf->rif_offsets)
+		panic("No backup register configuration");
+
+	for (i = 0; i < TAMP_RIF_OFFSET_CNT; i++) {
+		if (bkpregs_conf->rif_offsets[i] >
+		    (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG))
+			return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	/* Fill the 3 TAMP_BKPRIFRx registers */
+	io_clrsetbits32(base + _TAMP_BKPRIFR(1), _TAMP_BKPRIFR_1_MASK,
+			bkpregs_conf->rif_offsets[0]);
+	io_clrsetbits32(base + _TAMP_BKPRIFR(2), _TAMP_BKPRIFR_2_MASK,
+			bkpregs_conf->rif_offsets[1]);
+	io_clrsetbits32(base + _TAMP_BKPRIFR(3), _TAMP_BKPRIFR_3_MASK,
+			bkpregs_conf->rif_offsets[2] |
+			SHIFT_U32(bkpregs_conf->rif_offsets[3],
+				  _TAMP_BKPRIFR_ZONE3_RIF2_SHIFT));
+
+	DMSG("Backup registers mapping :");
+	DMSG("********START of zone 1********");
+	DMSG("Protection Zone 1-RIF1 begins at register: 0");
+	DMSG("Protection Zone 1-RIF2 begins at register: %"PRIu32,
+	     bkpregs_conf->rif_offsets[0]);
+	DMSG("Protection Zone 1-RIF2 ends at register: %"PRIu32,
+	     bkpregs_conf->zone1_end ? bkpregs_conf->zone1_end - 1 : 0);
+	DMSG("********END of zone 1********");
+	DMSG("********START of zone 2********");
+	DMSG("Protection Zone 2-RIF1 begins at register: %"PRIu32,
+	     bkpregs_conf->zone1_end);
+	DMSG("Protection Zone 2-RIF2 begins at register: %"PRIu32,
+	     bkpregs_conf->rif_offsets[1]);
+	DMSG("Protection Zone 2-RIF2 ends at register: %"PRIu32,
+	     bkpregs_conf->rif_offsets[1] > bkpregs_conf->zone1_end ?
+	     bkpregs_conf->zone2_end - 1 : 0);
+	DMSG("********END of zone 2********");
+	DMSG("********START of zone 3********");
+	DMSG("Protection Zone 3-RIF1 begins at register: %"PRIu32,
+	     bkpregs_conf->zone2_end);
+	DMSG("Protection Zone 3-RIF0 begins at register: %"PRIu32,
+	     bkpregs_conf->rif_offsets[2]);
+	DMSG("Protection Zone 3-RIF2 begins at register: %"PRIu32,
+	     bkpregs_conf->rif_offsets[3]);
+	DMSG("Protection Zone 3-RIF2 ends at the last register: %"PRIu32,
+	     stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG);
+	DMSG("********END of zone 3********");
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result stm32_tamp_set_secure_bkpregs(void)
+{
+	struct stm32_bkpregs_conf *bkpregs_conf =
+		&stm32_tamp_dev->pdata.bkpregs_conf;
 	vaddr_t base = 0;
 	uint32_t first_z2 = 0;
 	uint32_t first_z3 = 0;
 
-	if (!tamp)
-		return TEE_ERROR_DEFER_DRIVER_INIT;
-
-	if (!bkr_conf)
-		return TEE_ERROR_BAD_PARAMETERS;
-
-	base = io_pa_or_va(&tamp->base, 1);
+	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
 
-	first_z2 = bkr_conf->nb_zone1_regs;
-	first_z3 = bkr_conf->nb_zone1_regs + bkr_conf->nb_zone2_regs;
+	first_z2 = bkpregs_conf->zone1_end;
+	first_z3 = bkpregs_conf->zone2_end;
 
-	if ((first_z2 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
-	    (first_z3 > (tamp->hwconf1 & _TAMP_HWCFGR1_BKPREG)))
+	if ((first_z2 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)) ||
+	    (first_z3 > (stm32_tamp_dev->hwconf1 & _TAMP_HWCFGR1_BKPREG)))
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) {
+	if (stm32_tamp_dev->pdata.compat &&
+	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
 		io_clrsetbits32(base + _TAMP_SECCFGR,
 				_TAMP_SECCFGR_BKPRWSEC_MASK,
 				(first_z2 << _TAMP_SECCFGR_BKPRWSEC_SHIFT) &
@@ -182,12 +403,12 @@ TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *bkr_conf)
 	return TEE_SUCCESS;
 }
 
-static void stm32_tamp_set_secure(struct stm32_tamp_instance *tamp,
-				  uint32_t mode)
+static void stm32_tamp_set_secure(uint32_t mode)
 {
-	vaddr_t base = io_pa_or_va(&tamp->base, 1);
+	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
 
-	if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_SECCFG)) {
+	if (stm32_tamp_dev->pdata.compat &&
+	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_SECCFGR)) {
 		io_clrsetbits32(base + _TAMP_SECCFGR,
 				_TAMP_SECCFGR_BUT_BKP_MASK,
 				mode & _TAMP_SECCFGR_BUT_BKP_MASK);
@@ -203,20 +424,116 @@ static void stm32_tamp_set_secure(struct stm32_tamp_instance *tamp,
 	}
 }
 
-static void stm32_tamp_set_privilege(struct stm32_tamp_instance *tamp,
-				     uint32_t mode)
+static void stm32_tamp_set_privilege(uint32_t mode)
 {
-	vaddr_t base = io_pa_or_va(&tamp->base, 1);
+	vaddr_t base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
 
-	if (tamp->compat && (tamp->compat->tags & TAMP_HAS_REGISTER_PRIVCFGR))
+	if (stm32_tamp_dev->pdata.compat &&
+	    (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_REGISTER_PRIVCFGR))
 		io_clrsetbits32(base + _TAMP_PRIVCFGR, _TAMP_PRIVCFGR_MASK,
 				mode & _TAMP_PRIVCFGR_MASK);
 }
 
-static TEE_Result stm32_tamp_parse_fdt(struct stm32_tamp_instance *tamp,
-				       const void *fdt, int node,
+static void parse_bkpregs_dt_conf(const void *fdt, int node)
+{
+	struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata;
+	unsigned int bkpregs_count = 0;
+	const fdt32_t *cuint = NULL;
+	int lenp = 0;
+
+	cuint = fdt_getprop(fdt, node, "st,backup-zones", &lenp);
+	if (!cuint)
+		panic("Missing backup registers configuration");
+
+	/*
+	 * When TAMP does not support RIF, the backup registers can
+	 * be splited in 3 zones. These zones have specific read/write
+	 * access permissions based on the secure status of the accesser.
+	 * When RIF is supported, these zones can additionally be splited
+	 * in subzones that have CID filtering. Zones/Subzones can be empty and
+	 * are contiguous.
+	 */
+	if (!(pdata->compat->tags & TAMP_HAS_RIF_SUPPORT)) {
+		/* 3 zones, 2 offsets to apply */
+		if (lenp != sizeof(uint32_t) * TAMP_NB_BKPR_ZONES)
+			panic("Incorrect bkpregs configuration");
+
+		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]);
+		bkpregs_count = fdt32_to_cpu(cuint[0]);
+
+		pdata->bkpregs_conf.zone2_end = bkpregs_count +
+						fdt32_to_cpu(cuint[1]);
+	} else {
+		/*
+		 * Zone 3
+		 * ----------------------|
+		 * Protection Zone 3-RIF2|Read non-
+		 * ----------------------|secure
+		 * Protection Zone 3-RIF0|Write non-
+		 * ----------------------|secure
+		 * Protection Zone 3-RIF1|
+		 * ----------------------|
+		 *
+		 * Zone 2
+		 * ----------------------|
+		 * Protection Zone 2-RIF2|Read non-
+		 * ----------------------|secure
+		 * Protection Zone 2-RIF1|Write secure
+		 * ----------------------|
+		 *
+		 * Zone 1
+		 * ----------------------|
+		 * Protection Zone 1-RIF2|Read secure
+		 * ----------------------|Write secure
+		 * Protection Zone 1-RIF1|
+		 * ----------------------|
+		 *
+		 * (BHK => First 8 registers)
+		 */
+		pdata->bkpregs_conf.rif_offsets = calloc(TAMP_RIF_OFFSET_CNT,
+							 sizeof(uint32_t));
+		if (!pdata->bkpregs_conf.rif_offsets)
+			panic();
+
+		/*
+		 * 3 zones with 7 subzones in total(6 offsets):
+		 * - 2 zone offsets
+		 * - 4 subzones offsets
+		 */
+		if (lenp != sizeof(uint32_t) *
+		    (TAMP_RIF_OFFSET_CNT + TAMP_NB_BKPR_ZONES))
+			panic("Incorrect bkpregs configuration");
+
+		/* Backup registers zone 1 */
+		pdata->bkpregs_conf.rif_offsets[0] = fdt32_to_cpu(cuint[0]);
+		pdata->bkpregs_conf.zone1_end = fdt32_to_cpu(cuint[0]) +
+						fdt32_to_cpu(cuint[1]);
+
+		bkpregs_count = pdata->bkpregs_conf.zone1_end;
+
+		/* Backup registers zone 2 */
+		pdata->bkpregs_conf.rif_offsets[1] = bkpregs_count +
+						     fdt32_to_cpu(cuint[2]);
+		pdata->bkpregs_conf.zone2_end = bkpregs_count +
+						fdt32_to_cpu(cuint[2]) +
+						fdt32_to_cpu(cuint[3]);
+
+		bkpregs_count = pdata->bkpregs_conf.zone2_end;
+
+		/* Backup registers zone 3 */
+		pdata->bkpregs_conf.rif_offsets[2] = bkpregs_count +
+						     fdt32_to_cpu(cuint[4]);
+		pdata->bkpregs_conf.rif_offsets[3] = bkpregs_count +
+						      fdt32_to_cpu(cuint[4]) +
+						      fdt32_to_cpu(cuint[5]);
+	}
+}
+
+static TEE_Result stm32_tamp_parse_fdt(const void *fdt, int node,
 				       const void *compat)
 {
+	struct stm32_tamp_platdata *pdata = &stm32_tamp_dev->pdata;
+	TEE_Result res = TEE_ERROR_GENERIC;
 	struct dt_node_info dt_tamp = { };
 
 	fdt_fill_device_info(fdt, &dt_tamp, node);
@@ -225,75 +542,145 @@ static TEE_Result stm32_tamp_parse_fdt(struct stm32_tamp_instance *tamp,
 	    dt_tamp.reg_size == DT_INFO_INVALID_REG_SIZE)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	tamp->compat = (struct stm32_tamp_compat *)compat;
-	tamp->it = dt_tamp.interrupt;
-	tamp->base.pa = dt_tamp.reg;
-	io_pa_or_va_secure(&tamp->base, dt_tamp.reg_size);
+	pdata->compat = (struct stm32_tamp_compat *)compat;
+	pdata->it = dt_tamp.interrupt;
+	pdata->base.pa = dt_tamp.reg;
+	io_pa_or_va_secure(&pdata->base, dt_tamp.reg_size);
 
-	return clk_dt_get_by_index(fdt, node, 0, &tamp->clock);
+	res = clk_dt_get_by_index(fdt, node, 0, &pdata->clock);
+	if (res)
+		return res;
+
+	parse_bkpregs_dt_conf(fdt, node);
+
+	if (pdata->compat->tags & TAMP_HAS_RIF_SUPPORT) {
+		const fdt32_t *cuint = NULL;
+		unsigned int i = 0;
+		int lenp = 0;
+
+		res = stm32_rifsc_check_tdcid(&pdata->is_tdcid);
+		if (res)
+			return res;
+
+		cuint = fdt_getprop(fdt, node, "st,protreg", &lenp);
+		if (!cuint) {
+			DMSG("No RIF configuration available");
+			return TEE_SUCCESS;
+		}
+
+		pdata->conf_data = calloc(1, sizeof(*pdata->conf_data));
+		if (!pdata->conf_data)
+			panic();
+
+		pdata->nb_rif_resources = (unsigned int)(lenp /
+							 sizeof(uint32_t));
+		assert(pdata->nb_rif_resources <= TAMP_RIF_RESOURCES);
+
+		pdata->conf_data->cid_confs = calloc(TAMP_RIF_RESOURCES,
+						     sizeof(uint32_t));
+		pdata->conf_data->sec_conf = calloc(1, sizeof(uint32_t));
+		pdata->conf_data->priv_conf = calloc(1, sizeof(uint32_t));
+		pdata->conf_data->access_mask = calloc(1, sizeof(uint32_t));
+		if (!pdata->conf_data->cid_confs ||
+		    !pdata->conf_data->sec_conf ||
+		    !pdata->conf_data->priv_conf ||
+		    !pdata->conf_data->access_mask)
+			panic("Not enough memory capacity for TAMP RIF config");
+
+		for (i = 0; i < pdata->nb_rif_resources; i++)
+			stm32_rif_parse_cfg(fdt32_to_cpu(cuint[i]),
+					    pdata->conf_data,
+					    TAMP_RIF_RESOURCES);
+	}
+
+	return TEE_SUCCESS;
 }
 
 static TEE_Result stm32_tamp_probe(const void *fdt, int node,
 				   const void *compat_data)
 {
-	struct stm32_tamp_instance *tamp = NULL;
 	uint32_t __maybe_unused revision = 0;
 	TEE_Result res = TEE_SUCCESS;
 	vaddr_t base = 0;
 
-	tamp = calloc(1, sizeof(*tamp));
-	if (!tamp)
+	stm32_tamp_dev = calloc(1, sizeof(*stm32_tamp_dev));
+	if (!stm32_tamp_dev)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
-	res = stm32_tamp_parse_fdt(tamp, fdt, node, compat_data);
+	res = stm32_tamp_parse_fdt(fdt, node, compat_data);
 	if (res)
 		goto err;
 
-	clk_enable(tamp->clock);
+	if (clk_enable(stm32_tamp_dev->pdata.clock))
+		panic();
 
-	base = io_pa_or_va(&tamp->base, 1);
+	base = io_pa_or_va(&stm32_tamp_dev->pdata.base, 1);
 
-	tamp->hwconf1 = io_read32(base + _TAMP_HWCFGR1);
-	tamp->hwconf2 = io_read32(base + _TAMP_HWCFGR2);
+	stm32_tamp_dev->hwconf1 = io_read32(base + _TAMP_HWCFGR1);
+	stm32_tamp_dev->hwconf2 = io_read32(base + _TAMP_HWCFGR2);
 
 	revision = io_read32(base + _TAMP_VERR);
 	FMSG("STM32 TAMPER V%"PRIx32".%"PRIu32,
 	     (revision & _TAMP_VERR_MAJREV) >> 4, revision & _TAMP_VERR_MINREV);
 
-	if (!(tamp->hwconf2 & _TAMP_HWCFGR2_TZ)) {
+	if (!(stm32_tamp_dev->hwconf2 & _TAMP_HWCFGR2_TZ)) {
 		EMSG("TAMP doesn't support TrustZone");
 		res = TEE_ERROR_NOT_SUPPORTED;
 		goto err_clk;
 	}
 
-	/*
-	 * Enforce secure only access to protected TAMP registers.
-	 * Allow non-secure access to monotonic counter.
-	 */
-	stm32_tamp_set_secure(tamp, _TAMP_SECCFGR_TAMPSEC);
+	if (stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) {
+		apply_rif_config();
 
-	/*
-	 * Enforce privilege only access to TAMP registers, backup
-	 * registers and monotonic counter.
-	 */
-	stm32_tamp_set_privilege(tamp, _TAMP_PRIVCFG_TAMPPRIV |
-				 _TAMP_PRIVCFG_BKPRWPRIV |
-				 _TAMP_PRIVCFG_BKPWPRIV);
+		if (stm32_tamp_dev->pdata.is_tdcid) {
+			res = stm32_tamp_apply_bkpr_rif_conf();
+			if (res)
+				goto err_clk;
+		}
+	} else {
+		/*
+		 * Enforce secure only access to protected TAMP registers.
+		 * Allow non-secure access to monotonic counter.
+		 */
+		stm32_tamp_set_secure(_TAMP_SECCFGR_TAMPSEC);
 
-	stm32_tamp_device = tamp;
+		/*
+		 * Enforce privilege only access to TAMP registers, backup
+		 * registers and monotonic counter.
+		 */
+		stm32_tamp_set_privilege(_TAMP_PRIVCFG_TAMPPRIV |
+					 _TAMP_PRIVCFG_BKPRWPRIV |
+					 _TAMP_PRIVCFG_BKPWPRIV);
+	}
+
+	if (!(stm32_tamp_dev->pdata.compat->tags & TAMP_HAS_RIF_SUPPORT) ||
+	    stm32_tamp_dev->pdata.is_tdcid) {
+		res = stm32_tamp_set_secure_bkpregs();
+		if (res)
+			goto err_clk;
+	}
 
 	return TEE_SUCCESS;
 
 err_clk:
-	clk_disable(tamp->clock);
+	clk_disable(stm32_tamp_dev->pdata.clock);
 err:
-	free(tamp);
+	if (stm32_tamp_dev->pdata.conf_data) {
+		free(stm32_tamp_dev->pdata.conf_data->cid_confs);
+		free(stm32_tamp_dev->pdata.conf_data->sec_conf);
+		free(stm32_tamp_dev->pdata.conf_data->priv_conf);
+		free(stm32_tamp_dev->pdata.conf_data->access_mask);
+		free(stm32_tamp_dev->pdata.conf_data);
+	}
+	free(stm32_tamp_dev->pdata.bkpregs_conf.rif_offsets);
+	free(stm32_tamp_dev);
+
 	return res;
 }
 
 static const struct stm32_tamp_compat mp13_compat = {
 	.nb_monotonic_counter = 2,
-	.tags = TAMP_HAS_REGISTER_SECCFG | TAMP_HAS_REGISTER_PRIVCFGR,
+	.tags = TAMP_HAS_REGISTER_SECCFGR | TAMP_HAS_REGISTER_PRIVCFGR,
 };
 
 static const struct stm32_tamp_compat mp15_compat = {
@@ -301,7 +688,15 @@ static const struct stm32_tamp_compat mp15_compat = {
 	.tags = 0,
 };
 
+static const struct stm32_tamp_compat mp25_compat = {
+	.nb_monotonic_counter = 2,
+	.tags = TAMP_HAS_REGISTER_SECCFGR |
+		TAMP_HAS_REGISTER_PRIVCFGR |
+		TAMP_HAS_RIF_SUPPORT,
+};
+
 static const struct dt_device_match stm32_tamp_match_table[] = {
+	{ .compatible = "st,stm32mp25-tamp", .compat_data = &mp25_compat },
 	{ .compatible = "st,stm32mp13-tamp", .compat_data = &mp13_compat },
 	{ .compatible = "st,stm32-tamp", .compat_data = &mp15_compat },
 	{ }
diff --git a/core/drivers/stm32_uart.c b/core/drivers/stm32_uart.c
index f7375256fe20d201a92840b63d7ff6f294705e8e..9b4179306dc7c4578477f5c60a5c327a1cceb653 100644
--- a/core/drivers/stm32_uart.c
+++ b/core/drivers/stm32_uart.c
@@ -109,35 +109,6 @@ void stm32_uart_init(struct stm32_uart_pdata *pd, vaddr_t base)
 	pd->chip.ops = &stm32_uart_serial_ops;
 }
 
-static void register_secure_uart(struct stm32_uart_pdata *pd)
-{
-#ifndef CFG_STM32MP25
-	stm32mp_register_secure_periph_iomem(pd->base.pa);
-	stm32mp_register_secure_pinctrl(pd->pinctrl);
-	if (pd->pinctrl_sleep)
-		stm32mp_register_secure_pinctrl(pd->pinctrl_sleep);
-#else
-	stm32_pinctrl_set_secure_cfg(pd->pinctrl, true);
-	if (pd->pinctrl_sleep)
-		stm32_pinctrl_set_secure_cfg(pd->pinctrl, true);
-#endif
-}
-
-static void register_non_secure_uart(struct stm32_uart_pdata *pd)
-{
-#ifndef CFG_STM32MP25
-	stm32mp_register_non_secure_periph_iomem(pd->base.pa);
-	stm32mp_register_non_secure_pinctrl(pd->pinctrl);
-	if (pd->pinctrl_sleep)
-		stm32mp_register_non_secure_pinctrl(pd->pinctrl_sleep);
-#else
-	stm32_pinctrl_set_secure_cfg(pd->pinctrl, false);
-	if (pd->pinctrl_sleep)
-		stm32_pinctrl_set_secure_cfg(pd->pinctrl, false);
-#endif
-
-}
-
 struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
@@ -158,7 +129,6 @@ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node)
 
 	pd->chip.ops = &stm32_uart_serial_ops;
 	pd->base.pa = info.reg;
-	pd->secure = (info.status == DT_STATUS_OK_SEC);
 
 	res = clk_dt_get_by_index(fdt, node, 0, &pd->clock);
 	if (res) {
@@ -171,9 +141,8 @@ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node)
 		panic();
 
 	assert(cpu_mmu_enabled());
-	pd->base.va = (vaddr_t)phys_to_virt(pd->base.pa,
-					    pd->secure ? MEM_AREA_IO_SEC :
-					    MEM_AREA_IO_NSEC, info.reg_size);
+	pd->base.va = (vaddr_t)phys_to_virt(pd->base.pa, MEM_AREA_IO_SEC,
+					    info.reg_size);
 
 	res = pinctrl_get_state_by_name(fdt, node, "default", &pd->pinctrl);
 	if (res)
@@ -187,10 +156,5 @@ struct stm32_uart_pdata *stm32_uart_init_from_dt_node(void *fdt, int node)
 	if (res)
 		panic();
 
-	if (pd->secure)
-		register_secure_uart(pd);
-	else
-		register_non_secure_uart(pd);
-
 	return pd;
 }
diff --git a/core/drivers/sub.mk b/core/drivers/sub.mk
index 0bd5bc242290dee0ad3193b622a38e7def399a3c..de822caf981a5426e487a5ee290f94521213073b 100644
--- a/core/drivers/sub.mk
+++ b/core/drivers/sub.mk
@@ -32,12 +32,16 @@ srcs-$(CFG_ATMEL_WDT) += atmel_wdt.c
 srcs-$(CFG_ATMEL_RTC) += atmel_rtc.c
 srcs-$(CFG_ATMEL_PIOBU) += atmel_piobu.c
 srcs-$(CFG_ATMEL_TCB) += atmel_tcb.c
+srcs-$(CFG_MICROCHIP_PIT) += microchip_pit.c
 srcs-$(CFG_AMLOGIC_UART) += amlogic_uart.c
 srcs-$(CFG_MVEBU_UART) += mvebu_uart.c
 srcs-$(CFG_STM32_BSEC) += stm32_bsec.c
-srcs-$(CFG_STM32_ETZPC) += stm32_etzpc.c
+srcs-$(CFG_STM32_FMC) += stm32_fmc.c
 srcs-$(CFG_STM32_GPIO) += stm32_gpio.c
+srcs-$(CFG_STM32_HPDMA) += stm32_hpdma.c
+srcs-$(CFG_STM32_HSEM) += stm32_hsem.c
 srcs-$(CFG_STM32_IWDG) += stm32_iwdg.c
+srcs-$(CFG_STM32_IPCC) += stm32_ipcc.c
 srcs-$(CFG_STM32_I2C) += stm32_i2c.c
 srcs-$(CFG_STM32_RNG) += stm32_rng.c
 srcs-$(CFG_STM32_SHARED_IO) += stm32_shared_io.c
@@ -77,10 +81,17 @@ srcs-$(CFG_VERSAL_PUF) += versal_puf.c
 srcs-$(CFG_VERSAL_HUK) += versal_huk.c
 srcs-$(CFG_CBMEM_CONSOLE) += cbmem_console.c
 srcs-$(CFG_RISCV_PLIC) += plic.c
+srcs-$(CFG_RISCV_ZKR_RNG) += riscv_zkr_rng.c
 srcs-$(CFG_HISILICON_CRYPTO_DRIVER) += hisi_trng.c
+srcs-$(CFG_WIDEVINE_HUK) += widevine_huk.c
+srcs-$(CFG_SEMIHOSTING_CONSOLE) += semihosting_console.c
+srcs-$(CFG_FFA_CONSOLE) += ffa_console.c
+srcs-$(CFG_OPENEDGES_OMC) += openedges_omc.c
+
 subdirs-y += crypto
 subdirs-$(CFG_BNXT_FW) += bnxt
 subdirs-$(CFG_DRIVERS_CLK) += clk
+subdirs-$(CFG_DRIVERS_FIREWALL) += firewall
 subdirs-$(CFG_DRIVERS_GPIO) += gpio
 subdirs-$(CFG_DRIVERS_I2C) += i2c
 subdirs-$(CFG_DRIVERS_NVMEM) += nvmem
@@ -93,3 +104,4 @@ subdirs-y += imx
 subdirs-y += pm
 subdirs-y += wdt
 subdirs-y += rtc
+subdirs-y += firewall
diff --git a/core/drivers/widevine_huk.c b/core/drivers/widevine_huk.c
new file mode 100644
index 0000000000000000000000000000000000000000..de266325dd4b9dc9bc2b0662626d8ed92f118cc2
--- /dev/null
+++ b/core/drivers/widevine_huk.c
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, The ChromiumOS Authors
+ */
+
+#include <kernel/tee_common_otp.h>
+#include <libfdt.h>
+#include <stdint.h>
+#include <string.h>
+
+static uint8_t dt_huk[HW_UNIQUE_KEY_LENGTH];
+static bool dt_huk_initialized;
+
+static TEE_Result init_widevine_huk_dt_data(void)
+{
+	int node = 0;
+	int len = 0;
+	void *fdt = NULL;
+	const void *value = NULL;
+
+	if (dt_huk_initialized)
+		return TEE_SUCCESS;
+
+	fdt = get_secure_dt();
+	if (!fdt)
+		return TEE_ERROR_NO_DATA;
+
+	node = fdt_path_offset(fdt, "/options/op-tee/widevine");
+	if (node < 0)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	value = fdt_getprop(fdt, node, "op-tee,hardware-unique-key", &len);
+	if (!value)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (len >= HW_UNIQUE_KEY_LENGTH)
+		len = HW_UNIQUE_KEY_LENGTH;
+	else
+		return TEE_ERROR_BAD_FORMAT;
+
+	memcpy(dt_huk, value, len);
+	dt_huk_initialized = true;
+
+	return TEE_SUCCESS;
+}
+
+service_init(init_widevine_huk_dt_data);
+
+TEE_Result tee_otp_get_hw_unique_key(struct tee_hw_unique_key *hwkey)
+{
+	TEE_Result result = TEE_SUCCESS;
+
+	/*
+	 * Ensure we get data from the DT, in case called before service_init()
+	 * handler.
+	 */
+	result = init_widevine_huk_dt_data();
+	if (result != TEE_SUCCESS)
+		return result;
+
+	memcpy(hwkey->data, dt_huk, HW_UNIQUE_KEY_LENGTH);
+
+	return TEE_SUCCESS;
+}
diff --git a/core/include/bench.h b/core/include/bench.h
deleted file mode 100644
index d9f3cdd3f2285f74baa7a512bbe471325baee6cb..0000000000000000000000000000000000000000
--- a/core/include/bench.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-/*
- * Copyright (c) 2017, Linaro Limited
- */
-
-#ifndef __BENCH_H
-#define __BENCH_H
-
-#include <inttypes.h>
-#include <mm/core_memprot.h>
-#include <mm/core_mmu.h>
-#include <optee_msg.h>
-
-/*
- * Cycle count divider is enabled (in PMCR),
- * CCNT value is incremented every 64th clock cycle
- */
-#define TEE_BENCH_DIVIDER		U(64)
-
-/* Max amount of timestamps per buffer */
-#define TEE_BENCH_MAX_STAMPS		U(32)
-#define TEE_BENCH_MAX_MASK		(TEE_BENCH_MAX_STAMPS - 1)
-
-#define OPTEE_MSG_RPC_CMD_BENCH_REG_NEW		U(0)
-#define OPTEE_MSG_RPC_CMD_BENCH_REG_DEL		U(1)
-
-/* OP-TEE susbsystems ids */
-#define TEE_BENCH_CLIENT	U(0x10000000)
-#define TEE_BENCH_KMOD		U(0x20000000)
-#define TEE_BENCH_CORE		U(0x30000000)
-#define TEE_BENCH_UTEE		U(0x40000000)
-#define TEE_BENCH_DUMB_TA	U(0xF0000001)
-
-/* storing timestamp */
-struct tee_time_st {
-	uint64_t cnt;	/* stores value from CNTPCT register */
-	uint64_t addr;	/* stores value from program counter register */
-	uint64_t src;	/* OP-TEE subsystem id */
-};
-
-/* per-cpu circular buffer for timestamps */
-struct tee_ts_cpu_buf {
-	uint64_t head;
-	uint64_t tail;
-	struct tee_time_st stamps[TEE_BENCH_MAX_STAMPS];
-};
-
-/* memory layout for shared memory, where timestamps will be stored */
-struct tee_ts_global {
-	uint64_t cores;
-	struct tee_ts_cpu_buf cpu_buf[];
-};
-
-#ifdef CFG_TEE_BENCHMARK
-void bm_timestamp(void);
-#else
-static inline void bm_timestamp(void) {}
-#endif /* CFG_TEE_BENCHMARK */
-
-#endif /* __BENCH_H */
diff --git a/core/include/console.h b/core/include/console.h
index f9cfaca5133fcd48bfee530be33b1c2fa833e925..c5962839e81acccddc6590d535e4cbd64878cfa0 100644
--- a/core/include/console.h
+++ b/core/include/console.h
@@ -14,6 +14,8 @@ void console_init(void);
 void console_putc(int ch);
 void console_flush(void);
 
+void plat_console_init(void);
+
 struct serial_chip;
 void register_serial_console(struct serial_chip *chip);
 
diff --git a/core/include/crypto/crypto.h b/core/include/crypto/crypto.h
index d0ee5f38f07d02a8a3c6dda5cf50aff80aff8ac4..940db07ad420e32ca23d1ef427cb55367ebd001d 100644
--- a/core/include/crypto/crypto.h
+++ b/core/include/crypto/crypto.h
@@ -261,11 +261,13 @@ TEE_Result crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
 					   uint8_t *dst, size_t *dst_len);
 TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo, struct rsa_keypair *key,
 					const uint8_t *label, size_t label_len,
+					uint32_t mgf_algo,
 					const uint8_t *src, size_t src_len,
 					uint8_t *dst, size_t *dst_len);
 TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
 					struct rsa_public_key *key,
 					const uint8_t *label, size_t label_len,
+					uint32_t mgf_algo,
 					const uint8_t *src, size_t src_len,
 					uint8_t *dst, size_t *dst_len);
 /* RSA SSA sign/verify: if salt_len == -1, use default value */
diff --git a/core/include/crypto/crypto_impl.h b/core/include/crypto/crypto_impl.h
index ccff72c59c26f56f3624a8e5ba7dfadb7b0db7c2..3925620716795bef2b92c90baa559840dcd20ef6 100644
--- a/core/include/crypto/crypto_impl.h
+++ b/core/include/crypto/crypto_impl.h
@@ -463,7 +463,7 @@ crypto_asym_alloc_ecc_public_key(struct ecc_public_key *key __unused,
 }
 
 static inline const struct crypto_ecc_keypair_ops *
-crypto_asym_get_keypair_ops(uint32_t key_type __unused)
+crypto_asym_get_ecc_keypair_ops(uint32_t key_type __unused)
 {
 	return NULL;
 }
@@ -532,14 +532,18 @@ TEE_Result sw_crypto_acipher_rsanopad_encrypt(struct rsa_public_key *key,
 TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 					   struct rsa_keypair *key,
 					   const uint8_t *label,
-					   size_t label_len, const uint8_t *src,
+					   size_t label_len,
+					   uint32_t mgf_algo,
+					   const uint8_t *src,
 					   size_t src_len, uint8_t *dst,
 					   size_t *dst_len);
 
 TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 					   struct rsa_public_key *key,
 					   const uint8_t *label,
-					   size_t label_len, const uint8_t *src,
+					   size_t label_len,
+					   uint32_t mgf_algo,
+					   const uint8_t *src,
 					   size_t src_len, uint8_t *dst,
 					   size_t *dst_len);
 
diff --git a/core/include/drivers/atmel_rstc.h b/core/include/drivers/atmel_rstc.h
index 6561d0b0d65b66d967981f25b014b12e04ff165c..b12e93c9f0443662cb10b9ef85090e236c74df30 100644
--- a/core/include/drivers/atmel_rstc.h
+++ b/core/include/drivers/atmel_rstc.h
@@ -6,12 +6,22 @@
 #define __DRIVERS_ATMEL_RSTC_H
 
 #include <compiler.h>
+#include <drivers/rstctrl.h>
 #include <stdbool.h>
+#include <util.h>
+
+#define RESET_ID_MASK		GENMASK_32(8, 5)
+#define RESET_ID_SHIFT		U(5)
+#define RESET_BIT_POS_MASK	GENMASK_32(4, 0)
+#define RESET_OFFSET(id)	(((id) & RESET_ID_MASK) >> RESET_ID_SHIFT)
+#define RESET_BIT_POS(id)	((id) & RESET_BIT_POS_MASK)
 
 #if defined(CFG_ATMEL_RSTC)
 bool atmel_rstc_available(void);
 
 void __noreturn atmel_rstc_reset(void);
+void sam_rstc_usb_por(unsigned char id, bool enable);
+struct rstctrl *sam_get_rstctrl(unsigned int reset_id);
 #else
 static inline bool atmel_rstc_available(void)
 {
@@ -19,6 +29,12 @@ static inline bool atmel_rstc_available(void)
 }
 
 static inline void atmel_rstc_reset(void) {}
+static inline void sam_rstc_usb_por(unsigned char id __unused,
+				    bool enable __unused) {}
+static inline struct rstctrl *sam_get_rstctrl(unsigned int reset_id __unused)
+{
+	return NULL;
+}
 #endif
 
 #endif /* __DRIVERS_ATMEL_RSTC_H */
diff --git a/core/include/drivers/atmel_shdwc.h b/core/include/drivers/atmel_shdwc.h
index fbc7ead67c09fd9c267ca0085c8acbe9efe48240..4b449d5dfbd0e89055010bc61f32295ddefbbf14 100644
--- a/core/include/drivers/atmel_shdwc.h
+++ b/core/include/drivers/atmel_shdwc.h
@@ -27,6 +27,7 @@
 #define AT91_SHDW_WKUPDBC(x)	(SHIFT_U32((x), AT91_SHDW_WKUPDBC_SHIFT) & \
 				 AT91_SHDW_WKUPDBC_MASK)
 #define AT91_SHDW_RTCWKEN	BIT32(17)
+#define AT91_SHDW_RTTWKEN	BIT32(16)
 
 /* Shut Down Status Register */
 #define AT91_SHDW_SR		0x08
diff --git a/core/include/drivers/clk.h b/core/include/drivers/clk.h
index 20b7d54052a0d29a249fe99e10544266dc2b5b17..3b3b96618abe069a062f6050dd425b6f5e71b371 100644
--- a/core/include/drivers/clk.h
+++ b/core/include/drivers/clk.h
@@ -14,6 +14,10 @@
 /* Flags for clock */
 #define CLK_SET_RATE_GATE	BIT(0) /* must be gated across rate change */
 #define CLK_SET_PARENT_GATE	BIT(1) /* must be gated across re-parent */
+#define CLK_DUTY_CYCLE_PARENT	BIT(2) /* forward duty cycle call to parent */
+#define CLK_SET_RATE_PARENT	BIT(3) /* propagate rate change up to parent */
+#define CLK_SET_RATE_UNGATE	BIT(4) /* clock needs to run to set rate */
+#define CLK_SET_PARENT_PRE_ENABLE	BIT(5) /* enable new parent if needed */
 
 /**
  * struct clk - Clock structure
@@ -45,7 +49,18 @@ struct clk {
 };
 
 /**
- * struct clk_ops
+ * struct clk_duty_cycle - Encoding the duty cycle ratio of a clock
+ *
+ * @num:	Numerator of the duty cycle ratio
+ * @den:	Denominator of the duty cycle ratio
+ */
+struct clk_duty_cycle {
+	unsigned int num;
+	unsigned int den;
+};
+
+/**
+ * struct clk_ops - Clock operations
  *
  * @enable: Enable the clock
  * @disable: Disable the clock
@@ -53,7 +68,13 @@ struct clk {
  * @get_parent: Get the current parent index of the clock
  * @set_rate: Set the clock rate
  * @get_rate: Get the clock rate
- * @get_rates_array: Get the supported clock rates as array
+ * @get_rates_array: Get the supported clock rates as array in ascending order
+ * @get_rates_steps: Get support clock rates by min/max/step representation
+ * @get_duty_cycle: Get duty cytcle of the clock
+ *
+ * All clock operations are expected to execute in a interruptible thread
+ * context at the exclusion of power management sequence where non secure
+ * world is not operating (power off, suspend, resume).
  */
 struct clk_ops {
 	TEE_Result (*enable)(struct clk *clk);
@@ -66,10 +87,14 @@ struct clk_ops {
 				  unsigned long parent_rate);
 	TEE_Result (*get_rates_array)(struct clk *clk, size_t start_index,
 				      unsigned long *rates, size_t *nb_elts);
+	TEE_Result (*get_rates_steps)(struct clk *clk, unsigned long *min,
+				      unsigned long *max, unsigned long *step);
+	TEE_Result (*get_duty_cycle)(struct clk *clk,
+				     struct clk_duty_cycle *duty_cycle);
 };
 
 /**
- * Return the clock name
+ * clk_get_name() - Return the clock name
  *
  * @clk: Clock for which the name is needed
  * Return a const char * pointing to the clock name
@@ -80,7 +105,7 @@ static inline const char *clk_get_name(struct clk *clk)
 }
 
 /**
- * clk_alloc - Allocate a clock structure
+ * clk_alloc() - Allocate a clock structure
  *
  * @name: Clock name
  * @ops: Clock operations
@@ -93,14 +118,14 @@ struct clk *clk_alloc(const char *name, const struct clk_ops *ops,
 		      struct clk **parent_clks, size_t parent_count);
 
 /**
- * clk_free - Free a clock structure
+ * clk_free() - Free a clock structure
  *
  * @clk: Clock to be freed or NULL
  */
 void clk_free(struct clk *clk);
 
 /**
- * clk_register - Register a clock within the clock framework
+ * clk_register() - Register a clock within the clock framework
  *
  * @clk: Clock struct to be registered
  * Return a TEE_Result compliant value
@@ -108,7 +133,7 @@ void clk_free(struct clk *clk);
 TEE_Result clk_register(struct clk *clk);
 
 /**
- * clk_get_rate - Get clock rate
+ * clk_get_rate() - Get clock rate
  *
  * @clk: Clock for which the rate is needed
  * Return the clock rate in Hz
@@ -116,7 +141,7 @@ TEE_Result clk_register(struct clk *clk);
 unsigned long clk_get_rate(struct clk *clk);
 
 /**
- * clk_set_rate - Set a clock rate
+ * clk_set_rate() - Set a clock rate
  *
  * @clk: Clock to be set with the rate
  * @rate: Rate to set in Hz
@@ -125,7 +150,7 @@ unsigned long clk_get_rate(struct clk *clk);
 TEE_Result clk_set_rate(struct clk *clk, unsigned long rate);
 
 /**
- * clk_enable - Enable a clock and its ascendance
+ * clk_enable() - Enable a clock and its ascendance
  *
  * @clk: Clock to be enabled
  * Return a TEE_Result compliant value
@@ -133,14 +158,14 @@ TEE_Result clk_set_rate(struct clk *clk, unsigned long rate);
 TEE_Result clk_enable(struct clk *clk);
 
 /**
- * clk_disable - Disable a clock
+ * clk_disable() - Disable a clock
  *
  * @clk: Clock to be disabled
  */
 void clk_disable(struct clk *clk);
 
 /**
- * clk_is_enabled - Informative state on the clock
+ * clk_is_enabled() - Informative state on the clock
  *
  * This function is useful during specific system sequences where core
  * executes atomically (primary core boot, some low power sequences).
@@ -150,7 +175,7 @@ void clk_disable(struct clk *clk);
 bool clk_is_enabled(struct clk *clk);
 
 /**
- * clk_get_parent - Get the current clock parent
+ * clk_get_parent() - Get the current clock parent
  *
  * @clk: Clock for which the parent is needed
  * Return the clock parent or NULL if there is no parent
@@ -158,7 +183,7 @@ bool clk_is_enabled(struct clk *clk);
 struct clk *clk_get_parent(struct clk *clk);
 
 /**
- * clk_get_num_parents - Get the number of parents for a clock
+ * clk_get_num_parents() - Get the number of parents for a clock
  *
  * @clk: Clock for which the number of parents is needed
  * Return the number of parents
@@ -169,7 +194,7 @@ static inline size_t clk_get_num_parents(struct clk *clk)
 }
 
 /**
- * Get a clock parent by its index
+ * clk_get_parent_by_index() - Get a clock parent by its index
  *
  * @clk: Clock for which the parent is needed
  * @pidx: Parent index for the clock
@@ -178,7 +203,7 @@ static inline size_t clk_get_num_parents(struct clk *clk)
 struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx);
 
 /**
- * clk_set_parent - Set the current clock parent
+ * clk_set_parent() - Set the current clock parent
  *
  * @clk: Clock for which the parent should be set
  * @parent: Parent clock to set
@@ -187,7 +212,7 @@ struct clk *clk_get_parent_by_index(struct clk *clk, size_t pidx);
 TEE_Result clk_set_parent(struct clk *clk, struct clk *parent);
 
 /**
- * clk_get_rates_array - Get supported rates as an array
+ * clk_get_rates_array() - Get supported rates in ascending order
  *
  * @clk: Clock for which the rates are requested
  * @start_index: start index of requested rates
@@ -199,8 +224,34 @@ TEE_Result clk_set_parent(struct clk *clk, struct clk *parent);
 TEE_Result clk_get_rates_array(struct clk *clk, size_t start_index,
 			       unsigned long *rates, size_t *nb_elts);
 
-/* Print current clock tree summary to output console with debug trace level */
+/**
+ * clk_get_rates_steps() - Get supported rates as min/max/step triplet
+ *
+ * @clk: Clock for which the rates are requested
+ * @min: Output min supported rate in Hz
+ * @max: Output max supported rate in Hz
+ * @step: Output rate step in Hz
+ * Returns a TEE_Result compliant value
+ */
+TEE_Result clk_get_rates_steps(struct clk *clk, unsigned long *min,
+			       unsigned long *max, unsigned long *step);
+
+/**
+ * clk_get_duty_cycle() - Get clock duty cycle
+ *
+ * @clk: Clock for which the duty cycle is requested
+ * @duty: Output duty cycle info
+ * Return a TEE_Result compliant value
+ */
+TEE_Result clk_get_duty_cycle(struct clk *clk,
+			      struct clk_duty_cycle *duty_cycle);
+
 #ifdef CFG_DRIVERS_CLK
+/**
+ * clk_print_tree() - Print current clock tree summary to output console
+ *
+ * The clock is printed with the info trace level.
+ */
 void clk_print_tree(void);
 #else
 static inline void clk_print_tree(void)
diff --git a/core/include/drivers/clk_dt.h b/core/include/drivers/clk_dt.h
index 5ea10ade83395dc88a474f9f9ebcb976c3aba512..ba55d5e876a4c5537f36dadc6fd9b47b6547c753 100644
--- a/core/include/drivers/clk_dt.h
+++ b/core/include/drivers/clk_dt.h
@@ -13,7 +13,7 @@
 #include <sys/queue.h>
 
 /**
- * CLK_DT_DECLARE - Declare a clock driver
+ * CLK_DT_DECLARE() - Declare a clock driver
  * @__name: Clock driver name
  * @__compat: Compatible string
  * @__probe: Clock probe function
@@ -31,7 +31,7 @@
 	}
 
 /**
- * clk_dt_get_by_index - Get a clock at a specific index in "clocks" property
+ * clk_dt_get_by_index() - Get a clock at a specific index in "clocks" property
  *
  * @fdt: Device tree to work on
  * @nodeoffset: Node offset of the subnode containing a clock property
@@ -47,7 +47,7 @@ TEE_Result clk_dt_get_by_index(const void *fdt, int nodeoffset,
 			       unsigned int clk_idx, struct clk **clk);
 
 /**
- * clk_dt_get_by_name - Get a clock matching a name in "clock-names" property
+ * clk_dt_get_by_name() - Get a clock matching a name in "clock-names" property
  *
  * @fdt: Device tree to work on
  * @nodeoffset: Node offset of the subnode containing a clock property
@@ -73,7 +73,7 @@ typedef TEE_Result (*clk_dt_get_func)(struct dt_pargs *args, void *data,
 				      struct clk **out_clk);
 
 /**
- * clk_dt_register_clk_provider - Register a clock provider
+ * clk_dt_register_clk_provider() - Register a clock provider
  *
  * @fdt: Device tree to work on
  * @nodeoffset: Node offset of the clock
@@ -92,8 +92,12 @@ static inline TEE_Result clk_dt_register_clk_provider(const void *fdt,
 }
 
 /**
- * clk_dt_get_simple_clk: simple clock matching function for single clock
+ * clk_dt_get_simple_clk() - Simple clock matching function for single clock
  * providers
+ *
+ * @args: Unused argument as there is no description to parse
+ * @data: Pointer to data given at clk_dt_register_clk_provider() call
+ * @out_clk: Output clock reference filled with @data
  */
 static inline TEE_Result clk_dt_get_simple_clk(struct dt_pargs *args __unused,
 					       void *data, struct clk **out_clk)
diff --git a/core/include/drivers/ffa_console.h b/core/include/drivers/ffa_console.h
new file mode 100644
index 0000000000000000000000000000000000000000..b2162f0df46a18175b54248f6bd0504d2fb03e00
--- /dev/null
+++ b/core/include/drivers/ffa_console.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, NVIDIA CORPORATION
+ */
+
+#ifndef FFA_CONSOLE_H
+#define FFA_CONSOLE_H
+
+#ifdef CFG_FFA_CONSOLE
+/*
+ * Initialize console which uses FFA_CONSOLE_LOG of hafnium.
+ */
+void ffa_console_init(void);
+#else
+static inline void ffa_console_init(void)
+{
+}
+#endif
+
+#endif /* FFA_CONSOLE_H */
diff --git a/core/include/drivers/firewall.h b/core/include/drivers/firewall.h
new file mode 100644
index 0000000000000000000000000000000000000000..5bf7ddb73c691398c7be43fcb43019b98b293550
--- /dev/null
+++ b/core/include/drivers/firewall.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_FIREWALL_H
+#define __DRIVERS_FIREWALL_H
+
+#include <compiler.h>
+#include <drivers/firewall_device.h>
+#include <mm/core_memprot.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <tee_api_defines.h>
+#include <types_ext.h>
+
+struct firewall_controller_ops;
+
+/**
+ * struct firewall_controller - Firewall controller supplying services
+ *
+ * @ops: Operation handlers
+ * @name: Name of the firewall controller
+ * @base: Base address of the firewall controller
+ * @priv: Private data of the firewall controller
+ */
+struct firewall_controller {
+	const struct firewall_controller_ops *ops;
+	const char *name;
+	struct io_pa_va *base;
+	void *priv;
+};
+
+/**
+ * struct firewall_controller_ops - Firewall controller operation handlers
+ *
+ * @set_conf: Callback used to set given firewall configuration
+ * @check_access: Callback used to check access for a consumer on a resource
+ * against a firewall controller
+ * @acquire_access: Callback used to acquire access for OP-TEE on a resource
+ * against a firewall controller
+ * @release_access: Callback used to release resources taken by a consumer when
+ * the access was acquired with @acquire_access
+ * @check_memory_access: Callback used to check access for a consumer to a
+ * memory range covered by a firewall controller, for read and/or write accesses
+ * @acquire_memory_access: Callback used to acquire access for OP-TEE to a
+ * memory range covered by a firewall controller, for read and/or write accesses
+ * @release_memory_access: Callback used to release resources taken by a
+ * consumer when the memory access was acquired with @acquire_memory_access
+ * @set_memory_conf: Callback to set access rights to a physical memory range
+ */
+struct firewall_controller_ops {
+	TEE_Result (*set_conf)(struct firewall_query *conf);
+	TEE_Result (*check_access)(struct firewall_query *conf);
+	TEE_Result (*acquire_access)(struct firewall_query *conf);
+	void (*release_access)(struct firewall_query *conf);
+	TEE_Result (*check_memory_access)(struct firewall_query *fw,
+					  paddr_t paddr, size_t size,
+					  bool read, bool write);
+	TEE_Result (*acquire_memory_access)(struct firewall_query *fw,
+					    paddr_t paddr, size_t size,
+					    bool read, bool write);
+	void (*release_memory_access)(struct firewall_query *fw,
+				      paddr_t paddr, size_t size, bool read,
+				      bool write);
+	TEE_Result (*set_memory_conf)(struct firewall_query *fw, paddr_t paddr,
+				      size_t size);
+};
+
+#ifdef CFG_DRIVERS_FIREWALL
+/**
+ * firewall_dt_controller_register() - Register a firewall controller to the
+ * firewall framework
+ * @fdt: FDT to work on
+ * @node: DT node of the controller
+ * @ctrl: Firewall controller to register
+ */
+TEE_Result firewall_dt_controller_register(const void *fdt, int node,
+					   struct firewall_controller *ctrl);
+
+#else /* CFG_DRIVERS_FIREWALL */
+
+static inline TEE_Result
+firewall_dt_controller_register(const void *fdt __unused, int node __unused,
+				struct firewall_controller *ctrl __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+#endif /* CFG_DRIVERS_FIREWALL */
+#endif /* __DRIVERS_FIREWALL_H */
diff --git a/core/include/drivers/firewall_device.h b/core/include/drivers/firewall_device.h
new file mode 100644
index 0000000000000000000000000000000000000000..0ec2912c00475e72f0efb361749811e86dc4add2
--- /dev/null
+++ b/core/include/drivers/firewall_device.h
@@ -0,0 +1,241 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_FIREWALL_DEVICE_H
+#define __DRIVERS_FIREWALL_DEVICE_H
+
+#include <stdint.h>
+#include <tee_api.h>
+#include <types_ext.h>
+#include <util.h>
+
+/* Opaque reference to firewall_controller */
+struct firewall_controller;
+
+/**
+ * struct firewall_query - Information on a device's firewall.
+ *
+ * @ctrl: Pointer referencing a firewall controller of the device. It is opaque
+ * so a device cannot manipulate the controller's ops or access the controller's
+ * data
+ * @args: Firewall arguments that are implementation dependent
+ * @arg_count: Number of arguments
+ */
+struct firewall_query {
+	struct firewall_controller *ctrl;
+	uint32_t *args;
+	size_t arg_count;
+};
+
+#ifdef CFG_DRIVERS_FIREWALL
+/**
+ * firewall_dt_get_by_index() - Get the firewall configuration associated to a
+ * given index for a device node.
+ *
+ * @fdt: FDT to work on
+ * @node: Device node to read from
+ * @index: Index of the entry in the property
+ * @out_fw: Firewall query reference
+ *
+ * Returns TEE_SUCCESS on success, TEE_ERROR_ITEM_NOT_FOUND if there's no match
+ * with a firewall controller or appropriate TEE_Result error code if an
+ * error occurred.
+ */
+TEE_Result firewall_dt_get_by_index(const void *fdt, int node,
+				    unsigned int index,
+				    struct firewall_query **out_fw);
+
+/**
+ * firewall_dt_get_by_name() - Get the firewall configuration associated to a
+ * given name for a device node.
+ *
+ * @fdt: FDT to work on
+ * @node: Device node to read from
+ * @name: Name of the firewall configuration to search for
+ * @out_fw: Firewall query reference
+ *
+ * Returns TEE_SUCCESS on success, TEE_ERROR_ITEM_NOT_FOUND if there's no match
+ * with a firewall controller or appropriate TEE_Result error code if an
+ * error occurred.
+ */
+TEE_Result firewall_dt_get_by_name(const void *fdt, int node, const char *name,
+				   struct firewall_query **out_fw);
+
+/**
+ * firewall_set_configuration() - Reconfigure the firewall controller associated
+ * to the given firewall configuration with it.
+ *
+ * @fw:	Firewall query containing the configuration to set
+ */
+TEE_Result firewall_set_configuration(struct firewall_query *fw);
+
+/**
+ * firewall_check_access() - Check if the access is authorized for a consumer
+ * and the given firewall configuration according to the settings of its
+ * firewall controller
+ *
+ * @fw:	Firewall query containing the configuration to check against its
+ * firewall controller
+ */
+TEE_Result firewall_check_access(struct firewall_query *fw);
+
+/**
+ * firewall_acquire_access() - Check if OP-TEE can access the consumer and
+ * acquire potential resources to allow the access
+ *
+ * @fw:	Firewall query containing the configuration to check against its
+ * firewall controller
+ */
+TEE_Result firewall_acquire_access(struct firewall_query *fw);
+
+/**
+ * firewall_check_memory_access() - Check if a consumer can access the memory
+ * address range, in read and/or write mode and given the firewall
+ * configuration, against a firewall controller
+ *
+ * @fw: Firewall query containing the configuration to check against its
+ * firewall controller
+ * @paddr: Physical base address of the memory range to check
+ * @size: Size of the memory range to check
+ * @read: If true, check rights for a read access
+ * @write: If true, check rights for a write access
+ */
+TEE_Result firewall_check_memory_access(struct firewall_query *fw,
+					paddr_t paddr, size_t size, bool read,
+					bool write);
+
+/**
+ * firewall_acquire_memory_access() - Request OP-TEE access, in read and/or
+ * write mode, to the given memory address range against a firewall controller
+ * and acquire potential resources to allow the access
+ *
+ * @fw: Firewall query containing the configuration to check against its
+ * firewall controller
+ * @paddr: Physical base address of the memory range to check
+ * @size: Size of the memory range to check
+ * @read: Check rights for a read access
+ * @write: Check rights for a write access
+ */
+TEE_Result firewall_acquire_memory_access(struct firewall_query *fw,
+					  paddr_t paddr, size_t size, bool read,
+					  bool write);
+
+/**
+ * firewall_release_access() - Release resources obtained by a call to
+ * firewall_acquire_access()
+ *
+ * @fw:	Firewall query containing the configuration to release
+ */
+void firewall_release_access(struct firewall_query *fw);
+
+/**
+ * firewall_release_memory_access() - Release resources obtained by a call to
+ * firewall_acquire_memory_access()
+ *
+ * @fw:	Firewall configuration to release
+ * @paddr: Physical base address of the memory range to release
+ * @size: Size of the memory range to release
+ * @read: Release rights for read accesses
+ * @write: Release rights for write accesses
+ */
+void firewall_release_memory_access(struct firewall_query *fw, paddr_t paddr,
+				    size_t size, bool read, bool write);
+
+/**
+ * firewall_set_memory_configuration() - Reconfigure a memory range with
+ * the given firewall configuration
+ *
+ * @fw: Firewall query containing the configuration to set
+ * @paddr: Physical base address of the memory range
+ * @size: Size of the memory range
+ */
+TEE_Result firewall_set_memory_configuration(struct firewall_query *fw,
+					     paddr_t paddr, size_t size);
+
+/**
+ * firewall_put() - Release a firewall_query structure allocated by
+ * firewall_dt_get_by_index() or firewall_dt_get_by_name()
+ *
+ * @fw:	Firewall query to put
+ */
+void firewall_put(struct firewall_query *fw);
+
+#else /* CFG_DRIVERS_FIREWALL */
+
+static inline TEE_Result
+firewall_dt_get_by_index(const void *fdt __unused, int node __unused,
+			 unsigned int index __unused,
+			 struct firewall_query **out_fw __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_dt_get_by_name(const void *fdt __unused, int node __unused,
+			const char *name __unused,
+			struct firewall_query **out_fw __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_check_access(struct firewall_query *fw __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_acquire_access(struct firewall_query *fw __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_check_memory_access(struct firewall_query *fw __unused,
+			     paddr_t paddr __unused, size_t size __unused,
+			     bool read __unused, bool write __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_acquire_memory_access(struct firewall_query *fw __unused,
+			       paddr_t paddr __unused, size_t size __unused,
+			       bool read __unused, bool write __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline void
+firewall_release_access(struct firewall_query *fw __unused)
+{
+}
+
+static inline void
+firewall_release_memory_access(struct firewall_query *fw __unused,
+			       paddr_t paddr __unused, size_t size __unused,
+			       bool read __unused, bool write __unused)
+{
+}
+
+static inline TEE_Result
+firewall_set_configuration(struct firewall_query *fw __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline TEE_Result
+firewall_set_memory_configuration(struct firewall_query *fw __unused,
+				  paddr_t paddr __unused, size_t size __unused)
+{
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline void firewall_put(struct firewall_query *fw __unused)
+{
+}
+
+#endif /* CFG_DRIVERS_FIREWALL */
+#endif /* __DRIVERS_FIREWALL_DEVICE_H */
diff --git a/core/include/drivers/i2c.h b/core/include/drivers/i2c.h
index 1cc9cdaefbb1dd794a57711d486596a9e35a23b5..287689cc1eb652ceeb863f2be1ec7aad5e3a69a5 100644
--- a/core/include/drivers/i2c.h
+++ b/core/include/drivers/i2c.h
@@ -221,7 +221,7 @@ static inline TEE_Result i2c_smbus_raw(struct i2c_dev *i2c_dev __unused,
 
 static inline TEE_Result i2c_dt_get_dev(const void *fdt __unused,
 					int nodeoffset __unused,
-					struct i2c_dev **i2c_dev)
+					struct i2c_dev **i2c_dev __unused)
 {
 	return TEE_ERROR_NOT_SUPPORTED;
 }
diff --git a/core/include/drivers/imx_mu.h b/core/include/drivers/imx_mu.h
index 716af956622f255ab4ff755d403ca99f7f9498a1..61fc111805430af0a862ee886c7cbd15cca1992e 100644
--- a/core/include/drivers/imx_mu.h
+++ b/core/include/drivers/imx_mu.h
@@ -16,7 +16,7 @@
 #define IMX_MU_MSG_SIZE	  17
 #define IMX_MU_NB_CHANNEL 4
 
-#if defined(CFG_MX8ULP) || defined(CFG_MX93)
+#if defined(CFG_MX8ULP) || defined(CFG_MX93) || defined(CFG_MX91)
 struct imx_mu_msg_header {
 	uint8_t version;
 	uint8_t size;
diff --git a/core/include/drivers/openedges_omc.h b/core/include/drivers/openedges_omc.h
new file mode 100644
index 0000000000000000000000000000000000000000..d62c8f4a09e3e8eacf1d06842c397784cf3a7864
--- /dev/null
+++ b/core/include/drivers/openedges_omc.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Telechips Inc.
+ */
+
+#ifndef __DRIVERS_OPENEDGES_OMC_H
+#define __DRIVERS_OPENEDGES_OMC_H
+
+#include <types_ext.h>
+#include <util.h>
+
+#define OMC_FLAG_RELATIVE_ADDR	BIT(0)
+
+enum omc_action {
+	OMC_ACTION_NONE = 0,
+	OMC_ACTION_ERR,
+	OMC_ACTION_INT,
+	OMC_ACTION_ERR_INT
+};
+
+struct omc_region_config {
+	uint32_t filters;
+	uint64_t base;
+	uint64_t top;
+	uint32_t ns_device_access;
+	uint32_t flags;
+};
+
+void omc_init(vaddr_t base, uint32_t size, uint8_t num);
+void omc_configure_region(uint8_t region, const struct omc_region_config *cfg);
+void omc_set_action(enum omc_action action);
+
+void omc_fail_dump(uint8_t filter);
+void omc_int_clear(uint8_t filter);
+
+#endif /* __DRIVERS_OPENEDGES_OMC_H */
diff --git a/core/include/drivers/pm/sam/atmel_pm.h b/core/include/drivers/pm/sam/atmel_pm.h
index a9801d6dc251e8e272d759cf7009661702fdde19..d6d4678267ce3a4d59196e84ad9ad8639b5696b8 100644
--- a/core/include/drivers/pm/sam/atmel_pm.h
+++ b/core/include/drivers/pm/sam/atmel_pm.h
@@ -25,7 +25,7 @@ void atmel_pm_cpu_idle(void);
 
 TEE_Result atmel_pm_suspend(uintptr_t entry, struct sm_nsec_ctx *nsec);
 
-TEE_Result sama5d2_pm_init(const void *fdt, vaddr_t shdwc);
+TEE_Result sam_pm_init(const void *fdt, vaddr_t shdwc);
 
 enum sm_handler_ret at91_pm_set_suspend_mode(struct thread_smc_args *args);
 
@@ -46,8 +46,8 @@ static inline TEE_Result atmel_pm_suspend(uintptr_t entry __unused,
 	return TEE_ERROR_NOT_SUPPORTED;
 }
 
-static inline TEE_Result sama5d2_pm_init(const void *fdt __unused,
-					 vaddr_t shdwc __unused)
+static inline TEE_Result sam_pm_init(const void *fdt __unused,
+				     vaddr_t shdwc __unused)
 {
 	return TEE_SUCCESS;
 }
diff --git a/core/include/drivers/regulator.h b/core/include/drivers/regulator.h
index c9266bf323c6dfce501b6f8a0e8691199068b3b4..4642087ecd9ec49e41a681b0d3a14bf2da9b0c6e 100644
--- a/core/include/drivers/regulator.h
+++ b/core/include/drivers/regulator.h
@@ -7,7 +7,7 @@
 
 #include <assert.h>
 #include <bitstring.h>
-#include <kernel/mutex.h>
+#include <kernel/mutex_pm_aware.h>
 #include <sys/queue.h>
 #include <tee_api_types.h>
 #include <stdbool.h>
@@ -85,10 +85,9 @@ struct regulator_voltages_desc {
  * @name: Regulator string name for debug purpose or NULL
  * @min_uv: Min possible voltage level in microvolt (uV)
  * @max_uv: Max possible voltage level in microvolt (uV)
- * @cur_uv: Current voltage level in microvolt (uV)
  * @flags: REGULATOR_* property flags
  * @refcount: Regulator enable request reference counter
- * @lock: Mutex for concurrent access protection
+ * @mutex: Concurrent access protection considering PM context sequences
  * @voltages_fallback: Default supported voltage range description
  * @link: Link in initialized regulator list
  */
@@ -101,10 +100,9 @@ struct regulator {
 	int min_uv;
 	int max_uv;
 	/* Fields internal to regulator framework */
-	int cur_uv;
 	unsigned int flags;
 	unsigned int refcount;
-	struct mutex lock;	/* Concurrent access protection */
+	struct mutex_pm_aware mutex;
 	struct voltages_fallback {
 		struct regulator_voltages_desc desc;
 		int levels[3];
@@ -283,13 +281,10 @@ static inline TEE_Result regulator_set_min_voltage(struct regulator *regulator)
 }
 
 /*
- * regulator_get_voltage() - Get regulator current level in microvolt
+ * regulator_get_voltage() - Get regulator effective voltage level in microvolt
  * @regulator: Regulator reference
  */
-static inline int regulator_get_voltage(struct regulator *regulator)
-{
-	return regulator->cur_uv;
-}
+int regulator_get_voltage(struct regulator *regulator);
 
 /*
  * regulator_get_range() - Get regulator min and/or max support levels
@@ -323,7 +318,7 @@ TEE_Result regulator_supported_voltages(struct regulator *regulator,
 					struct regulator_voltages_desc **desc,
 					const int **levels);
 
-/* Print current regulator tree summary to console with debug trace level */
+/* Print current regulator tree summary to console with info trace level */
 #ifdef CFG_DRIVERS_REGULATOR
 void regulator_print_tree(void);
 #else
diff --git a/core/include/drivers/rstctrl.h b/core/include/drivers/rstctrl.h
index d1112404d42a7f40d343038929eeedc5bc22d550..ab3471d8f4614c1c7576486b18f5aa035277948f 100644
--- a/core/include/drivers/rstctrl.h
+++ b/core/include/drivers/rstctrl.h
@@ -70,10 +70,10 @@ struct rstctrl {
 #define RSTCTRL_NO_TIMEOUT	0
 
 /*
- * rstctrl_assert_to - Assert reset control possibly with timeout
- * rstctrl_assert - Assert reset control
- * rstctrl_deassert_to - Deassert reset control possibly with timeout
- * rstctrl_deassert - Deassert reset control
+ * rstctrl_assert_to() - Assert reset control possibly with timeout
+ * rstctrl_assert() - Assert reset control
+ * rstctrl_deassert_to() - Deassert reset control possibly with timeout
+ * rstctrl_deassert() - Deassert reset control
  *
  * @rstctrl: Reset controller
  * @to_us: Timeout in microseconds
@@ -102,7 +102,7 @@ static inline TEE_Result rstctrl_deassert(struct rstctrl *rstctrl)
 }
 
 /*
- * rstctrl_name - Get a name for the reset level control or NULL
+ * rstctrl_name() - Get a name for the reset level control or NULL
  *
  * @rstctrl: Reset controller
  * Return a pointer to controller name or NULL
@@ -116,7 +116,7 @@ static inline const char *rstctrl_name(struct rstctrl *rstctrl)
 }
 
 /**
- * rstctrl_dt_get_exclusive - Get exclusive access to reset controller
+ * rstctrl_get_exclusive() - Get exclusive access to reset controller
  *
  * @rstctrl: Reset controller
  * Return a TEE_Result compliant value
@@ -124,14 +124,14 @@ static inline const char *rstctrl_name(struct rstctrl *rstctrl)
 TEE_Result rstctrl_get_exclusive(struct rstctrl *rstctrl);
 
 /**
- * rstctrl_put_exclusive - Release exclusive access to target
+ * rstctrl_put_exclusive() - Release exclusive access to target
  *
  * @rstctrl: Reset controller
  */
 void rstctrl_put_exclusive(struct rstctrl *rstctrl);
 
 /**
- * rstctrl_ops_is_valid - Check reset controller ops is valid
+ * rstctrl_ops_is_valid() - Check reset controller ops is valid
  *
  * @ops: Reference to reset controller operator instance
  */
@@ -142,7 +142,7 @@ static inline bool rstctrl_ops_is_valid(const struct rstctrl_ops *ops)
 
 #ifdef CFG_DT
 /**
- * rstctrl_dt_get_by_index - Get a reset controller at a specific index in
+ * rstctrl_dt_get_by_index() - Get a reset controller at a specific index in
  * 'resets' property
  *
  * @fdt: Device tree to work on
@@ -182,7 +182,7 @@ static inline TEE_Result rstctrl_dt_get_by_index(const void *fdt __unused,
 #endif /*CFG_DT*/
 
 /**
- * rstctrl_dt_get_by_name - Get a reset controller matching a name in the
+ * rstctrl_dt_get_by_name() - Get a reset controller matching a name in the
  * 'reset-names' property
  *
  * @fdt: Device tree to work on
@@ -203,14 +203,14 @@ TEE_Result rstctrl_dt_get_by_name(const void *fdt, int nodeoffset,
  * devicetree properties
  *
  * @args: Pointer to devicetree description of the reset controller to parse
- * @data: Pointer to data given at rstctrl_dt_register_provider() call
+ * @data: Pointer to data given at rstctrl_register_provider() call
  * @rstctrl: Output reset controller reference upon success
  */
 typedef TEE_Result (*rstctrl_dt_get_func)(struct dt_pargs *args, void *data,
 					  struct rstctrl **out_rstctrl);
 
 /**
- * rstctrl_dt_register_provider - Register a reset controller provider
+ * rstctrl_register_provider() - Register a reset controller provider
  *
  * @fdt: Device tree to work on
  * @nodeoffset: Node offset of the reset controller
@@ -228,4 +228,3 @@ static inline TEE_Result rstctrl_register_provider(const void *fdt,
 					   DT_DRIVER_RSTCTRL);
 }
 #endif /* __DRIVERS_RSTCTRL_H */
-
diff --git a/core/include/drivers/sam/sama7-ddr.h b/core/include/drivers/sam/sama7-ddr.h
new file mode 100644
index 0000000000000000000000000000000000000000..8bbf691e73b26e6e46768a07df3baa05e7798a28
--- /dev/null
+++ b/core/include/drivers/sam/sama7-ddr.h
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Microchip SAMA7 UDDR Controller and DDR3 PHY Controller registers offsets
+ * and bit definitions.
+ *
+ * Copyright (C) [2024] Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Tony Han <tony.han@microchip.com>
+ */
+
+#ifndef __SAMA7_DDR_H__
+#define __SAMA7_DDR_H__
+
+/* DDR3PHY */
+/* DDR3PHY PHY Initialization Register */
+#define DDR3PHY_PIR		0x04
+#define DDR3PHY_PIR_DLLBYP	BIT(17)	/* DLL Bypass */
+#define DDR3PHY_PIR_ITMSRST	BIT(4)	/* Interface Timing Module Soft Reset */
+#define DDR3PHY_PIR_DLLLOCK	BIT(2)	/* DLL Lock */
+#define DDR3PHY_PIR_DLLSRST	BIT(1)	/* DLL Soft Rest */
+#define DDR3PHY_PIR_INIT	BIT(0)	/* Initialization Trigger */
+
+/* DDR3PHY PHY General Configuration Register */
+#define DDR3PHY_PGCR		0x08
+#define DDR3PHY_PGCR_CKDV1	BIT(13)	/* CK# Disable Value */
+#define DDR3PHY_PGCR_CKDV0	BIT(12)	/* CK Disable Value */
+
+/* DDR3PHY PHY General Status Register */
+#define DDR3PHY_PGSR		0x0C
+#define DDR3PHY_PGSR_IDONE	BIT(0)	/* Initialization Done */
+
+/* DDR3PHY AC DLL Control Register */
+#define DDR3PHY_ACDLLCR		0x14
+#define DDR3PHY_ACDLLCR_DLLSRST BIT(30)	/* DLL Soft Reset */
+
+/* DDR3PHY AC I/O Configuration Register */
+#define DDR3PHY_ACIOCR			0x24
+#define DDR3PHY_ACIOCR_CSPDD_CS0	BIT(18)	/* CS#[0] Power Down Driver */
+#define DDR3PHY_ACIOCR_CKPDD_CK0	BIT(8)	/* CK[0] Power Down Driver */
+#define DDR3PHY_ACIORC_ACPDD		BIT(3)	/* AC Power Down Driver */
+
+/* DDR3PHY DATX8 Common Configuration Register */
+#define DDR3PHY_DXCCR			0x28
+#define DDR3PHY_DXCCR_DXPDR		BIT(3)	/* Data Power Down Receiver */
+
+/* DDR3PHY DDR System General Configuration Register */
+#define DDR3PHY_DSGCR			0x2C
+#define DDR3PHY_DSGCR_ODTPDD_ODT0	BIT(20)	/* ODT[0] Power Down Driver */
+
+/* ZQ status register 0 */
+#define DDR3PHY_ZQ0SR0			0x188
+/* impedance select offset */
+#define DDR3PHY_ZQ0SR0_PDO_OFF		0  /* Pull-down output */
+#define DDR3PHY_ZQ0SR0_PUO_OFF		5  /* Pull-up output */
+#define DDR3PHY_ZQ0SR0_PDODT_OFF	10 /* Pull-down on-die termination*/
+#define DDR3PHY_ZQ0SRO_PUODT_OFF	15 /* Pull-up on-die termination */
+
+/* DDR3PHY DATX8 DLL Control Register */
+#define DDR3PHY_DX0DLLCR		0x1CC
+#define DDR3PHY_DX1DLLCR		0x20C	/* DATX8 DLL Control Register */
+#define DDR3PHY_DXDLLCR_DLLDIS		BIT(31)	/* DLL Disable */
+
+/* UDDRC */
+/* UDDRC Operating Mode Status Register */
+#define UDDRC_STAT			0x04
+/* SDRAM is not in Self-refresh */
+#define UDDRC_STAT_SELFREF_TYPE_DIS	SHIFT_U32(0, 4)
+/* SDRAM is in Self-refresh, which was caused by PHY Master Request */
+#define UDDRC_STAT_SELFREF_TYPE_PHY	SHIFT_U32(1, 4)
+/* SDRAM is in Self-refresh, which was not caused solely under
+ * Automatic Self-refresh control
+ */
+#define UDDRC_STAT_SELFREF_TYPE_SW	SHIFT_U32(2, 4)
+/* SDRAM is in Self-refresh, which was caused by Automatic Self-refresh only */
+#define UDDRC_STAT_SELFREF_TYPE_AUTO	SHIFT_U32(3, 4)
+#define UDDRC_STAT_SELFREF_TYPE_MSK	GENMASK_32(5, 4)
+#define UDDRC_STAT_OPMODE_INIT		0
+#define UDDRC_STAT_OPMODE_NORMAL	1
+#define UDDRC_STAT_OPMODE_PWRDOWN	2
+#define UDDRC_STAT_OPMODE_SELF_REFRESH	3
+#define UDDRC_STAT_OPMODE_MSK		GENMASK_32(2, 0)
+
+/* UDDRC Low Power Control Register */
+#define UDDRC_PWRCTL			0x30
+#define UDDRC_PWRCTL_SELFREF_EN		BIT(0)	/* Automatic self-refresh */
+#define UDDRC_PWRCTL_SELFREF_SW		BIT(5)	/* Software self-refresh */
+
+/* UDDRC DFI Miscellaneous Control Register */
+#define UDDRC_DFIMISC			0x1B0
+/* PHY initialization complete enable signal */
+#define UDDRC_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0)
+
+/* UDDRC Software Register Programming Control Enable */
+#define UDDRC_SWCTRL			0x320
+/* Enable quasi-dynamic register programming outside reset */
+#define UDDRC_SWCTRL_SW_DONE		BIT(0)
+
+/* UDDRC Software Register Programming Control Status */
+#define UDDRC_SWSTAT			0x324
+#define UDDRC_SWSTAT_SW_DONE_ACK	BIT(0)	/* Register programming done */
+
+/* UDDRC Port Status Register */
+#define UDDRC_PSTAT			0x3FC
+/* Read + writes outstanding transactions on all ports */
+#define UDDRC_PSTAT_ALL_PORTS		0x1F001F
+
+#define UDDRC_PCTRL_0			0x490	/* Port 0 Control Register */
+#define UDDRC_PCTRL_1			0x540	/* Port 1 Control Register */
+#define UDDRC_PCTRL_2			0x5F0	/* Port 2 Control Register */
+#define UDDRC_PCTRL_3			0x6A0	/* Port 3 Control Register */
+#define UDDRC_PCTRL_4			0x750	/* Port 4 Control Register */
+
+#endif /* __SAMA7_DDR_H__ */
diff --git a/core/include/drivers/semihosting_console.h b/core/include/drivers/semihosting_console.h
new file mode 100644
index 0000000000000000000000000000000000000000..93cc7264253a1444212d780af77fc31f4271df0c
--- /dev/null
+++ b/core/include/drivers/semihosting_console.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+#ifndef __DRIVERS_SEMIHOSTING_CONSOLE_H
+#define __DRIVERS_SEMIHOSTING_CONSOLE_H
+
+#ifdef CFG_SEMIHOSTING_CONSOLE
+/*
+ * Initialize console which uses architecture-specific semihosting mechanism.
+ * If @file_path is not NULL, OP-TEE OS will try to output log to that file,
+ * which is on the semihosting host system.
+ * Otherwise, if @file_path is NULL, OP-TEE OS will try to output log to the
+ * semihosting host debug console.
+ */
+void semihosting_console_init(const char *file_path);
+#else
+static inline void semihosting_console_init(const char *file_path __unused)
+{
+}
+#endif
+
+#endif /* __DRIVERS_SEMIHOSTING_CONSOLE_H */
diff --git a/core/include/drivers/serial.h b/core/include/drivers/serial.h
index 4c2f9646cebba6e16d5292150fad997f24b9d9dd..2a1e07482b8c8ea82d1a11e9e438947a329bec1b 100644
--- a/core/include/drivers/serial.h
+++ b/core/include/drivers/serial.h
@@ -22,6 +22,8 @@ struct serial_ops {
 	void (*flush)(struct serial_chip *chip);
 	bool (*have_rx_data)(struct serial_chip *chip);
 	int (*getchar)(struct serial_chip *chip);
+	void (*rx_intr_enable)(struct serial_chip *chip);
+	void (*rx_intr_disable)(struct serial_chip *chip);
 };
 
 struct serial_driver {
diff --git a/core/include/drivers/stm32_etzpc.h b/core/include/drivers/stm32_etzpc.h
index 48f0385a34747d285bfa4040628785839bb252d0..e49d30de6e478e24cdc1f7b1710ebc56ad8acca0 100644
--- a/core/include/drivers/stm32_etzpc.h
+++ b/core/include/drivers/stm32_etzpc.h
@@ -18,17 +18,6 @@ enum etzpc_decprot_attributes {
 	ETZPC_DECPROT_MAX = 4,
 };
 
-#define ETZPC_TZMA_ALL_SECURE		GENMASK_32(9, 0)
-#define ETZPC_TZMA_ALL_NO_SECURE	0x0
-
-/*
- * Load a DECPROT configuration
- * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface
- * @decprot_attr: Restriction access attributes
- */
-void etzpc_configure_decprot(uint32_t decprot_id,
-			     enum etzpc_decprot_attributes decprot_attr);
-
 /*
  * Get the DECPROT attribute
  * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface
@@ -37,41 +26,11 @@ void etzpc_configure_decprot(uint32_t decprot_id,
 enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id);
 
 /*
- * Lock access to the DECPROT attributes
- * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface
- */
-void etzpc_lock_decprot(uint32_t decprot_id);
-
-/*
- * Return the lock status of the target DECPROT
- * @decprot_id: ID that is the index of the DECPROT in the ETZPC interface
- */
-bool etzpc_get_lock_decprot(uint32_t decprot_id);
-
-/*
- * Configure the target TZMA read only size
+ * Configure the target TZMA secure memory range
  * @tzma_id: ID that is the index of the TZMA in the ETZPC interface
- * @tzma_value: Read-only size
+ * @tzma_value: Secure memory secure size in 4kByte page size. Note that this
+ * is an offset from the memory base address
  */
 void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value);
 
-/*
- * Get the target TZMA read only size
- * @tzma_id: ID that is the index of the TZMA in the ETZPC interface
- * Return the size of read-only area
- */
-uint16_t etzpc_get_tzma(uint32_t tzma_id);
-
-/*
- * Lock the target TZMA
- * @tzma_id: ID that is the index of the TZMA in the ETZPC interface
- */
-void etzpc_lock_tzma(uint32_t tzma_id);
-
-/*
- * Return the lock status of the target TZMA
- * @tzma_id: ID that is the index of the TZMA in the ETZPC interface
- * Return true if TZMA is locked, false otherwise
- */
-bool etzpc_get_lock_tzma(uint32_t tzma_id);
 #endif /*__DRIVERS_STM32_ETZPC_H*/
diff --git a/core/include/drivers/stm32_gpio.h b/core/include/drivers/stm32_gpio.h
index 883888171f3cd58009e4c141c371693453d40170..21660d524925694a00bdc69173573f39f1ccdd42 100644
--- a/core/include/drivers/stm32_gpio.h
+++ b/core/include/drivers/stm32_gpio.h
@@ -16,24 +16,6 @@ struct pinctrl_state;
 struct stm32_pinctrl;
 
 #ifdef CFG_STM32_GPIO
-/*
- * Configure pin muxing access permission: can be secure or not
- *
- * @bank: GPIO bank identifier as assigned by the platform
- * @pin: Pin number in the GPIO bank
- * @secure: True if pin is secure, false otherwise
- */
-void stm32_gpio_set_secure_cfg(unsigned int bank, unsigned int pin,
-			       bool secure);
-
-/*
- * Configure pin muxing access permission: can be secure or not
- *
- * @pinctrl: Pin control state where STM32_GPIO pin are to configure
- * @secure: True if pin is secure, false otherwise
- */
-void stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl, bool secure);
-
 /*
  * Get the bank and pin indices related to a pin control state
  * @pinctrl: Pinctrl state
@@ -45,12 +27,6 @@ void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *pinctrl,
 				 unsigned int *bank, unsigned int *pin,
 				 unsigned int *count);
 #else
-static inline void
-stm32_pinctrl_set_secure_cfg(struct pinctrl_state *pinctrl __unused,
-			     bool secure __unused)
-{
-}
-
 static inline void stm32_gpio_pinctrl_bank_pin(struct pinctrl_state *p __unused,
 					       unsigned int *bank __unused,
 					       unsigned int *pin __unused,
diff --git a/core/include/drivers/stm32_i2c.h b/core/include/drivers/stm32_i2c.h
index 0c955ade2b8b8aa8f3f68f12ac2dfa847820d57c..42b26b0eba9930d85f143fe21095f117ad52cc37 100644
--- a/core/include/drivers/stm32_i2c.h
+++ b/core/include/drivers/stm32_i2c.h
@@ -11,6 +11,7 @@
 #include <drivers/pinctrl.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
+#include <kernel/mutex_pm_aware.h>
 #include <mm/core_memprot.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -114,6 +115,7 @@ struct i2c_cfg {
  * @sec_cfg: I2C registers configuration storage
  * @pinctrl: Pin control configuration for the I2C bus in active state
  * @pinctrl_sleep: Pin control configuration for the I2C bus in standby state
+ * @mu: Protection on concurrent access to the I2C bus considering PM context
  */
 struct i2c_handle_s {
 	struct io_pa_va base;
@@ -127,6 +129,7 @@ struct i2c_handle_s {
 	struct i2c_cfg sec_cfg;
 	struct pinctrl_state *pinctrl;
 	struct pinctrl_state *pinctrl_sleep;
+	struct mutex_pm_aware mu;
 };
 
 /*
diff --git a/core/include/drivers/stm32_remoteproc.h b/core/include/drivers/stm32_remoteproc.h
index 8cb1efd863ccecc0f1ddab2fea72739bce9a8b6e..439d81e1190aec579e4f1eba6577875556f719b5 100644
--- a/core/include/drivers/stm32_remoteproc.h
+++ b/core/include/drivers/stm32_remoteproc.h
@@ -67,4 +67,21 @@ TEE_Result stm32_rproc_start(uint32_t rproc_id);
  */
 TEE_Result stm32_rproc_stop(uint32_t rproc_id);
 
+/*
+ * stm32_rproc_clean_up_memories() - clear remote processor memory regions
+ * @rproc_id	unique identifier of the remote processor
+ * Return TEE_SUCCESS or appropriate error.
+ */
+TEE_Result stm32_rproc_clean_up_memories(uint32_t rproc_id);
+
+#ifdef CFG_STM32MP_REMOTEPROC
+/* Return true is secure loading of remoteproc firmware is enabled */
+bool stm32_rproc_is_secure(uint32_t rproc_id);
+#else
+static inline bool stm32_rproc_is_secure(uint32_t rproc_id __unused)
+{
+	return false;
+}
+#endif
+
 #endif /* __DRIVERS_STM32_REMOTEPROC_H */
diff --git a/core/include/drivers/stm32_rif.h b/core/include/drivers/stm32_rif.h
new file mode 100644
index 0000000000000000000000000000000000000000..94dde7c1d446068d71c6b98f90ed1f55c6d55ce1
--- /dev/null
+++ b/core/include/drivers/stm32_rif.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32_RIF_H
+#define __DRIVERS_STM32_RIF_H
+
+#include <dt-bindings/firewall/stm32mp25-rif.h>
+#include <tee_api_types.h>
+#include <types_ext.h>
+#include <util.h>
+
+/*
+ * CIDCFGR register
+ */
+#define _CIDCFGR_CFEN			BIT(0)
+#define _CIDCFGR_SCID_SHIFT		U(4)
+#define _CIDCFGR_SEMEN			BIT(1)
+#define _CIDCFGR_SEMWL_SHIFT		U(16)
+#define _CIDCFGR_SEMWL(x)		BIT(_CIDCFGR_SEMWL_SHIFT + (x))
+
+/*
+ * SEMCR register
+ */
+#define _SEMCR_MUTEX			BIT(0)
+#define _SEMCR_SEMCID_SHIFT		U(4)
+#define _SEMCR_SEMCID_MASK		GENMASK_32(6, 4)
+
+/*
+ * Miscellaneous
+ */
+#define MAX_CID_SUPPORTED		U(8)
+
+#define RIF_CHANNEL_ID(x)		(RIF_PER_ID_MASK & (x))
+
+/**
+ * struct rif_conf_data - Structure containing RIF configuration data
+ *
+ * @access_mask: Array of the masks of the registers which will be configured.
+ * @sec_conf: Secure configuration registers.
+ * @priv_conf: Privilege configuration registers.
+ * @cid_confs: CID filtering configuration register value for a peripheral
+ *             resource (e.g: GPIO pins, FMC controllers)
+ * @lock_conf: RIF configuration locking registers
+ *
+ * For a hardware block having 56 channels, there will be 56 cid_confs
+ * registers and 2 sec_conf and priv_conf registers
+ */
+struct rif_conf_data {
+	uint32_t *access_mask;
+	uint32_t *sec_conf;
+	uint32_t *priv_conf;
+	uint32_t *cid_confs;
+	uint32_t *lock_conf;
+};
+
+#ifdef CFG_STM32_RIF
+/**
+ * stm32_rif_scid_ok() - Check if a given static CID configuration authorizes
+ *			 access to a given CID
+ *
+ * @cidcfgr: Value of the CIDCFGR register
+ * @scid_m: Mask of the static CID in the register
+ * @cid_to_check: CID of the target compartment
+ *
+ * Returns true if given CID is authorized, false otherwise.
+ */
+static inline bool stm32_rif_scid_ok(uint32_t cidcfgr, uint32_t scid_m,
+				     uint32_t cid_to_check)
+{
+	return (cidcfgr & scid_m) ==
+	       SHIFT_U32(cid_to_check, _CIDCFGR_SCID_SHIFT) &&
+	       !(cidcfgr & _CIDCFGR_SEMEN);
+}
+
+/**
+ * stm32_rif_semaphore_enabled_and_ok() - Check if semaphore mode is enabled and
+ *					  that a given CID can request the
+ *					  semaphore ownership
+ *
+ * @cidcfgr: Value of the cidcfgr register
+ * @cid_to_check: CID to check
+ *
+ * Returns true if the requested CID can request the semaphore ownership,
+ * false otherwise.
+ */
+static inline bool stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr,
+						      uint32_t cid_to_check)
+{
+	return (cidcfgr & _CIDCFGR_CFEN) && (cidcfgr & _CIDCFGR_SEMEN) &&
+	       (cidcfgr & _CIDCFGR_SEMWL(cid_to_check));
+}
+
+/**
+ * stm32_rifsc_check_tdcid() - Check if the execution context is TDCID or not
+ *
+ * @tdcid_state: [out] Set to true if TDCID, false otherwise.
+ *
+ * Returns TEE_ERROR_DEFER_DRIVER_INIT if RIFSC driver isn't probed, TEE_SUCCESS
+ * otherwise.
+ */
+TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state);
+
+/**
+ * stm32_rif_check_access() - Test peripheral access for a given compartment
+ *
+ * @cidcfgr: CIDCFGR configuration register value
+ * @semcr: SEMCR register value
+ * @nb_cid_supp: Number of supported CID for the peripheral
+ * @cid_to_check: CID of the target compartment
+ *
+ * Returns TEE_SUCCESS if access is authorized, a TEE_Result error value
+ * otherwise.
+ */
+TEE_Result stm32_rif_check_access(uint32_t cidcfgr,
+				  uint32_t semcr,
+				  unsigned int nb_cid_supp,
+				  unsigned int cid_to_check);
+
+/**
+ * stm32_rif_parse_cfg() - Parse RIF config from Device Tree extracted
+ *			   information
+ *
+ * @rif_conf: Configuration read in the device tree
+ * @conf_data: Buffer containing the RIF configuration to apply for a peripheral
+ * @nb_channel: Number of channels for the peripheral
+ */
+void stm32_rif_parse_cfg(uint32_t rif_conf,
+			 struct rif_conf_data *conf_data,
+			 unsigned int nb_channel);
+
+/**
+ * stm32_rif_semaphore_is_available() - Checks if the _SEMCR_MUTEX bit is set
+ *
+ * @addr: Address of the register to read from
+ */
+bool stm32_rif_semaphore_is_available(vaddr_t addr);
+
+/**
+ * stm32_rif_semaphore_is_available() - Acquires the semaphore by setting the
+ *					_SEMCR_MUTEX bit
+ *
+ * @addr: Address of the register to write to
+ * @nb_cid_supp: Number of CID supported
+ */
+TEE_Result stm32_rif_acquire_semaphore(vaddr_t addr,
+				       unsigned int nb_cid_supp);
+
+/**
+ * stm32_rif_semaphore_is_available() - Releases the semaphore by clearing the
+ *					_SEMCR_MUTEX bit
+ *
+ * @addr: Address of the register to write to
+ * @nb_cid_supp: Number of CID supported
+ */
+TEE_Result stm32_rif_release_semaphore(vaddr_t addr,
+				       unsigned int nb_cid_supp);
+
+/*
+ * The action to take upon an access violation depends on the platform.
+ * Therefore, it should be defined at platform level.
+ */
+void stm32_rif_access_violation_action(void);
+#else
+static inline bool stm32_rif_scid_ok(uint32_t cidcfgr __unused,
+				     uint32_t scid_m __unused,
+				     uint32_t cid_to_check __unused)
+{
+	return true;
+}
+
+static inline bool
+stm32_rif_semaphore_enabled_and_ok(uint32_t cidcfgr __unused,
+				   uint32_t cid_to_check __unused)
+{
+	return true;
+}
+
+static inline TEE_Result stm32_rifsc_check_tdcid(bool *tdcid_state)
+{
+	/* Without CFG_STM32_RIF every CPU can behave as TDCID */
+	*tdcid_state = true;
+
+	return TEE_SUCCESS;
+}
+
+static inline TEE_Result
+stm32_rif_check_access(uint32_t cidcfgr __unused,
+		       uint32_t semcr __unused,
+		       unsigned int nb_cid_supp __unused,
+		       unsigned int cid_to_check __unused)
+{
+	return TEE_SUCCESS;
+}
+
+static inline void
+stm32_rif_parse_cfg(uint32_t rif_conf __unused,
+		    struct rif_conf_data *conf_data __unused,
+		    unsigned int nb_channel __unused)
+{
+}
+
+static inline bool stm32_rif_semaphore_is_available(vaddr_t addr __unused)
+{
+	return true;
+}
+
+static inline TEE_Result
+stm32_rif_acquire_semaphore(vaddr_t addr __unused,
+			    unsigned int nb_cid_supp __unused)
+{
+	return TEE_SUCCESS;
+}
+
+static inline TEE_Result
+stm32_rif_release_semaphore(vaddr_t addr __unused,
+			    unsigned int nb_cid_supp __unused)
+{
+	return TEE_SUCCESS;
+}
+
+static inline void stm32_rif_access_violation_action(void)
+{
+}
+#endif /* CFG_STM32_RIF */
+#endif /* __DRIVERS_STM32_RIF_H */
diff --git a/core/include/drivers/stm32_risab.h b/core/include/drivers/stm32_risab.h
new file mode 100644
index 0000000000000000000000000000000000000000..1fa4d0f50597f9e6dd4c925d04d4fb452ea9039f
--- /dev/null
+++ b/core/include/drivers/stm32_risab.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32_RISAB_H__
+#define __DRIVERS_STM32_RISAB_H__
+
+/*
+ * stm32_risab_clear_illegal_access_flags() - Clears flags raised when an
+ * illegal access occurs on a memory region
+ */
+#if defined(CFG_STM32_RISAB)
+void stm32_risab_clear_illegal_access_flags(void);
+#else /* defined(CFG_STM32_RISAB) */
+static inline void stm32_risab_clear_illegal_access_flags(void)
+{
+}
+#endif /* defined(CFG_STM32_RISAB) */
+
+/*
+ * stm32_risab_print_erroneous_data() - Prints the data associated to an illegal
+ * access occurring on a memory protected by a RISAB : faulty address and
+ * firewall attributes of the master causing the illegal access.
+ */
+#if defined(CFG_STM32_RISAB) && defined(CFG_TEE_CORE_DEBUG)
+void stm32_risab_print_erroneous_data(void);
+#else /* defined(CFG_STM32_RISAB) && defined(CFG_TEE_CORE_DEBUG) */
+static inline void stm32_risab_print_erroneous_data(void)
+{
+}
+#endif /* defined(CFG_STM32_RISAB) && defined(CFG_TEE_CORE_DEBUG) */
+
+#endif /*__DRIVERS_STM32_RISAB_H__*/
diff --git a/core/include/drivers/stm32_risaf.h b/core/include/drivers/stm32_risaf.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d611f01323ceffe2d16c24b5fcbba85bea75566
--- /dev/null
+++ b/core/include/drivers/stm32_risaf.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2021-2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32_RISAF_H__
+#define __DRIVERS_STM32_RISAF_H__
+
+/*
+ * stm32_risaf_clear_illegal_access_flags() - Clears flags raised when an
+ * illegal access occurs on a memory region
+ */
+void stm32_risaf_clear_illegal_access_flags(void);
+
+/*
+ * stm32_risaf_print_erroneous_data() - Prints the data associated to an illegal
+ * access occurring on a memory protected by a RISAF : faulty address and
+ * firewall attributes of the master causing the illegal access. This function
+ * is stubbed when CFG_TEE_CORE_DEBUG is disabled.
+ */
+void stm32_risaf_print_erroneous_data(void);
+
+#endif /*__DRIVERS_STM32_RISAF_H__*/
diff --git a/core/include/drivers/stm32_tamp.h b/core/include/drivers/stm32_tamp.h
deleted file mode 100644
index 88c884987262ac245be78a74f99a5dc3bfc03351..0000000000000000000000000000000000000000
--- a/core/include/drivers/stm32_tamp.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: BSD-3-Clause */
-/*
- * Copyright (c) 2021-2022, STMicroelectronics
- */
-
-#ifndef __DRIVERS_STM32_TAMP_H__
-#define __DRIVERS_STM32_TAMP_H__
-
-#include <compiler.h>
-#include <stdint.h>
-#include <tee_api_types.h>
-
-/*
- * struct stm32_bkpregs_conf - Interface for stm32_tamp_set_secure_bkpregs()
- * @nb_zone1_regs - Number of backup registers in zone 1
- * @nb_zone2_regs - Number of backup registers in zone 2
- *
- * TAMP backup registers access permissions
- *
- * Zone 1: read/write in secure state, no access in non-secure state
- * Zone 2: read/write in secure state, read-only in non-secure state
- * Zone 3: read/write in secure state, read/write in non-secure state
- *
- * Protection zone 1
- * If nb_zone1_regs == 0 no backup register are in zone 1.
- * Otherwise backup registers from TAMP_BKP0R to TAMP_BKP<x>R are in zone 1,
- * with <x> = (@nb_zone1_regs - 1).
- *
- * Protection zone 2
- * If nb_zone2_regs == 0 no backup register are in zone 2.
- * Otherwise backup registers from TAMP_BKP<y>R ro TAMP_BKP<z>R are in zone 2,
- * with <y> = @nb_zone1_regs and <z> = (@nb_zone1_regs1 + @nb_zone2_regs - 1).
- *
- * Protection zone 3
- * Backup registers from TAMP_BKP<t>R to last backup register are in zone 3,
- * with <t> = (@nb_zone1_regs1 + @nb_zone2_regs).
- */
-struct stm32_bkpregs_conf {
-	uint32_t nb_zone1_regs;
-	uint32_t nb_zone2_regs;
-};
-
-#ifdef CFG_STM32_TAMP
-/*
- * stm32_tamp_set_secure_bkprwregs() - Configure backup registers zone.
- * @conf - Configuration to be programmed
- */
-TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *conf);
-#else
-static inline
-TEE_Result stm32_tamp_set_secure_bkpregs(struct stm32_bkpregs_conf *c __unused)
-{
-	return TEE_ERROR_NOT_SUPPORTED;
-}
-#endif
-#endif /* __DRIVERS_STM32_TAMP_H__ */
diff --git a/core/include/drivers/stm32_uart.h b/core/include/drivers/stm32_uart.h
index 6054df72c513f57ebfd02cebca7a1a79b2dd935c..150bf4f09c3dc722b665617eff6a20570e63dff2 100644
--- a/core/include/drivers/stm32_uart.h
+++ b/core/include/drivers/stm32_uart.h
@@ -16,7 +16,6 @@
 struct stm32_uart_pdata {
 	struct io_pa_va base;
 	struct serial_chip chip;
-	bool secure;
 	struct clk *clock;
 	struct pinctrl_state *pinctrl;
 	struct pinctrl_state *pinctrl_sleep;
diff --git a/core/include/drivers/stm32mp1_rcc.h b/core/include/drivers/stm32mp1_rcc.h
index 311cea8449ec5f1de87b9eecd4b986171dcc8f46..83f3ead80e7b6652f8e04152dd534eb6ede45f83 100644
--- a/core/include/drivers/stm32mp1_rcc.h
+++ b/core/include/drivers/stm32mp1_rcc.h
@@ -561,6 +561,17 @@ static inline bool stm32_rcc_is_mckprot(void)
 {
 	return io_read32(stm32_rcc_base() + RCC_TZCR) & RCC_TZCR_MCKPROT;
 }
+
+static inline void stm32_rcc_set_mckprot(bool enable)
+{
+	vaddr_t tzcr_reg = stm32_rcc_base() + RCC_TZCR;
+
+	if (enable)
+		io_setbits32(tzcr_reg, RCC_TZCR_MCKPROT);
+	else
+		io_clrbits32(tzcr_reg, RCC_TZCR_MCKPROT);
+}
+
 #endif /*__ASSEMBLER__*/
 
 #endif /*__DRIVERS_STM32MP1_RCC_H__*/
diff --git a/core/include/drivers/stm32mp25_rcc.h b/core/include/drivers/stm32mp25_rcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f28e92e656e927e9c0dda59d21e54ee74890530b
--- /dev/null
+++ b/core/include/drivers/stm32mp25_rcc.h
@@ -0,0 +1,2305 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+
+#ifndef __DRIVERS_STM32MP25_RCC_H
+#define __DRIVERS_STM32MP25_RCC_H
+
+#include <util.h>
+
+#define RCC_SECCFGR0				U(0x0)
+#define RCC_SECCFGR1				U(0x4)
+#define RCC_SECCFGR2				U(0x8)
+#define RCC_SECCFGR3				U(0xC)
+#define RCC_PRIVCFGR0				U(0x10)
+#define RCC_PRIVCFGR1				U(0x14)
+#define RCC_PRIVCFGR2				U(0x18)
+#define RCC_PRIVCFGR3				U(0x1C)
+#define RCC_RCFGLOCKR0				U(0x20)
+#define RCC_RCFGLOCKR1				U(0x24)
+#define RCC_RCFGLOCKR2				U(0x28)
+#define RCC_RCFGLOCKR3				U(0x2C)
+#define RCC_R0CIDCFGR				U(0x30)
+#define RCC_R0SEMCR				U(0x34)
+#define RCC_R1CIDCFGR				U(0x38)
+#define RCC_R1SEMCR				U(0x3C)
+#define RCC_R2CIDCFGR				U(0x40)
+#define RCC_R2SEMCR				U(0x44)
+#define RCC_R3CIDCFGR				U(0x48)
+#define RCC_R3SEMCR				U(0x4C)
+#define RCC_R4CIDCFGR				U(0x50)
+#define RCC_R4SEMCR				U(0x54)
+#define RCC_R5CIDCFGR				U(0x58)
+#define RCC_R5SEMCR				U(0x5C)
+#define RCC_R6CIDCFGR				U(0x60)
+#define RCC_R6SEMCR				U(0x64)
+#define RCC_R7CIDCFGR				U(0x68)
+#define RCC_R7SEMCR				U(0x6C)
+#define RCC_R8CIDCFGR				U(0x70)
+#define RCC_R8SEMCR				U(0x74)
+#define RCC_R9CIDCFGR				U(0x78)
+#define RCC_R9SEMCR				U(0x7C)
+#define RCC_R10CIDCFGR				U(0x80)
+#define RCC_R10SEMCR				U(0x84)
+#define RCC_R11CIDCFGR				U(0x88)
+#define RCC_R11SEMCR				U(0x8C)
+#define RCC_R12CIDCFGR				U(0x90)
+#define RCC_R12SEMCR				U(0x94)
+#define RCC_R13CIDCFGR				U(0x98)
+#define RCC_R13SEMCR				U(0x9C)
+#define RCC_R14CIDCFGR				U(0xA0)
+#define RCC_R14SEMCR				U(0xA4)
+#define RCC_R15CIDCFGR				U(0xA8)
+#define RCC_R15SEMCR				U(0xAC)
+#define RCC_R16CIDCFGR				U(0xB0)
+#define RCC_R16SEMCR				U(0xB4)
+#define RCC_R17CIDCFGR				U(0xB8)
+#define RCC_R17SEMCR				U(0xBC)
+#define RCC_R18CIDCFGR				U(0xC0)
+#define RCC_R18SEMCR				U(0xC4)
+#define RCC_R19CIDCFGR				U(0xC8)
+#define RCC_R19SEMCR				U(0xCC)
+#define RCC_R20CIDCFGR				U(0xD0)
+#define RCC_R20SEMCR				U(0xD4)
+#define RCC_R21CIDCFGR				U(0xD8)
+#define RCC_R21SEMCR				U(0xDC)
+#define RCC_R22CIDCFGR				U(0xE0)
+#define RCC_R22SEMCR				U(0xE4)
+#define RCC_R23CIDCFGR				U(0xE8)
+#define RCC_R23SEMCR				U(0xEC)
+#define RCC_R24CIDCFGR				U(0xF0)
+#define RCC_R24SEMCR				U(0xF4)
+#define RCC_R25CIDCFGR				U(0xF8)
+#define RCC_R25SEMCR				U(0xFC)
+#define RCC_R26CIDCFGR				U(0x100)
+#define RCC_R26SEMCR				U(0x104)
+#define RCC_R27CIDCFGR				U(0x108)
+#define RCC_R27SEMCR				U(0x10C)
+#define RCC_R28CIDCFGR				U(0x110)
+#define RCC_R28SEMCR				U(0x114)
+#define RCC_R29CIDCFGR				U(0x118)
+#define RCC_R29SEMCR				U(0x11C)
+#define RCC_R30CIDCFGR				U(0x120)
+#define RCC_R30SEMCR				U(0x124)
+#define RCC_R31CIDCFGR				U(0x128)
+#define RCC_R31SEMCR				U(0x12C)
+#define RCC_R32CIDCFGR				U(0x130)
+#define RCC_R32SEMCR				U(0x134)
+#define RCC_R33CIDCFGR				U(0x138)
+#define RCC_R33SEMCR				U(0x13C)
+#define RCC_R34CIDCFGR				U(0x140)
+#define RCC_R34SEMCR				U(0x144)
+#define RCC_R35CIDCFGR				U(0x148)
+#define RCC_R35SEMCR				U(0x14C)
+#define RCC_R36CIDCFGR				U(0x150)
+#define RCC_R36SEMCR				U(0x154)
+#define RCC_R37CIDCFGR				U(0x158)
+#define RCC_R37SEMCR				U(0x15C)
+#define RCC_R38CIDCFGR				U(0x160)
+#define RCC_R38SEMCR				U(0x164)
+#define RCC_R39CIDCFGR				U(0x168)
+#define RCC_R39SEMCR				U(0x16C)
+#define RCC_R40CIDCFGR				U(0x170)
+#define RCC_R40SEMCR				U(0x174)
+#define RCC_R41CIDCFGR				U(0x178)
+#define RCC_R41SEMCR				U(0x17C)
+#define RCC_R42CIDCFGR				U(0x180)
+#define RCC_R42SEMCR				U(0x184)
+#define RCC_R43CIDCFGR				U(0x188)
+#define RCC_R43SEMCR				U(0x18C)
+#define RCC_R44CIDCFGR				U(0x190)
+#define RCC_R44SEMCR				U(0x194)
+#define RCC_R45CIDCFGR				U(0x198)
+#define RCC_R45SEMCR				U(0x19C)
+#define RCC_R46CIDCFGR				U(0x1A0)
+#define RCC_R46SEMCR				U(0x1A4)
+#define RCC_R47CIDCFGR				U(0x1A8)
+#define RCC_R47SEMCR				U(0x1AC)
+#define RCC_R48CIDCFGR				U(0x1B0)
+#define RCC_R48SEMCR				U(0x1B4)
+#define RCC_R49CIDCFGR				U(0x1B8)
+#define RCC_R49SEMCR				U(0x1BC)
+#define RCC_R50CIDCFGR				U(0x1C0)
+#define RCC_R50SEMCR				U(0x1C4)
+#define RCC_R51CIDCFGR				U(0x1C8)
+#define RCC_R51SEMCR				U(0x1CC)
+#define RCC_R52CIDCFGR				U(0x1D0)
+#define RCC_R52SEMCR				U(0x1D4)
+#define RCC_R53CIDCFGR				U(0x1D8)
+#define RCC_R53SEMCR				U(0x1DC)
+#define RCC_R54CIDCFGR				U(0x1E0)
+#define RCC_R54SEMCR				U(0x1E4)
+#define RCC_R55CIDCFGR				U(0x1E8)
+#define RCC_R55SEMCR				U(0x1EC)
+#define RCC_R56CIDCFGR				U(0x1F0)
+#define RCC_R56SEMCR				U(0x1F4)
+#define RCC_R57CIDCFGR				U(0x1F8)
+#define RCC_R57SEMCR				U(0x1FC)
+#define RCC_R58CIDCFGR				U(0x200)
+#define RCC_R58SEMCR				U(0x204)
+#define RCC_R59CIDCFGR				U(0x208)
+#define RCC_R59SEMCR				U(0x20C)
+#define RCC_R60CIDCFGR				U(0x210)
+#define RCC_R60SEMCR				U(0x214)
+#define RCC_R61CIDCFGR				U(0x218)
+#define RCC_R61SEMCR				U(0x21C)
+#define RCC_R62CIDCFGR				U(0x220)
+#define RCC_R62SEMCR				U(0x224)
+#define RCC_R63CIDCFGR				U(0x228)
+#define RCC_R63SEMCR				U(0x22C)
+#define RCC_R64CIDCFGR				U(0x230)
+#define RCC_R64SEMCR				U(0x234)
+#define RCC_R65CIDCFGR				U(0x238)
+#define RCC_R65SEMCR				U(0x23C)
+#define RCC_R66CIDCFGR				U(0x240)
+#define RCC_R66SEMCR				U(0x244)
+#define RCC_R67CIDCFGR				U(0x248)
+#define RCC_R67SEMCR				U(0x24C)
+#define RCC_R68CIDCFGR				U(0x250)
+#define RCC_R68SEMCR				U(0x254)
+#define RCC_R69CIDCFGR				U(0x258)
+#define RCC_R69SEMCR				U(0x25C)
+#define RCC_R70CIDCFGR				U(0x260)
+#define RCC_R70SEMCR				U(0x264)
+#define RCC_R71CIDCFGR				U(0x268)
+#define RCC_R71SEMCR				U(0x26C)
+#define RCC_R72CIDCFGR				U(0x270)
+#define RCC_R72SEMCR				U(0x274)
+#define RCC_R73CIDCFGR				U(0x278)
+#define RCC_R73SEMCR				U(0x27C)
+#define RCC_R74CIDCFGR				U(0x280)
+#define RCC_R74SEMCR				U(0x284)
+#define RCC_R75CIDCFGR				U(0x288)
+#define RCC_R75SEMCR				U(0x28C)
+#define RCC_R76CIDCFGR				U(0x290)
+#define RCC_R76SEMCR				U(0x294)
+#define RCC_R77CIDCFGR				U(0x298)
+#define RCC_R77SEMCR				U(0x29C)
+#define RCC_R78CIDCFGR				U(0x2A0)
+#define RCC_R78SEMCR				U(0x2A4)
+#define RCC_R79CIDCFGR				U(0x2A8)
+#define RCC_R79SEMCR				U(0x2AC)
+#define RCC_R80CIDCFGR				U(0x2B0)
+#define RCC_R80SEMCR				U(0x2B4)
+#define RCC_R81CIDCFGR				U(0x2B8)
+#define RCC_R81SEMCR				U(0x2BC)
+#define RCC_R82CIDCFGR				U(0x2C0)
+#define RCC_R82SEMCR				U(0x2C4)
+#define RCC_R83CIDCFGR				U(0x2C8)
+#define RCC_R83SEMCR				U(0x2CC)
+#define RCC_R84CIDCFGR				U(0x2D0)
+#define RCC_R84SEMCR				U(0x2D4)
+#define RCC_R85CIDCFGR				U(0x2D8)
+#define RCC_R85SEMCR				U(0x2DC)
+#define RCC_R86CIDCFGR				U(0x2E0)
+#define RCC_R86SEMCR				U(0x2E4)
+#define RCC_R87CIDCFGR				U(0x2E8)
+#define RCC_R87SEMCR				U(0x2EC)
+#define RCC_R88CIDCFGR				U(0x2F0)
+#define RCC_R88SEMCR				U(0x2F4)
+#define RCC_R89CIDCFGR				U(0x2F8)
+#define RCC_R89SEMCR				U(0x2FC)
+#define RCC_R90CIDCFGR				U(0x300)
+#define RCC_R90SEMCR				U(0x304)
+#define RCC_R91CIDCFGR				U(0x308)
+#define RCC_R91SEMCR				U(0x30C)
+#define RCC_R92CIDCFGR				U(0x310)
+#define RCC_R92SEMCR				U(0x314)
+#define RCC_R93CIDCFGR				U(0x318)
+#define RCC_R93SEMCR				U(0x31C)
+#define RCC_R94CIDCFGR				U(0x320)
+#define RCC_R94SEMCR				U(0x324)
+#define RCC_R95CIDCFGR				U(0x328)
+#define RCC_R95SEMCR				U(0x32C)
+#define RCC_R96CIDCFGR				U(0x330)
+#define RCC_R96SEMCR				U(0x334)
+#define RCC_R97CIDCFGR				U(0x338)
+#define RCC_R97SEMCR				U(0x33C)
+#define RCC_R98CIDCFGR				U(0x340)
+#define RCC_R98SEMCR				U(0x344)
+#define RCC_R99CIDCFGR				U(0x348)
+#define RCC_R99SEMCR				U(0x34C)
+#define RCC_R100CIDCFGR				U(0x350)
+#define RCC_R100SEMCR				U(0x354)
+#define RCC_R101CIDCFGR				U(0x358)
+#define RCC_R101SEMCR				U(0x35C)
+#define RCC_R102CIDCFGR				U(0x360)
+#define RCC_R102SEMCR				U(0x364)
+#define RCC_R103CIDCFGR				U(0x368)
+#define RCC_R103SEMCR				U(0x36C)
+#define RCC_R104CIDCFGR				U(0x370)
+#define RCC_R104SEMCR				U(0x374)
+#define RCC_R105CIDCFGR				U(0x378)
+#define RCC_R105SEMCR				U(0x37C)
+#define RCC_R106CIDCFGR				U(0x380)
+#define RCC_R106SEMCR				U(0x384)
+#define RCC_R107CIDCFGR				U(0x388)
+#define RCC_R107SEMCR				U(0x38C)
+#define RCC_R108CIDCFGR				U(0x390)
+#define RCC_R108SEMCR				U(0x394)
+#define RCC_R109CIDCFGR				U(0x398)
+#define RCC_R109SEMCR				U(0x39C)
+#define RCC_R110CIDCFGR				U(0x3A0)
+#define RCC_R110SEMCR				U(0x3A4)
+#define RCC_R111CIDCFGR				U(0x3A8)
+#define RCC_R111SEMCR				U(0x3AC)
+#define RCC_R112CIDCFGR				U(0x3B0)
+#define RCC_R112SEMCR				U(0x3B4)
+#define RCC_R113CIDCFGR				U(0x3B8)
+#define RCC_R113SEMCR				U(0x3BC)
+#define RCC_GRSTCSETR				U(0x400)
+#define RCC_C1RSTCSETR				U(0x404)
+#define RCC_C1P1RSTCSETR			U(0x408)
+#define RCC_C2RSTCSETR				U(0x40C)
+#define RCC_HWRSTSCLRR				U(0x410)
+#define RCC_C1HWRSTSCLRR			U(0x414)
+#define RCC_C2HWRSTSCLRR			U(0x418)
+#define RCC_C1BOOTRSTSSETR			U(0x41C)
+#define RCC_C1BOOTRSTSCLRR			U(0x420)
+#define RCC_C2BOOTRSTSSETR			U(0x424)
+#define RCC_C2BOOTRSTSCLRR			U(0x428)
+#define RCC_C1SREQSETR				U(0x42C)
+#define RCC_C1SREQCLRR				U(0x430)
+#define RCC_CPUBOOTCR				U(0x434)
+#define RCC_STBYBOOTCR				U(0x438)
+#define RCC_LEGBOOTCR				U(0x43C)
+#define RCC_BDCR				U(0x440)
+#define RCC_D3DCR				U(0x444)
+#define RCC_D3DSR				U(0x448)
+#define RCC_RDCR				U(0x44C)
+#define RCC_C1MSRDCR				U(0x450)
+#define RCC_PWRLPDLYCR				U(0x454)
+#define RCC_C1CIESETR				U(0x458)
+#define RCC_C1CIFCLRR				U(0x45C)
+#define RCC_C2CIESETR				U(0x460)
+#define RCC_C2CIFCLRR				U(0x464)
+#define RCC_IWDGC1FZSETR			U(0x468)
+#define RCC_IWDGC1FZCLRR			U(0x46C)
+#define RCC_IWDGC1CFGSETR			U(0x470)
+#define RCC_IWDGC1CFGCLRR			U(0x474)
+#define RCC_IWDGC2FZSETR			U(0x478)
+#define RCC_IWDGC2FZCLRR			U(0x47C)
+#define RCC_IWDGC2CFGSETR			U(0x480)
+#define RCC_IWDGC2CFGCLRR			U(0x484)
+#define RCC_IWDGC3CFGSETR			U(0x488)
+#define RCC_IWDGC3CFGCLRR			U(0x48C)
+#define RCC_C3CFGR				U(0x490)
+#define RCC_MCO1CFGR				U(0x494)
+#define RCC_MCO2CFGR				U(0x498)
+#define RCC_OCENSETR				U(0x49C)
+#define RCC_OCENCLRR				U(0x4A0)
+#define RCC_OCRDYR				U(0x4A4)
+#define RCC_HSICFGR				U(0x4A8)
+#define RCC_MSICFGR				U(0x4AC)
+#define RCC_RTCDIVR				U(0x4B0)
+#define RCC_APB1DIVR				U(0x4B4)
+#define RCC_APB2DIVR				U(0x4B8)
+#define RCC_APB3DIVR				U(0x4BC)
+#define RCC_APB4DIVR				U(0x4C0)
+#define RCC_APBDBGDIVR				U(0x4C4)
+#define RCC_TIMG1PRER				U(0x4C8)
+#define RCC_TIMG2PRER				U(0x4CC)
+#define RCC_LSMCUDIVR				U(0x4D0)
+#define RCC_DDRCPCFGR				U(0x4D4)
+#define RCC_DDRCAPBCFGR				U(0x4D8)
+#define RCC_DDRPHYCAPBCFGR			U(0x4DC)
+#define RCC_DDRPHYCCFGR				U(0x4E0)
+#define RCC_DDRCFGR				U(0x4E4)
+#define RCC_DDRITFCFGR				U(0x4E8)
+#define RCC_SYSRAMCFGR				U(0x4F0)
+#define RCC_VDERAMCFGR				U(0x4F4)
+#define RCC_SRAM1CFGR				U(0x4F8)
+#define RCC_SRAM2CFGR				U(0x4FC)
+#define RCC_RETRAMCFGR				U(0x500)
+#define RCC_BKPSRAMCFGR				U(0x504)
+#define RCC_LPSRAM1CFGR				U(0x508)
+#define RCC_LPSRAM2CFGR				U(0x50C)
+#define RCC_LPSRAM3CFGR				U(0x510)
+#define RCC_OSPI1CFGR				U(0x514)
+#define RCC_OSPI2CFGR				U(0x518)
+#define RCC_FMCCFGR				U(0x51C)
+#define RCC_DBGCFGR				U(0x520)
+#define RCC_STMCFGR				U(0x524)
+#define RCC_ETRCFGR				U(0x528)
+#define RCC_GPIOACFGR				U(0x52C)
+#define RCC_GPIOBCFGR				U(0x530)
+#define RCC_GPIOCCFGR				U(0x534)
+#define RCC_GPIODCFGR				U(0x538)
+#define RCC_GPIOECFGR				U(0x53C)
+#define RCC_GPIOFCFGR				U(0x540)
+#define RCC_GPIOGCFGR				U(0x544)
+#define RCC_GPIOHCFGR				U(0x548)
+#define RCC_GPIOICFGR				U(0x54C)
+#define RCC_GPIOJCFGR				U(0x550)
+#define RCC_GPIOKCFGR				U(0x554)
+#define RCC_GPIOZCFGR				U(0x558)
+#define RCC_HPDMA1CFGR				U(0x55C)
+#define RCC_HPDMA2CFGR				U(0x560)
+#define RCC_HPDMA3CFGR				U(0x564)
+#define RCC_LPDMACFGR				U(0x568)
+#define RCC_HSEMCFGR				U(0x56C)
+#define RCC_IPCC1CFGR				U(0x570)
+#define RCC_IPCC2CFGR				U(0x574)
+#define RCC_RTCCFGR				U(0x578)
+#define RCC_SYSCPU1CFGR				U(0x580)
+#define RCC_BSECCFGR				U(0x584)
+#define RCC_IS2MCFGR				U(0x58C)
+#define RCC_PLL2CFGR1				U(0x590)
+#define RCC_PLL2CFGR2				U(0x594)
+#define RCC_PLL2CFGR3				U(0x598)
+#define RCC_PLL2CFGR4				U(0x59C)
+#define RCC_PLL2CFGR5				U(0x5A0)
+#define RCC_PLL2CFGR6				U(0x5A8)
+#define RCC_PLL2CFGR7				U(0x5AC)
+#define RCC_PLL3CFGR1				U(0x5B8)
+#define RCC_PLL3CFGR2				U(0x5BC)
+#define RCC_PLL3CFGR3				U(0x5C0)
+#define RCC_PLL3CFGR4				U(0x5C4)
+#define RCC_PLL3CFGR5				U(0x5C8)
+#define RCC_PLL3CFGR6				U(0x5D0)
+#define RCC_PLL3CFGR7				U(0x5D4)
+#define RCC_HSIFMONCR				U(0x5E0)
+#define RCC_HSIFVALR				U(0x5E4)
+#define RCC_TIM1CFGR				U(0x700)
+#define RCC_TIM2CFGR				U(0x704)
+#define RCC_TIM3CFGR				U(0x708)
+#define RCC_TIM4CFGR				U(0x70C)
+#define RCC_TIM5CFGR				U(0x710)
+#define RCC_TIM6CFGR				U(0x714)
+#define RCC_TIM7CFGR				U(0x718)
+#define RCC_TIM8CFGR				U(0x71C)
+#define RCC_TIM10CFGR				U(0x720)
+#define RCC_TIM11CFGR				U(0x724)
+#define RCC_TIM12CFGR				U(0x728)
+#define RCC_TIM13CFGR				U(0x72C)
+#define RCC_TIM14CFGR				U(0x730)
+#define RCC_TIM15CFGR				U(0x734)
+#define RCC_TIM16CFGR				U(0x738)
+#define RCC_TIM17CFGR				U(0x73C)
+#define RCC_TIM20CFGR				U(0x740)
+#define RCC_LPTIM1CFGR				U(0x744)
+#define RCC_LPTIM2CFGR				U(0x748)
+#define RCC_LPTIM3CFGR				U(0x74C)
+#define RCC_LPTIM4CFGR				U(0x750)
+#define RCC_LPTIM5CFGR				U(0x754)
+#define RCC_SPI1CFGR				U(0x758)
+#define RCC_SPI2CFGR				U(0x75C)
+#define RCC_SPI3CFGR				U(0x760)
+#define RCC_SPI4CFGR				U(0x764)
+#define RCC_SPI5CFGR				U(0x768)
+#define RCC_SPI6CFGR				U(0x76C)
+#define RCC_SPI7CFGR				U(0x770)
+#define RCC_SPI8CFGR				U(0x774)
+#define RCC_SPDIFRXCFGR				U(0x778)
+#define RCC_USART1CFGR				U(0x77C)
+#define RCC_USART2CFGR				U(0x780)
+#define RCC_USART3CFGR				U(0x784)
+#define RCC_UART4CFGR				U(0x788)
+#define RCC_UART5CFGR				U(0x78C)
+#define RCC_USART6CFGR				U(0x790)
+#define RCC_UART7CFGR				U(0x794)
+#define RCC_UART8CFGR				U(0x798)
+#define RCC_UART9CFGR				U(0x79C)
+#define RCC_LPUART1CFGR				U(0x7A0)
+#define RCC_I2C1CFGR				U(0x7A4)
+#define RCC_I2C2CFGR				U(0x7A8)
+#define RCC_I2C3CFGR				U(0x7AC)
+#define RCC_I2C4CFGR				U(0x7B0)
+#define RCC_I2C5CFGR				U(0x7B4)
+#define RCC_I2C6CFGR				U(0x7B8)
+#define RCC_I2C7CFGR				U(0x7BC)
+#define RCC_I2C8CFGR				U(0x7C0)
+#define RCC_SAI1CFGR				U(0x7C4)
+#define RCC_SAI2CFGR				U(0x7C8)
+#define RCC_SAI3CFGR				U(0x7CC)
+#define RCC_SAI4CFGR				U(0x7D0)
+#define RCC_MDF1CFGR				U(0x7D8)
+#define RCC_ADF1CFGR				U(0x7DC)
+#define RCC_FDCANCFGR				U(0x7E0)
+#define RCC_HDPCFGR				U(0x7E4)
+#define RCC_ADC12CFGR				U(0x7E8)
+#define RCC_ADC3CFGR				U(0x7EC)
+#define RCC_ETH1CFGR				U(0x7F0)
+#define RCC_ETH2CFGR				U(0x7F4)
+#define RCC_USB2CFGR				U(0x7FC)
+#define RCC_USB2PHY1CFGR			U(0x800)
+#define RCC_USB2PHY2CFGR			U(0x804)
+#define RCC_USB3DRCFGR				U(0x808)
+#define RCC_USB3PCIEPHYCFGR			U(0x80C)
+#define RCC_PCIECFGR				U(0x810)
+#define RCC_USBTCCFGR				U(0x814)
+#define RCC_ETHSWCFGR				U(0x818)
+#define RCC_ETHSWACMCFGR			U(0x81C)
+#define RCC_ETHSWACMMSGCFGR			U(0x820)
+#define RCC_STGENCFGR				U(0x824)
+#define RCC_SDMMC1CFGR				U(0x830)
+#define RCC_SDMMC2CFGR				U(0x834)
+#define RCC_SDMMC3CFGR				U(0x838)
+#define RCC_GPUCFGR				U(0x83C)
+#define RCC_LTDCCFGR				U(0x840)
+#define RCC_DSICFGR				U(0x844)
+#define RCC_LVDSCFGR				U(0x850)
+#define RCC_CSICFGR				U(0x858)
+#define RCC_DCMIPPCFGR				U(0x85C)
+#define RCC_CCICFGR				U(0x860)
+#define RCC_VDECCFGR				U(0x864)
+#define RCC_VENCCFGR				U(0x868)
+#define RCC_RNGCFGR				U(0x870)
+#define RCC_PKACFGR				U(0x874)
+#define RCC_SAESCFGR				U(0x878)
+#define RCC_HASHCFGR				U(0x87C)
+#define RCC_CRYP1CFGR				U(0x880)
+#define RCC_CRYP2CFGR				U(0x884)
+#define RCC_IWDG1CFGR				U(0x888)
+#define RCC_IWDG2CFGR				U(0x88C)
+#define RCC_IWDG3CFGR				U(0x890)
+#define RCC_IWDG4CFGR				U(0x894)
+#define RCC_IWDG5CFGR				U(0x898)
+#define RCC_WWDG1CFGR				U(0x89C)
+#define RCC_WWDG2CFGR				U(0x8A0)
+#define RCC_VREFCFGR				U(0x8A8)
+#define RCC_DTSCFGR				U(0x8AC)
+#define RCC_CRCCFGR				U(0x8B4)
+#define RCC_SERCCFGR				U(0x8B8)
+#define RCC_OSPIIOMCFGR				U(0x8BC)
+#define RCC_GICV2MCFGR				U(0x8C0)
+#define RCC_I3C1CFGR				U(0x8C8)
+#define RCC_I3C2CFGR				U(0x8CC)
+#define RCC_I3C3CFGR				U(0x8D0)
+#define RCC_I3C4CFGR				U(0x8D4)
+#define RCC_MUXSELCFGR				U(0x1000)
+#define RCC_XBAR0CFGR				U(0x1018)
+#define RCC_XBAR1CFGR				U(0x101C)
+#define RCC_XBAR2CFGR				U(0x1020)
+#define RCC_XBAR3CFGR				U(0x1024)
+#define RCC_XBAR4CFGR				U(0x1028)
+#define RCC_XBAR5CFGR				U(0x102C)
+#define RCC_XBAR6CFGR				U(0x1030)
+#define RCC_XBAR7CFGR				U(0x1034)
+#define RCC_XBAR8CFGR				U(0x1038)
+#define RCC_XBAR9CFGR				U(0x103C)
+#define RCC_XBAR10CFGR				U(0x1040)
+#define RCC_XBAR11CFGR				U(0x1044)
+#define RCC_XBAR12CFGR				U(0x1048)
+#define RCC_XBAR13CFGR				U(0x104C)
+#define RCC_XBAR14CFGR				U(0x1050)
+#define RCC_XBAR15CFGR				U(0x1054)
+#define RCC_XBAR16CFGR				U(0x1058)
+#define RCC_XBAR17CFGR				U(0x105C)
+#define RCC_XBAR18CFGR				U(0x1060)
+#define RCC_XBAR19CFGR				U(0x1064)
+#define RCC_XBAR20CFGR				U(0x1068)
+#define RCC_XBAR21CFGR				U(0x106C)
+#define RCC_XBAR22CFGR				U(0x1070)
+#define RCC_XBAR23CFGR				U(0x1074)
+#define RCC_XBAR24CFGR				U(0x1078)
+#define RCC_XBAR25CFGR				U(0x107C)
+#define RCC_XBAR26CFGR				U(0x1080)
+#define RCC_XBAR27CFGR				U(0x1084)
+#define RCC_XBAR28CFGR				U(0x1088)
+#define RCC_XBAR29CFGR				U(0x108C)
+#define RCC_XBAR30CFGR				U(0x1090)
+#define RCC_XBAR31CFGR				U(0x1094)
+#define RCC_XBAR32CFGR				U(0x1098)
+#define RCC_XBAR33CFGR				U(0x109C)
+#define RCC_XBAR34CFGR				U(0x10A0)
+#define RCC_XBAR35CFGR				U(0x10A4)
+#define RCC_XBAR36CFGR				U(0x10A8)
+#define RCC_XBAR37CFGR				U(0x10AC)
+#define RCC_XBAR38CFGR				U(0x10B0)
+#define RCC_XBAR39CFGR				U(0x10B4)
+#define RCC_XBAR40CFGR				U(0x10B8)
+#define RCC_XBAR41CFGR				U(0x10BC)
+#define RCC_XBAR42CFGR				U(0x10C0)
+#define RCC_XBAR43CFGR				U(0x10C4)
+#define RCC_XBAR44CFGR				U(0x10C8)
+#define RCC_XBAR45CFGR				U(0x10CC)
+#define RCC_XBAR46CFGR				U(0x10D0)
+#define RCC_XBAR47CFGR				U(0x10D4)
+#define RCC_XBAR48CFGR				U(0x10D8)
+#define RCC_XBAR49CFGR				U(0x10DC)
+#define RCC_XBAR50CFGR				U(0x10E0)
+#define RCC_XBAR51CFGR				U(0x10E4)
+#define RCC_XBAR52CFGR				U(0x10E8)
+#define RCC_XBAR53CFGR				U(0x10EC)
+#define RCC_XBAR54CFGR				U(0x10F0)
+#define RCC_XBAR55CFGR				U(0x10F4)
+#define RCC_XBAR56CFGR				U(0x10F8)
+#define RCC_XBAR57CFGR				U(0x10FC)
+#define RCC_XBAR58CFGR				U(0x1100)
+#define RCC_XBAR59CFGR				U(0x1104)
+#define RCC_XBAR60CFGR				U(0x1108)
+#define RCC_XBAR61CFGR				U(0x110C)
+#define RCC_XBAR62CFGR				U(0x1110)
+#define RCC_XBAR63CFGR				U(0x1114)
+#define RCC_PREDIV0CFGR				U(0x1118)
+#define RCC_PREDIV1CFGR				U(0x111C)
+#define RCC_PREDIV2CFGR				U(0x1120)
+#define RCC_PREDIV3CFGR				U(0x1124)
+#define RCC_PREDIV4CFGR				U(0x1128)
+#define RCC_PREDIV5CFGR				U(0x112C)
+#define RCC_PREDIV6CFGR				U(0x1130)
+#define RCC_PREDIV7CFGR				U(0x1134)
+#define RCC_PREDIV8CFGR				U(0x1138)
+#define RCC_PREDIV9CFGR				U(0x113C)
+#define RCC_PREDIV10CFGR			U(0x1140)
+#define RCC_PREDIV11CFGR			U(0x1144)
+#define RCC_PREDIV12CFGR			U(0x1148)
+#define RCC_PREDIV13CFGR			U(0x114C)
+#define RCC_PREDIV14CFGR			U(0x1150)
+#define RCC_PREDIV15CFGR			U(0x1154)
+#define RCC_PREDIV16CFGR			U(0x1158)
+#define RCC_PREDIV17CFGR			U(0x115C)
+#define RCC_PREDIV18CFGR			U(0x1160)
+#define RCC_PREDIV19CFGR			U(0x1164)
+#define RCC_PREDIV20CFGR			U(0x1168)
+#define RCC_PREDIV21CFGR			U(0x116C)
+#define RCC_PREDIV22CFGR			U(0x1170)
+#define RCC_PREDIV23CFGR			U(0x1174)
+#define RCC_PREDIV24CFGR			U(0x1178)
+#define RCC_PREDIV25CFGR			U(0x117C)
+#define RCC_PREDIV26CFGR			U(0x1180)
+#define RCC_PREDIV27CFGR			U(0x1184)
+#define RCC_PREDIV28CFGR			U(0x1188)
+#define RCC_PREDIV29CFGR			U(0x118C)
+#define RCC_PREDIV30CFGR			U(0x1190)
+#define RCC_PREDIV31CFGR			U(0x1194)
+#define RCC_PREDIV32CFGR			U(0x1198)
+#define RCC_PREDIV33CFGR			U(0x119C)
+#define RCC_PREDIV34CFGR			U(0x11A0)
+#define RCC_PREDIV35CFGR			U(0x11A4)
+#define RCC_PREDIV36CFGR			U(0x11A8)
+#define RCC_PREDIV37CFGR			U(0x11AC)
+#define RCC_PREDIV38CFGR			U(0x11B0)
+#define RCC_PREDIV39CFGR			U(0x11B4)
+#define RCC_PREDIV40CFGR			U(0x11B8)
+#define RCC_PREDIV41CFGR			U(0x11BC)
+#define RCC_PREDIV42CFGR			U(0x11C0)
+#define RCC_PREDIV43CFGR			U(0x11C4)
+#define RCC_PREDIV44CFGR			U(0x11C8)
+#define RCC_PREDIV45CFGR			U(0x11CC)
+#define RCC_PREDIV46CFGR			U(0x11D0)
+#define RCC_PREDIV47CFGR			U(0x11D4)
+#define RCC_PREDIV48CFGR			U(0x11D8)
+#define RCC_PREDIV49CFGR			U(0x11DC)
+#define RCC_PREDIV50CFGR			U(0x11E0)
+#define RCC_PREDIV51CFGR			U(0x11E4)
+#define RCC_PREDIV52CFGR			U(0x11E8)
+#define RCC_PREDIV53CFGR			U(0x11EC)
+#define RCC_PREDIV54CFGR			U(0x11F0)
+#define RCC_PREDIV55CFGR			U(0x11F4)
+#define RCC_PREDIV56CFGR			U(0x11F8)
+#define RCC_PREDIV57CFGR			U(0x11FC)
+#define RCC_PREDIV58CFGR			U(0x1200)
+#define RCC_PREDIV59CFGR			U(0x1204)
+#define RCC_PREDIV60CFGR			U(0x1208)
+#define RCC_PREDIV61CFGR			U(0x120C)
+#define RCC_PREDIV62CFGR			U(0x1210)
+#define RCC_PREDIV63CFGR			U(0x1214)
+#define RCC_PREDIVSR1				U(0x1218)
+#define RCC_PREDIVSR2				U(0x121C)
+#define RCC_FINDIV0CFGR				U(0x1224)
+#define RCC_FINDIV1CFGR				U(0x1228)
+#define RCC_FINDIV2CFGR				U(0x122C)
+#define RCC_FINDIV3CFGR				U(0x1230)
+#define RCC_FINDIV4CFGR				U(0x1234)
+#define RCC_FINDIV5CFGR				U(0x1238)
+#define RCC_FINDIV6CFGR				U(0x123C)
+#define RCC_FINDIV7CFGR				U(0x1240)
+#define RCC_FINDIV8CFGR				U(0x1244)
+#define RCC_FINDIV9CFGR				U(0x1248)
+#define RCC_FINDIV10CFGR			U(0x124C)
+#define RCC_FINDIV11CFGR			U(0x1250)
+#define RCC_FINDIV12CFGR			U(0x1254)
+#define RCC_FINDIV13CFGR			U(0x1258)
+#define RCC_FINDIV14CFGR			U(0x125C)
+#define RCC_FINDIV15CFGR			U(0x1260)
+#define RCC_FINDIV16CFGR			U(0x1264)
+#define RCC_FINDIV17CFGR			U(0x1268)
+#define RCC_FINDIV18CFGR			U(0x126C)
+#define RCC_FINDIV19CFGR			U(0x1270)
+#define RCC_FINDIV20CFGR			U(0x1274)
+#define RCC_FINDIV21CFGR			U(0x1278)
+#define RCC_FINDIV22CFGR			U(0x127C)
+#define RCC_FINDIV23CFGR			U(0x1280)
+#define RCC_FINDIV24CFGR			U(0x1284)
+#define RCC_FINDIV25CFGR			U(0x1288)
+#define RCC_FINDIV26CFGR			U(0x128C)
+#define RCC_FINDIV27CFGR			U(0x1290)
+#define RCC_FINDIV28CFGR			U(0x1294)
+#define RCC_FINDIV29CFGR			U(0x1298)
+#define RCC_FINDIV30CFGR			U(0x129C)
+#define RCC_FINDIV31CFGR			U(0x12A0)
+#define RCC_FINDIV32CFGR			U(0x12A4)
+#define RCC_FINDIV33CFGR			U(0x12A8)
+#define RCC_FINDIV34CFGR			U(0x12AC)
+#define RCC_FINDIV35CFGR			U(0x12B0)
+#define RCC_FINDIV36CFGR			U(0x12B4)
+#define RCC_FINDIV37CFGR			U(0x12B8)
+#define RCC_FINDIV38CFGR			U(0x12BC)
+#define RCC_FINDIV39CFGR			U(0x12C0)
+#define RCC_FINDIV40CFGR			U(0x12C4)
+#define RCC_FINDIV41CFGR			U(0x12C8)
+#define RCC_FINDIV42CFGR			U(0x12CC)
+#define RCC_FINDIV43CFGR			U(0x12D0)
+#define RCC_FINDIV44CFGR			U(0x12D4)
+#define RCC_FINDIV45CFGR			U(0x12D8)
+#define RCC_FINDIV46CFGR			U(0x12DC)
+#define RCC_FINDIV47CFGR			U(0x12E0)
+#define RCC_FINDIV48CFGR			U(0x12E4)
+#define RCC_FINDIV49CFGR			U(0x12E8)
+#define RCC_FINDIV50CFGR			U(0x12EC)
+#define RCC_FINDIV51CFGR			U(0x12F0)
+#define RCC_FINDIV52CFGR			U(0x12F4)
+#define RCC_FINDIV53CFGR			U(0x12F8)
+#define RCC_FINDIV54CFGR			U(0x12FC)
+#define RCC_FINDIV55CFGR			U(0x1300)
+#define RCC_FINDIV56CFGR			U(0x1304)
+#define RCC_FINDIV57CFGR			U(0x1308)
+#define RCC_FINDIV58CFGR			U(0x130C)
+#define RCC_FINDIV59CFGR			U(0x1310)
+#define RCC_FINDIV60CFGR			U(0x1314)
+#define RCC_FINDIV61CFGR			U(0x1318)
+#define RCC_FINDIV62CFGR			U(0x131C)
+#define RCC_FINDIV63CFGR			U(0x1320)
+#define RCC_FINDIVSR1				U(0x1324)
+#define RCC_FINDIVSR2				U(0x1328)
+#define RCC_FCALCOBS0CFGR			U(0x1340)
+#define RCC_FCALCOBS1CFGR			U(0x1344)
+#define RCC_FCALCREFCFGR			U(0x1348)
+#define RCC_FCALCCR1				U(0x134C)
+#define RCC_FCALCCR2				U(0x1354)
+#define RCC_FCALCSR				U(0x1358)
+#define RCC_PLL4CFGR1				U(0x1360)
+#define RCC_PLL4CFGR2				U(0x1364)
+#define RCC_PLL4CFGR3				U(0x1368)
+#define RCC_PLL4CFGR4				U(0x136C)
+#define RCC_PLL4CFGR5				U(0x1370)
+#define RCC_PLL4CFGR6				U(0x1378)
+#define RCC_PLL4CFGR7				U(0x137C)
+#define RCC_PLL5CFGR1				U(0x1388)
+#define RCC_PLL5CFGR2				U(0x138C)
+#define RCC_PLL5CFGR3				U(0x1390)
+#define RCC_PLL5CFGR4				U(0x1394)
+#define RCC_PLL5CFGR5				U(0x1398)
+#define RCC_PLL5CFGR6				U(0x13A0)
+#define RCC_PLL5CFGR7				U(0x13A4)
+#define RCC_PLL6CFGR1				U(0x13B0)
+#define RCC_PLL6CFGR2				U(0x13B4)
+#define RCC_PLL6CFGR3				U(0x13B8)
+#define RCC_PLL6CFGR4				U(0x13BC)
+#define RCC_PLL6CFGR5				U(0x13C0)
+#define RCC_PLL6CFGR6				U(0x13C8)
+#define RCC_PLL6CFGR7				U(0x13CC)
+#define RCC_PLL7CFGR1				U(0x13D8)
+#define RCC_PLL7CFGR2				U(0x13DC)
+#define RCC_PLL7CFGR3				U(0x13E0)
+#define RCC_PLL7CFGR4				U(0x13E4)
+#define RCC_PLL7CFGR5				U(0x13E8)
+#define RCC_PLL7CFGR6				U(0x13F0)
+#define RCC_PLL7CFGR7				U(0x13F4)
+#define RCC_PLL8CFGR1				U(0x1400)
+#define RCC_PLL8CFGR2				U(0x1404)
+#define RCC_PLL8CFGR3				U(0x1408)
+#define RCC_PLL8CFGR4				U(0x140C)
+#define RCC_PLL8CFGR5				U(0x1410)
+#define RCC_PLL8CFGR6				U(0x1418)
+#define RCC_PLL8CFGR7				U(0x141C)
+#define RCC_VERR				U(0xFFF4)
+#define RCC_IDR					U(0xFFF8)
+#define RCC_SIDR				U(0xFFFC)
+
+/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */
+#define RCC_MP_ENCLRR_OFFSET			U(4)
+
+/* RCC_GRSTCSETR register fields */
+#define RCC_GRSTCSETR_SYSRST			BIT(0)
+
+/* RCC_C1RSTCSETR register fields */
+#define RCC_C1RSTCSETR_C1RST			BIT(0)
+
+/* RCC_C1P1RSTCSETR register fields */
+#define RCC_C1P1RSTCSETR_C1P1PORRST		BIT(0)
+#define RCC_C1P1RSTCSETR_C1P1RST		BIT(1)
+
+/* RCC_C2RSTCSETR register fields */
+#define RCC_C2RSTCSETR_C2RST			BIT(0)
+
+/* RCC_CxRSTCSETR register fields */
+#define RCC_CxRSTCSETR_CxRST			BIT(0)
+
+/* RCC_HWRSTSCLRR register fields */
+#define RCC_HWRSTSCLRR_PORRSTF			BIT(0)
+#define RCC_HWRSTSCLRR_BORRSTF			BIT(1)
+#define RCC_HWRSTSCLRR_PADRSTF			BIT(2)
+#define RCC_HWRSTSCLRR_HCSSRSTF			BIT(3)
+#define RCC_HWRSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_HWRSTSCLRR_SYSC1RSTF		BIT(5)
+#define RCC_HWRSTSCLRR_SYSC2RSTF		BIT(6)
+#define RCC_HWRSTSCLRR_IWDG1SYSRSTF		BIT(7)
+#define RCC_HWRSTSCLRR_IWDG2SYSRSTF		BIT(8)
+#define RCC_HWRSTSCLRR_IWDG3SYSRSTF		BIT(9)
+#define RCC_HWRSTSCLRR_IWDG4SYSRSTF		BIT(10)
+#define RCC_HWRSTSCLRR_IWDG5SYSRSTF		BIT(11)
+#define RCC_HWRSTSCLRR_RETCRCERRRSTF		BIT(12)
+#define RCC_HWRSTSCLRR_RETECCFAILCRCRSTF	BIT(13)
+#define RCC_HWRSTSCLRR_RETECCFAILRESTRSTF	BIT(14)
+
+/* RCC_C1HWRSTSCLRR register fields */
+#define RCC_C1HWRSTSCLRR_VCPURSTF		BIT(0)
+#define RCC_C1HWRSTSCLRR_C1RSTF			BIT(1)
+#define RCC_C1HWRSTSCLRR_C1P1RSTF		BIT(2)
+
+/* RCC_C2HWRSTSCLRR register fields */
+#define RCC_C2HWRSTSCLRR_C2RSTF			BIT(0)
+
+/* RCC_C1BOOTRSTSSETR register fields */
+#define RCC_C1BOOTRSTSSETR_PORRSTF		BIT(0)
+#define RCC_C1BOOTRSTSSETR_BORRSTF		BIT(1)
+#define RCC_C1BOOTRSTSSETR_PADRSTF		BIT(2)
+#define RCC_C1BOOTRSTSSETR_HCSSRSTF		BIT(3)
+#define RCC_C1BOOTRSTSSETR_VCORERSTF		BIT(4)
+#define RCC_C1BOOTRSTSSETR_VCPURSTF		BIT(5)
+#define RCC_C1BOOTRSTSSETR_SYSC1RSTF		BIT(6)
+#define RCC_C1BOOTRSTSSETR_SYSC2RSTF		BIT(7)
+#define RCC_C1BOOTRSTSSETR_IWDG1SYSRSTF		BIT(8)
+#define RCC_C1BOOTRSTSSETR_IWDG2SYSRSTF		BIT(9)
+#define RCC_C1BOOTRSTSSETR_IWDG3SYSRSTF		BIT(10)
+#define RCC_C1BOOTRSTSSETR_IWDG4SYSRSTF		BIT(11)
+#define RCC_C1BOOTRSTSSETR_IWDG5SYSRSTF		BIT(12)
+#define RCC_C1BOOTRSTSSETR_C1RSTF		BIT(13)
+#define RCC_C1BOOTRSTSSETR_C1P1RSTF		BIT(16)
+#define RCC_C1BOOTRSTSSETR_RETCRCERRRSTF	BIT(17)
+#define RCC_C1BOOTRSTSSETR_RETECCFAILCRCRSTF	BIT(18)
+#define RCC_C1BOOTRSTSSETR_RETECCFAILRESTRSTF	BIT(19)
+#define RCC_C1BOOTRSTSSETR_STBYC1RSTF		BIT(20)
+#define RCC_C1BOOTRSTSSETR_D1STBYRSTF		BIT(22)
+#define RCC_C1BOOTRSTSSETR_D2STBYRSTF		BIT(23)
+
+/* RCC_C1BOOTRSTSCLRR register fields */
+#define RCC_C1BOOTRSTSCLRR_PORRSTF		BIT(0)
+#define RCC_C1BOOTRSTSCLRR_BORRSTF		BIT(1)
+#define RCC_C1BOOTRSTSCLRR_PADRSTF		BIT(2)
+#define RCC_C1BOOTRSTSCLRR_HCSSRSTF		BIT(3)
+#define RCC_C1BOOTRSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_C1BOOTRSTSCLRR_VCPURSTF		BIT(5)
+#define RCC_C1BOOTRSTSCLRR_SYSC1RSTF		BIT(6)
+#define RCC_C1BOOTRSTSCLRR_SYSC2RSTF		BIT(7)
+#define RCC_C1BOOTRSTSCLRR_IWDG1SYSRSTF		BIT(8)
+#define RCC_C1BOOTRSTSCLRR_IWDG2SYSRSTF		BIT(9)
+#define RCC_C1BOOTRSTSCLRR_IWDG3SYSRSTF		BIT(10)
+#define RCC_C1BOOTRSTSCLRR_IWDG4SYSRSTF		BIT(11)
+#define RCC_C1BOOTRSTSCLRR_IWDG5SYSRSTF		BIT(12)
+#define RCC_C1BOOTRSTSCLRR_C1RSTF		BIT(13)
+#define RCC_C1BOOTRSTSCLRR_C1P1RSTF		BIT(16)
+#define RCC_C1BOOTRSTSCLRR_RETCRCERRRSTF	BIT(17)
+#define RCC_C1BOOTRSTSCLRR_RETECCFAILCRCRSTF	BIT(18)
+#define RCC_C1BOOTRSTSCLRR_RETECCFAILRESTRSTF	BIT(19)
+#define RCC_C1BOOTRSTSCLRR_STBYC1RSTF		BIT(20)
+#define RCC_C1BOOTRSTSCLRR_D1STBYRSTF		BIT(22)
+#define RCC_C1BOOTRSTSCLRR_D2STBYRSTF		BIT(23)
+
+/* RCC_C2BOOTRSTSSETR register fields */
+#define RCC_C2BOOTRSTSSETR_PORRSTF		BIT(0)
+#define RCC_C2BOOTRSTSSETR_BORRSTF		BIT(1)
+#define RCC_C2BOOTRSTSSETR_PADRSTF		BIT(2)
+#define RCC_C2BOOTRSTSSETR_HCSSRSTF		BIT(3)
+#define RCC_C2BOOTRSTSSETR_VCORERSTF		BIT(4)
+#define RCC_C2BOOTRSTSSETR_SYSC1RSTF		BIT(6)
+#define RCC_C2BOOTRSTSSETR_SYSC2RSTF		BIT(7)
+#define RCC_C2BOOTRSTSSETR_IWDG1SYSRSTF		BIT(8)
+#define RCC_C2BOOTRSTSSETR_IWDG2SYSRSTF		BIT(9)
+#define RCC_C2BOOTRSTSSETR_IWDG3SYSRSTF		BIT(10)
+#define RCC_C2BOOTRSTSSETR_IWDG4SYSRSTF		BIT(11)
+#define RCC_C2BOOTRSTSSETR_IWDG5SYSRSTF		BIT(12)
+#define RCC_C2BOOTRSTSSETR_C2RSTF		BIT(14)
+#define RCC_C2BOOTRSTSSETR_RETCRCERRRSTF	BIT(17)
+#define RCC_C2BOOTRSTSSETR_RETECCFAILCRCRSTF	BIT(18)
+#define RCC_C2BOOTRSTSSETR_RETECCFAILRESTRSTF	BIT(19)
+#define RCC_C2BOOTRSTSSETR_STBYC2RSTF		BIT(21)
+#define RCC_C2BOOTRSTSSETR_D2STBYRSTF		BIT(23)
+#define RCC_C2BOOTRSTSSETR_IWDG3LOCRSTF		BIT(26)
+#define RCC_C2BOOTRSTSSETR_IWDG4LOCRSTF		BIT(27)
+
+/* RCC_C2BOOTRSTSCLRR register fields */
+#define RCC_C2BOOTRSTSCLRR_PORRSTF		BIT(0)
+#define RCC_C2BOOTRSTSCLRR_BORRSTF		BIT(1)
+#define RCC_C2BOOTRSTSCLRR_PADRSTF		BIT(2)
+#define RCC_C2BOOTRSTSCLRR_HCSSRSTF		BIT(3)
+#define RCC_C2BOOTRSTSCLRR_VCORERSTF		BIT(4)
+#define RCC_C2BOOTRSTSCLRR_SYSC1RSTF		BIT(6)
+#define RCC_C2BOOTRSTSCLRR_SYSC2RSTF		BIT(7)
+#define RCC_C2BOOTRSTSCLRR_IWDG1SYSRSTF		BIT(8)
+#define RCC_C2BOOTRSTSCLRR_IWDG2SYSRSTF		BIT(9)
+#define RCC_C2BOOTRSTSCLRR_IWDG3SYSRSTF		BIT(10)
+#define RCC_C2BOOTRSTSCLRR_IWDG4SYSRSTF		BIT(11)
+#define RCC_C2BOOTRSTSCLRR_IWDG5SYSRSTF		BIT(12)
+#define RCC_C2BOOTRSTSCLRR_C2RSTF		BIT(14)
+#define RCC_C2BOOTRSTSCLRR_RETCRCERRRSTF	BIT(17)
+#define RCC_C2BOOTRSTSCLRR_RETECCFAILCRCRSTF	BIT(18)
+#define RCC_C2BOOTRSTSCLRR_RETECCFAILRESTRSTF	BIT(19)
+#define RCC_C2BOOTRSTSCLRR_STBYC2RSTF		BIT(21)
+#define RCC_C2BOOTRSTSCLRR_D2STBYRSTF		BIT(23)
+
+/* RCC_C1SREQSETR register fields */
+#define RCC_C1SREQSETR_STPREQ_P0		BIT(0)
+#define RCC_C1SREQSETR_STPREQ_P1		BIT(1)
+
+/* RCC_C1SREQCLRR register fields */
+#define RCC_C1SREQCLRR_STPREQ_P0		BIT(0)
+#define RCC_C1SREQCLRR_STPREQ_P1		BIT(1)
+
+/* RCC_CPUBOOTCR register fields */
+#define RCC_CPUBOOTCR_BOOT_CPU2			BIT(0)
+#define RCC_CPUBOOTCR_BOOT_CPU1			BIT(1)
+
+/* RCC_STBYBOOTCR register fields */
+#define RCC_STBYBOOTCR_CPU_BEN_SEL		BIT(1)
+#define RCC_STBYBOOTCR_COLD_CPU2		BIT(2)
+#define RCC_STBYBOOTCR_CPU2_HW_BEN		BIT(4)
+#define RCC_STBYBOOTCR_CPU1_HW_BEN		BIT(5)
+#define RCC_STBYBOOTCR_RET_CRCERR_RSTEN		BIT(8)
+
+/* RCC_LEGBOOTCR register fields */
+#define RCC_LEGBOOTCR_LEGACY_BEN		BIT(0)
+
+/* RCC_BDCR register fields */
+#define RCC_BDCR_LSEON				BIT(0)
+#define RCC_BDCR_LSEBYP				BIT(1)
+#define RCC_BDCR_LSERDY				BIT(2)
+#define RCC_BDCR_LSEDIGBYP			BIT(3)
+#define RCC_BDCR_LSEDRV_MASK			GENMASK_32(5, 4)
+#define RCC_BDCR_LSEDRV_SHIFT			4
+#define RCC_BDCR_LSECSSON			BIT(6)
+#define RCC_BDCR_LSEGFON			BIT(7)
+#define RCC_BDCR_LSECSSD			BIT(8)
+#define RCC_BDCR_LSION				BIT(9)
+#define RCC_BDCR_LSIRDY				BIT(10)
+#define RCC_BDCR_RTCSRC_MASK			GENMASK_32(17, 16)
+#define RCC_BDCR_RTCSRC_SHIFT			16
+#define RCC_BDCR_RTCCKEN			BIT(20)
+#define RCC_BDCR_MSIFREQSEL			BIT(24)
+#define RCC_BDCR_C3SYSTICKSEL			BIT(25)
+#define RCC_BDCR_VSWRST				BIT(31)
+#define RCC_BDCR_LSEBYP_BIT			1
+#define RCC_BDCR_LSEDIGBYP_BIT			3
+#define RCC_BDCR_LSECSSON_BIT			6
+#define RCC_BDCR_LSERDY_BIT			2
+#define RCC_BDCR_LSIRDY_BIT			10
+
+#define RCC_BDCR_LSEDRV_SHIFT			4
+#define RCC_BDCR_LSEDRV_WIDTH			2
+
+/* RCC_D3DCR register fields */
+#define RCC_D3DCR_MSION				BIT(0)
+#define RCC_D3DCR_MSIKERON			BIT(1)
+#define RCC_D3DCR_MSIRDY			BIT(2)
+#define RCC_D3DCR_D3PERCKSEL_MASK		GENMASK_32(17, 16)
+#define RCC_D3DCR_D3PERCKSEL_SHIFT		16
+#define RCC_D3DCR_MSIRDY_BIT			2
+
+/* RCC_D3DSR register fields */
+#define RCC_D3DSR_D3STATE_MASK			GENMASK_32(1, 0)
+#define RCC_D3DSR_D3STATE_SHIFT			0
+
+/* RCC_RDCR register fields */
+#define RCC_RDCR_MRD_MASK			GENMASK_32(20, 16)
+#define RCC_RDCR_MRD_SHIFT			16
+#define RCC_RDCR_EADLY_MASK			GENMASK_32(27, 24)
+#define RCC_RDCR_EADLY_SHIFT			24
+
+/* RCC_C1MSRDCR register fields */
+#define RCC_C1MSRDCR_C1MSRD_MASK		GENMASK_32(4, 0)
+#define RCC_C1MSRDCR_C1MSRD_SHIFT		0
+#define RCC_C1MSRDCR_C1MSRST			BIT(8)
+
+/* RCC_PWRLPDLYCR register fields */
+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK		GENMASK_32(21, 0)
+#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT		0
+#define RCC_PWRLPDLYCR_CPU2TMPSKP		BIT(24)
+
+/* RCC_C1CIESETR register fields */
+#define RCC_C1CIESETR_LSIRDYIE			BIT(0)
+#define RCC_C1CIESETR_LSERDYIE			BIT(1)
+#define RCC_C1CIESETR_HSIRDYIE			BIT(2)
+#define RCC_C1CIESETR_HSERDYIE			BIT(3)
+#define RCC_C1CIESETR_MSIRDYIE			BIT(4)
+#define RCC_C1CIESETR_PLL1RDYIE			BIT(5)
+#define RCC_C1CIESETR_PLL2RDYIE			BIT(6)
+#define RCC_C1CIESETR_PLL3RDYIE			BIT(7)
+#define RCC_C1CIESETR_PLL4RDYIE			BIT(8)
+#define RCC_C1CIESETR_PLL5RDYIE			BIT(9)
+#define RCC_C1CIESETR_PLL6RDYIE			BIT(10)
+#define RCC_C1CIESETR_PLL7RDYIE			BIT(11)
+#define RCC_C1CIESETR_PLL8RDYIE			BIT(12)
+#define RCC_C1CIESETR_LSECSSIE			BIT(16)
+#define RCC_C1CIESETR_WKUPIE			BIT(20)
+
+/* RCC_C1CIFCLRR register fields */
+#define RCC_C1CIFCLRR_LSIRDYF			BIT(0)
+#define RCC_C1CIFCLRR_LSERDYF			BIT(1)
+#define RCC_C1CIFCLRR_HSIRDYF			BIT(2)
+#define RCC_C1CIFCLRR_HSERDYF			BIT(3)
+#define RCC_C1CIFCLRR_MSIRDYF			BIT(4)
+#define RCC_C1CIFCLRR_PLL1RDYF			BIT(5)
+#define RCC_C1CIFCLRR_PLL2RDYF			BIT(6)
+#define RCC_C1CIFCLRR_PLL3RDYF			BIT(7)
+#define RCC_C1CIFCLRR_PLL4RDYF			BIT(8)
+#define RCC_C1CIFCLRR_PLL5RDYF			BIT(9)
+#define RCC_C1CIFCLRR_PLL6RDYF			BIT(10)
+#define RCC_C1CIFCLRR_PLL7RDYF			BIT(11)
+#define RCC_C1CIFCLRR_PLL8RDYF			BIT(12)
+#define RCC_C1CIFCLRR_LSECSSF			BIT(16)
+#define RCC_C1CIFCLRR_WKUPF			BIT(20)
+
+/* RCC_C2CIESETR register fields */
+#define RCC_C2CIESETR_LSIRDYIE			BIT(0)
+#define RCC_C2CIESETR_LSERDYIE			BIT(1)
+#define RCC_C2CIESETR_HSIRDYIE			BIT(2)
+#define RCC_C2CIESETR_HSERDYIE			BIT(3)
+#define RCC_C2CIESETR_MSIRDYIE			BIT(4)
+#define RCC_C2CIESETR_PLL1RDYIE			BIT(5)
+#define RCC_C2CIESETR_PLL2RDYIE			BIT(6)
+#define RCC_C2CIESETR_PLL3RDYIE			BIT(7)
+#define RCC_C2CIESETR_PLL4RDYIE			BIT(8)
+#define RCC_C2CIESETR_PLL5RDYIE			BIT(9)
+#define RCC_C2CIESETR_PLL6RDYIE			BIT(10)
+#define RCC_C2CIESETR_PLL7RDYIE			BIT(11)
+#define RCC_C2CIESETR_PLL8RDYIE			BIT(12)
+#define RCC_C2CIESETR_LSECSSIE			BIT(16)
+#define RCC_C2CIESETR_WKUPIE			BIT(20)
+
+/* RCC_C2CIFCLRR register fields */
+#define RCC_C2CIFCLRR_LSIRDYF			BIT(0)
+#define RCC_C2CIFCLRR_LSERDYF			BIT(1)
+#define RCC_C2CIFCLRR_HSIRDYF			BIT(2)
+#define RCC_C2CIFCLRR_HSERDYF			BIT(3)
+#define RCC_C2CIFCLRR_MSIRDYF			BIT(4)
+#define RCC_C2CIFCLRR_PLL1RDYF			BIT(5)
+#define RCC_C2CIFCLRR_PLL2RDYF			BIT(6)
+#define RCC_C2CIFCLRR_PLL3RDYF			BIT(7)
+#define RCC_C2CIFCLRR_PLL4RDYF			BIT(8)
+#define RCC_C2CIFCLRR_PLL5RDYF			BIT(9)
+#define RCC_C2CIFCLRR_PLL6RDYF			BIT(10)
+#define RCC_C2CIFCLRR_PLL7RDYF			BIT(11)
+#define RCC_C2CIFCLRR_PLL8RDYF			BIT(12)
+#define RCC_C2CIFCLRR_LSECSSF			BIT(16)
+#define RCC_C2CIFCLRR_WKUPF			BIT(20)
+
+/* RCC_CxCIESETR register fields */
+#define RCC_CxCIESETR_LSIRDYIE			BIT(0)
+#define RCC_CxCIESETR_LSERDYIE			BIT(1)
+#define RCC_CxCIESETR_HSIRDYIE			BIT(2)
+#define RCC_CxCIESETR_HSERDYIE			BIT(3)
+#define RCC_CxCIESETR_MSIRDYIE			BIT(4)
+#define RCC_CxCIESETR_SHSIRDYIE			BIT(5)
+#define RCC_CxCIESETR_PLL1RDYIE			BIT(6)
+#define RCC_CxCIESETR_PLL2RDYIE			BIT(7)
+#define RCC_CxCIESETR_PLL3RDYIE			BIT(8)
+#define RCC_CxCIESETR_PLL4RDYIE			BIT(9)
+#define RCC_CxCIESETR_PLL5RDYIE			BIT(10)
+#define RCC_CxCIESETR_PLL6RDYIE			BIT(11)
+#define RCC_CxCIESETR_PLL7RDYIE			BIT(12)
+#define RCC_CxCIESETR_PLL8RDYIE			BIT(13)
+#define RCC_CxCIESETR_LSECSSIE			BIT(16)
+#define RCC_CxCIESETR_WKUPIE			BIT(20)
+
+/* RCC_CxCIFCLRR register fields */
+#define RCC_CxCIFCLRR_LSIRDYF			BIT(0)
+#define RCC_CxCIFCLRR_LSERDYF			BIT(1)
+#define RCC_CxCIFCLRR_HSIRDYF			BIT(2)
+#define RCC_CxCIFCLRR_HSERDYF			BIT(3)
+#define RCC_CxCIFCLRR_MSIRDYF			BIT(4)
+#define RCC_CxCIFCLRR_SHSIRDYF			BIT(5)
+#define RCC_CxCIFCLRR_PLL1RDYF			BIT(6)
+#define RCC_CxCIFCLRR_PLL2RDYF			BIT(7)
+#define RCC_CxCIFCLRR_PLL3RDYF			BIT(8)
+#define RCC_CxCIFCLRR_PLL4RDYF			BIT(9)
+#define RCC_CxCIFCLRR_PLL5RDYF			BIT(10)
+#define RCC_CxCIFCLRR_PLL6RDYF			BIT(11)
+#define RCC_CxCIFCLRR_PLL7RDYF			BIT(12)
+#define RCC_CxCIFCLRR_PLL8RDYF			BIT(13)
+#define RCC_CxCIFCLRR_LSECSSF			BIT(16)
+#define RCC_CxCIFCLRR_WKUPF			BIT(20)
+
+/* RCC_IWDGC1FZSETR register fields */
+#define RCC_IWDGC1FZSETR_FZ_IWDG1		BIT(0)
+#define RCC_IWDGC1FZSETR_FZ_IWDG2		BIT(1)
+
+/* RCC_IWDGC1FZCLRR register fields */
+#define RCC_IWDGC1FZCLRR_FZ_IWDG1		BIT(0)
+#define RCC_IWDGC1FZCLRR_FZ_IWDG2		BIT(1)
+
+/* RCC_IWDGC1CFGSETR register fields */
+#define RCC_IWDGC1CFGSETR_IWDG1_SYSRSTEN	BIT(0)
+#define RCC_IWDGC1CFGSETR_IWDG2_SYSRSTEN	BIT(2)
+#define RCC_IWDGC1CFGSETR_IWDG2_KERRST		BIT(18)
+
+/* RCC_IWDGC1CFGCLRR register fields */
+#define RCC_IWDGC1CFGCLRR_IWDG1_SYSRSTEN	BIT(0)
+#define RCC_IWDGC1CFGCLRR_IWDG2_SYSRSTEN	BIT(2)
+#define RCC_IWDGC1CFGCLRR_IWDG2_KERRST		BIT(18)
+
+/* RCC_IWDGC2FZSETR register fields */
+#define RCC_IWDGC2FZSETR_FZ_IWDG3		BIT(0)
+#define RCC_IWDGC2FZSETR_FZ_IWDG4		BIT(1)
+
+/* RCC_IWDGC2FZCLRR register fields */
+#define RCC_IWDGC2FZCLRR_FZ_IWDG3		BIT(0)
+#define RCC_IWDGC2FZCLRR_FZ_IWDG4		BIT(1)
+
+/* RCC_IWDGC2CFGSETR register fields */
+#define RCC_IWDGC2CFGSETR_IWDG3_SYSRSTEN	BIT(0)
+#define RCC_IWDGC2CFGSETR_IWDG4_SYSRSTEN	BIT(2)
+#define RCC_IWDGC2CFGSETR_IWDG4_KERRST		BIT(18)
+
+/* RCC_IWDGC2CFGCLRR register fields */
+#define RCC_IWDGC2CFGCLRR_IWDG3_SYSRSTEN	BIT(0)
+#define RCC_IWDGC2CFGCLRR_IWDG4_SYSRSTEN	BIT(2)
+#define RCC_IWDGC2CFGCLRR_IWDG4_KERRST		BIT(18)
+
+/* RCC_IWDGC3CFGSETR register fields */
+#define RCC_IWDGC3CFGSETR_IWDG5_SYSRSTEN	BIT(0)
+
+/* RCC_IWDGC3CFGCLRR register fields */
+#define RCC_IWDGC3CFGCLRR_IWDG5_SYSRSTEN	BIT(0)
+
+/* RCC_C3CFGR register fields */
+#define RCC_C3CFGR_C3RST			BIT(0)
+#define RCC_C3CFGR_C3EN				BIT(1)
+#define RCC_C3CFGR_C3LPEN			BIT(2)
+#define RCC_C3CFGR_C3AMEN			BIT(3)
+#define RCC_C3CFGR_LPTIM3C3EN			BIT(16)
+#define RCC_C3CFGR_LPTIM4C3EN			BIT(17)
+#define RCC_C3CFGR_LPTIM5C3EN			BIT(18)
+#define RCC_C3CFGR_SPI8C3EN			BIT(19)
+#define RCC_C3CFGR_LPUART1C3EN			BIT(20)
+#define RCC_C3CFGR_I2C8C3EN			BIT(21)
+#define RCC_C3CFGR_ADF1C3EN			BIT(23)
+#define RCC_C3CFGR_GPIOZC3EN			BIT(24)
+#define RCC_C3CFGR_LPDMAC3EN			BIT(25)
+#define RCC_C3CFGR_RTCC3EN			BIT(26)
+#define RCC_C3CFGR_I3C4C3EN			BIT(27)
+
+/* RCC_MCO1CFGR register fields */
+#define RCC_MCO1CFGR_MCO1SEL			BIT(0)
+#define RCC_MCO1CFGR_MCO1ON			BIT(8)
+
+/* RCC_MCO2CFGR register fields */
+#define RCC_MCO2CFGR_MCO2SEL			BIT(0)
+#define RCC_MCO2CFGR_MCO2ON			BIT(8)
+
+/* RCC_MCOxCFGR register fields */
+#define RCC_MCOxCFGR_MCOxSEL			BIT(0)
+#define RCC_MCOxCFGR_MCOxON			BIT(8)
+
+/* RCC_OCENSETR register fields */
+#define RCC_OCENSETR_HSION			BIT(0)
+#define RCC_OCENSETR_HSIKERON			BIT(1)
+#define RCC_OCENSETR_HSEDIV2ON			BIT(5)
+#define RCC_OCENSETR_HSEDIV2BYP			BIT(6)
+#define RCC_OCENSETR_HSEDIGBYP			BIT(7)
+#define RCC_OCENSETR_HSEON			BIT(8)
+#define RCC_OCENSETR_HSEKERON			BIT(9)
+#define RCC_OCENSETR_HSEBYP			BIT(10)
+#define RCC_OCENSETR_HSECSSON			BIT(11)
+
+#define RCC_OCENSETR_HSEDIGBYP_BIT		7
+#define RCC_OCENSETR_HSEBYP_BIT			10
+#define RCC_OCENSETR_HSECSSON_BIT		11
+
+/* RCC_OCENCLRR register fields */
+#define RCC_OCENCLRR_HSION			BIT(0)
+#define RCC_OCENCLRR_HSIKERON			BIT(1)
+#define RCC_OCENCLRR_HSEDIV2ON			BIT(5)
+#define RCC_OCENCLRR_HSEDIV2BYP			BIT(6)
+#define RCC_OCENCLRR_HSEDIGBYP			BIT(7)
+#define RCC_OCENCLRR_HSEON			BIT(8)
+#define RCC_OCENCLRR_HSEKERON			BIT(9)
+#define RCC_OCENCLRR_HSEBYP			BIT(10)
+
+/* RCC_OCRDYR register fields */
+#define RCC_OCRDYR_HSIRDY			BIT(0)
+#define RCC_OCRDYR_HSERDY			BIT(8)
+#define RCC_OCRDYR_CKREST			BIT(25)
+
+#define RCC_OCRDYR_HSIRDY_BIT			0
+#define RCC_OCRDYR_HSERDY_BIT			8
+
+/* RCC_HSICFGR register fields */
+#define RCC_HSICFGR_HSITRIM_MASK		GENMASK_32(14, 8)
+#define RCC_HSICFGR_HSITRIM_SHIFT		8
+#define RCC_HSICFGR_HSICAL_MASK			GENMASK_32(24, 16)
+#define RCC_HSICFGR_HSICAL_SHIFT		16
+
+/* RCC_MSICFGR register fields */
+#define RCC_MSICFGR_MSITRIM_MASK		GENMASK_32(12, 8)
+#define RCC_MSICFGR_MSITRIM_SHIFT		8
+#define RCC_MSICFGR_MSICAL_MASK			GENMASK_32(23, 16)
+#define RCC_MSICFGR_MSICAL_SHIFT		16
+
+/* RCC_RTCDIVR register fields */
+#define RCC_RTCDIVR_RTCDIV_MASK			GENMASK_32(5, 0)
+#define RCC_RTCDIVR_RTCDIV_SHIFT		0
+
+/* RCC_APB1DIVR register fields */
+#define RCC_APB1DIVR_APB1DIV_MASK		GENMASK_32(2, 0)
+#define RCC_APB1DIVR_APB1DIV_SHIFT		0
+#define RCC_APB1DIVR_APB1DIVRDY			BIT(31)
+
+/* RCC_APB2DIVR register fields */
+#define RCC_APB2DIVR_APB2DIV_MASK		GENMASK_32(2, 0)
+#define RCC_APB2DIVR_APB2DIV_SHIFT		0
+#define RCC_APB2DIVR_APB2DIVRDY			BIT(31)
+
+/* RCC_APB3DIVR register fields */
+#define RCC_APB3DIVR_APB3DIV_MASK		GENMASK_32(2, 0)
+#define RCC_APB3DIVR_APB3DIV_SHIFT		0
+#define RCC_APB3DIVR_APB3DIVRDY			BIT(31)
+
+/* RCC_APB4DIVR register fields */
+#define RCC_APB4DIVR_APB4DIV_MASK		GENMASK_32(2, 0)
+#define RCC_APB4DIVR_APB4DIV_SHIFT		0
+#define RCC_APB4DIVR_APB4DIVRDY			BIT(31)
+
+/* RCC_APBDBGDIVR register fields */
+#define RCC_APBDBGDIVR_APBDBGDIV_MASK		GENMASK_32(2, 0)
+#define RCC_APBDBGDIVR_APBDBGDIV_SHIFT		0
+#define RCC_APBDBGDIVR_APBDBGDIVRDY		BIT(31)
+
+/* RCC_APBxDIVR register fields */
+#define RCC_APBxDIVR_APBxDIV_MASK		GENMASK_32(2, 0)
+#define RCC_APBxDIVR_APBxDIV_SHIFT		0
+#define RCC_APBxDIVR_APBxDIVRDY			BIT(31)
+
+/* RCC_TIMG1PRER register fields */
+#define RCC_TIMG1PRER_TIMG1PRE			BIT(0)
+#define RCC_TIMG1PRER_TIMG1PRERDY		BIT(31)
+
+/* RCC_TIMG2PRER register fields */
+#define RCC_TIMG2PRER_TIMG2PRE			BIT(0)
+#define RCC_TIMG2PRER_TIMG2PRERDY		BIT(31)
+
+/* RCC_TIMGxPRER register fields */
+#define RCC_TIMGxPRER_TIMGxPRE			BIT(0)
+#define RCC_TIMGxPRER_TIMGxPRERDY		BIT(31)
+
+/* RCC_LSMCUDIVR register fields */
+#define RCC_LSMCUDIVR_LSMCUDIV			BIT(0)
+#define RCC_LSMCUDIVR_LSMCUDIVRDY		BIT(31)
+
+/* RCC_DDRCPCFGR register fields */
+#define RCC_DDRCPCFGR_DDRCPRST			BIT(0)
+#define RCC_DDRCPCFGR_DDRCPEN			BIT(1)
+#define RCC_DDRCPCFGR_DDRCPLPEN			BIT(2)
+
+/* RCC_DDRCAPBCFGR register fields */
+#define RCC_DDRCAPBCFGR_DDRCAPBRST		BIT(0)
+#define RCC_DDRCAPBCFGR_DDRCAPBEN		BIT(1)
+#define RCC_DDRCAPBCFGR_DDRCAPBLPEN		BIT(2)
+
+/* RCC_DDRPHYCAPBCFGR register fields */
+#define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBRST	BIT(0)
+#define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBEN		BIT(1)
+#define RCC_DDRPHYCAPBCFGR_DDRPHYCAPBLPEN	BIT(2)
+
+/* RCC_DDRPHYCCFGR register fields */
+#define RCC_DDRPHYCCFGR_DDRPHYCEN		BIT(1)
+
+/* RCC_DDRCFGR register fields */
+#define RCC_DDRCFGR_DDRCFGRST			BIT(0)
+#define RCC_DDRCFGR_DDRCFGEN			BIT(1)
+#define RCC_DDRCFGR_DDRCFGLPEN			BIT(2)
+
+/* RCC_DDRITFCFGR register fields */
+#define RCC_DDRITFCFGR_DDRRST			BIT(0)
+#define RCC_DDRITFCFGR_DDRCKMOD_MASK		GENMASK_32(5, 4)
+#define RCC_DDRITFCFGR_DDRCKMOD_SHIFT		4
+#define RCC_DDRITFCFGR_DDRSHR			BIT(8)
+#define RCC_DDRITFCFGR_DDRPHYDLP		BIT(16)
+
+/* RCC_SYSRAMCFGR register fields */
+#define RCC_SYSRAMCFGR_SYSRAMEN			BIT(1)
+#define RCC_SYSRAMCFGR_SYSRAMLPEN		BIT(2)
+
+/* RCC_VDERAMCFGR register fields */
+#define RCC_VDERAMCFGR_VDERAMEN			BIT(1)
+#define RCC_VDERAMCFGR_VDERAMLPEN		BIT(2)
+
+/* RCC_SRAM1CFGR register fields */
+#define RCC_SRAM1CFGR_SRAM1EN			BIT(1)
+#define RCC_SRAM1CFGR_SRAM1LPEN			BIT(2)
+
+/* RCC_SRAM2CFGR register fields */
+#define RCC_SRAM2CFGR_SRAM2EN			BIT(1)
+#define RCC_SRAM2CFGR_SRAM2LPEN			BIT(2)
+
+/* RCC_RETRAMCFGR register fields */
+#define RCC_RETRAMCFGR_RETRAMEN			BIT(1)
+#define RCC_RETRAMCFGR_RETRAMLPEN		BIT(2)
+
+/* RCC_BKPSRAMCFGR register fields */
+#define RCC_BKPSRAMCFGR_BKPSRAMEN		BIT(1)
+#define RCC_BKPSRAMCFGR_BKPSRAMLPEN		BIT(2)
+
+/* RCC_LPSRAM1CFGR register fields */
+#define RCC_LPSRAM1CFGR_LPSRAM1EN		BIT(1)
+#define RCC_LPSRAM1CFGR_LPSRAM1LPEN		BIT(2)
+#define RCC_LPSRAM1CFGR_LPSRAM1AMEN		BIT(3)
+
+/* RCC_LPSRAM2CFGR register fields */
+#define RCC_LPSRAM2CFGR_LPSRAM2EN		BIT(1)
+#define RCC_LPSRAM2CFGR_LPSRAM2LPEN		BIT(2)
+#define RCC_LPSRAM2CFGR_LPSRAM2AMEN		BIT(3)
+
+/* RCC_LPSRAM3CFGR register fields */
+#define RCC_LPSRAM3CFGR_LPSRAM3EN		BIT(1)
+#define RCC_LPSRAM3CFGR_LPSRAM3LPEN		BIT(2)
+#define RCC_LPSRAM3CFGR_LPSRAM3AMEN		BIT(3)
+
+/* RCC_OSPI1CFGR register fields */
+#define RCC_OSPI1CFGR_OSPI1RST			BIT(0)
+#define RCC_OSPI1CFGR_OSPI1EN			BIT(1)
+#define RCC_OSPI1CFGR_OSPI1LPEN			BIT(2)
+#define RCC_OSPI1CFGR_OTFDEC1RST		BIT(8)
+#define RCC_OSPI1CFGR_OSPI1DLLRST		BIT(16)
+
+/* RCC_OSPI2CFGR register fields */
+#define RCC_OSPI2CFGR_OSPI2RST			BIT(0)
+#define RCC_OSPI2CFGR_OSPI2EN			BIT(1)
+#define RCC_OSPI2CFGR_OSPI2LPEN			BIT(2)
+#define RCC_OSPI2CFGR_OTFDEC2RST		BIT(8)
+#define RCC_OSPI2CFGR_OSPI2DLLRST		BIT(16)
+
+/* RCC_OSPIxCFGR register fields */
+#define RCC_OSPIxCFGR_OSPIxRST			BIT(0)
+#define RCC_OSPIxCFGR_OSPIxEN			BIT(1)
+#define RCC_OSPIxCFGR_OSPIxLPEN			BIT(2)
+#define RCC_OSPIxCFGR_OTFDECxRST		BIT(8)
+#define RCC_OSPIxCFGR_OSPIxDLLRST		BIT(16)
+
+/* RCC_FMCCFGR register fields */
+#define RCC_FMCCFGR_FMCRST			BIT(0)
+#define RCC_FMCCFGR_FMCEN			BIT(1)
+#define RCC_FMCCFGR_FMCLPEN			BIT(2)
+
+/* RCC_DBGCFGR register fields */
+#define RCC_DBGCFGR_DBGEN			BIT(8)
+#define RCC_DBGCFGR_TRACEEN			BIT(9)
+#define RCC_DBGCFGR_DBGRST			BIT(12)
+
+/* RCC_STMCFGR register fields */
+#define RCC_STMCFGR_STMEN			BIT(1)
+#define RCC_STMCFGR_STMLPEN			BIT(2)
+
+/* RCC_ETRCFGR register fields */
+#define RCC_ETRCFGR_ETREN			BIT(1)
+#define RCC_ETRCFGR_ETRLPEN			BIT(2)
+
+/* RCC_GPIOACFGR register fields */
+#define RCC_GPIOACFGR_GPIOARST			BIT(0)
+#define RCC_GPIOACFGR_GPIOAEN			BIT(1)
+#define RCC_GPIOACFGR_GPIOALPEN			BIT(2)
+
+/* RCC_GPIOBCFGR register fields */
+#define RCC_GPIOBCFGR_GPIOBRST			BIT(0)
+#define RCC_GPIOBCFGR_GPIOBEN			BIT(1)
+#define RCC_GPIOBCFGR_GPIOBLPEN			BIT(2)
+
+/* RCC_GPIOCCFGR register fields */
+#define RCC_GPIOCCFGR_GPIOCRST			BIT(0)
+#define RCC_GPIOCCFGR_GPIOCEN			BIT(1)
+#define RCC_GPIOCCFGR_GPIOCLPEN			BIT(2)
+
+/* RCC_GPIODCFGR register fields */
+#define RCC_GPIODCFGR_GPIODRST			BIT(0)
+#define RCC_GPIODCFGR_GPIODEN			BIT(1)
+#define RCC_GPIODCFGR_GPIODLPEN			BIT(2)
+
+/* RCC_GPIOECFGR register fields */
+#define RCC_GPIOECFGR_GPIOERST			BIT(0)
+#define RCC_GPIOECFGR_GPIOEEN			BIT(1)
+#define RCC_GPIOECFGR_GPIOELPEN			BIT(2)
+
+/* RCC_GPIOFCFGR register fields */
+#define RCC_GPIOFCFGR_GPIOFRST			BIT(0)
+#define RCC_GPIOFCFGR_GPIOFEN			BIT(1)
+#define RCC_GPIOFCFGR_GPIOFLPEN			BIT(2)
+
+/* RCC_GPIOGCFGR register fields */
+#define RCC_GPIOGCFGR_GPIOGRST			BIT(0)
+#define RCC_GPIOGCFGR_GPIOGEN			BIT(1)
+#define RCC_GPIOGCFGR_GPIOGLPEN			BIT(2)
+
+/* RCC_GPIOHCFGR register fields */
+#define RCC_GPIOHCFGR_GPIOHRST			BIT(0)
+#define RCC_GPIOHCFGR_GPIOHEN			BIT(1)
+#define RCC_GPIOHCFGR_GPIOHLPEN			BIT(2)
+
+/* RCC_GPIOICFGR register fields */
+#define RCC_GPIOICFGR_GPIOIRST			BIT(0)
+#define RCC_GPIOICFGR_GPIOIEN			BIT(1)
+#define RCC_GPIOICFGR_GPIOILPEN			BIT(2)
+
+/* RCC_GPIOJCFGR register fields */
+#define RCC_GPIOJCFGR_GPIOJRST			BIT(0)
+#define RCC_GPIOJCFGR_GPIOJEN			BIT(1)
+#define RCC_GPIOJCFGR_GPIOJLPEN			BIT(2)
+
+/* RCC_GPIOKCFGR register fields */
+#define RCC_GPIOKCFGR_GPIOKRST			BIT(0)
+#define RCC_GPIOKCFGR_GPIOKEN			BIT(1)
+#define RCC_GPIOKCFGR_GPIOKLPEN			BIT(2)
+
+/* RCC_GPIOZCFGR register fields */
+#define RCC_GPIOZCFGR_GPIOZRST			BIT(0)
+#define RCC_GPIOZCFGR_GPIOZEN			BIT(1)
+#define RCC_GPIOZCFGR_GPIOZLPEN			BIT(2)
+#define RCC_GPIOZCFGR_GPIOZAMEN			BIT(3)
+
+/* RCC_GPIOxCFGR register fields */
+#define RCC_GPIOxCFGR_GPIOxRST			BIT(0)
+#define RCC_GPIOxCFGR_GPIOxEN			BIT(1)
+#define RCC_GPIOxCFGR_GPIOxLPEN			BIT(2)
+#define RCC_GPIOxCFGR_GPIOxAMEN			BIT(3)
+
+/* RCC_HPDMA1CFGR register fields */
+#define RCC_HPDMA1CFGR_HPDMA1RST		BIT(0)
+#define RCC_HPDMA1CFGR_HPDMA1EN			BIT(1)
+#define RCC_HPDMA1CFGR_HPDMA1LPEN		BIT(2)
+
+/* RCC_HPDMA2CFGR register fields */
+#define RCC_HPDMA2CFGR_HPDMA2RST		BIT(0)
+#define RCC_HPDMA2CFGR_HPDMA2EN			BIT(1)
+#define RCC_HPDMA2CFGR_HPDMA2LPEN		BIT(2)
+
+/* RCC_HPDMA3CFGR register fields */
+#define RCC_HPDMA3CFGR_HPDMA3RST		BIT(0)
+#define RCC_HPDMA3CFGR_HPDMA3EN			BIT(1)
+#define RCC_HPDMA3CFGR_HPDMA3LPEN		BIT(2)
+
+/* RCC_HPDMAxCFGR register fields */
+#define RCC_HPDMAxCFGR_HPDMAxRST		BIT(0)
+#define RCC_HPDMAxCFGR_HPDMAxEN			BIT(1)
+#define RCC_HPDMAxCFGR_HPDMAxLPEN		BIT(2)
+
+/* RCC_LPDMACFGR register fields */
+#define RCC_LPDMACFGR_LPDMARST			BIT(0)
+#define RCC_LPDMACFGR_LPDMAEN			BIT(1)
+#define RCC_LPDMACFGR_LPDMALPEN			BIT(2)
+#define RCC_LPDMACFGR_LPDMAAMEN			BIT(3)
+
+/* RCC_HSEMCFGR register fields */
+#define RCC_HSEMCFGR_HSEMRST			BIT(0)
+#define RCC_HSEMCFGR_HSEMEN			BIT(1)
+#define RCC_HSEMCFGR_HSEMLPEN			BIT(2)
+#define RCC_HSEMCFGR_HSEMAMEN			BIT(3)
+
+/* RCC_IPCC1CFGR register fields */
+#define RCC_IPCC1CFGR_IPCC1RST			BIT(0)
+#define RCC_IPCC1CFGR_IPCC1EN			BIT(1)
+#define RCC_IPCC1CFGR_IPCC1LPEN			BIT(2)
+
+/* RCC_IPCC2CFGR register fields */
+#define RCC_IPCC2CFGR_IPCC2RST			BIT(0)
+#define RCC_IPCC2CFGR_IPCC2EN			BIT(1)
+#define RCC_IPCC2CFGR_IPCC2LPEN			BIT(2)
+#define RCC_IPCC2CFGR_IPCC2AMEN			BIT(3)
+
+/* RCC_RTCCFGR register fields */
+#define RCC_RTCCFGR_RTCEN			BIT(1)
+#define RCC_RTCCFGR_RTCLPEN			BIT(2)
+#define RCC_RTCCFGR_RTCAMEN			BIT(3)
+
+/* RCC_SYSCPU1CFGR register fields */
+#define RCC_SYSCPU1CFGR_SYSCPU1EN		BIT(1)
+#define RCC_SYSCPU1CFGR_SYSCPU1LPEN		BIT(2)
+
+/* RCC_BSECCFGR register fields */
+#define RCC_BSECCFGR_BSECEN			BIT(1)
+#define RCC_BSECCFGR_BSECLPEN			BIT(2)
+
+/* RCC_IS2MCFGR register fields */
+#define RCC_IS2MCFGR_IS2MRST			BIT(0)
+#define RCC_IS2MCFGR_IS2MEN			BIT(1)
+#define RCC_IS2MCFGR_IS2MLPEN			BIT(2)
+
+/* RCC_PLL2CFGR1 register fields */
+#define RCC_PLL2CFGR1_SSMODRST			BIT(0)
+#define RCC_PLL2CFGR1_PLLEN			BIT(8)
+#define RCC_PLL2CFGR1_PLLRDY			BIT(24)
+#define RCC_PLL2CFGR1_CKREFST			BIT(28)
+
+/* RCC_PLL2CFGR2 register fields */
+#define RCC_PLL2CFGR2_FREFDIV_MASK		GENMASK_32(5, 0)
+#define RCC_PLL2CFGR2_FREFDIV_SHIFT		0
+#define RCC_PLL2CFGR2_FBDIV_MASK		GENMASK_32(27, 16)
+#define RCC_PLL2CFGR2_FBDIV_SHIFT		16
+
+/* RCC_PLL2CFGR3 register fields */
+#define RCC_PLL2CFGR3_FRACIN_MASK		GENMASK_32(23, 0)
+#define RCC_PLL2CFGR3_FRACIN_SHIFT		0
+#define RCC_PLL2CFGR3_DOWNSPREAD		BIT(24)
+#define RCC_PLL2CFGR3_DACEN			BIT(25)
+#define RCC_PLL2CFGR3_SSCGDIS			BIT(26)
+
+/* RCC_PLL2CFGR4 register fields */
+#define RCC_PLL2CFGR4_DSMEN			BIT(8)
+#define RCC_PLL2CFGR4_FOUTPOSTDIVEN		BIT(9)
+#define RCC_PLL2CFGR4_BYPASS			BIT(10)
+
+/* RCC_PLL2CFGR5 register fields */
+#define RCC_PLL2CFGR5_DIVVAL_MASK		GENMASK_32(3, 0)
+#define RCC_PLL2CFGR5_DIVVAL_SHIFT		0
+#define RCC_PLL2CFGR5_SPREAD_MASK		GENMASK_32(20, 16)
+#define RCC_PLL2CFGR5_SPREAD_SHIFT		16
+
+/* RCC_PLL2CFGR6 register fields */
+#define RCC_PLL2CFGR6_POSTDIV1_MASK		GENMASK_32(2, 0)
+#define RCC_PLL2CFGR6_POSTDIV1_SHIFT		0
+
+/* RCC_PLL2CFGR7 register fields */
+#define RCC_PLL2CFGR7_POSTDIV2_MASK		GENMASK_32(2, 0)
+#define RCC_PLL2CFGR7_POSTDIV2_SHIFT		0
+
+/* RCC_PLL3CFGR1 register fields */
+#define RCC_PLL3CFGR1_SSMODRST			BIT(0)
+#define RCC_PLL3CFGR1_PLLEN			BIT(8)
+#define RCC_PLL3CFGR1_PLLRDY			BIT(24)
+#define RCC_PLL3CFGR1_CKREFST			BIT(28)
+
+/* RCC_PLL3CFGR2 register fields */
+#define RCC_PLL3CFGR2_FREFDIV_MASK		GENMASK_32(5, 0)
+#define RCC_PLL3CFGR2_FREFDIV_SHIFT		0
+#define RCC_PLL3CFGR2_FBDIV_MASK		GENMASK_32(27, 16)
+#define RCC_PLL3CFGR2_FBDIV_SHIFT		16
+
+/* RCC_PLL3CFGR3 register fields */
+#define RCC_PLL3CFGR3_FRACIN_MASK		GENMASK_32(23, 0)
+#define RCC_PLL3CFGR3_FRACIN_SHIFT		0
+#define RCC_PLL3CFGR3_DOWNSPREAD		BIT(24)
+#define RCC_PLL3CFGR3_DACEN			BIT(25)
+#define RCC_PLL3CFGR3_SSCGDIS			BIT(26)
+
+/* RCC_PLL3CFGR4 register fields */
+#define RCC_PLL3CFGR4_DSMEN			BIT(8)
+#define RCC_PLL3CFGR4_FOUTPOSTDIVEN		BIT(9)
+#define RCC_PLL3CFGR4_BYPASS			BIT(10)
+
+/* RCC_PLL3CFGR5 register fields */
+#define RCC_PLL3CFGR5_DIVVAL_MASK		GENMASK_32(3, 0)
+#define RCC_PLL3CFGR5_DIVVAL_SHIFT		0
+#define RCC_PLL3CFGR5_SPREAD_MASK		GENMASK_32(20, 16)
+#define RCC_PLL3CFGR5_SPREAD_SHIFT		16
+
+/* RCC_PLL3CFGR6 register fields */
+#define RCC_PLL3CFGR6_POSTDIV1_MASK		GENMASK_32(2, 0)
+#define RCC_PLL3CFGR6_POSTDIV1_SHIFT		0
+
+/* RCC_PLL3CFGR7 register fields */
+#define RCC_PLL3CFGR7_POSTDIV2_MASK		GENMASK_32(2, 0)
+#define RCC_PLL3CFGR7_POSTDIV2_SHIFT		0
+
+/* RCC_PLLxCFGR1 register fields */
+#define RCC_PLLxCFGR1_SSMODRST			BIT(0)
+#define RCC_PLLxCFGR1_PLLEN			BIT(8)
+#define RCC_PLLxCFGR1_PLLRDY			BIT(24)
+#define RCC_PLLxCFGR1_CKREFST			BIT(28)
+
+/* RCC_PLLxCFGR2 register fields */
+#define RCC_PLLxCFGR2_FREFDIV_MASK		GENMASK_32(5, 0)
+#define RCC_PLLxCFGR2_FREFDIV_SHIFT		0
+#define RCC_PLLxCFGR2_FBDIV_MASK		GENMASK_32(27, 16)
+#define RCC_PLLxCFGR2_FBDIV_SHIFT		16
+
+/* RCC_PLLxCFGR3 register fields */
+#define RCC_PLLxCFGR3_FRACIN_MASK		GENMASK_32(23, 0)
+#define RCC_PLLxCFGR3_FRACIN_SHIFT		0
+#define RCC_PLLxCFGR3_DOWNSPREAD		BIT(24)
+#define RCC_PLLxCFGR3_DACEN			BIT(25)
+#define RCC_PLLxCFGR3_SSCGDIS			BIT(26)
+
+/* RCC_PLLxCFGR4 register fields */
+#define RCC_PLLxCFGR4_DSMEN			BIT(8)
+#define RCC_PLLxCFGR4_FOUTPOSTDIVEN		BIT(9)
+#define RCC_PLLxCFGR4_BYPASS			BIT(10)
+
+/* RCC_PLLxCFGR5 register fields */
+#define RCC_PLLxCFGR5_DIVVAL_MASK		GENMASK_32(3, 0)
+#define RCC_PLLxCFGR5_DIVVAL_SHIFT		0
+#define RCC_PLLxCFGR5_SPREAD_MASK		GENMASK_32(20, 16)
+#define RCC_PLLxCFGR5_SPREAD_SHIFT		16
+
+/* RCC_PLLxCFGR6 register fields */
+#define RCC_PLLxCFGR6_POSTDIV1_MASK		GENMASK_32(2, 0)
+#define RCC_PLLxCFGR6_POSTDIV1_SHIFT		0
+
+/* RCC_PLLxCFGR7 register fields */
+#define RCC_PLLxCFGR7_POSTDIV2_MASK		GENMASK_32(2, 0)
+#define RCC_PLLxCFGR7_POSTDIV2_SHIFT		0
+
+/* RCC_HSIFMONCR register fields */
+#define RCC_HSIFMONCR_HSIREF_MASK		GENMASK_32(10, 0)
+#define RCC_HSIFMONCR_HSIREF_SHIFT		0
+#define RCC_HSIFMONCR_HSIMONEN			BIT(15)
+#define RCC_HSIFMONCR_HSIDEV_MASK		GENMASK_32(21, 16)
+#define RCC_HSIFMONCR_HSIDEV_SHIFT		16
+#define RCC_HSIFMONCR_HSIMONIE			BIT(30)
+#define RCC_HSIFMONCR_HSIMONF			BIT(31)
+
+/* RCC_HSIFVALR register fields */
+#define RCC_HSIFVALR_HSIVAL_MASK		GENMASK_32(10, 0)
+#define RCC_HSIFVALR_HSIVAL_SHIFT		0
+
+/* RCC_TIM1CFGR register fields */
+#define RCC_TIM1CFGR_TIM1RST			BIT(0)
+#define RCC_TIM1CFGR_TIM1EN			BIT(1)
+#define RCC_TIM1CFGR_TIM1LPEN			BIT(2)
+
+/* RCC_TIM2CFGR register fields */
+#define RCC_TIM2CFGR_TIM2RST			BIT(0)
+#define RCC_TIM2CFGR_TIM2EN			BIT(1)
+#define RCC_TIM2CFGR_TIM2LPEN			BIT(2)
+
+/* RCC_TIM3CFGR register fields */
+#define RCC_TIM3CFGR_TIM3RST			BIT(0)
+#define RCC_TIM3CFGR_TIM3EN			BIT(1)
+#define RCC_TIM3CFGR_TIM3LPEN			BIT(2)
+
+/* RCC_TIM4CFGR register fields */
+#define RCC_TIM4CFGR_TIM4RST			BIT(0)
+#define RCC_TIM4CFGR_TIM4EN			BIT(1)
+#define RCC_TIM4CFGR_TIM4LPEN			BIT(2)
+
+/* RCC_TIM5CFGR register fields */
+#define RCC_TIM5CFGR_TIM5RST			BIT(0)
+#define RCC_TIM5CFGR_TIM5EN			BIT(1)
+#define RCC_TIM5CFGR_TIM5LPEN			BIT(2)
+
+/* RCC_TIM6CFGR register fields */
+#define RCC_TIM6CFGR_TIM6RST			BIT(0)
+#define RCC_TIM6CFGR_TIM6EN			BIT(1)
+#define RCC_TIM6CFGR_TIM6LPEN			BIT(2)
+
+/* RCC_TIM7CFGR register fields */
+#define RCC_TIM7CFGR_TIM7RST			BIT(0)
+#define RCC_TIM7CFGR_TIM7EN			BIT(1)
+#define RCC_TIM7CFGR_TIM7LPEN			BIT(2)
+
+/* RCC_TIM8CFGR register fields */
+#define RCC_TIM8CFGR_TIM8RST			BIT(0)
+#define RCC_TIM8CFGR_TIM8EN			BIT(1)
+#define RCC_TIM8CFGR_TIM8LPEN			BIT(2)
+
+/* RCC_TIM10CFGR register fields */
+#define RCC_TIM10CFGR_TIM10RST			BIT(0)
+#define RCC_TIM10CFGR_TIM10EN			BIT(1)
+#define RCC_TIM10CFGR_TIM10LPEN			BIT(2)
+
+/* RCC_TIM11CFGR register fields */
+#define RCC_TIM11CFGR_TIM11RST			BIT(0)
+#define RCC_TIM11CFGR_TIM11EN			BIT(1)
+#define RCC_TIM11CFGR_TIM11LPEN			BIT(2)
+
+/* RCC_TIM12CFGR register fields */
+#define RCC_TIM12CFGR_TIM12RST			BIT(0)
+#define RCC_TIM12CFGR_TIM12EN			BIT(1)
+#define RCC_TIM12CFGR_TIM12LPEN			BIT(2)
+
+/* RCC_TIM13CFGR register fields */
+#define RCC_TIM13CFGR_TIM13RST			BIT(0)
+#define RCC_TIM13CFGR_TIM13EN			BIT(1)
+#define RCC_TIM13CFGR_TIM13LPEN			BIT(2)
+
+/* RCC_TIM14CFGR register fields */
+#define RCC_TIM14CFGR_TIM14RST			BIT(0)
+#define RCC_TIM14CFGR_TIM14EN			BIT(1)
+#define RCC_TIM14CFGR_TIM14LPEN			BIT(2)
+
+/* RCC_TIM15CFGR register fields */
+#define RCC_TIM15CFGR_TIM15RST			BIT(0)
+#define RCC_TIM15CFGR_TIM15EN			BIT(1)
+#define RCC_TIM15CFGR_TIM15LPEN			BIT(2)
+
+/* RCC_TIM16CFGR register fields */
+#define RCC_TIM16CFGR_TIM16RST			BIT(0)
+#define RCC_TIM16CFGR_TIM16EN			BIT(1)
+#define RCC_TIM16CFGR_TIM16LPEN			BIT(2)
+
+/* RCC_TIM17CFGR register fields */
+#define RCC_TIM17CFGR_TIM17RST			BIT(0)
+#define RCC_TIM17CFGR_TIM17EN			BIT(1)
+#define RCC_TIM17CFGR_TIM17LPEN			BIT(2)
+
+/* RCC_TIM20CFGR register fields */
+#define RCC_TIM20CFGR_TIM20RST			BIT(0)
+#define RCC_TIM20CFGR_TIM20EN			BIT(1)
+#define RCC_TIM20CFGR_TIM20LPEN			BIT(2)
+
+/* RCC_LPTIM1CFGR register fields */
+#define RCC_LPTIM1CFGR_LPTIM1RST		BIT(0)
+#define RCC_LPTIM1CFGR_LPTIM1EN			BIT(1)
+#define RCC_LPTIM1CFGR_LPTIM1LPEN		BIT(2)
+
+/* RCC_LPTIM2CFGR register fields */
+#define RCC_LPTIM2CFGR_LPTIM2RST		BIT(0)
+#define RCC_LPTIM2CFGR_LPTIM2EN			BIT(1)
+#define RCC_LPTIM2CFGR_LPTIM2LPEN		BIT(2)
+
+/* RCC_LPTIM3CFGR register fields */
+#define RCC_LPTIM3CFGR_LPTIM3RST		BIT(0)
+#define RCC_LPTIM3CFGR_LPTIM3EN			BIT(1)
+#define RCC_LPTIM3CFGR_LPTIM3LPEN		BIT(2)
+#define RCC_LPTIM3CFGR_LPTIM3AMEN		BIT(3)
+
+/* RCC_LPTIM4CFGR register fields */
+#define RCC_LPTIM4CFGR_LPTIM4RST		BIT(0)
+#define RCC_LPTIM4CFGR_LPTIM4EN			BIT(1)
+#define RCC_LPTIM4CFGR_LPTIM4LPEN		BIT(2)
+#define RCC_LPTIM4CFGR_LPTIM4AMEN		BIT(3)
+
+/* RCC_LPTIM5CFGR register fields */
+#define RCC_LPTIM5CFGR_LPTIM5RST		BIT(0)
+#define RCC_LPTIM5CFGR_LPTIM5EN			BIT(1)
+#define RCC_LPTIM5CFGR_LPTIM5LPEN		BIT(2)
+#define RCC_LPTIM5CFGR_LPTIM5AMEN		BIT(3)
+
+/* RCC_LPTIMxCFGR register fields */
+#define RCC_LPTIMxCFGR_LPTIMxRST		BIT(0)
+#define RCC_LPTIMxCFGR_LPTIMxEN			BIT(1)
+#define RCC_LPTIMxCFGR_LPTIMxLPEN		BIT(2)
+#define RCC_LPTIMxCFGR_LPTIMxAMEN		BIT(3)
+
+/* RCC_SPI1CFGR register fields */
+#define RCC_SPI1CFGR_SPI1RST			BIT(0)
+#define RCC_SPI1CFGR_SPI1EN			BIT(1)
+#define RCC_SPI1CFGR_SPI1LPEN			BIT(2)
+
+/* RCC_SPI2CFGR register fields */
+#define RCC_SPI2CFGR_SPI2RST			BIT(0)
+#define RCC_SPI2CFGR_SPI2EN			BIT(1)
+#define RCC_SPI2CFGR_SPI2LPEN			BIT(2)
+
+/* RCC_SPI3CFGR register fields */
+#define RCC_SPI3CFGR_SPI3RST			BIT(0)
+#define RCC_SPI3CFGR_SPI3EN			BIT(1)
+#define RCC_SPI3CFGR_SPI3LPEN			BIT(2)
+
+/* RCC_SPI4CFGR register fields */
+#define RCC_SPI4CFGR_SPI4RST			BIT(0)
+#define RCC_SPI4CFGR_SPI4EN			BIT(1)
+#define RCC_SPI4CFGR_SPI4LPEN			BIT(2)
+
+/* RCC_SPI5CFGR register fields */
+#define RCC_SPI5CFGR_SPI5RST			BIT(0)
+#define RCC_SPI5CFGR_SPI5EN			BIT(1)
+#define RCC_SPI5CFGR_SPI5LPEN			BIT(2)
+
+/* RCC_SPI6CFGR register fields */
+#define RCC_SPI6CFGR_SPI6RST			BIT(0)
+#define RCC_SPI6CFGR_SPI6EN			BIT(1)
+#define RCC_SPI6CFGR_SPI6LPEN			BIT(2)
+
+/* RCC_SPI7CFGR register fields */
+#define RCC_SPI7CFGR_SPI7RST			BIT(0)
+#define RCC_SPI7CFGR_SPI7EN			BIT(1)
+#define RCC_SPI7CFGR_SPI7LPEN			BIT(2)
+
+/* RCC_SPI8CFGR register fields */
+#define RCC_SPI8CFGR_SPI8RST			BIT(0)
+#define RCC_SPI8CFGR_SPI8EN			BIT(1)
+#define RCC_SPI8CFGR_SPI8LPEN			BIT(2)
+#define RCC_SPI8CFGR_SPI8AMEN			BIT(3)
+
+/* RCC_SPIxCFGR register fields */
+#define RCC_SPIxCFGR_SPIxRST			BIT(0)
+#define RCC_SPIxCFGR_SPIxEN			BIT(1)
+#define RCC_SPIxCFGR_SPIxLPEN			BIT(2)
+#define RCC_SPIxCFGR_SPIxAMEN			BIT(3)
+
+/* RCC_SPDIFRXCFGR register fields */
+#define RCC_SPDIFRXCFGR_SPDIFRXRST		BIT(0)
+#define RCC_SPDIFRXCFGR_SPDIFRXEN		BIT(1)
+#define RCC_SPDIFRXCFGR_SPDIFRXLPEN		BIT(2)
+
+/* RCC_USART1CFGR register fields */
+#define RCC_USART1CFGR_USART1RST		BIT(0)
+#define RCC_USART1CFGR_USART1EN			BIT(1)
+#define RCC_USART1CFGR_USART1LPEN		BIT(2)
+
+/* RCC_USART2CFGR register fields */
+#define RCC_USART2CFGR_USART2RST		BIT(0)
+#define RCC_USART2CFGR_USART2EN			BIT(1)
+#define RCC_USART2CFGR_USART2LPEN		BIT(2)
+
+/* RCC_USART3CFGR register fields */
+#define RCC_USART3CFGR_USART3RST		BIT(0)
+#define RCC_USART3CFGR_USART3EN			BIT(1)
+#define RCC_USART3CFGR_USART3LPEN		BIT(2)
+
+/* RCC_UART4CFGR register fields */
+#define RCC_UART4CFGR_UART4RST			BIT(0)
+#define RCC_UART4CFGR_UART4EN			BIT(1)
+#define RCC_UART4CFGR_UART4LPEN			BIT(2)
+
+/* RCC_UART5CFGR register fields */
+#define RCC_UART5CFGR_UART5RST			BIT(0)
+#define RCC_UART5CFGR_UART5EN			BIT(1)
+#define RCC_UART5CFGR_UART5LPEN			BIT(2)
+
+/* RCC_USART6CFGR register fields */
+#define RCC_USART6CFGR_USART6RST		BIT(0)
+#define RCC_USART6CFGR_USART6EN			BIT(1)
+#define RCC_USART6CFGR_USART6LPEN		BIT(2)
+
+/* RCC_UART7CFGR register fields */
+#define RCC_UART7CFGR_UART7RST			BIT(0)
+#define RCC_UART7CFGR_UART7EN			BIT(1)
+#define RCC_UART7CFGR_UART7LPEN			BIT(2)
+
+/* RCC_UART8CFGR register fields */
+#define RCC_UART8CFGR_UART8RST			BIT(0)
+#define RCC_UART8CFGR_UART8EN			BIT(1)
+#define RCC_UART8CFGR_UART8LPEN			BIT(2)
+
+/* RCC_UART9CFGR register fields */
+#define RCC_UART9CFGR_UART9RST			BIT(0)
+#define RCC_UART9CFGR_UART9EN			BIT(1)
+#define RCC_UART9CFGR_UART9LPEN			BIT(2)
+
+/* RCC_USARTxCFGR register fields */
+#define RCC_USARTxCFGR_USARTxRST		BIT(0)
+#define RCC_USARTxCFGR_USARTxEN			BIT(1)
+#define RCC_USARTxCFGR_USARTxLPEN		BIT(2)
+
+/* RCC_UARTxCFGR register fields */
+#define RCC_UARTxCFGR_UARTxRST			BIT(0)
+#define RCC_UARTxCFGR_UARTxEN			BIT(1)
+#define RCC_UARTxCFGR_UARTxLPEN			BIT(2)
+
+/* RCC_LPUART1CFGR register fields */
+#define RCC_LPUART1CFGR_LPUART1RST		BIT(0)
+#define RCC_LPUART1CFGR_LPUART1EN		BIT(1)
+#define RCC_LPUART1CFGR_LPUART1LPEN		BIT(2)
+#define RCC_LPUART1CFGR_LPUART1AMEN		BIT(3)
+
+/* RCC_I2C1CFGR register fields */
+#define RCC_I2C1CFGR_I2C1RST			BIT(0)
+#define RCC_I2C1CFGR_I2C1EN			BIT(1)
+#define RCC_I2C1CFGR_I2C1LPEN			BIT(2)
+
+/* RCC_I2C2CFGR register fields */
+#define RCC_I2C2CFGR_I2C2RST			BIT(0)
+#define RCC_I2C2CFGR_I2C2EN			BIT(1)
+#define RCC_I2C2CFGR_I2C2LPEN			BIT(2)
+
+/* RCC_I2C3CFGR register fields */
+#define RCC_I2C3CFGR_I2C3RST			BIT(0)
+#define RCC_I2C3CFGR_I2C3EN			BIT(1)
+#define RCC_I2C3CFGR_I2C3LPEN			BIT(2)
+
+/* RCC_I2C4CFGR register fields */
+#define RCC_I2C4CFGR_I2C4RST			BIT(0)
+#define RCC_I2C4CFGR_I2C4EN			BIT(1)
+#define RCC_I2C4CFGR_I2C4LPEN			BIT(2)
+
+/* RCC_I2C5CFGR register fields */
+#define RCC_I2C5CFGR_I2C5RST			BIT(0)
+#define RCC_I2C5CFGR_I2C5EN			BIT(1)
+#define RCC_I2C5CFGR_I2C5LPEN			BIT(2)
+
+/* RCC_I2C6CFGR register fields */
+#define RCC_I2C6CFGR_I2C6RST			BIT(0)
+#define RCC_I2C6CFGR_I2C6EN			BIT(1)
+#define RCC_I2C6CFGR_I2C6LPEN			BIT(2)
+
+/* RCC_I2C7CFGR register fields */
+#define RCC_I2C7CFGR_I2C7RST			BIT(0)
+#define RCC_I2C7CFGR_I2C7EN			BIT(1)
+#define RCC_I2C7CFGR_I2C7LPEN			BIT(2)
+
+/* RCC_I2C8CFGR register fields */
+#define RCC_I2C8CFGR_I2C8RST			BIT(0)
+#define RCC_I2C8CFGR_I2C8EN			BIT(1)
+#define RCC_I2C8CFGR_I2C8LPEN			BIT(2)
+#define RCC_I2C8CFGR_I2C8AMEN			BIT(3)
+
+/* RCC_I2CxCFGR register fields */
+#define RCC_I2CxCFGR_I2CxRST			BIT(0)
+#define RCC_I2CxCFGR_I2CxEN			BIT(1)
+#define RCC_I2CxCFGR_I2CxLPEN			BIT(2)
+#define RCC_I2CxCFGR_I2CxAMEN			BIT(3)
+
+/* RCC_SAI1CFGR register fields */
+#define RCC_SAI1CFGR_SAI1RST			BIT(0)
+#define RCC_SAI1CFGR_SAI1EN			BIT(1)
+#define RCC_SAI1CFGR_SAI1LPEN			BIT(2)
+
+/* RCC_SAI2CFGR register fields */
+#define RCC_SAI2CFGR_SAI2RST			BIT(0)
+#define RCC_SAI2CFGR_SAI2EN			BIT(1)
+#define RCC_SAI2CFGR_SAI2LPEN			BIT(2)
+
+/* RCC_SAI3CFGR register fields */
+#define RCC_SAI3CFGR_SAI3RST			BIT(0)
+#define RCC_SAI3CFGR_SAI3EN			BIT(1)
+#define RCC_SAI3CFGR_SAI3LPEN			BIT(2)
+
+/* RCC_SAI4CFGR register fields */
+#define RCC_SAI4CFGR_SAI4RST			BIT(0)
+#define RCC_SAI4CFGR_SAI4EN			BIT(1)
+#define RCC_SAI4CFGR_SAI4LPEN			BIT(2)
+
+/* RCC_SAIxCFGR register fields */
+#define RCC_SAIxCFGR_SAIxRST			BIT(0)
+#define RCC_SAIxCFGR_SAIxEN			BIT(1)
+#define RCC_SAIxCFGR_SAIxLPEN			BIT(2)
+
+/* RCC_MDF1CFGR register fields */
+#define RCC_MDF1CFGR_MDF1RST			BIT(0)
+#define RCC_MDF1CFGR_MDF1EN			BIT(1)
+#define RCC_MDF1CFGR_MDF1LPEN			BIT(2)
+
+/* RCC_MDF2CFGR register fields */
+#define RCC_MDF2CFGR_MDF2RST			BIT(0)
+#define RCC_MDF2CFGR_MDF2EN			BIT(1)
+#define RCC_MDF2CFGR_MDF2LPEN			BIT(2)
+#define RCC_MDF2CFGR_MDF2AMEN			BIT(3)
+
+/* RCC_FDCANCFGR register fields */
+#define RCC_FDCANCFGR_FDCANRST			BIT(0)
+#define RCC_FDCANCFGR_FDCANEN			BIT(1)
+#define RCC_FDCANCFGR_FDCANLPEN			BIT(2)
+
+/* RCC_HDPCFGR register fields */
+#define RCC_HDPCFGR_HDPRST			BIT(0)
+#define RCC_HDPCFGR_HDPEN			BIT(1)
+
+/* RCC_ADC12CFGR register fields */
+#define RCC_ADC12CFGR_ADC12RST			BIT(0)
+#define RCC_ADC12CFGR_ADC12EN			BIT(1)
+#define RCC_ADC12CFGR_ADC12LPEN			BIT(2)
+#define RCC_ADC12CFGR_ADC12KERSEL		BIT(12)
+
+/* RCC_ADC3CFGR register fields */
+#define RCC_ADC3CFGR_ADC3RST			BIT(0)
+#define RCC_ADC3CFGR_ADC3EN			BIT(1)
+#define RCC_ADC3CFGR_ADC3LPEN			BIT(2)
+#define RCC_ADC3CFGR_ADC3KERSEL_MASK		GENMASK_32(13, 12)
+#define RCC_ADC3CFGR_ADC3KERSEL_SHIFT		12
+
+/* RCC_ETH1CFGR register fields */
+#define RCC_ETH1CFGR_ETH1RST			BIT(0)
+#define RCC_ETH1CFGR_ETH1MACEN			BIT(1)
+#define RCC_ETH1CFGR_ETH1MACLPEN		BIT(2)
+#define RCC_ETH1CFGR_ETH1STPEN			BIT(4)
+#define RCC_ETH1CFGR_ETH1EN			BIT(5)
+#define RCC_ETH1CFGR_ETH1LPEN			BIT(6)
+#define RCC_ETH1CFGR_ETH1TXEN			BIT(8)
+#define RCC_ETH1CFGR_ETH1TXLPEN			BIT(9)
+#define RCC_ETH1CFGR_ETH1RXEN			BIT(10)
+#define RCC_ETH1CFGR_ETH1RXLPEN			BIT(11)
+
+/* RCC_ETH2CFGR register fields */
+#define RCC_ETH2CFGR_ETH2RST			BIT(0)
+#define RCC_ETH2CFGR_ETH2MACEN			BIT(1)
+#define RCC_ETH2CFGR_ETH2MACLPEN		BIT(2)
+#define RCC_ETH2CFGR_ETH2STPEN			BIT(4)
+#define RCC_ETH2CFGR_ETH2EN			BIT(5)
+#define RCC_ETH2CFGR_ETH2LPEN			BIT(6)
+#define RCC_ETH2CFGR_ETH2TXEN			BIT(8)
+#define RCC_ETH2CFGR_ETH2TXLPEN			BIT(9)
+#define RCC_ETH2CFGR_ETH2RXEN			BIT(10)
+#define RCC_ETH2CFGR_ETH2RXLPEN			BIT(11)
+
+/* RCC_ETHxCFGR register fields */
+#define RCC_ETHxCFGR_ETHxRST			BIT(0)
+#define RCC_ETHxCFGR_ETHxMACEN			BIT(1)
+#define RCC_ETHxCFGR_ETHxMACLPEN		BIT(2)
+#define RCC_ETHxCFGR_ETHxSTPEN			BIT(4)
+#define RCC_ETHxCFGR_ETHxEN			BIT(5)
+#define RCC_ETHxCFGR_ETHxLPEN			BIT(6)
+#define RCC_ETHxCFGR_ETHxTXEN			BIT(8)
+#define RCC_ETHxCFGR_ETHxTXLPEN			BIT(9)
+#define RCC_ETHxCFGR_ETHxRXEN			BIT(10)
+#define RCC_ETHxCFGR_ETHxRXLPEN			BIT(11)
+
+/* RCC_USB2CFGR register fields */
+#define RCC_USB2CFGR_USB2RST			BIT(0)
+#define RCC_USB2CFGR_USB2EN			BIT(1)
+#define RCC_USB2CFGR_USB2LPEN			BIT(2)
+#define RCC_USB2CFGR_USB2STPEN			BIT(4)
+
+/* RCC_USB2PHY1CFGR register fields */
+#define RCC_USB2PHY1CFGR_USB2PHY1RST		BIT(0)
+#define RCC_USB2PHY1CFGR_USB2PHY1EN		BIT(1)
+#define RCC_USB2PHY1CFGR_USB2PHY1LPEN		BIT(2)
+#define RCC_USB2PHY1CFGR_USB2PHY1STPEN		BIT(4)
+#define RCC_USB2PHY1CFGR_USB2PHY1CKREFSEL	BIT(15)
+
+/* RCC_USB2PHY2CFGR register fields */
+#define RCC_USB2PHY2CFGR_USB2PHY2RST		BIT(0)
+#define RCC_USB2PHY2CFGR_USB2PHY2EN		BIT(1)
+#define RCC_USB2PHY2CFGR_USB2PHY2LPEN		BIT(2)
+#define RCC_USB2PHY2CFGR_USB2PHY2STPEN		BIT(4)
+#define RCC_USB2PHY2CFGR_USB2PHY2CKREFSEL	BIT(15)
+
+/* RCC_USB2PHYxCFGR register fields */
+#define RCC_USB2PHYxCFGR_USB2PHY1RST		BIT(0)
+#define RCC_USB2PHYxCFGR_USB2PHY1EN		BIT(1)
+#define RCC_USB2PHYxCFGR_USB2PHY1LPEN		BIT(2)
+#define RCC_USB2PHYxCFGR_USB2PHY1STPEN		BIT(4)
+#define RCC_USB2PHYxCFGR_USB2PHY1CKREFSEL	BIT(15)
+
+/* RCC_USB3DRCFGR register fields */
+#define RCC_USB3DRCFGR_USB3DRRST		BIT(0)
+#define RCC_USB3DRCFGR_USB3DREN			BIT(1)
+#define RCC_USB3DRCFGR_USB3DRLPEN		BIT(2)
+#define RCC_USB3DRCFGR_USB3DRSTPEN		BIT(4)
+
+/* RCC_USB3PCIEPHYCFGR register fields */
+#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYRST	BIT(0)
+#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYEN	BIT(1)
+#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYLPEN	BIT(2)
+#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYSTPEN	BIT(4)
+#define RCC_USB3PCIEPHYCFGR_USB3PCIEPHYCKREFSEL	BIT(15)
+
+/* RCC_PCIECFGR register fields */
+#define RCC_PCIECFGR_PCIERST			BIT(0)
+#define RCC_PCIECFGR_PCIEEN			BIT(1)
+#define RCC_PCIECFGR_PCIELPEN			BIT(2)
+#define RCC_PCIECFGR_PCIESTPEN			BIT(4)
+
+/* RCC_USBTCCFGR register fields */
+#define RCC_USBTCCFGR_USBTCRST			BIT(0)
+#define RCC_USBTCCFGR_USBTCEN			BIT(1)
+#define RCC_USBTCCFGR_USBTCLPEN			BIT(2)
+
+/* RCC_ETHSWCFGR register fields */
+#define RCC_ETHSWCFGR_ETHSWRST			BIT(0)
+#define RCC_ETHSWCFGR_ETHSWMACEN		BIT(1)
+#define RCC_ETHSWCFGR_ETHSWMACLPEN		BIT(2)
+#define RCC_ETHSWCFGR_ETHSWEN			BIT(5)
+#define RCC_ETHSWCFGR_ETHSWLPEN			BIT(6)
+#define RCC_ETHSWCFGR_ETHSWREFEN		BIT(21)
+#define RCC_ETHSWCFGR_ETHSWREFLPEN		BIT(22)
+
+/* RCC_ETHSWACMCFGR register fields */
+#define RCC_ETHSWACMCFGR_ETHSWACMEN		BIT(1)
+#define RCC_ETHSWACMCFGR_ETHSWACMLPEN		BIT(2)
+
+/* RCC_ETHSWACMMSGCFGR register fields */
+#define RCC_ETHSWACMMSGCFGR_ETHSWACMMSGEN	BIT(1)
+#define RCC_ETHSWACMMSGCFGR_ETHSWACMMSGLPEN	BIT(2)
+
+/* RCC_STGENCFGR register fields */
+#define RCC_STGENCFGR_STGENEN			BIT(1)
+#define RCC_STGENCFGR_STGENLPEN			BIT(2)
+#define RCC_STGENCFGR_STGENSTPEN		BIT(4)
+
+/* RCC_SDMMC1CFGR register fields */
+#define RCC_SDMMC1CFGR_SDMMC1RST		BIT(0)
+#define RCC_SDMMC1CFGR_SDMMC1EN			BIT(1)
+#define RCC_SDMMC1CFGR_SDMMC1LPEN		BIT(2)
+#define RCC_SDMMC1CFGR_SDMMC1DLLRST		BIT(16)
+
+/* RCC_SDMMC2CFGR register fields */
+#define RCC_SDMMC2CFGR_SDMMC2RST		BIT(0)
+#define RCC_SDMMC2CFGR_SDMMC2EN			BIT(1)
+#define RCC_SDMMC2CFGR_SDMMC2LPEN		BIT(2)
+#define RCC_SDMMC2CFGR_SDMMC2DLLRST		BIT(16)
+
+/* RCC_SDMMC3CFGR register fields */
+#define RCC_SDMMC3CFGR_SDMMC3RST		BIT(0)
+#define RCC_SDMMC3CFGR_SDMMC3EN			BIT(1)
+#define RCC_SDMMC3CFGR_SDMMC3LPEN		BIT(2)
+#define RCC_SDMMC3CFGR_SDMMC3DLLRST		BIT(16)
+
+/* RCC_SDMMCxCFGR register fields */
+#define RCC_SDMMCxCFGR_SDMMC1RST		BIT(0)
+#define RCC_SDMMCxCFGR_SDMMC1EN			BIT(1)
+#define RCC_SDMMCxCFGR_SDMMC1LPEN		BIT(2)
+#define RCC_SDMMCxCFGR_SDMMC1DLLRST		BIT(16)
+
+/* RCC_GPUCFGR register fields */
+#define RCC_GPUCFGR_GPURST			BIT(0)
+#define RCC_GPUCFGR_GPUEN			BIT(1)
+#define RCC_GPUCFGR_GPULPEN			BIT(2)
+
+/* RCC_LTDCCFGR register fields */
+#define RCC_LTDCCFGR_LTDCRST			BIT(0)
+#define RCC_LTDCCFGR_LTDCEN			BIT(1)
+#define RCC_LTDCCFGR_LTDCLPEN			BIT(2)
+
+/* RCC_DSICFGR register fields */
+#define RCC_DSICFGR_DSIRST			BIT(0)
+#define RCC_DSICFGR_DSIEN			BIT(1)
+#define RCC_DSICFGR_DSILPEN			BIT(2)
+#define RCC_DSICFGR_DSIBLSEL			BIT(12)
+#define RCC_DSICFGR_DSIPHYCKREFSEL		BIT(15)
+
+/* RCC_LVDSCFGR register fields */
+#define RCC_LVDSCFGR_LVDSRST			BIT(0)
+#define RCC_LVDSCFGR_LVDSEN			BIT(1)
+#define RCC_LVDSCFGR_LVDSLPEN			BIT(2)
+#define RCC_LVDSCFGR_LVDSPHYCKREFSEL		BIT(15)
+
+/* RCC_CSICFGR register fields */
+#define RCC_CSICFGR_CSIRST			BIT(0)
+#define RCC_CSICFGR_CSIEN			BIT(1)
+#define RCC_CSICFGR_CSILPEN			BIT(2)
+
+/* RCC_DCMIPPCFGR register fields */
+#define RCC_DCMIPPCFGR_DCMIPPRST		BIT(0)
+#define RCC_DCMIPPCFGR_DCMIPPEN			BIT(1)
+#define RCC_DCMIPPCFGR_DCMIPPLPEN		BIT(2)
+
+/* RCC_CCICFGR register fields */
+#define RCC_CCICFGR_CCIRST			BIT(0)
+#define RCC_CCICFGR_CCIEN			BIT(1)
+#define RCC_CCICFGR_CCILPEN			BIT(2)
+
+/* RCC_VDECCFGR register fields */
+#define RCC_VDECCFGR_VDECRST			BIT(0)
+#define RCC_VDECCFGR_VDECEN			BIT(1)
+#define RCC_VDECCFGR_VDECLPEN			BIT(2)
+
+/* RCC_VENCCFGR register fields */
+#define RCC_VENCCFGR_VENCRST			BIT(0)
+#define RCC_VENCCFGR_VENCEN			BIT(1)
+#define RCC_VENCCFGR_VENCLPEN			BIT(2)
+
+/* RCC_RNGCFGR register fields */
+#define RCC_RNGCFGR_RNGRST			BIT(0)
+#define RCC_RNGCFGR_RNGEN			BIT(1)
+#define RCC_RNGCFGR_RNGLPEN			BIT(2)
+
+/* RCC_PKACFGR register fields */
+#define RCC_PKACFGR_PKARST			BIT(0)
+#define RCC_PKACFGR_PKAEN			BIT(1)
+#define RCC_PKACFGR_PKALPEN			BIT(2)
+
+/* RCC_SAESCFGR register fields */
+#define RCC_SAESCFGR_SAESRST			BIT(0)
+#define RCC_SAESCFGR_SAESEN			BIT(1)
+#define RCC_SAESCFGR_SAESLPEN			BIT(2)
+
+/* RCC_HASHCFGR register fields */
+#define RCC_HASHCFGR_HASHRST			BIT(0)
+#define RCC_HASHCFGR_HASHEN			BIT(1)
+#define RCC_HASHCFGR_HASHLPEN			BIT(2)
+
+/* RCC_CRYP1CFGR register fields */
+#define RCC_CRYP1CFGR_CRYP1RST			BIT(0)
+#define RCC_CRYP1CFGR_CRYP1EN			BIT(1)
+#define RCC_CRYP1CFGR_CRYP1LPEN			BIT(2)
+
+/* RCC_CRYP2CFGR register fields */
+#define RCC_CRYP2CFGR_CRYP2RST			BIT(0)
+#define RCC_CRYP2CFGR_CRYP2EN			BIT(1)
+#define RCC_CRYP2CFGR_CRYP2LPEN			BIT(2)
+
+/* RCC_CRYPxCFGR register fields */
+#define RCC_CRYPxCFGR_CRYPxRST			BIT(0)
+#define RCC_CRYPxCFGR_CRYPxEN			BIT(1)
+#define RCC_CRYPxCFGR_CRYPxLPEN			BIT(2)
+
+/* RCC_IWDG1CFGR register fields */
+#define RCC_IWDG1CFGR_IWDG1EN			BIT(1)
+#define RCC_IWDG1CFGR_IWDG1LPEN			BIT(2)
+
+/* RCC_IWDG2CFGR register fields */
+#define RCC_IWDG2CFGR_IWDG2EN			BIT(1)
+#define RCC_IWDG2CFGR_IWDG2LPEN			BIT(2)
+
+/* RCC_IWDG3CFGR register fields */
+#define RCC_IWDG3CFGR_IWDG3EN			BIT(1)
+#define RCC_IWDG3CFGR_IWDG3LPEN			BIT(2)
+
+/* RCC_IWDG4CFGR register fields */
+#define RCC_IWDG4CFGR_IWDG4EN			BIT(1)
+#define RCC_IWDG4CFGR_IWDG4LPEN			BIT(2)
+
+/* RCC_IWDGxCFGR register fields */
+#define RCC_IWDGxCFGR_IWDGxEN			BIT(1)
+#define RCC_IWDGxCFGR_IWDGxLPEN			BIT(2)
+
+/* RCC_IWDG5CFGR register fields */
+#define RCC_IWDG5CFGR_IWDG5EN			BIT(1)
+#define RCC_IWDG5CFGR_IWDG5LPEN			BIT(2)
+#define RCC_IWDG5CFGR_IWDG5AMEN			BIT(3)
+
+/* RCC_WWDG1CFGR register fields */
+#define RCC_WWDG1CFGR_WWDG1RST			BIT(0)
+#define RCC_WWDG1CFGR_WWDG1EN			BIT(1)
+#define RCC_WWDG1CFGR_WWDG1LPEN			BIT(2)
+
+/* RCC_WWDG2CFGR register fields */
+#define RCC_WWDG2CFGR_WWDG2RST			BIT(0)
+#define RCC_WWDG2CFGR_WWDG2EN			BIT(1)
+#define RCC_WWDG2CFGR_WWDG2LPEN			BIT(2)
+#define RCC_WWDG2CFGR_WWDG2AMEN			BIT(3)
+
+/* RCC_VREFCFGR register fields */
+#define RCC_VREFCFGR_VREFRST			BIT(0)
+#define RCC_VREFCFGR_VREFEN			BIT(1)
+#define RCC_VREFCFGR_VREFLPEN			BIT(2)
+
+/* RCC_DTSCFGR register fields */
+#define RCC_DTSCFGR_DTSRST			BIT(0)
+#define RCC_DTSCFGR_DTSEN			BIT(1)
+#define RCC_DTSCFGR_DTSLPEN			BIT(2)
+#define RCC_DTSCFGR_DTSKERSEL_MASK		GENMASK_32(13, 12)
+#define RCC_DTSCFGR_DTSKERSEL_SHIFT		12
+
+/* RCC_CRCCFGR register fields */
+#define RCC_CRCCFGR_CRCRST			BIT(0)
+#define RCC_CRCCFGR_CRCEN			BIT(1)
+#define RCC_CRCCFGR_CRCLPEN			BIT(2)
+
+/* RCC_SERCCFGR register fields */
+#define RCC_SERCCFGR_SERCRST			BIT(0)
+#define RCC_SERCCFGR_SERCEN			BIT(1)
+#define RCC_SERCCFGR_SERCLPEN			BIT(2)
+
+/* RCC_OSPIIOMCFGR register fields */
+#define RCC_OSPIIOMCFGR_OSPIIOMRST		BIT(0)
+#define RCC_OSPIIOMCFGR_OSPIIOMEN		BIT(1)
+#define RCC_OSPIIOMCFGR_OSPIIOMLPEN		BIT(2)
+
+/* RCC_GICV2MCFGR register fields */
+#define RCC_GICV2MCFGR_GICV2MEN			BIT(1)
+#define RCC_GICV2MCFGR_GICV2MLPEN		BIT(2)
+
+/* RCC_I3C1CFGR register fields */
+#define RCC_I3C1CFGR_I3C1RST			BIT(0)
+#define RCC_I3C1CFGR_I3C1EN			BIT(1)
+#define RCC_I3C1CFGR_I3C1LPEN			BIT(2)
+
+/* RCC_I3C2CFGR register fields */
+#define RCC_I3C2CFGR_I3C2RST			BIT(0)
+#define RCC_I3C2CFGR_I3C2EN			BIT(1)
+#define RCC_I3C2CFGR_I3C2LPEN			BIT(2)
+
+/* RCC_I3C3CFGR register fields */
+#define RCC_I3C3CFGR_I3C3RST			BIT(0)
+#define RCC_I3C3CFGR_I3C3EN			BIT(1)
+#define RCC_I3C3CFGR_I3C3LPEN			BIT(2)
+
+/* RCC_I3C4CFGR register fields */
+#define RCC_I3C4CFGR_I3C4RST			BIT(0)
+#define RCC_I3C4CFGR_I3C4EN			BIT(1)
+#define RCC_I3C4CFGR_I3C4LPEN			BIT(2)
+#define RCC_I3C4CFGR_I3C4AMEN			BIT(3)
+
+/* RCC_I3CxCFGR register fields */
+#define RCC_I3CxCFGR_I3CxRST			BIT(0)
+#define RCC_I3CxCFGR_I3CxEN			BIT(1)
+#define RCC_I3CxCFGR_I3CxLPEN			BIT(2)
+#define RCC_I3CxCFGR_I3CxAMEN			BIT(3)
+
+/* RCC_MUXSELCFGR register fields */
+#define RCC_MUXSELCFGR_MUXSEL0_MASK		GENMASK_32(1, 0)
+#define RCC_MUXSELCFGR_MUXSEL0_SHIFT		0
+#define RCC_MUXSELCFGR_MUXSEL1_MASK		GENMASK_32(5, 4)
+#define RCC_MUXSELCFGR_MUXSEL1_SHIFT		4
+#define RCC_MUXSELCFGR_MUXSEL2_MASK		GENMASK_32(9, 8)
+#define RCC_MUXSELCFGR_MUXSEL2_SHIFT		8
+#define RCC_MUXSELCFGR_MUXSEL3_MASK		GENMASK_32(13, 12)
+#define RCC_MUXSELCFGR_MUXSEL3_SHIFT		12
+#define RCC_MUXSELCFGR_MUXSEL4_MASK		GENMASK_32(17, 16)
+#define RCC_MUXSELCFGR_MUXSEL4_SHIFT		16
+#define RCC_MUXSELCFGR_MUXSEL5_MASK		GENMASK_32(21, 20)
+#define RCC_MUXSELCFGR_MUXSEL5_SHIFT		20
+#define RCC_MUXSELCFGR_MUXSEL6_MASK		GENMASK_32(25, 24)
+#define RCC_MUXSELCFGR_MUXSEL6_SHIFT		24
+#define RCC_MUXSELCFGR_MUXSEL7_MASK		GENMASK_32(29, 28)
+#define RCC_MUXSELCFGR_MUXSEL7_SHIFT		28
+
+/* RCC_XBAR0CFGR register fields */
+#define RCC_XBAR0CFGR_XBAR0SEL_MASK		GENMASK_32(3, 0)
+#define RCC_XBAR0CFGR_XBAR0SEL_SHIFT		0
+#define RCC_XBAR0CFGR_XBAR0EN			BIT(6)
+#define RCC_XBAR0CFGR_XBAR0STS			BIT(7)
+
+/* RCC_PREDIVCFGR register fields */
+#define RCC_PREDIV0CFGR_PREDIV0_MASK		GENMASK_32(9, 0)
+#define RCC_PREDIV0CFGR_PREDIV0_SHIFT		0
+
+/* RCC_FINDIVxCFGR register fields */
+#define RCC_FINDIV0CFGR_FINDIV0_MASK		GENMASK_32(5, 0)
+#define RCC_FINDIV0CFGR_FINDIV0_SHIFT		0
+#define RCC_FINDIV0CFGR_FINDIV0EN		BIT(6)
+
+/* RCC_FINDIV0CFGR register fields */
+#define RCC_FINDIV0CFGR_FINDIV0_MASK		GENMASK_32(5, 0)
+#define RCC_FINDIV0CFGR_FINDIV0_SHIFT		0
+#define RCC_FINDIV0CFGR_FINDIV0EN		BIT(6)
+
+/* RCC_PREDIVSR1 register fields */
+#define RCC_PREDIVSR1_PREDIVSTS_MASK		GENMASK_32(31, 0)
+
+/* RCC_PREDIVSR2 register fields */
+#define RCC_PREDIVSR2_PREDIVSTS_MASK		GENMASK_32(31, 0)
+
+/* RCC_FINDIVSR1 register fields */
+#define RCC_FINDIVSR1_FINDIVSTS_MASK		GENMASK_32(31, 0)
+
+/* RCC_FINDIVSR2 register fields */
+#define RCC_FINDIVSR2_FINDIVSTS_MASK		GENMASK_32(31, 0)
+
+/* RCC_FCALCOBS0CFGR register fields */
+#define RCC_FCALCOBS0CFGR_CKINTSEL_MASK		GENMASK_32(7, 0)
+#define RCC_FCALCOBS0CFGR_CKINTSEL_SHIFT	0
+#define RCC_FCALCOBS0CFGR_CKEXTSEL_MASK		GENMASK_32(10, 8)
+#define RCC_FCALCOBS0CFGR_CKEXTSEL_SHIFT	8
+#define RCC_FCALCOBS0CFGR_FCALCCKEXTSEL		BIT(15)
+#define RCC_FCALCOBS0CFGR_CKOBSEXTSEL		BIT(16)
+#define RCC_FCALCOBS0CFGR_FCALCCKINV		BIT(17)
+#define RCC_FCALCOBS0CFGR_CKOBSINV		BIT(18)
+#define RCC_FCALCOBS0CFGR_CKOBSDIV_MASK		GENMASK_32(24, 22)
+#define RCC_FCALCOBS0CFGR_CKOBSDIV_SHIFT	22
+#define RCC_FCALCOBS0CFGR_FCALCCKEN		BIT(25)
+#define RCC_FCALCOBS0CFGR_CKOBSEN		BIT(26)
+
+/* RCC_FCALCOBS1CFGR register fields */
+#define RCC_FCALCOBS1CFGR_CKINTSEL_MASK		GENMASK_32(7, 0)
+#define RCC_FCALCOBS1CFGR_CKINTSEL_SHIFT	0
+#define RCC_FCALCOBS1CFGR_CKEXTSEL_MASK		GENMASK_32(10, 8)
+#define RCC_FCALCOBS1CFGR_CKEXTSEL_SHIFT	8
+#define RCC_FCALCOBS1CFGR_CKOBSEXTSEL		BIT(16)
+#define RCC_FCALCOBS1CFGR_CKOBSINV		BIT(18)
+#define RCC_FCALCOBS1CFGR_CKOBSDIV_MASK		GENMASK_32(24, 22)
+#define RCC_FCALCOBS1CFGR_CKOBSDIV_SHIFT	22
+#define RCC_FCALCOBS1CFGR_CKOBSEN		BIT(26)
+#define RCC_FCALCOBS1CFGR_FCALCRSTN		BIT(27)
+
+/* RCC_FCALCREFCFGR register fields */
+#define RCC_FCALCREFCFGR_FCALCREFCKSEL_MASK	GENMASK_32(2, 0)
+#define RCC_FCALCREFCFGR_FCALCREFCKSEL_SHIFT	0
+
+/* RCC_FCALCCR1 register fields */
+#define RCC_FCALCCR1_FCALCRUN			BIT(0)
+
+/* RCC_FCALCCR2 register fields */
+#define RCC_FCALCCR2_FCALCMD_MASK		GENMASK_32(4, 3)
+#define RCC_FCALCCR2_FCALCMD_SHIFT		3
+#define RCC_FCALCCR2_FCALCTWC_MASK		GENMASK_32(14, 11)
+#define RCC_FCALCCR2_FCALCTWC_SHIFT		11
+#define RCC_FCALCCR2_FCALCTYP_MASK		GENMASK_32(21, 17)
+#define RCC_FCALCCR2_FCALCTYP_SHIFT		17
+
+/* RCC_FCALCSR register fields */
+#define RCC_FCALCSR_FVAL_MASK			GENMASK_32(15, 0)
+#define RCC_FCALCSR_FVAL_SHIFT			0
+#define RCC_FCALCSR_FCALCSTS			BIT(19)
+#define RCC_FCALCSR_FVAL_OVERFLOW		BIT(16)
+
+/* RCC_VERR register fields */
+#define RCC_VERR_MINREV_MASK			GENMASK_32(3, 0)
+#define RCC_VERR_MINREV_SHIFT			0
+#define RCC_VERR_MAJREV_MASK			GENMASK_32(7, 4)
+#define RCC_VERR_MAJREV_SHIFT			4
+
+#endif /* __DRIVERS_STM32MP25_RCC_H */
diff --git a/core/include/drivers/stm32mp2_rcc_util.h b/core/include/drivers/stm32mp2_rcc_util.h
new file mode 100644
index 0000000000000000000000000000000000000000..1b5aab35201fe1376240845fddde16abbaae5575
--- /dev/null
+++ b/core/include/drivers/stm32mp2_rcc_util.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+#ifndef __DRIVERS_STM32MP2_RCC_UTIL_H__
+#define __DRIVERS_STM32MP2_RCC_UTIL_H__
+
+#include <drivers/clk.h>
+#include <drivers/rstctrl.h>
+#include <types_ext.h>
+
+/* Return RCC base address */
+vaddr_t stm32_rcc_base(void);
+
+/* Return the clock handle related to a clock DT binding ID */
+struct clk *stm32mp_rcc_clock_id_to_clk(unsigned long clock_id);
+
+/* Return rstctrl instance related to RCC reset controller DT binding ID */
+struct rstctrl *stm32mp_rcc_reset_id_to_rstctrl(unsigned int binding_id);
+
+#endif /*__DRIVERS_STM32MP2_RCC_UTIL_H__*/
diff --git a/core/include/drivers/stm32mp_dt_bindings.h b/core/include/drivers/stm32mp_dt_bindings.h
index 1c438ecefa4d4b178cb3263f18bd1a8defe26c61..0a04a9b51b29c347b6d2569a075e7d4f088f6d25 100644
--- a/core/include/drivers/stm32mp_dt_bindings.h
+++ b/core/include/drivers/stm32mp_dt_bindings.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (c) 2022, STMicroelectronics
+ * Copyright (c) 2022-2024, STMicroelectronics
  */
 #ifndef __DRIVERS_STM32MP_DT_BINDINGS_H
 #define __DRIVERS_STM32MP_DT_BINDINGS_H
@@ -8,14 +8,27 @@
 #ifdef CFG_STM32MP13
 #include <dt-bindings/clock/stm32mp13-clks.h>
 #include <dt-bindings/clock/stm32mp13-clksrc.h>
+#include <dt-bindings/firewall/stm32mp13-etzpc.h>
+#include <dt-bindings/firewall/stm32mp13-tzc400.h>
 #include <dt-bindings/regulator/st,stm32mp13-regulator.h>
 #include <dt-bindings/reset/stm32mp13-resets.h>
 #endif
 
 #ifdef CFG_STM32MP15
 #include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/firewall/stm32mp15-etzpc.h>
+#include <dt-bindings/firewall/stm32mp15-tzc400.h>
 #include <dt-bindings/regulator/st,stm32mp15-regulator.h>
 #include <dt-bindings/reset/stm32mp1-resets.h>
 #endif
 
+#ifdef CFG_STM32MP25
+#include <dt-bindings/clock/st,stm32mp25-rcc.h>
+#include <dt-bindings/clock/stm32mp25-clksrc.h>
+#include <dt-bindings/firewall/stm32mp25-rif.h>
+#include <dt-bindings/firewall/stm32mp25-rifsc.h>
+#include <dt-bindings/firewall/stm32mp25-risaf.h>
+#include <dt-bindings/reset/st,stm32mp25-rcc.h>
+#endif
+
 #endif /* __DRIVERS_STM32MP_DT_BINDINGS_H */
diff --git a/core/include/drivers/stpmic1_regulator.h b/core/include/drivers/stpmic1_regulator.h
index 5e0e655025e0caf7e1fac9af0f6594f0cba68ca4..106ff35bbe8425dded3bd8eda8791f4a63266fa9 100644
--- a/core/include/drivers/stpmic1_regulator.h
+++ b/core/include/drivers/stpmic1_regulator.h
@@ -1,11 +1,13 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (c) 2021-2022, STMicroelectronics
+ * Copyright (c) 2021-2024, STMicroelectronics
  */
 
 #ifndef __DRIVERS_STPMIC1_REGULATOR_H
 #define __DRIVERS_STPMIC1_REGULATOR_H
 
+#include <stdbool.h>
+#include <stddef.h>
 #include <stdint.h>
 
 /*
diff --git a/core/include/dt-bindings/clock/at91.h b/core/include/dt-bindings/clock/at91.h
index 79470e3b9522cae46fcf8751c9aca083a8c7ae72..c10e0de4e77641d07062afbf866aca57f29c7904 100644
--- a/core/include/dt-bindings/clock/at91.h
+++ b/core/include/dt-bindings/clock/at91.h
@@ -38,9 +38,15 @@
 #define PMC_IMGPLL		(PMC_MAIN + 4)
 #define PMC_BAUDPLL		(PMC_MAIN + 5)
 #define PMC_AUDIOPMCPLL		(PMC_MAIN + 6)
-#define PMC_AUDIOIOPLL		(PMC_MAIN + 7)
-#define PMC_ETHPLL		(PMC_MAIN + 8)
-#define PMC_CPU			(PMC_MAIN + 9)
+/* Reserved for PMC_MCK_PRES */
+#define PMC_AUDIOIOPLL		(PMC_MAIN + 8)
+#define PMC_ETHPLL		(PMC_MAIN + 9)
+#define PMC_MCK1		(PMC_MAIN + 10)
+/* Reserved for MCK2, MCK3, MCK4 */
+#define PMC_UTMI1		(PMC_MAIN + 14)
+#define PMC_UTMI2		(PMC_MAIN + 15)
+#define PMC_UTMI3		(PMC_MAIN + 16)
+#define PMC_SAMA7G5_CORE_CLK_COUNT	(PMC_MAIN + 17)
 
 #define AT91_SCMI_CLK_CORE_MCK		0
 #define AT91_SCMI_CLK_CORE_UTMI		1
@@ -130,5 +136,61 @@
 #define AT91_SCMI_CLK_PROG_PROG2	81
 
 #define AT91_SCMI_CLK_SCKC_SLOWCK_32K	82
+#define AT91_SCMI_CLK_CPU_OPP		101
+
+#ifdef CFG_SAMA7G5
+#define AT91_SCMI_CLK_CORE_CPUPLLCK		4
+#define AT91_SCMI_CLK_CORE_SYSPLLCK		5
+#define AT91_SCMI_CLK_CORE_DDRPLLCK		6
+#define AT91_SCMI_CLK_CORE_IMGPLLCK		7
+#define AT91_SCMI_CLK_CORE_ETHPLLCK		10
+#define AT91_SCMI_CLK_SYSTEM_PCK3		11
+#define AT91_SCMI_CLK_SYSTEM_PCK4		12
+#define AT91_SCMI_CLK_SYSTEM_PCK5		13
+#define AT91_SCMI_CLK_SYSTEM_PCK6		17
+#define AT91_SCMI_CLK_SYSTEM_PCK7		20
+#define AT91_SCMI_CLK_UTMI1			97
+#define AT91_SCMI_CLK_UTMI2			98
+#define AT91_SCMI_CLK_UTMI3			99
+#define AT91_SCMI_CLK_PERIPH_DMA2_CLK		100
+#define AT91_SCMI_CLK_PERIPH_FLX5_CLK		28
+#define AT91_SCMI_CLK_PERIPH_FLX6_CLK		29
+#define AT91_SCMI_CLK_PERIPH_FLX7_CLK		30
+#define AT91_SCMI_CLK_PERIPH_FLX8_CLK		31
+#define AT91_SCMI_CLK_PERIPH_FLX9_CLK		32
+#define AT91_SCMI_CLK_PERIPH_FLX10_CLK		33
+#define AT91_SCMI_CLK_PERIPH_FLX11_CLK		34
+#define AT91_SCMI_CLK_PERIPH_UDPHSB_CLK		35
+#define AT91_SCMI_CLK_PERIPH_PDMC1_CLK		36
+#define AT91_SCMI_CLK_PERIPH_UDPHSA_CLK		42
+#define AT91_SCMI_CLK_GCK_ADC_GCLK		40
+#define AT91_SCMI_CLK_PERIPH_PDMC0_CLK		46
+#define AT91_SCMI_CLK_PERIPH_CAN2_CLK		52
+#define AT91_SCMI_CLK_PERIPH_CAN3_CLK		53
+#define AT91_SCMI_CLK_PERIPH_CAN4_CLK		59
+#define AT91_SCMI_CLK_PERIPH_CAN5_CLK		60
+#define AT91_SCMI_CLK_PERIPH_SDMMC2_HCLK	63
+#define AT91_SCMI_CLK_GCK_SDMMC2_GCLK		71
+#define AT91_SCMI_CLK_GCK_MACB0_GCLK		72
+#define AT91_SCMI_CLK_GCK_MACB0_TSU		73
+#define AT91_SCMI_CLK_GCK_CAN2_GCLK		78
+#define AT91_SCMI_CLK_GCK_CAN3_GCLK		79
+#define AT91_SCMI_CLK_GCK_CAN4_GCLK		80
+#define AT91_SCMI_CLK_GCK_CAN5_GCLK		81
+#define AT91_SCMI_CLK_PERIPH_SPDIFRX_CLK	83
+#define AT91_SCMI_CLK_PERIPH_SPDIFTX_CLK	84
+#define AT91_SCMI_CLK_GCK_QSPI0_GCLK		85
+#define AT91_SCMI_CLK_GCK_QSPI1_GCLK		86
+#define AT91_SCMI_CLK_GCK_SPDIFRX_GCLK		87
+#define AT91_SCMI_CLK_GCK_SPDIFTX_GCLK		88
+#define AT91_SCMI_CLK_GCK_MACB1_GCLK		89
+#define AT91_SCMI_CLK_PERIPH_MACB1_CLK		90
+#define AT91_SCMI_CLK_GCK_MACB1_TSU		91
+#define AT91_SCMI_CLK_PERIPH_CSI_CLK		92
+#define AT91_SCMI_CLK_GCK_CSI_GCLK		93
+#define AT91_SCMI_CLK_PERIPH_CSI2DC_CLK		94
+#define AT91_SCMI_CLK_PERIPH_ASRC_CLK		95
+#define AT91_SCMI_CLK_GCK_ASRC_GCLK		96
+#endif
 
 #endif
diff --git a/core/include/dt-bindings/clock/st,stm32mp25-rcc.h b/core/include/dt-bindings/clock/st,stm32mp25-rcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f523d1906963a3694c8eff2eb7aca9f80c24c8e3
--- /dev/null
+++ b/core/include/dt-bindings/clock/st,stm32mp25-rcc.h
@@ -0,0 +1,495 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_
+#define _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_
+
+/* INTERNAL/EXTERNAL OSCILLATORS */
+#define HSI_CK			0
+#define HSE_CK			1
+#define MSI_CK			2
+#define LSI_CK			3
+#define LSE_CK			4
+#define I2S_CK			5
+#define RTC_CK			6
+#define SPDIF_CK_SYMB		7
+
+/* PLL CLOCKS */
+#define PLL1_CK			8
+#define PLL2_CK			9
+#define PLL3_CK			10
+#define PLL4_CK			11
+#define PLL5_CK			12
+#define PLL6_CK			13
+#define PLL7_CK			14
+#define PLL8_CK			15
+
+#define CK_CPU1			16
+
+/* APB DIV CLOCKS */
+#define CK_ICN_APB1		17
+#define CK_ICN_APB2		18
+#define CK_ICN_APB3		19
+#define CK_ICN_APB4		20
+#define CK_ICN_APBDBG		21
+
+/* GLOBAL TIMER */
+#define TIMG1_CK		22
+#define TIMG2_CK		23
+
+/* FLEXGEN CLOCKS */
+#define CK_ICN_HS_MCU		24
+#define CK_ICN_SDMMC		25
+#define CK_ICN_DDR		26
+#define CK_ICN_DISPLAY		27
+#define CK_ICN_HSL		28
+#define CK_ICN_NIC		29
+#define CK_ICN_VID		30
+#define CK_FLEXGEN_07		31
+#define CK_FLEXGEN_08		32
+#define CK_FLEXGEN_09		33
+#define CK_FLEXGEN_10		34
+#define CK_FLEXGEN_11		35
+#define CK_FLEXGEN_12		36
+#define CK_FLEXGEN_13		37
+#define CK_FLEXGEN_14		38
+#define CK_FLEXGEN_15		39
+#define CK_FLEXGEN_16		40
+#define CK_FLEXGEN_17		41
+#define CK_FLEXGEN_18		42
+#define CK_FLEXGEN_19		43
+#define CK_FLEXGEN_20		44
+#define CK_FLEXGEN_21		45
+#define CK_FLEXGEN_22		46
+#define CK_FLEXGEN_23		47
+#define CK_FLEXGEN_24		48
+#define CK_FLEXGEN_25		49
+#define CK_FLEXGEN_26		50
+#define CK_FLEXGEN_27		51
+#define CK_FLEXGEN_28		52
+#define CK_FLEXGEN_29		53
+#define CK_FLEXGEN_30		54
+#define CK_FLEXGEN_31		55
+#define CK_FLEXGEN_32		56
+#define CK_FLEXGEN_33		57
+#define CK_FLEXGEN_34		58
+#define CK_FLEXGEN_35		59
+#define CK_FLEXGEN_36		60
+#define CK_FLEXGEN_37		61
+#define CK_FLEXGEN_38		62
+#define CK_FLEXGEN_39		63
+#define CK_FLEXGEN_40		64
+#define CK_FLEXGEN_41		65
+#define CK_FLEXGEN_42		66
+#define CK_FLEXGEN_43		67
+#define CK_FLEXGEN_44		68
+#define CK_FLEXGEN_45		69
+#define CK_FLEXGEN_46		70
+#define CK_FLEXGEN_47		71
+#define CK_FLEXGEN_48		72
+#define CK_FLEXGEN_49		73
+#define CK_FLEXGEN_50		74
+#define CK_FLEXGEN_51		75
+#define CK_FLEXGEN_52		76
+#define CK_FLEXGEN_53		77
+#define CK_FLEXGEN_54		78
+#define CK_FLEXGEN_55		79
+#define CK_FLEXGEN_56		80
+#define CK_FLEXGEN_57		81
+#define CK_FLEXGEN_58		82
+#define CK_FLEXGEN_59		83
+#define CK_FLEXGEN_60		84
+#define CK_FLEXGEN_61		85
+#define CK_FLEXGEN_62		86
+#define CK_FLEXGEN_63		87
+
+/* LOW SPEED MCU CLOCK */
+#define CK_ICN_LS_MCU		88
+
+#define CK_BUS_STM		89
+#define CK_BUS_FMC		90
+#define CK_BUS_GPU		91
+#define CK_BUS_ETH1		92
+#define CK_BUS_ETH2		93
+#define CK_BUS_PCIE		94
+#define CK_BUS_DDRPHYC		95
+#define CK_BUS_SYSCPU1		96
+#define CK_BUS_ETHSW		97
+#define CK_BUS_HPDMA1		98
+#define CK_BUS_HPDMA2		99
+#define CK_BUS_HPDMA3		100
+#define CK_BUS_ADC12		101
+#define CK_BUS_ADC3		102
+#define CK_BUS_IPCC1		103
+#define CK_BUS_CCI		104
+#define CK_BUS_CRC		105
+#define CK_BUS_MDF1		106
+#define CK_BUS_OSPIIOM		107
+#define CK_BUS_BKPSRAM		108
+#define CK_BUS_HASH		109
+#define CK_BUS_RNG		110
+#define CK_BUS_CRYP1		111
+#define CK_BUS_CRYP2		112
+#define CK_BUS_SAES		113
+#define CK_BUS_PKA		114
+#define CK_BUS_GPIOA		115
+#define CK_BUS_GPIOB		116
+#define CK_BUS_GPIOC		117
+#define CK_BUS_GPIOD		118
+#define CK_BUS_GPIOE		119
+#define CK_BUS_GPIOF		120
+#define CK_BUS_GPIOG		121
+#define CK_BUS_GPIOH		122
+#define CK_BUS_GPIOI		123
+#define CK_BUS_GPIOJ		124
+#define CK_BUS_GPIOK		125
+#define CK_BUS_LPSRAM1		126
+#define CK_BUS_LPSRAM2		127
+#define CK_BUS_LPSRAM3		128
+#define CK_BUS_GPIOZ		129
+#define CK_BUS_LPDMA		130
+#define CK_BUS_HSEM		131
+#define CK_BUS_IPCC2		132
+#define CK_BUS_RTC		133
+#define CK_BUS_SPI8		134
+#define CK_BUS_LPUART1		135
+#define CK_BUS_I2C8		136
+#define CK_BUS_LPTIM3		137
+#define CK_BUS_LPTIM4		138
+#define CK_BUS_LPTIM5		139
+#define CK_BUS_IWDG5		140
+#define CK_BUS_WWDG2		141
+#define CK_BUS_I3C4		142
+#define CK_BUS_TIM2		143
+#define CK_BUS_TIM3		144
+#define CK_BUS_TIM4		145
+#define CK_BUS_TIM5		146
+#define CK_BUS_TIM6		147
+#define CK_BUS_TIM7		148
+#define CK_BUS_TIM10		149
+#define CK_BUS_TIM11		150
+#define CK_BUS_TIM12		151
+#define CK_BUS_TIM13		152
+#define CK_BUS_TIM14		153
+#define CK_BUS_LPTIM1		154
+#define CK_BUS_LPTIM2		155
+#define CK_BUS_SPI2		156
+#define CK_BUS_SPI3		157
+#define CK_BUS_SPDIFRX		158
+#define CK_BUS_USART2		159
+#define CK_BUS_USART3		160
+#define CK_BUS_UART4		161
+#define CK_BUS_UART5		162
+#define CK_BUS_I2C1		163
+#define CK_BUS_I2C2		164
+#define CK_BUS_I2C3		165
+#define CK_BUS_I2C4		166
+#define CK_BUS_I2C5		167
+#define CK_BUS_I2C6		168
+#define CK_BUS_I2C7		169
+#define CK_BUS_I3C1		170
+#define CK_BUS_I3C2		171
+#define CK_BUS_I3C3		172
+#define CK_BUS_TIM1		173
+#define CK_BUS_TIM8		174
+#define CK_BUS_TIM15		175
+#define CK_BUS_TIM16		176
+#define CK_BUS_TIM17		177
+#define CK_BUS_TIM20		178
+#define CK_BUS_SAI1		179
+#define CK_BUS_SAI2		180
+#define CK_BUS_SAI3		181
+#define CK_BUS_SAI4		182
+#define CK_BUS_USART1		183
+#define CK_BUS_USART6		184
+#define CK_BUS_UART7		185
+#define CK_BUS_UART8		186
+#define CK_BUS_UART9		187
+#define CK_BUS_FDCAN		188
+#define CK_BUS_SPI1		189
+#define CK_BUS_SPI4		190
+#define CK_BUS_SPI5		191
+#define CK_BUS_SPI6		192
+#define CK_BUS_SPI7		193
+#define CK_BUS_BSEC		194
+#define CK_BUS_IWDG1		195
+#define CK_BUS_IWDG2		196
+#define CK_BUS_IWDG3		197
+#define CK_BUS_IWDG4		198
+#define CK_BUS_WWDG1		199
+#define CK_BUS_VREF		200
+#define CK_BUS_DTS		201
+#define CK_BUS_SERC		202
+#define CK_BUS_HDP		203
+#define CK_BUS_IS2M		204
+#define CK_BUS_DSI		205
+#define CK_BUS_LTDC		206
+#define CK_BUS_CSI		207
+#define CK_BUS_DCMIPP		208
+#define CK_BUS_DDRC		209
+#define CK_BUS_DDRCFG		210
+#define CK_BUS_GICV2M		211
+#define CK_BUS_USBTC		212
+#define CK_BUS_USB3PCIEPHY	214
+#define CK_BUS_STGEN		215
+#define CK_BUS_VDEC		216
+#define CK_BUS_VENC		217
+#define CK_SYSDBG		218
+#define CK_KER_TIM2		219
+#define CK_KER_TIM3		220
+#define CK_KER_TIM4		221
+#define CK_KER_TIM5		222
+#define CK_KER_TIM6		223
+#define CK_KER_TIM7		224
+#define CK_KER_TIM10		225
+#define CK_KER_TIM11		226
+#define CK_KER_TIM12		227
+#define CK_KER_TIM13		228
+#define CK_KER_TIM14		229
+#define CK_KER_TIM1		230
+#define CK_KER_TIM8		231
+#define CK_KER_TIM15		232
+#define CK_KER_TIM16		233
+#define CK_KER_TIM17		234
+#define CK_KER_TIM20		235
+#define CK_BUS_SYSRAM		236
+#define CK_BUS_VDERAM		237
+#define CK_BUS_RETRAM		238
+#define CK_BUS_OSPI1		239
+#define CK_BUS_OSPI2		240
+#define CK_BUS_OTFD1		241
+#define CK_BUS_OTFD2		242
+#define CK_BUS_SRAM1		243
+#define CK_BUS_SRAM2		244
+#define CK_BUS_SDMMC1		245
+#define CK_BUS_SDMMC2		246
+#define CK_BUS_SDMMC3		247
+#define CK_BUS_DDR		248
+#define CK_BUS_RISAF4		249
+#define CK_BUS_USB2OHCI		250
+#define CK_BUS_USB2EHCI		251
+#define CK_BUS_USB3DR		252
+#define CK_KER_LPTIM1		253
+#define CK_KER_LPTIM2		254
+#define CK_KER_USART2		255
+#define CK_KER_UART4		256
+#define CK_KER_USART3		257
+#define CK_KER_UART5		258
+#define CK_KER_SPI2		259
+#define CK_KER_SPI3		260
+#define CK_KER_SPDIFRX		261
+#define CK_KER_I2C1		262
+#define CK_KER_I2C2		263
+#define CK_KER_I3C1		264
+#define CK_KER_I3C2		265
+#define CK_KER_I2C3		266
+#define CK_KER_I2C5		267
+#define CK_KER_I3C3		268
+#define CK_KER_I2C4		269
+#define CK_KER_I2C6		270
+#define CK_KER_I2C7		271
+#define CK_KER_SPI1		272
+#define CK_KER_SPI4		273
+#define CK_KER_SPI5		274
+#define CK_KER_SPI6		275
+#define CK_KER_SPI7		276
+#define CK_KER_USART1		277
+#define CK_KER_USART6		278
+#define CK_KER_UART7		279
+#define CK_KER_UART8		280
+#define CK_KER_UART9		281
+#define CK_KER_MDF1		282
+#define CK_KER_SAI1		283
+#define CK_KER_SAI2		284
+#define CK_KER_SAI3		285
+#define CK_KER_SAI4		286
+#define CK_KER_FDCAN		287
+#define CK_KER_DSIBLANE		288
+#define CK_KER_DSIPHY		289
+#define CK_KER_CSI		290
+#define CK_KER_CSITXESC		291
+#define CK_KER_CSIPHY		292
+#define CK_KER_LVDSPHY		293
+#define CK_KER_STGEN		294
+#define CK_KER_USB3PCIEPHY	295
+#define CK_KER_USB2PHY2EN	296
+#define CK_KER_I3C4		297
+#define CK_KER_SPI8		298
+#define CK_KER_I2C8		299
+#define CK_KER_LPUART1		300
+#define CK_KER_LPTIM3		301
+#define CK_KER_LPTIM4		302
+#define CK_KER_LPTIM5		303
+#define CK_KER_TSDBG		304
+#define CK_KER_TPIU		305
+#define CK_BUS_ETR		306
+#define CK_BUS_SYSATB		307
+#define CK_KER_ADC12		308
+#define CK_KER_ADC3		309
+#define CK_KER_OSPI1		310
+#define CK_KER_OSPI2		311
+#define CK_KER_FMC		312
+#define CK_KER_SDMMC1		313
+#define CK_KER_SDMMC2		314
+#define CK_KER_SDMMC3		315
+#define CK_KER_ETH1		316
+#define CK_KER_ETH2		317
+#define CK_KER_ETH1PTP		318
+#define CK_KER_ETH2PTP		319
+#define CK_KER_USB2PHY1		320
+#define CK_KER_USB2PHY2		321
+#define CK_KER_ETHSW		322
+#define CK_KER_ETHSWREF		323
+#define CK_MCO1			324
+#define CK_MCO2			325
+#define CK_KER_DTS		326
+#define CK_ETH1_RX		327
+#define CK_ETH1_TX		328
+#define CK_ETH1_MAC		329
+#define CK_ETH2_RX		330
+#define CK_ETH2_TX		331
+#define CK_ETH2_MAC		332
+#define CK_ETH1_STP		333
+#define CK_ETH2_STP		334
+#define CK_KER_USBTC		335
+#define CK_BUS_ADF1		336
+#define CK_KER_ADF1		337
+#define CK_BUS_LVDS		338
+#define CK_KER_LTDC		339
+#define CK_KER_GPU		340
+#define CK_BUS_ETHSWACMCFG	341
+#define CK_BUS_ETHSWACMMSG	342
+#define HSE_DIV2_CK		343
+#define CK_KER_ETR		344
+#define CK_KER_STM		345
+
+#define STM32MP25_LAST_CLK	346
+
+#define CK_SCMI_ICN_HS_MCU	0
+#define CK_SCMI_ICN_SDMMC	1
+#define CK_SCMI_ICN_DDR		2
+#define CK_SCMI_ICN_DISPLAY	3
+#define CK_SCMI_ICN_HSL		4
+#define CK_SCMI_ICN_NIC		5
+#define CK_SCMI_ICN_VID		6
+#define CK_SCMI_FLEXGEN_07	7
+#define CK_SCMI_FLEXGEN_08	8
+#define CK_SCMI_FLEXGEN_09	9
+#define CK_SCMI_FLEXGEN_10	10
+#define CK_SCMI_FLEXGEN_11	11
+#define CK_SCMI_FLEXGEN_12	12
+#define CK_SCMI_FLEXGEN_13	13
+#define CK_SCMI_FLEXGEN_14	14
+#define CK_SCMI_FLEXGEN_15	15
+#define CK_SCMI_FLEXGEN_16	16
+#define CK_SCMI_FLEXGEN_17	17
+#define CK_SCMI_FLEXGEN_18	18
+#define CK_SCMI_FLEXGEN_19	19
+#define CK_SCMI_FLEXGEN_20	20
+#define CK_SCMI_FLEXGEN_21	21
+#define CK_SCMI_FLEXGEN_22	22
+#define CK_SCMI_FLEXGEN_23	23
+#define CK_SCMI_FLEXGEN_24	24
+#define CK_SCMI_FLEXGEN_25	25
+#define CK_SCMI_FLEXGEN_26	26
+#define CK_SCMI_FLEXGEN_27	27
+#define CK_SCMI_FLEXGEN_28	28
+#define CK_SCMI_FLEXGEN_29	29
+#define CK_SCMI_FLEXGEN_30	30
+#define CK_SCMI_FLEXGEN_31	31
+#define CK_SCMI_FLEXGEN_32	32
+#define CK_SCMI_FLEXGEN_33	33
+#define CK_SCMI_FLEXGEN_34	34
+#define CK_SCMI_FLEXGEN_35	35
+#define CK_SCMI_FLEXGEN_36	36
+#define CK_SCMI_FLEXGEN_37	37
+#define CK_SCMI_FLEXGEN_38	38
+#define CK_SCMI_FLEXGEN_39	39
+#define CK_SCMI_FLEXGEN_40	40
+#define CK_SCMI_FLEXGEN_41	41
+#define CK_SCMI_FLEXGEN_42	42
+#define CK_SCMI_FLEXGEN_43	43
+#define CK_SCMI_FLEXGEN_44	44
+#define CK_SCMI_FLEXGEN_45	45
+#define CK_SCMI_FLEXGEN_46	46
+#define CK_SCMI_FLEXGEN_47	47
+#define CK_SCMI_FLEXGEN_48	48
+#define CK_SCMI_FLEXGEN_49	49
+#define CK_SCMI_FLEXGEN_50	50
+#define CK_SCMI_FLEXGEN_51	51
+#define CK_SCMI_FLEXGEN_52	52
+#define CK_SCMI_FLEXGEN_53	53
+#define CK_SCMI_FLEXGEN_54	54
+#define CK_SCMI_FLEXGEN_55	55
+#define CK_SCMI_FLEXGEN_56	56
+#define CK_SCMI_FLEXGEN_57	57
+#define CK_SCMI_FLEXGEN_58	58
+#define CK_SCMI_FLEXGEN_59	59
+#define CK_SCMI_FLEXGEN_60	60
+#define CK_SCMI_FLEXGEN_61	61
+#define CK_SCMI_FLEXGEN_62	62
+#define CK_SCMI_FLEXGEN_63	63
+#define CK_SCMI_ICN_LS_MCU	64
+#define CK_SCMI_HSE		65
+#define CK_SCMI_LSE		66
+#define CK_SCMI_HSI		67
+#define CK_SCMI_LSI		68
+#define CK_SCMI_MSI		69
+#define CK_SCMI_HSE_DIV2	70
+#define CK_SCMI_CPU1		71
+#define CK_SCMI_SYSCPU1		72
+#define CK_SCMI_PLL2		73
+#define CK_SCMI_PLL3		74
+#define CK_SCMI_RTC		75
+#define CK_SCMI_RTCCK		76
+#define CK_SCMI_ICN_APB1	77
+#define CK_SCMI_ICN_APB2	78
+#define CK_SCMI_ICN_APB3	79
+#define CK_SCMI_ICN_APB4	80
+#define CK_SCMI_ICN_APBDBG	81
+#define CK_SCMI_TIMG1		82
+#define CK_SCMI_TIMG2		83
+#define CK_SCMI_BKPSRAM		84
+#define CK_SCMI_BSEC		85
+#define CK_SCMI_BUS_ETR		87
+#define CK_SCMI_FMC		88
+#define CK_SCMI_GPIOA		89
+#define CK_SCMI_GPIOB		90
+#define CK_SCMI_GPIOC		91
+#define CK_SCMI_GPIOD		92
+#define CK_SCMI_GPIOE		93
+#define CK_SCMI_GPIOF		94
+#define CK_SCMI_GPIOG		95
+#define CK_SCMI_GPIOH		96
+#define CK_SCMI_GPIOI		97
+#define CK_SCMI_GPIOJ		98
+#define CK_SCMI_GPIOK		99
+#define CK_SCMI_GPIOZ		100
+#define CK_SCMI_HPDMA1		101
+#define CK_SCMI_HPDMA2		102
+#define CK_SCMI_HPDMA3		103
+#define CK_SCMI_HSEM		104
+#define CK_SCMI_IPCC1		105
+#define CK_SCMI_IPCC2		106
+#define CK_SCMI_LPDMA		107
+#define CK_SCMI_RETRAM		108
+#define CK_SCMI_SRAM1		109
+#define CK_SCMI_SRAM2		110
+#define CK_SCMI_LPSRAM1		111
+#define CK_SCMI_LPSRAM2		112
+#define CK_SCMI_LPSRAM3		113
+#define CK_SCMI_VDERAM		114
+#define CK_SCMI_SYSRAM		115
+#define CK_SCMI_OSPI1		116
+#define CK_SCMI_OSPI2		117
+#define CK_SCMI_TPIU		118
+#define CK_SCMI_SYSDBG		119
+#define CK_SCMI_SYSATB		120
+#define CK_SCMI_TSDBG		121
+#define CK_SCMI_BUS_STM		122
+#define CK_SCMI_KER_STM		123
+#define CK_SCMI_KER_ETR		124
+
+#endif /* _DT_BINDINGS_CLOCK_ST_STM32MP25_RCC_H_ */
diff --git a/core/include/dt-bindings/clock/stm32mp25-clksrc.h b/core/include/dt-bindings/clock/stm32mp25-clksrc.h
new file mode 100644
index 0000000000000000000000000000000000000000..6f242c752ec7b8e40bb5072fc25eebf4f41960c2
--- /dev/null
+++ b/core/include/dt-bindings/clock/stm32mp25-clksrc.h
@@ -0,0 +1,275 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_
+#define _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_
+
+#define CMD_DIV		0
+#define CMD_MUX		1
+#define CMD_CLK		2
+#define CMD_FLEXGEN	3
+#define CMD_OBS		4
+
+#define CMD_ADDR_BIT	0x80000000
+
+#define CMD_SHIFT	26
+#define CMD_MASK	0xFC000000
+#define CMD_DATA_MASK	0x03FFFFFF
+
+#define DIV_ID_SHIFT	8
+#define DIV_ID_MASK	0x0000FF00
+
+#define DIV_DIVN_SHIFT	0
+#define DIV_DIVN_MASK	0x000000FF
+
+#define MUX_ID_SHIFT	4
+#define MUX_ID_MASK	0x00000FF0
+
+#define MUX_SEL_SHIFT	0
+#define MUX_SEL_MASK	0x0000000F
+
+/* CLK define */
+#define CLK_ON_MASK	BIT(21)
+#define CLK_ON_SHIFT	21
+
+#define CLK_ID_MASK	GENMASK_32(20, 12)
+#define CLK_ID_SHIFT	12
+
+#define CLK_NO_DIV_MASK	0x0000080
+#define CLK_DIV_MASK	GENMASK_32(10, 5)
+#define CLK_DIV_SHIFT	5
+
+#define CLK_NO_SEL_MASK	0x00000010
+#define CLK_SEL_MASK	GENMASK_32(3, 0)
+#define CLK_SEL_SHIFT	0
+
+#define CLK_CFG(clk_id, sel, div, state)	((CMD_CLK << CMD_SHIFT) |\
+						 ((state) << CLK_ON_SHIFT) |\
+						 ((clk_id) << CLK_ID_SHIFT) |\
+						 ((div) << CLK_DIV_SHIFT) |\
+						 ((sel) << CLK_SEL_SHIFT))
+
+#define CLK_OFF		0
+#define CLK_ON		1
+#define CLK_NODIV	0x00000040
+#define CLK_NOMUX	0x00000010
+
+/* Flexgen define */
+#define FLEX_ID_SHIFT	13
+#define FLEX_SEL_SHIFT	9
+#define FLEX_PDIV_SHIFT	6
+#define FLEX_FDIV_SHIFT	0
+
+#define FLEX_ID_MASK	GENMASK_32(18, 13)
+#define FLEX_SEL_MASK	GENMASK_32(12, 9)
+#define FLEX_PDIV_MASK	GENMASK_32(8, 6)
+#define FLEX_FDIV_MASK	GENMASK_32(5, 0)
+
+#define DIV_CFG(div_id, div)	((CMD_DIV << CMD_SHIFT) |\
+				 ((div_id) << DIV_ID_SHIFT |\
+				 (div)))
+
+#define MUX_CFG(mux_id, sel)	((CMD_MUX << CMD_SHIFT) |\
+				 ((mux_id) << MUX_ID_SHIFT |\
+				 (sel)))
+
+#define CLK_ADDR_SHIFT		16
+#define CLK_ADDR_MASK		0x7FFF0000
+#define CLK_ADDR_VAL_MASK	0xFFFF
+
+#define DIV_LSMCU	0
+#define DIV_APB1	1
+#define DIV_APB2	2
+#define DIV_APB3	3
+#define DIV_APB4	4
+#define DIV_APBDBG	5
+#define DIV_RTC		6
+#define DIV_NB		7
+
+#define MUX_MUXSEL0	0
+#define MUX_MUXSEL1	1
+#define MUX_MUXSEL2	2
+#define MUX_MUXSEL3	3
+#define MUX_MUXSEL4	4
+#define MUX_MUXSEL5	5
+#define MUX_MUXSEL6	6
+#define MUX_MUXSEL7	7
+#define MUX_XBARSEL	8
+#define MUX_RTC		9
+#define MUX_MCO1	10
+#define MUX_MCO2	11
+#define MUX_ADC12	12
+#define MUX_ADC3	13
+#define MUX_USB2PHY1	14
+#define MUX_USB2PHY2	15
+#define MUX_USB3PCIEPHY	16
+#define MUX_DSIBLANE	17
+#define MUX_DSIPHY	18
+#define MUX_LVDSPHY	19
+#define MUX_DTS		20
+#define MUX_D3PER	21
+#define MUX_NB		22
+
+#define MUXSEL_HSI		0
+#define MUXSEL_HSE		1
+#define MUXSEL_MSI		2
+
+/* KERNEL source clocks */
+#define MUX_RTC_DISABLED	0x0
+#define MUX_RTC_LSE		0x1
+#define MUX_RTC_LSI		0x2
+#define MUX_RTC_HSE		0x3
+
+#define MUX_MCO1_FLEX61		0x0
+#define MUX_MCO1_OBSER0		0x1
+
+#define MUX_MCO2_FLEX62		0x0
+#define MUX_MCO2_OBSER1		0x1
+
+#define MUX_ADC12_FLEX46	0x0
+#define MUX_ADC12_LSMCU		0x1
+
+#define MUX_ADC3_FLEX47		0x0
+#define MUX_ADC3_LSMCU		0x1
+#define MUX_ADC3_FLEX46		0x2
+
+#define MUX_USB2PHY1_FLEX57	0x0
+#define MUX_USB2PHY1_HSE	0x1
+
+#define MUX_USB2PHY2_FLEX58	0x0
+#define MUX_USB2PHY2_HSE	0x1
+
+#define MUX_USB3PCIEPHY_FLEX34	0x0
+#define MUX_USB3PCIEPHY_HSE	0x1
+
+#define MUX_DSIBLANE_DSIPHY	0x0
+#define MUX_DSIBLANE_FLEX27	0x1
+
+#define MUX_DSIPHY_FLEX28	0x0
+#define MUX_DSIPHY_HSE		0x1
+
+#define MUX_LVDSPHY_FLEX32	0x0
+#define MUX_LVDSPHY_HSE		0x1
+
+#define MUX_DTS_HSI		0x0
+#define MUX_DTS_HSE		0x1
+#define MUX_DTS_MSI		0x2
+
+#define MUX_D3PER_MSI		0x0
+#define MUX_D3PER_LSI		0x1
+#define MUX_D3PER_LSE		0x2
+
+/* PLLs source clocks */
+#define PLL_SRC_HSI		0x0
+#define PLL_SRC_HSE		0x1
+#define PLL_SRC_MSI		0x2
+#define PLL_SRC_DISABLED	0x3
+
+/* XBAR source clocks */
+#define XBAR_SRC_PLL4		0x0
+#define XBAR_SRC_PLL5		0x1
+#define XBAR_SRC_PLL6		0x2
+#define XBAR_SRC_PLL7		0x3
+#define XBAR_SRC_PLL8		0x4
+#define XBAR_SRC_HSI		0x5
+#define XBAR_SRC_HSE		0x6
+#define XBAR_SRC_MSI		0x7
+#define XBAR_SRC_HSI_KER	0x8
+#define XBAR_SRC_HSE_KER	0x9
+#define XBAR_SRC_MSI_KER	0xA
+#define XBAR_SRC_SPDIF_SYMB	0xB
+#define XBAR_SRC_I2S		0xC
+#define XBAR_SRC_LSI		0xD
+#define XBAR_SRC_LSE		0xE
+
+/*
+ * Configure a XBAR channel with its clock source
+ * channel_nb: XBAR channel number from 0 to 63
+ * channel_src: one of the 15 previous XBAR source clocks defines
+ * channel_prediv: value of the PREDIV in channel RCC_PREDIVxCFGR register
+ *		   can be either 1, 2, 4 or 1024
+ * channel_findiv: value of the FINDIV in channel RCC_FINDIVxCFGR register
+ *		   from 1 to 64
+ */
+
+#define FLEXGEN_CFG(ch, sel, pdiv, fdiv)	((CMD_FLEXGEN << CMD_SHIFT) |\
+						((ch) << FLEX_ID_SHIFT) |\
+						((sel) << FLEX_SEL_SHIFT) |\
+						((pdiv) << FLEX_PDIV_SHIFT) |\
+						((fdiv) << FLEX_FDIV_SHIFT))
+
+/* Register addresses of MCO1 & MCO2 */
+#define MCO1			0x494
+#define MCO2			0x498
+
+#define MCO_OFF			0
+#define MCO_ON			1
+#define MCO_STATUS_SHIFT	8
+
+#define MCO_CFG(addr, sel, status)	(CMD_ADDR_BIT |\
+					((addr) << CLK_ADDR_SHIFT) |\
+					((status) << MCO_STATUS_SHIFT) |\
+					(sel))
+#define OBS_ID_SHIFT		14
+#define OBS_STATUS_SHIFT	13
+#define OBS_INTEXT_SHIFT	12
+#define OBS_DIV_SHIFT		9
+#define OBS_INV_SHIFT		8
+#define OBS_SEL_SHIFT		0
+
+#define OBS_ID_MASK		GENMASK_32(14, 14)
+#define OBS_STATUS_MASK		GENMASK_32(13, 13)
+#define OBS_INTEXT_MASK		GENMASK_32(12, 12)
+#define OBS_DIV_MASK		GENMASK_32(11, 9)
+#define OBS_INV_MASK		BIT(8)
+#define OBS_SEL_MASK		GENMASK_32(7, 0)
+
+#define OBS_CFG(id, status, int_ext, div, inv, sel)\
+	((CMD_OBS << CMD_SHIFT) |\
+	((id) << OBS_ID_SHIFT) |\
+	((status) << OBS_STATUS_SHIFT) |\
+	((int_ext) << OBS_INTEXT_SHIFT) |\
+	((div) << OBS_DIV_SHIFT) |\
+	((inv) << OBS_INV_SHIFT) |\
+	((sel) << OBS_SEL_SHIFT))
+
+#define OBS0			0
+#define OBS1			1
+
+#define OBS_OFF			0
+#define OBS_ON			1
+
+#define OBS_INT			0
+#define OBS_EXT			1
+
+#define OBS_DIV1		0
+#define OBS_DIV2		1
+#define OBS_DIV4		2
+#define OBS_DIV8		3
+#define OBS_DIV16		4
+#define OBS_DIV32		5
+#define OBS_DIV64		6
+#define OBS_DIV128		7
+
+#define OBS_NO_INV		0
+#define OBS_INV			1
+
+#define OBS_INT_CFG(id, status, div, inv, sel)\
+		OBS_CFG(id, status, OBS_INT, div, inv, sel)
+
+#define OBS_EXT_CFG(id, status, div, inv, sel)\
+		OBS_CFG(id, status, OBS_EXT, div, inv, sel)
+
+/* define for st,pll /csg */
+#define SSCG_MODE_CENTER_SPREAD	0
+#define SSCG_MODE_DOWN_SPREAD	1
+
+/* define for st,drive */
+#define LSEDRV_LOWEST		0
+#define LSEDRV_MEDIUM_LOW	2
+#define LSEDRV_MEDIUM_HIGH	1
+#define LSEDRV_HIGHEST		3
+
+#endif /* _DT_BINDINGS_CLOCK_STM32MP25_CLKSRC_H_ */
diff --git a/core/include/dt-bindings/firewall/stm32mp13-etzpc.h b/core/include/dt-bindings/firewall/stm32mp13-etzpc.h
new file mode 100644
index 0000000000000000000000000000000000000000..74662116fdead3b23b6d02c8a9ba50e322017f43
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp13-etzpc.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2022-2024, STMicroelectronics
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP13_ETZPC_H
+#define _DT_BINDINGS_FIREWALL_STM32MP13_ETZPC_H
+
+/*  define DECPROT modes */
+#define DECPROT_S_RW		0x0
+#define DECPROT_NS_R_S_W	0x1
+#define DECPROT_NS_RW		0x3
+
+/*  define DECPROT lock */
+#define DECPROT_UNLOCK		0x0
+#define DECPROT_LOCK		0x1
+
+/* define TZMA IDs*/
+#define ETZPC_TZMA0_ID			200
+#define ETZPC_TZMA1_ID			201
+
+/* define ETZPC ID */
+#define STM32MP1_ETZPC_VREFBUF_ID	0
+#define STM32MP1_ETZPC_LPTIM2_ID	1
+#define STM32MP1_ETZPC_LPTIM3_ID	2
+#define STM32MP1_ETZPC_LTDC_ID		3
+#define STM32MP1_ETZPC_DCMIPP_ID	4
+#define STM32MP1_ETZPC_USBPHYCTRL_ID	5
+#define STM32MP1_ETZPC_DDRCTRLPHY_ID	6
+/* 7-11 Reserved */
+#define STM32MP1_ETZPC_IWDG1_ID		12
+#define STM32MP1_ETZPC_STGENC_ID	13
+/* 14-15 Reserved */
+#define STM32MP1_ETZPC_USART1_ID	16
+#define STM32MP1_ETZPC_USART2_ID	17
+#define STM32MP1_ETZPC_SPI4_ID		18
+#define STM32MP1_ETZPC_SPI5_ID		19
+#define STM32MP1_ETZPC_I2C3_ID		20
+#define STM32MP1_ETZPC_I2C4_ID		21
+#define STM32MP1_ETZPC_I2C5_ID		22
+#define STM32MP1_ETZPC_TIM12_ID		23
+#define STM32MP1_ETZPC_TIM13_ID		24
+#define STM32MP1_ETZPC_TIM14_ID		25
+#define STM32MP1_ETZPC_TIM15_ID		26
+#define STM32MP1_ETZPC_TIM16_ID		27
+#define STM32MP1_ETZPC_TIM17_ID		28
+/* 29-31 Reserved */
+#define STM32MP1_ETZPC_ADC1_ID		32
+#define STM32MP1_ETZPC_ADC2_ID		33
+#define STM32MP1_ETZPC_OTG_ID		34
+#define STM32MP1_ETZPC_TSC_ID		37
+/* 38-39 Reserved */
+#define STM32MP1_ETZPC_RNG_ID		40
+#define STM32MP1_ETZPC_HASH_ID		41
+#define STM32MP1_ETZPC_CRYP_ID		42
+#define STM32MP1_ETZPC_SAES_ID		43
+#define STM32MP1_ETZPC_PKA_ID		44
+#define STM32MP1_ETZPC_BKPSRAM_ID	45
+/* 46-47 Reserved */
+#define STM32MP1_ETZPC_ETH1_ID		48
+#define STM32MP1_ETZPC_ETH2_ID		49
+#define STM32MP1_ETZPC_SDMMC1_ID	50
+#define STM32MP1_ETZPC_SDMMC2_ID	51
+/* 52 Reserved */
+#define STM32MP1_ETZPC_MCE_ID		53
+#define STM32MP1_ETZPC_FMC_ID		54
+#define STM32MP1_ETZPC_QSPI_ID		55
+/* 56-59 Reserved */
+#define STM32MP1_ETZPC_SRAM1_ID		60
+#define STM32MP1_ETZPC_SRAM2_ID		61
+#define STM32MP1_ETZPC_SRAM3_ID		62
+/* 63 Reserved */
+
+#define STM32MP1_ETZPC_MAX_ID		64
+
+#define DECPROT(id, mode, lock)		((id) | ((mode) << ETZPC_MODE_SHIFT) | \
+					 ((lock) << ETZPC_LOCK_SHIFT))
+
+#define ETZPC_ID_MASK			GENMASK_32(7, 0)
+#define ETZPC_LOCK_MASK			BIT(8)
+#define ETZPC_LOCK_SHIFT		8
+#define ETZPC_MODE_SHIFT		9
+#define ETZPC_MODE_MASK			GENMASK_32(31, 9)
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP13_ETZPC_H */
diff --git a/core/include/dt-bindings/firewall/stm32mp13-tzc400.h b/core/include/dt-bindings/firewall/stm32mp13-tzc400.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba6a9079463bf0a53d9e1970a0c615b19c35d9ab
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp13-tzc400.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP13_TZC400_H
+#define _DT_BINDINGS_FIREWALL_STM32MP13_TZC400_H
+
+#include <dt-bindings/firewall/tzc400.h>
+
+/* NSAID */
+#define STM32MP1_TZC_A7_ID		0
+#define STM32MP1_TZC_LCD_ID		3
+#define STM32MP1_TZC_MDMA_ID		5
+#define STM32MP1_TZC_DMA_ID		6
+#define STM32MP1_TZC_USB_HOST_ID	7
+#define STM32MP1_TZC_USB_OTG_ID		8
+#define STM32MP1_TZC_SDMMC_ID		9
+#define STM32MP1_TZC_ETH_ID		10
+#define STM32MP1_TZC_DCMIPP_ID		11
+#define STM32MP1_TZC_DAP_ID		15
+
+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
+	(TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DCMIPP_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID))
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP13_TZC400_H */
diff --git a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h b/core/include/dt-bindings/firewall/stm32mp15-etzpc.h
similarity index 60%
rename from core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h
rename to core/include/dt-bindings/firewall/stm32mp15-etzpc.h
index bc0b78fa25aecdcc5a889a9bcc1c3cd932c1dc63..cc99f4931bafd0a8524c69929fe805fb98795055 100644
--- a/core/arch/arm/plat-stm32mp1/drivers/stm32mp1_etzpc.h
+++ b/core/include/dt-bindings/firewall/stm32mp15-etzpc.h
@@ -1,13 +1,26 @@
-/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (C) 2018-2019, STMicroelectronics
+ * Copyright (c) 2018-2024, STMicroelectronics
  */
 
-#ifndef __STM32MP1_ETZPC_H
-#define __STM32MP1_ETZPC_H
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP15_ETZPC_H
+#define _DT_BINDINGS_FIREWALL_STM32MP15_ETZPC_H
 
-/* Define DECPROT IDs for stm32mp1 familly */
-#ifdef CFG_STM32MP15
+/*  define DECPROT modes */
+#define DECPROT_S_RW		0x0
+#define DECPROT_NS_R_S_W	0x1
+#define DECPROT_MCU_ISOLATION	0x2
+#define DECPROT_NS_RW		0x3
+
+/*  define DECPROT lock */
+#define DECPROT_UNLOCK		0x0
+#define DECPROT_LOCK		0x1
+
+/* define TZMA IDs*/
+#define ETZPC_TZMA0_ID			200
+#define ETZPC_TZMA1_ID			201
+
+/* define ETZPC ID */
 #define STM32MP1_ETZPC_STGENC_ID	0
 #define STM32MP1_ETZPC_BKPSRAM_ID	1
 #define STM32MP1_ETZPC_IWDG1_ID		2
@@ -96,61 +109,16 @@
 #define STM32MP1_ETZPC_DLYBQ_ID		93
 #define STM32MP1_ETZPC_ETH_ID		94
 /* 95 Reserved */
+
 #define STM32MP1_ETZPC_MAX_ID		96
-#endif /* CFG_STM32MP15 */
 
-#ifdef CFG_STM32MP13
-#define STM32MP1_ETZPC_VREFBUF_ID	0
-#define STM32MP1_ETZPC_LPTIM2_ID	1
-#define STM32MP1_ETZPC_LPTIM3_ID	2
-#define STM32MP1_ETZPC_LTDC_ID		3
-#define STM32MP1_ETZPC_DCMIPP_ID	4
-#define STM32MP1_ETZPC_USBPHYCTRL_ID	5
-#define STM32MP1_ETZPC_DDRCTRLPHY_ID	6
-/* 7-11 Reserved */
-#define STM32MP1_ETZPC_IWDG1_ID		12
-#define STM32MP1_ETZPC_STGENC_ID	13
-/* 14-15 Reserved */
-#define STM32MP1_ETZPC_USART1_ID	16
-#define STM32MP1_ETZPC_USART2_ID	17
-#define STM32MP1_ETZPC_SPI4_ID		18
-#define STM32MP1_ETZPC_SPI5_ID		19
-#define STM32MP1_ETZPC_I2C3_ID		20
-#define STM32MP1_ETZPC_I2C4_ID		21
-#define STM32MP1_ETZPC_I2C5_ID		22
-#define STM32MP1_ETZPC_TIM12_ID		23
-#define STM32MP1_ETZPC_TIM13_ID		24
-#define STM32MP1_ETZPC_TIM14_ID		25
-#define STM32MP1_ETZPC_TIM15_ID		26
-#define STM32MP1_ETZPC_TIM16_ID		27
-#define STM32MP1_ETZPC_TIM17_ID		28
-/* 29-31 Reserved */
-#define STM32MP1_ETZPC_ADC1_ID		32
-#define STM32MP1_ETZPC_ADC2_ID		33
-#define STM32MP1_ETZPC_OTG_ID		34
-/* 35-36 Reserved */
-#define STM32MP1_ETZPC_TSC_ID		37
-/* 38-39 Reserved */
-#define STM32MP1_ETZPC_RNG_ID		40
-#define STM32MP1_ETZPC_HASH_ID		41
-#define STM32MP1_ETZPC_CRYP_ID		42
-#define STM32MP1_ETZPC_SAES_ID		43
-#define STM32MP1_ETZPC_PKA_ID		44
-#define STM32MP1_ETZPC_BKPSRAM_ID	45
-/* 46-47 Reserved */
-#define STM32MP1_ETZPC_ETH1_ID		48
-#define STM32MP1_ETZPC_ETH2_ID		49
-#define STM32MP1_ETZPC_SDMMC1_ID	50
-#define STM32MP1_ETZPC_SDMMC2_ID	51
-/* 52 Reserved */
-#define STM32MP1_ETZPC_MCE_ID		53
-#define STM32MP1_ETZPC_FMC_ID		54
-#define STM32MP1_ETZPC_QSPI_ID		55
-/* 56-59 Reserved */
-#define STM32MP1_ETZPC_SRAM1_ID		60
-#define STM32MP1_ETZPC_SRAM2_ID		61
-#define STM32MP1_ETZPC_SRAM3_ID		62
-/* 63 Reserved */
-#define STM32MP1_ETZPC_MAX_ID		64
-#endif /* CFG_STM32MP13 */
-#endif /*__STM32MP1_ETZPC_H*/
+#define DECPROT(id, mode, lock)		((id) | ((mode) << ETZPC_MODE_SHIFT) | \
+					 ((lock) << ETZPC_LOCK_SHIFT))
+
+#define ETZPC_ID_MASK			GENMASK_32(7, 0)
+#define ETZPC_LOCK_MASK			BIT(8)
+#define ETZPC_LOCK_SHIFT		8
+#define ETZPC_MODE_SHIFT		9
+#define ETZPC_MODE_MASK			GENMASK_32(31, 9)
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP15_ETZPC_H */
diff --git a/core/include/dt-bindings/firewall/stm32mp15-tzc400.h b/core/include/dt-bindings/firewall/stm32mp15-tzc400.h
new file mode 100644
index 0000000000000000000000000000000000000000..aaf7de519343e7ff9c0847e02dba72a0ce36e756
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp15-tzc400.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP15_TZC400_H
+#define _DT_BINDINGS_FIREWALL_STM32MP15_TZC400_H
+
+#include <dt-bindings/firewall/tzc400.h>
+
+/* NSAID */
+#define STM32MP1_TZC_A7_ID		0
+#define STM32MP1_TZC_M4_ID		1
+#define STM32MP1_TZC_LCD_ID		3
+#define STM32MP1_TZC_GPU_ID		4
+#define STM32MP1_TZC_MDMA_ID		5
+#define STM32MP1_TZC_DMA_ID		6
+#define STM32MP1_TZC_USB_HOST_ID	7
+#define STM32MP1_TZC_USB_OTG_ID		8
+#define STM32MP1_TZC_SDMMC_ID		9
+#define STM32MP1_TZC_ETH_ID		10
+#define STM32MP1_TZC_DAP_ID		15
+
+#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \
+	(TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \
+	 TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID))
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP15_TZC400_H */
diff --git a/core/include/dt-bindings/firewall/stm32mp25-rif.h b/core/include/dt-bindings/firewall/stm32mp25-rif.h
new file mode 100644
index 0000000000000000000000000000000000000000..e740581ef6489292863ebe8f8f40a187df42b4e2
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp25-rif.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H
+#define _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H
+
+/* RIF CIDs */
+#define RIF_CID0		0x0
+#define RIF_CID1		0x1
+#define RIF_CID2		0x2
+#define RIF_CID3		0x3
+#define RIF_CID4		0x4
+#define RIF_CID5		0x5
+#define RIF_CID6		0x6
+#define RIF_CID7		0x7
+
+/* RIF semaphore list */
+#define EMPTY_SEMWL		0x0
+#ifdef __ASSEMBLER__
+#define RIF_CID0_BF		(1 << RIF_CID0)
+#define RIF_CID1_BF		(1 << RIF_CID1)
+#define RIF_CID2_BF		(1 << RIF_CID2)
+#define RIF_CID3_BF		(1 << RIF_CID3)
+#define RIF_CID4_BF		(1 << RIF_CID4)
+#define RIF_CID5_BF		(1 << RIF_CID5)
+#define RIF_CID6_BF		(1 << RIF_CID6)
+#define RIF_CID7_BF		(1 << RIF_CID7)
+#else /* __ASSEMBLER__ */
+#define RIF_CID0_BF		BIT(RIF_CID0)
+#define RIF_CID1_BF		BIT(RIF_CID1)
+#define RIF_CID2_BF		BIT(RIF_CID2)
+#define RIF_CID3_BF		BIT(RIF_CID3)
+#define RIF_CID4_BF		BIT(RIF_CID4)
+#define RIF_CID5_BF		BIT(RIF_CID5)
+#define RIF_CID6_BF		BIT(RIF_CID6)
+#define RIF_CID7_BF		BIT(RIF_CID7)
+#endif /* __ASSEMBLER__ */
+
+/* RIF secure levels */
+#define RIF_NSEC		0x0
+#define RIF_SEC			0x1
+
+/* RIF privilege levels */
+#define RIF_NPRIV		0x0
+#define RIF_PRIV		0x1
+
+/* RIF semaphore modes */
+#define RIF_SEM_DIS		0x0
+#define RIF_SEM_EN		0x1
+
+/* RIF CID filtering modes */
+#define RIF_CFDIS		0x0
+#define RIF_CFEN		0x1
+
+/* RIF lock states */
+#define RIF_UNLOCK		0x0
+#define RIF_LOCK		0x1
+
+/* Used when a field in a macro has no impact */
+#define RIF_UNUSED		0x0
+
+/* Most below macros aim to ease DTS files readability */
+#define RIF_EXTI1_RESOURCE(x)	(x)
+
+#define RIF_EXTI2_RESOURCE(x)	(x)
+
+#define RIF_FMC_CTRL(x)		(x)
+
+#define RIF_IOPORT_PIN(x)	(x)
+
+#define RIF_HPDMA_CHANNEL(x)	(x)
+
+#define RIF_IPCC_CPU1_CHANNEL(x)	((x) - 1)
+
+#define RIF_IPCC_CPU2_CHANNEL(x)	(((x) - 1) + 16)
+
+#define RIF_PWR_RESOURCE(x)	(x)
+
+#define RIF_HSEM_RESOURCE(x)	(x)
+
+/* Shareable PWR resources, RIF_PWR_RESOURCE_WIO(0) doesn't exist */
+#define RIF_PWR_RESOURCE_WIO(x)	((x) + 6)
+
+#define RIF_RCC_RESOURCE(x)	(x)
+
+#define RIF_RTC_RESOURCE(x)	(x)
+
+#define RIF_TAMP_RESOURCE(x)	(x)
+
+#define RIF_PER_ID_SHIFT		0
+#define RIF_CFEN_SHIFT			8
+#define RIF_SEM_EN_SHIFT		9
+#define RIF_SCID_SHIFT			12
+#define RIF_SEC_SHIFT			16
+#define RIF_PRIV_SHIFT			17
+#define RIF_LOCK_SHIFT			18
+#define RIF_SEML_SHIFT			24
+#define RIF_PERx_CID_SHIFT		8
+#ifndef __ASSEMBLER__
+#define RIF_PER_ID_MASK			GENMASK_32(7, 0)
+#define RIF_SCID_MASK			GENMASK_32(15, 12)
+#define RIF_SEC_MASK			BIT(16)
+#define RIF_PRIV_MASK			BIT(17)
+#define RIF_LOCK_MASK			BIT(18)
+#define RIF_SEML_MASK			GENMASK_32(31, 24)
+#endif
+
+#define RIF_PERx_CID_MASK		(BIT(RIF_CFEN_SHIFT) | \
+					 BIT(RIF_SEM_EN_SHIFT) | \
+					 RIF_SCID_MASK | RIF_SEML_MASK)
+
+#define RIFPROT(rifid, sem_list, lock, sec, priv, scid, sem_en, cfen) \
+	(((sem_list) << RIF_SEML_SHIFT) | \
+	 ((lock) << RIF_LOCK_SHIFT) | \
+	 ((priv) << RIF_PRIV_SHIFT) | \
+	 ((sec) << RIF_SEC_SHIFT) | \
+	 ((scid) << RIF_SCID_SHIFT) | \
+	 ((sem_en) << RIF_SEM_EN_SHIFT) | \
+	 ((cfen) << RIF_CFEN_SHIFT) | \
+	 ((rifid) << RIF_PER_ID_SHIFT))
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIF_H */
diff --git a/core/include/dt-bindings/firewall/stm32mp25-rifsc.h b/core/include/dt-bindings/firewall/stm32mp25-rifsc.h
new file mode 100644
index 0000000000000000000000000000000000000000..f2f6de0575f9cfb7c66e5539adbc8a9577d9184a
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp25-rifsc.h
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * Copyright (c) 2020-2024, STMicroelectronics
+ */
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H
+#define _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H
+
+/* RIFSC ID */
+#define STM32MP25_RIFSC_TIM1_ID			0
+#define STM32MP25_RIFSC_TIM2_ID			1
+#define STM32MP25_RIFSC_TIM3_ID			2
+#define STM32MP25_RIFSC_TIM4_ID			3
+#define STM32MP25_RIFSC_TIM5_ID			4
+#define STM32MP25_RIFSC_TIM6_ID			5
+#define STM32MP25_RIFSC_TIM7_ID			6
+#define STM32MP25_RIFSC_TIM8_ID			7
+#define STM32MP25_RIFSC_TIM10_ID		8
+#define STM32MP25_RIFSC_TIM11_ID		9
+#define STM32MP25_RIFSC_TIM12_ID		10
+#define STM32MP25_RIFSC_TIM13_ID		11
+#define STM32MP25_RIFSC_TIM14_ID		12
+#define STM32MP25_RIFSC_TIM15_ID		13
+#define STM32MP25_RIFSC_TIM16_ID		14
+#define STM32MP25_RIFSC_TIM17_ID		15
+#define STM32MP25_RIFSC_TIM20_ID		16
+#define STM32MP25_RIFSC_LPTIM1_ID		17
+#define STM32MP25_RIFSC_LPTIM2_ID		18
+#define STM32MP25_RIFSC_LPTIM3_ID		19
+#define STM32MP25_RIFSC_LPTIM4_ID		20
+#define STM32MP25_RIFSC_LPTIM5_ID		21
+#define STM32MP25_RIFSC_SPI1_ID			22
+#define STM32MP25_RIFSC_SPI2_ID			23
+#define STM32MP25_RIFSC_SPI3_ID			24
+#define STM32MP25_RIFSC_SPI4_ID			25
+#define STM32MP25_RIFSC_SPI5_ID			26
+#define STM32MP25_RIFSC_SPI6_ID			27
+#define STM32MP25_RIFSC_SPI7_ID			28
+#define STM32MP25_RIFSC_SPI8_ID			29
+#define STM32MP25_RIFSC_SPDIFRX_ID		30
+#define STM32MP25_RIFSC_USART1_ID		31
+#define STM32MP25_RIFSC_USART2_ID		32
+#define STM32MP25_RIFSC_USART3_ID		33
+#define STM32MP25_RIFSC_UART4_ID		34
+#define STM32MP25_RIFSC_UART5_ID		35
+#define STM32MP25_RIFSC_USART6_ID		36
+#define STM32MP25_RIFSC_UART7_ID		37
+#define STM32MP25_RIFSC_UART8_ID		38
+#define STM32MP25_RIFSC_UART9_ID		39
+#define STM32MP25_RIFSC_LPUART1_ID		40
+#define STM32MP25_RIFSC_I2C1_ID			41
+#define STM32MP25_RIFSC_I2C2_ID			42
+#define STM32MP25_RIFSC_I2C3_ID			43
+#define STM32MP25_RIFSC_I2C4_ID			44
+#define STM32MP25_RIFSC_I2C5_ID			45
+#define STM32MP25_RIFSC_I2C6_ID			46
+#define STM32MP25_RIFSC_I2C7_ID			47
+#define STM32MP25_RIFSC_I2C8_ID			48
+#define STM32MP25_RIFSC_SAI1_ID			49
+#define STM32MP25_RIFSC_SAI2_ID			50
+#define STM32MP25_RIFSC_SAI3_ID			51
+#define STM32MP25_RIFSC_SAI4_ID			52
+#define STM32MP25_RIFSC_MDF1_ID			54
+#define STM32MP25_RIFSC_ADF1_ID			55
+#define STM32MP25_RIFSC_FDCAN_ID		56
+#define STM32MP25_RIFSC_HDP_ID			57
+#define STM32MP25_RIFSC_ADC12_ID		58
+#define STM32MP25_RIFSC_ADC3_ID			59
+#define STM32MP25_RIFSC_ETH1_ID			60
+#define STM32MP25_RIFSC_ETH2_ID			61
+#define STM32MP25_RIFSC_USBH_ID			63
+#define STM32MP25_RIFSC_USB3DR_ID		66
+#define STM32MP25_RIFSC_COMBOPHY_ID		67
+#define STM32MP25_RIFSC_PCIE_ID			68
+#define STM32MP25_RIFSC_UCPD1_ID		69
+#define STM32MP25_RIFSC_ETHSW_DEIP_ID		70
+#define STM32MP25_RIFSC_ETHSW_ACM_CFG_ID	71
+#define STM32MP25_RIFSC_ETHSW_ACM_MSGBUF_ID	72
+#define STM32MP25_RIFSC_STGEN_ID		73
+#define STM32MP25_RIFSC_OCTOSPI1_ID		74
+#define STM32MP25_RIFSC_OCTOSPI2_ID		75
+#define STM32MP25_RIFSC_SDMMC1_ID		76
+#define STM32MP25_RIFSC_SDMMC2_ID		77
+#define STM32MP25_RIFSC_SDMMC3_ID		78
+#define STM32MP25_RIFSC_GPU_ID			79
+#define STM32MP25_RIFSC_LTDC_CMN_ID		80
+#define STM32MP25_RIFSC_DSI_CMN_ID		81
+#define STM32MP25_RIFSC_LVDS_ID			84
+#define STM32MP25_RIFSC_CSI_ID			86
+#define STM32MP25_RIFSC_DCMIPP_ID		87
+#define STM32MP25_RIFSC_DCMI_PSSI_ID		88
+#define STM32MP25_RIFSC_VDEC_ID			89
+#define STM32MP25_RIFSC_VENC_ID			90
+#define STM32MP25_RIFSC_RNG_ID			92
+#define STM32MP25_RIFSC_PKA_ID			93
+#define STM32MP25_RIFSC_SAES_ID			94
+#define STM32MP25_RIFSC_HASH_ID			95
+#define STM32MP25_RIFSC_CRYP1_ID		96
+#define STM32MP25_RIFSC_CRYP2_ID		97
+#define STM32MP25_RIFSC_IWDG1_ID		98
+#define STM32MP25_RIFSC_IWDG2_ID		99
+#define STM32MP25_RIFSC_IWDG3_ID		100
+#define STM32MP25_RIFSC_IWDG4_ID		101
+#define STM32MP25_RIFSC_IWDG5_ID		102
+#define STM32MP25_RIFSC_WWDG1_ID		103
+#define STM32MP25_RIFSC_WWDG2_ID		104
+#define STM32MP25_RIFSC_VREFBUF_ID		106
+#define STM32MP25_RIFSC_DTS_ID			107
+#define STM32MP25_RIFSC_RAMCFG_ID		108
+#define STM32MP25_RIFSC_CRC_ID			109
+#define STM32MP25_RIFSC_SERC_ID			110
+#define STM32MP25_RIFSC_OCTOSPIM_ID		111
+#define STM32MP25_RIFSC_GICV2M_ID		112
+#define STM32MP25_RIFSC_I3C1_ID			114
+#define STM32MP25_RIFSC_I3C2_ID			115
+#define STM32MP25_RIFSC_I3C3_ID			116
+#define STM32MP25_RIFSC_I3C4_ID			117
+#define STM32MP25_RIFSC_ICACHE_DCACHE_ID	118
+#define STM32MP25_RIFSC_LTDC_L0L1_ID		119
+#define STM32MP25_RIFSC_LTDC_L2_ID		120
+#define STM32MP25_RIFSC_LTDC_ROT_ID		121
+#define STM32MP25_RIFSC_DSI_TRIG_ID		122
+#define STM32MP25_RIFSC_DSI_RDFIFO_ID		123
+#define STM32MP25_RIFSC_OTFDEC1_ID		125
+#define STM32MP25_RIFSC_OTFDEC2_ID		126
+#define STM32MP25_RIFSC_IAC_ID			127
+
+/* RIF-aware IPs */
+#define STM32MP25_RIFSC_PWR_ID			155
+#define STM32MP25_RIFSC_GPIOA_ID		160
+#define STM32MP25_RIFSC_GPIOB_ID		161
+#define STM32MP25_RIFSC_GPIOC_ID		162
+#define STM32MP25_RIFSC_GPIOD_ID		163
+#define STM32MP25_RIFSC_GPIOE_ID		164
+#define STM32MP25_RIFSC_GPIOF_ID		165
+#define STM32MP25_RIFSC_GPIOG_ID		166
+#define STM32MP25_RIFSC_GPIOH_ID		167
+#define STM32MP25_RIFSC_GPIOI_ID		168
+#define STM32MP25_RIFSC_GPIOJ_ID		169
+#define STM32MP25_RIFSC_GPIOK_ID		170
+#define STM32MP25_RIFSC_GPIOZ_ID		171
+
+/* Global lock bindings */
+#define RIFSC_RIMU_GLOCK			1
+#define RIFSC_RISUP_GLOCK			2
+
+/* masters ID */
+#define RIMU_ID_OFFSET		200
+#define RIMU_ID(idx)		((idx) + RIMU_ID_OFFSET)
+
+/* master configuration modes */
+#define RIF_CIDSEL_P	0x0 /* config from RISUP */
+#define RIF_CIDSEL_M	0x1 /* config from RIMU */
+
+#define RIMUPROT_RIMC_M_ID_SHIFT	0
+#define RIMUPROT_RIMC_MODE_SHIFT	10
+#define RIMUPROT_RIMC_MCID_SHIFT	12
+#define RIMUPROT_RIMC_MSEC_SHIFT	16
+#define RIMUPROT_RIMC_MPRIV_SHIFT	17
+#define RIMUPROT_RIMC_ATTRx_SHIFT	8
+#define RIMUPROT_RIMC_M_ID_MASK		GENMASK_32(7, 0)
+#define RIMUPROT_RIMC_MCID_MASK		GENMASK_32(15, 12)
+#define RIMUPROT_RIMC_ATTRx_MASK	(BIT(RIMUPROT_RIMC_MODE_SHIFT) | \
+					 RIMUPROT_RIMC_MCID_MASK | \
+					 BIT(RIMUPROT_RIMC_MSEC_SHIFT) | \
+					 BIT(RIMUPROT_RIMC_MPRIV_SHIFT))
+
+#define RIMUPROT(rimuid, mcid, msec, mpriv, mode) \
+	(((rimuid) << RIMUPROT_RIMC_M_ID_SHIFT) | \
+	 ((mpriv) << RIMUPROT_RIMC_MPRIV_SHIFT) | \
+	 ((msec) << RIMUPROT_RIMC_MSEC_SHIFT) | \
+	 ((mcid) << RIMUPROT_RIMC_MCID_SHIFT) | \
+	 ((mode) << RIMUPROT_RIMC_MODE_SHIFT))
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RIFSC_H */
+
diff --git a/core/include/dt-bindings/firewall/stm32mp25-risab.h b/core/include/dt-bindings/firewall/stm32mp25-risab.h
new file mode 100644
index 0000000000000000000000000000000000000000..e04e4fb856b863a64492f77b64ae67c8a4e90b85
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp25-risab.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2022-2024, STMicroelectronics
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RISAB_H
+#define _DT_BINDINGS_FIREWALL_STM32MP25_RISAB_H
+
+/* RISAB control modes */
+#define RIF_DDCID_DIS				0x0
+#define RIF_DDCID_EN				0x1
+
+#define RISAB_READ_LIST_SHIFT			8
+#define RISAB_WRITE_LIST_SHIFT			16
+#define RISAB_CFEN_SHIFT			24
+#define RISAB_DPRIV_SHIFT			25
+#define RISAB_SEC_SHIFT				26
+#define RISAB_DCCID_SHIFT			27
+#define RISAB_DCEN_SHIFT			31
+
+#define RISABPROT(delegate_en, delegate_cid, sec, default_priv, \
+		  enabled, cid_read_list, cid_write_list, cid_priv_list) \
+	(((delegate_en) << RISAB_DCEN_SHIFT) | \
+	 ((delegate_cid) << RISAB_DCCID_SHIFT) | \
+	 ((sec) << RISAB_SEC_SHIFT) | ((default_priv) << RISAB_DPRIV_SHIFT) | \
+	 ((enabled) << RISAB_CFEN_SHIFT) | \
+	 ((cid_write_list) << RISAB_WRITE_LIST_SHIFT) | \
+	 ((cid_read_list) << RISAB_READ_LIST_SHIFT) | (cid_priv_list))
+
+/* RISABPROT macro masks */
+#define RISAB_PLIST_MASK			GENMASK_32(7, 0)
+#define RISAB_RLIST_MASK			GENMASK_32(15, 8)
+#define RISAB_WLIST_MASK			GENMASK_32(23, 16)
+#define RISAB_DCCID_MASK			GENMASK_32(30, 27)
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RISAB_H */
diff --git a/core/include/dt-bindings/firewall/stm32mp25-risaf.h b/core/include/dt-bindings/firewall/stm32mp25-risaf.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4731ed3e0e664c597cda0ed397872a34050cf72
--- /dev/null
+++ b/core/include/dt-bindings/firewall/stm32mp25-risaf.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2020-2024, STMicroelectronics
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_STM32MP25_RISAF_H
+#define _DT_BINDINGS_FIREWALL_STM32MP25_RISAF_H
+
+/* RISAF region IDs */
+#define RISAF_REG_ID(idx)	(idx)
+
+/* RISAF base region enable modes */
+#define RIF_BREN_DIS		0x0
+#define RIF_BREN_EN		0x1
+
+/* RISAF encryption modes */
+#define RIF_ENC_DIS		0x0
+#define RIF_ENC_EN		0x2
+
+#define DT_RISAF_EN_SHIFT	4
+#define DT_RISAF_SEC_SHIFT	5
+#define DT_RISAF_ENC_SHIFT	6
+#define DT_RISAF_PRIV_SHIFT	8
+#define DT_RISAF_READ_SHIFT	16
+#define DT_RISAF_WRITE_SHIFT	24
+
+#define DT_RISAF_REG_ID_MASK		U(0xF)
+#define DT_RISAF_EN_MASK		BIT(DT_RISAF_EN_SHIFT)
+#define DT_RISAF_SEC_MASK		BIT(DT_RISAF_SEC_SHIFT)
+#define DT_RISAF_ENC_MASK		GENMASK_32(7, 6)
+#define DT_RISAF_PRIV_MASK		GENMASK_32(15, 8)
+#define DT_RISAF_READ_MASK		GENMASK_32(23, 16)
+#define DT_RISAF_WRITE_MASK		GENMASK_32(31, 24)
+
+#define RISAFPROT(risaf_region, cid_read_list, cid_write_list, cid_priv_list, \
+		  sec, enc, enabled) \
+	(((cid_write_list) << DT_RISAF_WRITE_SHIFT) | \
+	 ((cid_read_list) << DT_RISAF_READ_SHIFT) | \
+	 ((cid_priv_list) << DT_RISAF_PRIV_SHIFT) | \
+	 ((enc) << DT_RISAF_ENC_SHIFT) | \
+	 ((sec) << DT_RISAF_SEC_SHIFT) | \
+	 ((enabled) << DT_RISAF_EN_SHIFT) | \
+	 (risaf_region))
+
+#endif /* _DT_BINDINGS_FIREWALL_STM32MP25_RISAF_H */
diff --git a/core/include/dt-bindings/firewall/tzc400.h b/core/include/dt-bindings/firewall/tzc400.h
new file mode 100644
index 0000000000000000000000000000000000000000..52d327c861801eef2666ce545f5f191d1fd37934
--- /dev/null
+++ b/core/include/dt-bindings/firewall/tzc400.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (C) 2020-2024, STMicroelectronics - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_FIREWALL_TZC400_H
+#define _DT_BINDINGS_FIREWALL_TZC400_H
+
+#define	DT_TZC_REGION_S_NONE	0
+#define	DT_TZC_REGION_S_RD	1
+#define	DT_TZC_REGION_S_WR	2
+#define	DT_TZC_REGION_S_RDWR	3
+
+#define DT_REGION_ID_ACCESS_NSAID_WR_EN_SHIFT	16
+#define DT_REGION_ID_ACCESS_NSAID_RD_EN_SHIFT	0
+#define DT_REGION_ID_ACCESS_NSAID_ID_MASK	0xf
+
+#define DT_TZC_REGION_ACCESS_RD(id)					\
+		((1 << ((id) & DT_REGION_ID_ACCESS_NSAID_ID_MASK)) <<	\
+		 DT_REGION_ID_ACCESS_NSAID_RD_EN_SHIFT)
+
+#define DT_TZC_REGION_ACCESS_WR(id)					\
+		((1 << ((id) & DT_REGION_ID_ACCESS_NSAID_ID_MASK)) <<	\
+		 DT_REGION_ID_ACCESS_NSAID_WR_EN_SHIFT)
+
+#define DT_TZC_REGION_ACCESS_RDWR(id)					\
+		(DT_TZC_REGION_ACCESS_RD(id) | DT_TZC_REGION_ACCESS_WR(id))
+
+#endif /* _DT_BINDINGS_FIREWALL_TZC400_H */
diff --git a/core/include/dt-bindings/gpio/stm32mp_gpio.h b/core/include/dt-bindings/gpio/stm32mp_gpio.h
index 3afcf415824620394a826730e396681dbedc0f7d..7c5ac399fd5ca0f66e5e29af72e98eb66b7911f9 100644
--- a/core/include/dt-bindings/gpio/stm32mp_gpio.h
+++ b/core/include/dt-bindings/gpio/stm32mp_gpio.h
@@ -15,4 +15,11 @@
 #define TZPROT(id)	(UINT32_C(1) << (id))
 #endif
 
+/* GPIO phandle argument bitmask for a non-secure GPIO */
+#ifdef __ASSEMBLER__
+#define GPIO_STM32_NSEC	(1 << 31)
+#else
+#define GPIO_STM32_NSEC	(UINT32_C(1) << 31)
+#endif
+
 #endif
diff --git a/core/include/dt-bindings/mfd/st,stpmic1.h b/core/include/dt-bindings/mfd/st,stpmic1.h
index 321cd08797d9a888b321fc7a3ca5a113f683dd4a..9dd15b9c743e949d84e5406cd2f7b518c2199832 100644
--- a/core/include/dt-bindings/mfd/st,stpmic1.h
+++ b/core/include/dt-bindings/mfd/st,stpmic1.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
 /*
  * Copyright (C) STMicroelectronics 2018 - All Rights Reserved
  * Author: Philippe Peurichard <philippe.peurichard@st.com>,
diff --git a/core/include/dt-bindings/pinctrl/stm32-pinfunc.h b/core/include/dt-bindings/pinctrl/stm32-pinfunc.h
index 370a25a9366cc87a87cc7c0a664eabf8f7915a39..afd118f8b5fe55867c89347a36059cf9341e8391 100644
--- a/core/include/dt-bindings/pinctrl/stm32-pinfunc.h
+++ b/core/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -33,6 +33,11 @@
 
 #define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode))
 
+#define STM32_PIN_NSEC		(1 << 31)
+
+#define STM32_PINMUX_NSEC(port, line, mode) \
+	(STM32_PIN_NSEC | STM32_PINMUX((port), (line), (mode)))
+
 /*  package information */
 #define STM32MP_PKG_AA	0x1
 #define STM32MP_PKG_AB	0x2
diff --git a/core/include/dt-bindings/reset/st,stm32mp25-rcc.h b/core/include/dt-bindings/reset/st,stm32mp25-rcc.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b2b07a09bb80305d62c179f95f4f06de24d1b7f
--- /dev/null
+++ b/core/include/dt-bindings/reset/st,stm32mp25-rcc.h
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics 2024 - All Rights Reserved
+ */
+
+#ifndef _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_
+#define _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_
+
+#define TIM1_R		0
+#define TIM2_R		1
+#define TIM3_R		2
+#define TIM4_R		3
+#define TIM5_R		4
+#define TIM6_R		5
+#define TIM7_R		6
+#define TIM8_R		7
+#define TIM10_R		8
+#define TIM11_R		9
+#define TIM12_R		10
+#define TIM13_R		11
+#define TIM14_R		12
+#define TIM15_R		13
+#define TIM16_R		14
+#define TIM17_R		15
+#define TIM20_R		16
+#define LPTIM1_R	17
+#define LPTIM2_R	18
+#define LPTIM3_R	19
+#define LPTIM4_R	20
+#define LPTIM5_R	21
+#define SPI1_R		22
+#define SPI2_R		23
+#define SPI3_R		24
+#define SPI4_R		25
+#define SPI5_R		26
+#define SPI6_R		27
+#define SPI7_R		28
+#define SPI8_R		29
+#define SPDIFRX_R	30
+#define USART1_R	31
+#define USART2_R	32
+#define USART3_R	33
+#define UART4_R		34
+#define UART5_R		35
+#define USART6_R	36
+#define UART7_R		37
+#define UART8_R		38
+#define UART9_R		39
+#define LPUART1_R	40
+#define IS2M_R		41
+#define I2C1_R		42
+#define I2C2_R		43
+#define I2C3_R		44
+#define I2C4_R		45
+#define I2C5_R		46
+#define I2C6_R		47
+#define I2C7_R		48
+#define I2C8_R		49
+#define SAI1_R		50
+#define SAI2_R		51
+#define SAI3_R		52
+#define SAI4_R		53
+#define MDF1_R		54
+#define MDF2_R		55
+#define FDCAN_R		56
+#define HDP_R		57
+#define ADC12_R		58
+#define ADC3_R		59
+#define ETH1_R		60
+#define ETH2_R		61
+#define USB2_R		62
+#define USB2PHY1_R	63
+#define USB2PHY2_R	64
+#define USB3DR_R	65
+#define USB3PCIEPHY_R	66
+#define USBTC_R		67
+#define ETHSW_R		68
+#define SDMMC1_R	69
+#define SDMMC1DLL_R	70
+#define SDMMC2_R	71
+#define SDMMC2DLL_R	72
+#define SDMMC3_R	73
+#define SDMMC3DLL_R	74
+#define GPU_R		75
+#define LTDC_R		76
+#define DSI_R		77
+#define LVDS_R		78
+#define CSI_R		79
+#define DCMIPP_R	80
+#define CCI_R		81
+#define VDEC_R		82
+#define VENC_R		83
+#define WWDG1_R		84
+#define WWDG2_R		85
+#define VREF_R		86
+#define DTS_R		87
+#define CRC_R		88
+#define SERC_R		89
+#define OSPIIOM_R	90
+#define I3C1_R		91
+#define I3C2_R		92
+#define I3C3_R		93
+#define I3C4_R		94
+#define IWDG2_KER_R	95
+#define IWDG4_KER_R	96
+#define RNG_R		97
+#define PKA_R		98
+#define SAES_R		99
+#define HASH_R		100
+#define CRYP1_R		101
+#define CRYP2_R		102
+#define PCIE_R		103
+#define OSPI1_R		104
+#define OSPI1DLL_R	105
+#define OSPI2_R		106
+#define OSPI2DLL_R	107
+#define FMC_R		108
+#define DBG_R		109
+#define GPIOA_R		110
+#define GPIOB_R		111
+#define GPIOC_R		112
+#define GPIOD_R		113
+#define GPIOE_R		114
+#define GPIOF_R		115
+#define GPIOG_R		116
+#define GPIOH_R		117
+#define GPIOI_R		118
+#define GPIOJ_R		119
+#define GPIOK_R		120
+#define GPIOZ_R		121
+#define HPDMA1_R	122
+#define HPDMA2_R	123
+#define HPDMA3_R	124
+#define LPDMA_R		125
+#define HSEM_R		126
+#define IPCC1_R		127
+#define IPCC2_R		128
+#define C2_HOLDBOOT_R	129
+#define C1_HOLDBOOT_R	130
+#define C1_R		131
+#define C1P1POR_R	132
+#define C1P1_R		133
+#define C2_R		134
+#define C3_R		135
+#define SYS_R		136
+#define VSW_R		137
+#define C1MS_R		138
+#define DDRCP_R		139
+#define DDRCAPB_R	140
+#define DDRPHYCAPB_R	141
+#define DDRCFG_R	142
+#define DDR_R		143
+#define IWDG1_SYS_R	144
+#define IWDG2_SYS_R	145
+#define IWDG3_SYS_R	146
+#define IWDG4_SYS_R	147
+
+#define STM32MP25_LAST_RESET	148
+
+#define RST_SCMI_C1_R		0
+#define RST_SCMI_C2_R		1
+#define RST_SCMI_C1_HOLDBOOT_R	2
+#define RST_SCMI_C2_HOLDBOOT_R	3
+#define RST_SCMI_FMC		4
+#define RST_SCMI_OSPI1		5
+#define RST_SCMI_OSPI1DLL	6
+#define RST_SCMI_OSPI2		7
+#define RST_SCMI_OSPI2DLL	8
+
+#endif /* _DT_BINDINGS_RESET_ST_STM32MP25_RCC_H_ */
diff --git a/core/include/initcall.h b/core/include/initcall.h
index db3d95e2179139e4342d04c847dab71feb145aa8..7de843e728344b743762a2ef2d573a3c4199ccf4 100644
--- a/core/include/initcall.h
+++ b/core/include/initcall.h
@@ -34,8 +34,20 @@ struct initcall {
 			SCATTERED_ARRAY_BEGIN(preinitcall, struct initcall)
 #define preinitcall_end SCATTERED_ARRAY_END(preinitcall, struct initcall)
 
-#define initcall_begin	SCATTERED_ARRAY_BEGIN(initcall, struct initcall)
-#define initcall_end	SCATTERED_ARRAY_END(initcall, struct initcall)
+#define early_initcall_begin \
+			SCATTERED_ARRAY_BEGIN(early_initcall, struct initcall)
+#define early_initcall_end \
+			SCATTERED_ARRAY_END(early_initcall, struct initcall)
+
+#define service_initcall_begin \
+			SCATTERED_ARRAY_BEGIN(service_initcall, struct initcall)
+#define service_initcall_end \
+			SCATTERED_ARRAY_END(service_initcall, struct initcall)
+
+#define driver_initcall_begin \
+			SCATTERED_ARRAY_BEGIN(driver_initcall, struct initcall)
+#define driver_initcall_end \
+			SCATTERED_ARRAY_END(driver_initcall, struct initcall)
 
 #define finalcall_begin	SCATTERED_ARRAY_BEGIN(finalcall, struct initcall)
 #define finalcall_end	SCATTERED_ARRAY_END(finalcall, struct initcall)
@@ -66,9 +78,9 @@ struct initcall {
  *  | At the end of boot_init_primary_late() just before the print:     |
  *  | "Primary CPU switching to normal world boot"                      |
  *  +-------------------------------+-----------------------------------+
- *  | 1. call_preinitcalls()        | In the nexus                      |
+ *  | 1. call_preinitcalls()        | In the nexus, final calls         |
  *  | 2. call_initcalls()           +-----------------------------------+
- *  | 3. call_finalcalls()          | 1. call_finalcalls()              |
+ *  | 3. call_finalcalls()          | 1. boot_final() / nex_*init*()    |
  *  +-------------------------------+-----------------------------------+
  *  | "Primary CPU switching to normal world boot" is printed           |
  *  +-------------------------------+-----------------------------------+
@@ -91,17 +103,46 @@ struct initcall {
 #define preinit(fn)			__define_initcall(preinit, 2, fn)
 #define preinit_late(fn)		__define_initcall(preinit, 3, fn)
 
-#define early_init(fn)			__define_initcall(init, 1, fn)
-#define early_init_late(fn)		__define_initcall(init, 2, fn)
-#define service_init(fn)		__define_initcall(init, 3, fn)
-#define service_init_late(fn)		__define_initcall(init, 4, fn)
-#define driver_init(fn)			__define_initcall(init, 5, fn)
-#define driver_init_late(fn)		__define_initcall(init, 6, fn)
-#define release_init_resource(fn)	__define_initcall(init, 7, fn)
+#define early_init(fn)			__define_initcall(early_init, 1, fn)
+#define early_init_late(fn)		__define_initcall(early_init, 2, fn)
+#define service_init_crypto(fn)		__define_initcall(service_init, 1, fn)
+#define service_init(fn)		__define_initcall(service_init, 2, fn)
+#define service_init_late(fn)		__define_initcall(service_init, 3, fn)
+#define driver_init(fn)			__define_initcall(driver_init, 1, fn)
+#define driver_init_late(fn)		__define_initcall(driver_init, 2, fn)
+#define release_init_resource(fn)	__define_initcall(driver_init, 3, fn)
 
 #define boot_final(fn)			__define_initcall(final, 1, fn)
 
+/*
+ * These nex_* init-calls are provided for drivers and services that reside
+ * in the nexus in case of virtualization. The init-calls are performed
+ * before exiting to the non-secure world at the end of boot
+ * initialization. In case of virtualization the init-calls are based on
+ * final calls, while otherwise are the same as the non-nex counterpart.
+ */
+#ifdef CFG_NS_VIRTUALIZATION
+#define nex_early_init(fn)		boot_final(fn)
+#define nex_early_init_late(fn)		__define_initcall(final, 2, fn)
+#define nex_service_init(fn)		__define_initcall(final, 3, fn)
+#define nex_service_init_late(fn)	__define_initcall(final, 4, fn)
+#define nex_driver_init(fn)		__define_initcall(final, 5, fn)
+#define nex_driver_init_late(fn)	__define_initcall(final, 6, fn)
+#define nex_release_init_resource(fn)	__define_initcall(final, 7, fn)
+#else
+#define nex_early_init(fn)		early_init(fn)
+#define nex_early_init_late(fn)		early_init_late(fn)
+#define nex_service_init(fn)		service_init(fn)
+#define nex_service_init_late(fn)	service_init_late(fn)
+#define nex_driver_init(fn)		driver_init(fn)
+#define nex_driver_init_late(fn)	driver_init_late(fn)
+#define nex_release_init_resource(fn)	release_init_resource(fn)
+#endif
+
 void call_preinitcalls(void);
+void call_early_initcalls(void);
+void call_service_initcalls(void);
+void call_driver_initcalls(void);
 void call_initcalls(void);
 void call_finalcalls(void);
 
diff --git a/core/include/io.h b/core/include/io.h
index 0ef91907b3423cd85da30449db9d31f50c6fecb0..2b4717661096f46843745fe8b86804d89cb24cb4 100644
--- a/core/include/io.h
+++ b/core/include/io.h
@@ -7,6 +7,7 @@
 
 #include <compiler.h>
 #include <kernel/delay.h>
+#include <kernel/delay_arch.h>
 #include <stdint.h>
 #include <types_ext.h>
 #include <utee_defines.h>
@@ -287,14 +288,13 @@ static inline void io_clrsetbits8(vaddr_t addr, uint8_t clear_mask,
  */
 #define IO_READ32_POLL_TIMEOUT(_addr, _val, _cond, _delay_us, _timeout_us) \
 	({ \
-		uint32_t __timeout = 0; \
+		uint64_t __timeout = timeout_init_us(_timeout_us); \
 		uint32_t __delay = (_delay_us); \
 		\
-		while (__timeout < (_timeout_us)) { \
+		while (!timeout_elapsed(__timeout)) { \
 			(_val) = io_read32(_addr); \
 			if (_cond) \
 				break; \
-			__timeout += (__delay); \
 			udelay(__delay); \
 		} \
 		(_val) = io_read32(_addr); \
diff --git a/core/include/kernel/boot.h b/core/include/kernel/boot.h
index bf78d5c3808fffef1911b27388cb0a50d7f28c01..012fdfdf94cf697cf0236ef98bff492942b8eadd 100644
--- a/core/include/kernel/boot.h
+++ b/core/include/kernel/boot.h
@@ -7,6 +7,7 @@
 #define __KERNEL_BOOT_H
 
 #include <initcall.h>
+#include <kernel/dt.h>
 #include <types_ext.h>
 
 /*
@@ -44,7 +45,9 @@ extern const struct core_mmu_config boot_mmu_config;
 
 void boot_init_primary_early(void);
 void boot_init_primary_late(unsigned long fdt, unsigned long manifest);
+void boot_init_primary_final(void);
 void boot_init_memtag(void);
+void boot_clear_memtag(void);
 void boot_save_args(unsigned long a0, unsigned long a1, unsigned long a2,
 		    unsigned long a3, unsigned long a4);
 
@@ -90,9 +93,6 @@ int boot_core_release(size_t core_idx, paddr_t entry);
 struct ns_entry_context *boot_core_hpen(void);
 #endif
 
-/* Returns TOS_FW_CONFIG DTB or SP manifest DTB if present, otherwise NULL */
-void *get_manifest_dt(void);
-
 /*
  * get_aslr_seed() - return a random seed for core ASLR
  *
@@ -100,4 +100,35 @@ void *get_manifest_dt(void);
  */
 unsigned long get_aslr_seed(void);
 
+/* Identify non-secure memory regions for dynamic shared memory */
+void discover_nsec_memory(void);
+/* Add reserved memory for static shared memory in the device-tree */
+int mark_static_shm_as_reserved(struct dt_descriptor *dt);
+
+#ifdef CFG_BOOT_MEM
+/*
+ * Stack-like memory allocations during boot before a heap has been
+ * configured. boot_mem_relocate() performs relocation of the boot memory
+ * and address cells registered with boot_mem_add_reloc() during virtual
+ * memory initialization. Unused memory is unmapped and released to pool of
+ * free physical memory once MMU is initialized.
+ */
+void boot_mem_init(vaddr_t start, vaddr_t end, vaddr_t orig_end);
+void boot_mem_add_reloc(void *ptr);
+void boot_mem_relocate(size_t offs);
+void *boot_mem_alloc(size_t len, size_t align);
+void *boot_mem_alloc_tmp(size_t len, size_t align);
+vaddr_t boot_mem_release_unused(void);
+void boot_mem_release_tmp_alloc(void);
+#else
+static inline void boot_mem_add_reloc(void *ptr __unused) { }
+static inline void *boot_mem_alloc(size_t len __unused, size_t align __unused)
+{ return NULL; }
+static inline void *boot_mem_alloc_tmp(size_t len __unused,
+				       size_t align __unused)
+{ return NULL; }
+static inline vaddr_t boot_mem_release_unused(void) { return 0; }
+static inline void boot_mem_release_tmp_alloc(void) { }
+#endif
+
 #endif /* __KERNEL_BOOT_H */
diff --git a/core/include/kernel/callout.h b/core/include/kernel/callout.h
new file mode 100644
index 0000000000000000000000000000000000000000..07fb2fcb9517e5aa32fc7b07186eb61fe6e5061f
--- /dev/null
+++ b/core/include/kernel/callout.h
@@ -0,0 +1,134 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#ifndef __KERNEL_CALLOUT_H
+#define __KERNEL_CALLOUT_H
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <sys/queue.h>
+
+/*
+ * struct callout - callout reference
+ * @callback:	  function to be called when a callout expires
+ * @expiry_value: callout expiry time counter value
+ * @period:	  ticks to next timeout
+ * @link:	  linked list element
+ *
+ * @callback is called from an interrupt handler so thread resources must
+ * not be used. The main callout service lock is held while @callback is
+ * called so callout_rem() and callout_add() can't be used, but it is safe
+ * to call callout_set_next_timeout() if the call period should be changed.
+ * @callback returns true if it should be called again in @period ticks
+ * or false if the callout should be removed and inactivated. Returning
+ * false from @callback is the equivalent of calling callout_rem() on the
+ * callout reference.
+ */
+struct callout {
+	bool (*callback)(struct callout *co);
+	uint64_t expiry_value;
+	uint64_t period;
+	TAILQ_ENTRY(callout) link;
+};
+
+/*
+ * callout_add() - Add a callout
+ * @co:		callout reference
+ * @callback:	callback function accociated with the callout
+ * @ms:		time to next callout in milliseconds
+ *
+ * Adds a callout to the callout service with an associated callback
+ * function @callback that is to be called in @ms milliseconds.
+ *
+ * If callout_add() is called before callout_service_init() has been called
+ * then it will be called @ms milliseconds after callout_service_init() has
+ * been called.
+ *
+ * The callout structure can reside in global data or on the heap. It's
+ * safe to embed it inside another struct, but it must not be freed until
+ * removed with callout_rem() or equivalent.
+ *
+ * The function takes the main callout service for synchronization so it
+ * can't be called from within a callback function in a callout or there's
+ * deadlock.
+ */
+void callout_add(struct callout *co, bool (*callback)(struct callout *co),
+		 uint32_t ms);
+
+/*
+ * callout_rem() - Remove a callout
+ * @co:		callout reference
+ *
+ * Removes a callout previously added to the callout service with
+ * callout_add(). Note that when the callback function in a callout
+ * returns false the callout is also removed.
+ *
+ * It's safe to try to remove a callback even if it isn't active any
+ * longer. Nothing will happen in that case, but it's guaranteed to be
+ * inactive and it's safe to free the memory after callout_rem() has
+ * returned.
+ */
+void callout_rem(struct callout *co);
+
+/*
+ * callout_set_next_timeout() - set time to next callout
+ * @co:		callout reference
+ * @ms:		time to next callout in milliseconds
+ *
+ * Updates the @co->ticks field with the new number of ticks based on @ms.
+ * This value is used to when to calculate the time of the next callout
+ * following then one already set.
+ *
+ * Must only be called from @co->callback() when the callout is triggered.
+ */
+void callout_set_next_timeout(struct callout *co, uint32_t ms);
+
+/*
+ * struct callout_timer_desc - callout timer descriptor
+ * @disable_timeout:	disables the timer from triggering an interrupt
+ * @set_next_timeout:	sets the next timeout and enables the timer
+ * @ms_to_ticks:	converts milliseconds to ticks, the counter value
+ *			unit
+ * @get_now:		get the current counter value
+ * @is_per_cpu:		flag to indicate if this timer is per CPU (true) or
+ *			global (false).
+ *
+ * This descriptor provides an abstract timer interface first used by
+ * callout_service_init() and then stored to be used by
+ * callout_service_cb().
+ *
+ * When @is_per_cpu is true there is one private timer per CPU so
+ * @disable_timeout() and @set_next_timeout() only affects the timer on the
+ * current CPU. If for instance @set_next_timeout() is called on a new CPU
+ * compared to last time the timer on the old CPU will remain unchanged.
+ * Timer interrupts may trigger based on obsolete configuration, the
+ * callout service is expected to handle this gracefully.
+ */
+struct callout_timer_desc {
+	void (*disable_timeout)(const struct callout_timer_desc *desc);
+	void (*set_next_timeout)(const struct callout_timer_desc *desc,
+				 uint64_t expiry_value);
+	uint64_t (*ms_to_ticks)(const struct callout_timer_desc *desc,
+				uint32_t ms);
+	uint64_t (*get_now)(const struct callout_timer_desc *desc);
+	bool is_per_cpu;
+};
+
+/*
+ * callout_service_init() - Initialize the callout service
+ * @desc:	Pointer to the timer interface
+ *
+ * The callout service is initialized with the supplied timer interface
+ */
+void callout_service_init(const struct callout_timer_desc *desc);
+
+/*
+ * callout_service_cb() - Callout service callback
+ *
+ * Called from interrupt service function for the timer.
+ */
+void callout_service_cb(void);
+
+#endif /*__KERNEL_CALLOUT_H*/
diff --git a/core/include/kernel/delay.h b/core/include/kernel/delay.h
index 6cb72689800ab7425f4970a789fd4b72b8bad444..289d2140f644232d357b9b9461c58462bc55ea9b 100644
--- a/core/include/kernel/delay.h
+++ b/core/include/kernel/delay.h
@@ -33,8 +33,39 @@
 #include <kernel/delay_arch.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <util.h>
 
+#ifdef CFG_CORE_HAS_GENERIC_TIMER
+/* Convert microsecond base delay @us into architecture time tick counts */
+static inline uint64_t delay_us2cnt(uint32_t us)
+{
+	return ((uint64_t)us * (uint64_t)delay_cnt_freq()) / ULL(1000000);
+}
+
+/* Return delay tick counter for a timeout expiration in @us microseconds */
+static inline uint64_t timeout_init_us(uint32_t us)
+{
+	return delay_cnt_read() + delay_us2cnt(us);
+}
+
+/* Check if timeout tick counter @expire from timeout_init_us() has expired */
+
+static inline bool timeout_elapsed(uint64_t expire)
+{
+	return delay_cnt_read() >= expire;
+}
+
+/*
+ * Return the time in microseconds since/until timeout tick counter @expired,
+ * that was initialized with timeout_init_us() or like, has/will expire.
+ * A positive value means the timeout has expired and a negative one it has not.
+ */
+int timeout_elapsed_us(uint64_t expire);
+#endif /*CFG_CORE_HAS_GENERIC_TIMER*/
+
+/* Wait @us microseconds actively polling on architecture timer */
 void udelay(uint32_t us);
-void mdelay(uint32_t ms);
 
+/* Wait @ms milliseconds actively polling on architecture timer */
+void mdelay(uint32_t ms);
 #endif
diff --git a/core/include/kernel/dt.h b/core/include/kernel/dt.h
index ad5cde23ab97bcbf2d9c36d654f4dfc615eafdf9..275517eb345b37568c738bc94c35d2ab5c65cb58 100644
--- a/core/include/kernel/dt.h
+++ b/core/include/kernel/dt.h
@@ -86,6 +86,7 @@ struct dt_descriptor {
 
 extern uint8_t embedded_secure_dtb[];
 
+#ifdef CFG_DT
 /*
  * dt_getprop_as_number() - get a DT property a unsigned number
  * @fdt: DT base address
@@ -100,7 +101,6 @@ extern uint8_t embedded_secure_dtb[];
 int dt_getprop_as_number(const void *fdt, int nodeoffset, const char *name,
 			 uint64_t *num);
 
-#ifdef CFG_DT
 /*
  * Find a driver that is suitable for the given DT node, that is, with
  * a matching "compatible" property.
@@ -174,6 +174,17 @@ paddr_t fdt_reg_base_address(const void *fdt, int offs);
  */
 size_t fdt_reg_size(const void *fdt, int offs);
 
+/*
+ * Read the base address and/or reg size for the "reg" property of the
+ * specified node.
+ * @fdt: Reference to the Device Tree
+ * @offs: Offset to the node to read "reg" property from
+ * @base: Pointer to the output base address value, or NULL
+ * @size: Pointer to the output size value, or NULL
+ * Returns 0 on success and a negative FDT error value in case of failure
+ */
+int fdt_reg_info(const void *fdt, int offs, paddr_t *base, size_t *size);
+
 /*
  * Read the status and secure-status properties into a bitfield.
  * Return -1 on failure, DT_STATUS_DISABLED if the node is disabled,
@@ -237,7 +248,10 @@ int fdt_get_reg_props_by_index(const void *fdt, int node, int index,
 int fdt_get_reg_props_by_name(const void *fdt, int node, const char *name,
 			      paddr_t *base, size_t *size);
 
-/* Returns embedded DTB if present, then external DTB if found, then NULL */
+/*
+ * Returns embedded DTB if present, then external DTB if found,
+ * then manifest DTB if found, then NULL.
+ */
 void *get_dt(void);
 
 /*
@@ -247,7 +261,8 @@ void *get_dt(void);
  *
  * 1. Returns embedded DTB if available,
  * 2. Secure external DTB if available,
- * 3. If neither then NULL
+ * 3. Manifest DTB if available,
+ * 4. If neither then NULL
  */
 void *get_secure_dt(void);
 
@@ -302,6 +317,24 @@ int add_dt_path_subnode(struct dt_descriptor *dt, const char *path,
 int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name,
 			paddr_t pa, size_t size);
 
+/*
+ * init_manifest_dt() - Initialize the manifest DTB to given address.
+ * @fdt:	Physical address where the manifest DTB located.
+ *
+ * Initialize the manifest DTB to physical address
+ */
+void init_manifest_dt(void *fdt);
+
+/*
+ * reinit_manifest_dt() - Reinitialize the manifest DTB
+ *
+ * Add MMU mapping of the manifest DTB and initialize device tree overlay
+ */
+void reinit_manifest_dt(void);
+
+/* Returns TOS_FW_CONFIG DTB or SP manifest DTB if present, otherwise NULL */
+void *get_manifest_dt(void);
+
 #else /* !CFG_DT */
 
 static inline const struct dt_driver *dt_find_compatible_driver(
@@ -330,6 +363,12 @@ static inline size_t fdt_reg_size(const void *fdt __unused,
 	return (size_t)-1;
 }
 
+static inline int fdt_reg_info(const void *fdt __unused, int offs __unused,
+			       paddr_t *base __unused, size_t *size __unused)
+{
+	return -1;
+}
+
 static inline int fdt_get_status(const void *fdt __unused, int offs __unused)
 {
 	return -1;
@@ -395,6 +434,14 @@ static inline int fdt_get_reg_props_by_name(const void *fdt __unused,
 	return -1;
 }
 
+static inline int dt_getprop_as_number(const void *fdt __unused,
+				       int nodeoffset __unused,
+				       const char *name __unused,
+				       uint64_t *num __unused)
+{
+	return -1;
+}
+
 static inline void *get_dt(void)
 {
 	return NULL;
@@ -445,5 +492,72 @@ static inline int add_res_mem_dt_node(struct dt_descriptor *dt __unused,
 	return -1;
 }
 
+static inline void init_manifest_dt(void *fdt __unused)
+{
+}
+
+static inline void reinit_manifest_dt(void)
+{
+}
+
+static inline void *get_manifest_dt(void)
+{
+	return NULL;
+}
+
 #endif /* !CFG_DT */
+
+#ifdef CFG_DT_CACHED_NODE_INFO
+/*
+ * Find the offset of a parent node in the parent node cache
+ * @fdt: FDT to work on
+ * @node_offset: Offset of the node we look for its parent
+ * @parent_offset: Output parent node offset upon success
+ * @return 0 on success and -1 on failure
+ */
+int fdt_find_cached_parent_node(const void *fdt, int node_offset,
+				int *parent_offset);
+
+/*
+ * Find the address/size cells value of a parent node in the parent node cache
+ * @fdt: FDT to work on
+ * @node_offset: Offset of the node we look for its parent
+ * @address_cells: Pointer to output #address-cells value upon success or NULL
+ * @size_cells: Pointer to output #size-cells value upon success or NULL
+ * @return 0 on success and -FDT_ERR_NOTFOUND on failure
+ */
+int fdt_find_cached_parent_reg_cells(const void *fdt, int node_offset,
+				     int *address_cells, int *size_cells);
+/*
+ * Find the node offset from its phandle in the phandle cache
+ * @fdt: FDT to work on
+ * @phandle: Node phandle
+ * @node_offset: Pointer to output node offset upon success
+ * @return 0 on success and -FDT_ERR_NOTFOUND on failure
+ */
+int fdt_find_cached_node_phandle(const void *fdt, uint32_t phandle,
+				 int *node_offset);
+#else
+static inline int fdt_find_cached_parent_node(const void *fdt __unused,
+					      int node_offset __unused,
+					      int *parent_offset __unused)
+{
+	return -1;
+}
+
+static inline int fdt_find_cached_parent_reg_cells(const void *fdt __unused,
+						   int node_offset __unused,
+						   int *address_cells __unused,
+						   int *size_cells __unused)
+{
+	return -1;
+}
+
+static inline int fdt_find_cached_node_phandle(const void *fdt __unused,
+					       uint32_t phandle __unused,
+					       int *node_offset __unused)
+{
+	return -1;
+}
+#endif /* CFG_DT_CACHED_NODE_INFO */
 #endif /* __KERNEL_DT_H */
diff --git a/core/include/kernel/dt_driver.h b/core/include/kernel/dt_driver.h
index f73f30073acff86a635330e3788b8d985f9e406b..6a04fcdfe212decb1fb7268b6a4d689a66d0ae2f 100644
--- a/core/include/kernel/dt_driver.h
+++ b/core/include/kernel/dt_driver.h
@@ -26,6 +26,7 @@
  * DT_DRIVER_INTERRUPT Interrupt controller using generic DT bindings
  * DT_DRIVER_REGULATOR Voltage regulator controller using generic DT bindings
  * DT_DRIVER_NVMEM NVMEM controller using generic NVMEM DT bindings
+ * DT_DRIVER_FIREWALL Firewall controller using generic DT bindings
  */
 enum dt_driver_type {
 	DT_DRIVER_NOTYPE,
@@ -38,6 +39,7 @@ enum dt_driver_type {
 	DT_DRIVER_INTERRUPT,
 	DT_DRIVER_REGULATOR,
 	DT_DRIVER_NVMEM,
+	DT_DRIVER_FIREWALL,
 };
 
 /*
@@ -87,12 +89,14 @@ struct dt_driver_provider;
  * struct dt_pargs - Devicetree phandle arguments
  * @fdt: Device-tree to work on
  * @phandle_node: Node pointed by the specifier phandle
+ * @consumer_node: Node of the consumer requesting this device
  * @args_count: Count of cells for the device
  * @args: Device consumer specifiers
  */
 struct dt_pargs {
 	const void *fdt;
 	int phandle_node;
+	int consumer_node;
 	int args_count;
 	uint32_t args[];
 };
diff --git a/core/include/kernel/huk_subkey.h b/core/include/kernel/huk_subkey.h
index f8e876b17f299600a5acf916afb8701f93d52c7d..c8c5f9fa1fb07a253f8d7c44a423fce3b36296ea 100644
--- a/core/include/kernel/huk_subkey.h
+++ b/core/include/kernel/huk_subkey.h
@@ -53,7 +53,7 @@ enum huk_subkey_usage {
  * implementation.
  * __huk_subkey_derive() implements the default behavior of HUK derivation.
  *
- * Return TEE_SUCCES on success or an error code on failure.
+ * Return TEE_SUCCESS on success or an error code on failure.
  */
 TEE_Result huk_subkey_derive(enum huk_subkey_usage usage,
 			     const void *const_data, size_t const_data_len,
diff --git a/core/include/kernel/interrupt.h b/core/include/kernel/interrupt.h
index 22a7a044945b5c353e1e18ff25a0b8f20997ef91..2b0a51d1875feef8d07dced8882cde2c87f3cb5b 100644
--- a/core/include/kernel/interrupt.h
+++ b/core/include/kernel/interrupt.h
@@ -474,7 +474,7 @@ TEE_Result interrupt_register_provider(const void *fdt, int node,
  *
  * @fdt		Device tree to work on
  * @node	Node offset of the subnode containing interrupt(s) references
- * @index	Index in "interrupts" or "extended-interrupts" property list
+ * @index	Index in "interrupts" or "interrupts-extended" property list
  * @chip	Output interrupt controller reference upon success
  * @itr_num	Output interrupt number upon success
  *
@@ -533,7 +533,7 @@ static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused,
 
 /*
  * Helper function for when caller retrieves the first interrupt defined
- * in "interrupts" or "extended-interrupts" DT binding property list.
+ * in "interrupts" or "interrupts-extended" DT binding property list.
  */
 static inline TEE_Result interrupt_dt_get(const void *fdt, int node,
 					  struct itr_chip **chip,
diff --git a/core/include/kernel/linker.h b/core/include/kernel/linker.h
index 949ffd8cba6e87af103003560661aff567e80308..5a2c917ed0e2e5320e3325eafd1731c9f9b1a258 100644
--- a/core/include/kernel/linker.h
+++ b/core/include/kernel/linker.h
@@ -46,6 +46,18 @@ extern const uint8_t __extab_end[];
 
 #define VCORE_START_VA		((vaddr_t)__text_start)
 
+#ifndef CFG_WITH_PAGER
+#define VCORE_FREE_PA		((unsigned long)__vcore_free_start)
+#define VCORE_FREE_SZ		((size_t)(__vcore_free_end - \
+					  __vcore_free_start))
+#define VCORE_FREE_END_PA	((unsigned long)__vcore_free_end)
+#else
+/* No VCORE_FREE range in pager configuration since it uses all memory */
+#define VCORE_FREE_PA		PADDR_MAX
+#define VCORE_FREE_SZ		0
+#define VCORE_FREE_END_PA	PADDR_MAX
+#endif
+
 #define EMIT_SECTION_INFO_SYMBOLS(section_name) \
 	extern const uint8_t __vcore_ ## section_name ## _start[]; \
 	extern const uint8_t __vcore_ ## section_name ## _end[]; \
@@ -57,6 +69,7 @@ EMIT_SECTION_INFO_SYMBOLS(unpg_rw);
 EMIT_SECTION_INFO_SYMBOLS(nex_rw);
 EMIT_SECTION_INFO_SYMBOLS(init_ro);
 EMIT_SECTION_INFO_SYMBOLS(init_rx);
+EMIT_SECTION_INFO_SYMBOLS(free);
 
 #undef EMIT_SECTION_INFO_SYMBOLS
 
diff --git a/core/include/kernel/msg_param.h b/core/include/kernel/msg_param.h
index 2cf3da657d39901a4c7dcfca241bb8a3feb5d5b7..d840dfae14e795d75f42cea0db6f52e98ffe9f8d 100644
--- a/core/include/kernel/msg_param.h
+++ b/core/include/kernel/msg_param.h
@@ -30,7 +30,6 @@
 #define __KERNEL_MSG_PARAM_H
 
 #include <compiler.h>
-#include <kernel/msg_param.h>
 #include <mm/mobj.h>
 #include <optee_msg.h>
 #include <stdio.h>
diff --git a/core/include/kernel/mutex.h b/core/include/kernel/mutex.h
index c701188d79c274ceb7185f76443d86253baf43fd..72d60f0eb14ddce4bc8593a086fd0b9bd67f312a 100644
--- a/core/include/kernel/mutex.h
+++ b/core/include/kernel/mutex.h
@@ -77,7 +77,7 @@ void mutex_lock_recursive(struct recursive_mutex *m);
 #endif
 
 struct condvar {
-	unsigned spin_lock;
+	unsigned int spin_lock;
 	struct mutex *m;
 };
 #define CONDVAR_INITIALIZER { .m = NULL }
@@ -95,11 +95,36 @@ void condvar_broadcast_debug(struct condvar *cv, const char *fname, int lineno);
 void condvar_wait_debug(struct condvar *cv, struct mutex *m,
 			const char *fname, int lineno);
 #define condvar_wait(cv, m) condvar_wait_debug((cv), (m), __FILE__, __LINE__)
+
+/*
+ * Return TEE_ERROR_TIMEOUT if the normal world returns before
+ * the condvar has been signaled.
+ */
+TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m,
+				      uint32_t timeout_ms, const char *fname,
+				      int lineno);
+#define condvar_wait_timeout(cv, m, timeout_ms) \
+	condvar_wait_timeout_debug((cv), (m), (timeout_ms), __FILE__, __LINE__)
 #else
 void condvar_signal(struct condvar *cv);
 void condvar_broadcast(struct condvar *cv);
 void condvar_wait(struct condvar *cv, struct mutex *m);
+/*
+ * Return TEE_ERROR_TIMEOUT if the normal world returns before
+ * the condvar has been signaled.
+ */
+TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m,
+				uint32_t timeout_ms);
 #endif
 
+/*
+ * Helper for testing that a given mutex is locked for writing. This helper
+ * is to be used with caution since it does not guarantee that the executing
+ * thread is holding the mutex.
+ */
+static inline bool mutex_is_locked(struct mutex *m)
+{
+	return m->state == -1; /* write locked */
+}
 #endif /*__KERNEL_MUTEX_H*/
 
diff --git a/core/include/kernel/mutex_pm_aware.h b/core/include/kernel/mutex_pm_aware.h
new file mode 100644
index 0000000000000000000000000000000000000000..1345feb527559a04cf927cc6143e8204a8db4d35
--- /dev/null
+++ b/core/include/kernel/mutex_pm_aware.h
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+#ifndef __KERNEL_MUTEX_PM_AWARE_H
+#define __KERNEL_MUTEX_PM_AWARE_H
+
+#include <kernel/mutex.h>
+#include <kernel/spinlock.h>
+
+/*
+ * struct mutex_pm_aware - Mutex usable in PM atomic sequence
+ *
+ * Some resources need a mutex protection for runtime operations but are
+ * also accessed during specific system power transition (PM power off,
+ * suspend and resume) that operate in atomic execution environment where
+ * non-secure world is not operational, for example in fastcall SMC entries
+ * of the PSCI services. In such case we cannot take a mutex and we expect
+ * the mutex is unlocked. Additionally a spinning lock is attempted to be
+ * locked to check the resource access consistency.
+ *
+ * Core intentionally panics in case of unexpected resource access contention:
+ * - When a thread requests a mutex held by a non-thread context;
+ * - When a non-thread context requests a mutex held by a thread;
+ * - When a non-thread context requests a mutex held by a non-thread context.
+ */
+struct mutex_pm_aware {
+	struct mutex mutex;	/* access protection in thread context */
+	unsigned int lock;	/* access consistency in PM context */
+};
+
+#define MUTEX_PM_AWARE_INITIALIZER { \
+		.mutex = MUTEX_INITIALIZER, \
+		.lock = SPINLOCK_UNLOCK, \
+	}
+
+void mutex_pm_aware_init(struct mutex_pm_aware *m);
+void mutex_pm_aware_destroy(struct mutex_pm_aware *m);
+void mutex_pm_aware_lock(struct mutex_pm_aware *m);
+void mutex_pm_aware_unlock(struct mutex_pm_aware *m);
+
+#endif /*__KERNEL_MUTEX_PM_AWARE_H*/
+
diff --git a/core/include/kernel/notif.h b/core/include/kernel/notif.h
index 71b53d8eaccb025370acf976a107fab3f943c01e..d0ca1ee50c0c0a15b799584eef872971b6b7a6b0 100644
--- a/core/include/kernel/notif.h
+++ b/core/include/kernel/notif.h
@@ -64,6 +64,7 @@ enum notif_event {
 	NOTIF_EVENT_STARTED,
 	NOTIF_EVENT_DO_BOTTOM_HALF,
 	NOTIF_EVENT_STOPPED,
+	NOTIF_EVENT_SHUTDOWN,
 };
 
 /*
@@ -78,21 +79,27 @@ enum notif_event {
  * A atomic context means that interrupts are masked and a common spinlock
  * is held. Calls via @atomic_cb are only atomic with regards to each
  * other, other CPUs may execute yielding calls or even receive interrupts.
+ * If CFG_NS_VIRTUALIZATION=y then code is executing in Nexus context
+ * without a partition activated, the @guest_id triggering the event is
+ * instead supplied as an argument to the callback. The @guest_id should be
+ * ignored if CFG_NS_VIRTUALIZATION isn't enabled.
  *
  * A yielding context means that the function is executing in a normal
  * threaded context allowing RPC and synchronization with other thread
- * using mutexes and condition variables.
+ * using mutexes and condition variables. If CFG_NS_VIRTUALIZATION=y then
+ * is a partition matching the guest or VM that triggered the event.
  */
 struct notif_driver {
-	void (*atomic_cb)(struct notif_driver *ndrv, enum notif_event ev);
+	void (*atomic_cb)(struct notif_driver *ndrv, enum notif_event ev,
+			  uint16_t guest_id);
 	void (*yielding_cb)(struct notif_driver *ndrv, enum notif_event ev);
 	SLIST_ENTRY(notif_driver) link;
 };
 
 #if defined(CFG_CORE_ASYNC_NOTIF)
-bool notif_async_is_started(void);
+bool notif_async_is_started(uint16_t guest_id);
 #else
-static inline bool notif_async_is_started(void)
+static inline bool notif_async_is_started(uint16_t guest_id __unused)
 {
 	return false;
 }
@@ -106,13 +113,19 @@ void notif_free_async_value(uint32_t value);
  */
 TEE_Result notif_wait(uint32_t value);
 
+/*
+ * Wait timeout in normal world for a value to be sent by notif_send()
+ */
+TEE_Result notif_wait_timeout(uint32_t value, uint32_t timeout_ms);
+
 /*
  * Send an asynchronous value, note that it must be <= NOTIF_ASYNC_VALUE_MAX
  */
 #if defined(CFG_CORE_ASYNC_NOTIF)
-void notif_send_async(uint32_t value);
+void notif_send_async(uint32_t value, uint16_t guest_id);
 #else
-static inline void notif_send_async(uint32_t value __unused)
+static inline void notif_send_async(uint32_t value __unused,
+				    uint16_t guest_id __unused)
 {
 }
 #endif
@@ -152,17 +165,14 @@ static inline uint32_t notif_get_value(bool *value_valid, bool *value_pending)
 }
 #endif
 
-/*
- * These are called from yielding calls
- */
 #if defined(CFG_CORE_ASYNC_NOTIF)
-void notif_deliver_atomic_event(enum notif_event ev);
+void notif_deliver_atomic_event(enum notif_event ev, uint16_t guest_id);
 void notif_deliver_event(enum notif_event ev);
 #else
-static inline void notif_deliver_atomic_event(enum notif_event ev __unused)
+static inline void notif_deliver_atomic_event(enum notif_event ev __unused,
+					      uint16_t guest_id __unused)
 {
 }
-
 static inline void notif_deliver_event(enum notif_event ev __unused)
 {
 }
diff --git a/core/include/kernel/pm.h b/core/include/kernel/pm.h
index 2badce965ecb20d648a9bbaa8904c6f120a308f9..3f40de03d6b3cc0ae6c59711c0edb1b40a22e14b 100644
--- a/core/include/kernel/pm.h
+++ b/core/include/kernel/pm.h
@@ -20,6 +20,7 @@
  * PM_HINT_POWER_STATE - When set device power shall be suspended/restored
  * PM_HINT_IO_STATE - When set IO pins shall be suspended/restored
  * PM_HINT_CONTEXT_STATE - When set the full context be suspended/restored
+ * PM_HINT_SUSPEND_TYPE - Contains the type of suspend operation
  * PM_HINT_PLATFORM_STATE_MASK - Bit mask reserved for platform specific hints
  * PM_HINT_PLATFORM_STATE_SHIFT - LSBit position of platform specific hints mask
  */
@@ -27,9 +28,25 @@
 #define PM_HINT_POWER_STATE		BIT(1)
 #define PM_HINT_IO_STATE		BIT(2)
 #define PM_HINT_CONTEXT_STATE		BIT(3)
+#define PM_HINT_SUSPEND_TYPE_MASK       GENMASK_32(5, 4)
+#define PM_HINT_SUSPEND_TYPE_SHIFT      U(4)
 #define PM_HINT_PLATFORM_STATE_MASK	GENMASK_32(31, 16)
 #define PM_HINT_PLATFORM_STATE_SHIFT	U(16)
 
+enum pm_suspend_type {
+	PM_SUSPEND_STANDBY,
+	PM_SUSPEND_TO_MEM,
+};
+
+#define PM_HINT_SUSPEND_TYPE(__hint) \
+	(((__hint) & PM_HINT_SUSPEND_TYPE_MASK) >> PM_HINT_SUSPEND_TYPE_SHIFT)
+
+#define PM_HINT_STATE(_x)		((_x) & ~PM_HINT_PLATFORM_STATE_MASK)
+#define PM_HINT_PLATFORM_STATE(_x) \
+	(((_x) & PM_HINT_PLATFORM_STATE_MASK) >> PM_HINT_PLATFORM_STATE_SHIFT)
+
+#define PM_HINT_IS_STATE(_x, _name) ((_x) & PM_HINT_ ## _name ## _STATE)
+
 /*
  * PM_OP_SUSPEND: platform is suspending to a target low power state
  * PM_OP_RESUME: platform is resuming from low power state
@@ -122,6 +139,19 @@ struct pm_callback_handle {
  */
 void register_pm_cb(struct pm_callback_handle *pm_handle);
 
+/*
+ * Unregister a previously registered PM callback handle
+ * Refer to struct pm_callback_handle for description of the callbacks
+ * API and the registration directives.
+ *
+ * @pm_handle: Reference previously registered
+ *
+ * This function removes from the list of the PM called callbacks the
+ * entry that match callback function reference and private handle and
+ * PM order (PM_CB_ORDER_*).
+ */
+void unregister_pm_cb(struct pm_callback_handle *pm_handle);
+
 /*
  * Register a driver callback for generic suspend/resume.
  * Refer to struct pm_callback_handle for description of the callbacks
@@ -139,6 +169,19 @@ static inline void register_pm_driver_cb(pm_callback callback, void *handle,
 						       name));
 }
 
+/*
+ * Unregister a driver callback from generic suspend/resume sequence.
+ *
+ * @callback: Callback function that what registered
+ * @handle: Private handle argument that was registered for the callback
+ */
+static inline void unregister_pm_driver_cb(pm_callback callback, void *handle)
+{
+	unregister_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle,
+							 PM_CB_ORDER_DRIVER,
+							 NULL));
+}
+
 /*
  * Register a core service callback for generic suspend/resume.
  * Refer to struct pm_callback_handle for description of the callbacks
@@ -152,8 +195,23 @@ static inline void register_pm_core_service_cb(pm_callback callback,
 					       void *handle, const char *name)
 {
 	register_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle,
-						PM_CB_ORDER_CORE_SERVICE,
-						name));
+						       PM_CB_ORDER_CORE_SERVICE,
+						       name));
+}
+
+/*
+ * Unregister a core service callback from generic suspend/resume sequences
+ *
+ * @callback: Registered callback function
+ * @handle: Private handle argument that was registered for the callback
+ */
+static inline void unregister_pm_core_service_cb(pm_callback callback,
+						 void *handle)
+{
+	enum pm_callback_order order = PM_CB_ORDER_CORE_SERVICE;
+
+	unregister_pm_cb(&PM_CALLBACK_HANDLE_INITIALIZER(callback, handle,
+							 order, NULL));
 }
 
 /*
diff --git a/core/include/kernel/pseudo_ta.h b/core/include/kernel/pseudo_ta.h
index 965ca0d4364d4bfcdfa25f5fa96149907460b71a..4eef0f47da9ae50e54c0819e59854f6472c43ef4 100644
--- a/core/include/kernel/pseudo_ta.h
+++ b/core/include/kernel/pseudo_ta.h
@@ -59,6 +59,13 @@ static inline struct pseudo_ta_ctx *to_pseudo_ta_ctx(struct ts_ctx *ctx)
 	return container_of(ctx, struct pseudo_ta_ctx, ctx.ts_ctx);
 }
 
+/*
+ * Setup session context for a pseudo TA
+ * @uuid: Pseudo TA UUID
+ * @s: Session for which to setup a pseudo TA context
+ *
+ * This function must be called with tee_ta_mutex locked.
+ */
 TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
 			struct tee_ta_session *s);
 
diff --git a/core/include/kernel/semihosting.h b/core/include/kernel/semihosting.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed81a51450ce8abcf2c94f46396052481ea37c73
--- /dev/null
+++ b/core/include/kernel/semihosting.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+#ifndef __KERNEL_SEMIHOSTING_H
+#define __KERNEL_SEMIHOSTING_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/fcntl.h>
+#include <util.h>
+
+/* Perform architecture-specific semihosting instructions. */
+uintptr_t __do_semihosting(uintptr_t op, uintptr_t arg);
+
+char semihosting_sys_readc(void);
+void semihosting_sys_writec(char c);
+int semihosting_open(const char *fname, int flags);
+size_t semihosting_read(int fd, void *ptr, size_t len);
+size_t semihosting_write(int fd, const void *ptr, size_t len);
+int semihosting_close(int fd);
+
+#endif /* __KERNEL_SEMIHOSTING_H */
diff --git a/core/include/kernel/spinlock.h b/core/include/kernel/spinlock.h
index e7a84d32b678f404e81d0ee726803457a17118df..c43141535645b883babc0307822743dd99192c9a 100644
--- a/core/include/kernel/spinlock.h
+++ b/core/include/kernel/spinlock.h
@@ -13,8 +13,8 @@
 #ifndef __ASSEMBLER__
 #include <assert.h>
 #include <compiler.h>
-#include <stdbool.h>
 #include <kernel/thread.h>
+#include <stdbool.h>
 
 #ifdef CFG_TEE_CORE_DEBUG
 void spinlock_count_incr(void);
@@ -42,6 +42,28 @@ static inline void cpu_spin_lock_no_dldetect(unsigned int *lock)
 	spinlock_count_incr();
 }
 
+static inline bool thread_spin_trylock(unsigned int *lock)
+{
+	assert(thread_get_id_may_fail() != THREAD_ID_INVALID);
+	return !__cpu_spin_trylock(lock);
+}
+
+/*
+ * To be used with lot of care: it is not recommended to spin in a thread
+ * context without masking foreign interrupts
+ */
+static inline void thread_spin_lock(unsigned int *lock)
+{
+	assert(thread_get_id_may_fail() != THREAD_ID_INVALID);
+	__cpu_spin_lock(lock);
+}
+
+static inline void thread_spin_unlock(unsigned int *lock)
+{
+	assert(thread_get_id_may_fail() != THREAD_ID_INVALID);
+	__cpu_spin_unlock(lock);
+}
+
 #ifdef CFG_TEE_CORE_DEBUG
 #define cpu_spin_lock(lock) \
 	cpu_spin_lock_dldetect(__func__, __LINE__, lock)
@@ -93,7 +115,8 @@ static inline void cpu_spin_unlock(unsigned int *lock)
 	spinlock_count_decr();
 }
 
-static inline uint32_t cpu_spin_lock_xsave_no_dldetect(unsigned int *lock)
+static inline uint32_t __must_check
+cpu_spin_lock_xsave_no_dldetect(unsigned int *lock)
 {
 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
 
@@ -105,9 +128,9 @@ static inline uint32_t cpu_spin_lock_xsave_no_dldetect(unsigned int *lock)
 #define cpu_spin_lock_xsave(lock) \
 	cpu_spin_lock_xsave_dldetect(__func__, __LINE__, lock)
 
-static inline uint32_t cpu_spin_lock_xsave_dldetect(const char *func,
-						    const int line,
-						    unsigned int *lock)
+static inline uint32_t __must_check
+cpu_spin_lock_xsave_dldetect(const char *func, const int line,
+			     unsigned int *lock)
 {
 	uint32_t exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
 
@@ -115,7 +138,7 @@ static inline uint32_t cpu_spin_lock_xsave_dldetect(const char *func,
 	return exceptions;
 }
 #else
-static inline uint32_t cpu_spin_lock_xsave(unsigned int *lock)
+static inline uint32_t __must_check cpu_spin_lock_xsave(unsigned int *lock)
 {
 	return cpu_spin_lock_xsave_no_dldetect(lock);
 }
diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h
index 8cae35002e19df258cd6613860dfeb5e688703ca..2aa467a5c2d48d5b1c7236ecc16eddb4c659fb07 100644
--- a/core/include/kernel/tee_ta_manager.h
+++ b/core/include/kernel/tee_ta_manager.h
@@ -73,6 +73,7 @@ struct tee_ta_ctx {
 	uint32_t panic_code;	/* Code supplied for panic */
 	uint32_t ref_count;	/* Reference counter for multi session TA */
 	bool busy;		/* Context is busy and cannot be entered */
+	bool is_initializing;	/* Context initialization is not completed */
 	bool is_releasing;	/* Context is about to be released */
 	struct condvar busy_cv;	/* CV used when context is busy */
 };
diff --git a/core/include/kernel/thread.h b/core/include/kernel/thread.h
index b7f497e1091188582bb56493eaa1077831e25ab5..21285d880c808d646f0a81ad2d9d7507a92a5d52 100644
--- a/core/include/kernel/thread.h
+++ b/core/include/kernel/thread.h
@@ -60,14 +60,6 @@ static inline void thread_update_canaries(void) { }
 
 struct thread_core_local *thread_get_core_local(void);
 
-/*
- * Sets the stacks to be used by the different threads. Use THREAD_ID_0 for
- * first stack, THREAD_ID_0 + 1 for the next and so on.
- *
- * Returns true on success and false on errors.
- */
-bool thread_init_stack(uint32_t stack_id, vaddr_t sp);
-
 /*
  * Initializes thread contexts. Called in thread_init_boot_thread() if
  * virtualization is disabled. Virtualization subsystem calls it for
@@ -252,7 +244,9 @@ bool thread_is_in_normal_mode(void);
 bool thread_is_from_abort_mode(void);
 
 /**
- * Allocates data for payload buffers.
+ * Allocates data for payload buffers shared with a non-secure user space
+ * application. Ensure consistency with the enumeration
+ * THREAD_SHM_TYPE_APPLICATION.
  *
  * @size:	size in bytes of payload buffer
  *
@@ -268,7 +262,8 @@ struct mobj *thread_rpc_alloc_payload(size_t size);
 void thread_rpc_free_payload(struct mobj *mobj);
 
 /**
- * Allocate data for payload buffers only shared with the non-secure kernel
+ * Allocate data for payload buffers shared with the non-secure kernel.
+ * Ensure consistency with the enumeration THREAD_SHM_TYPE_KERNEL_PRIVATE.
  *
  * @size:	size in bytes of payload buffer
  *
@@ -341,8 +336,9 @@ uint32_t thread_rpc_cmd(uint32_t cmd, size_t num_params,
 		struct thread_param *params);
 
 /**
- * Allocate data for payload buffers.
- * Buffer is exported to user mode applications.
+ * Allocate data for payload buffers shared with both user space applications
+ * and the non-secure kernel. Ensure consistency with the enumeration
+ * THREAD_SHM_TYPE_GLOBAL.
  *
  * @size:	size in bytes of payload buffer
  *
@@ -375,6 +371,7 @@ enum thread_shm_type {
  * @THREAD_SHM_CACHE_USER_SOCKET - socket communication
  * @THREAD_SHM_CACHE_USER_FS - filesystem access
  * @THREAD_SHM_CACHE_USER_I2C - I2C communication
+ * @THREAD_SHM_CACHE_USER_RPMB - RPMB communication
  *
  * To ensure that each user of the shared memory cache doesn't interfere
  * with each other a unique ID per user is used.
@@ -383,6 +380,7 @@ enum thread_shm_cache_user {
 	THREAD_SHM_CACHE_USER_SOCKET,
 	THREAD_SHM_CACHE_USER_FS,
 	THREAD_SHM_CACHE_USER_I2C,
+	THREAD_SHM_CACHE_USER_RPMB,
 };
 
 /*
diff --git a/core/include/kernel/time_source.h b/core/include/kernel/time_source.h
deleted file mode 100644
index e02f98432a320f2012315ac6ab9ea7d2838f0ef2..0000000000000000000000000000000000000000
--- a/core/include/kernel/time_source.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-/*
- * Copyright (c) 2014, Linaro Limited
- */
-#ifndef __KERNEL_TIME_SOURCE_H
-#define __KERNEL_TIME_SOURCE_H
-
-#include <kernel/tee_time.h>
-
-struct time_source {
-	const char *name;
-	uint32_t protection_level;
-	TEE_Result (*get_sys_time)(TEE_Time *time);
-};
-void time_source_init(void);
-
-#define REGISTER_TIME_SOURCE(source)	\
-	void time_source_init(void) { \
-		_time_source = source; \
-	}
-
-extern struct time_source _time_source;
-#endif /*__KERNEL_TIME_SOURCE_H*/
diff --git a/core/include/kernel/timer.h b/core/include/kernel/timer.h
index 19abd115bd376a91dbd9620fc0f1b91b787cbb49..1638a4ac176d7cf40ef9b07f94000aa8adebb1dc 100644
--- a/core/include/kernel/timer.h
+++ b/core/include/kernel/timer.h
@@ -1,15 +1,34 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
 /*
- * Copyright (C) 2018, Linaro Limited
+ * Copyright (C) 2018, 2024, Linaro Limited
  */
 
 #ifndef __KERNEL_TIMER_H
 #define __KERNEL_TIMER_H
 
+#include <kernel/interrupt.h>
+#include <types_ext.h>
+
 void generic_timer_start(uint32_t time_ms);
 void generic_timer_stop(void);
 
 /* Handler for timer expiry interrupt */
 void generic_timer_handler(uint32_t time_ms);
 
+/*
+ * timer_init_callout_service() - Initializes the callout service
+ * @itr_chip:	Interrupt chip, typically interrupt_get_main_chip()
+ * @itr_number:	Interrupt number in @itr_chip space for the timer.
+ *
+ * This function starts the callout service via interrupts from the timer.
+ * The platform or architecture specific code provides the implementation
+ * of this function. The interrupt callback function for the timer calls
+ * callout_service_cb() to drive the callout service.
+ *
+ * Note that usage of this function is incompatible with usage of the
+ * generic_timer_start(), generic_timer_stop() and generic_timer_handler()
+ * functions.
+ */
+void timer_init_callout_service(struct itr_chip *itr_chip, size_t itr_number);
+
 #endif /* __KERNEL_TIMER_H */
diff --git a/core/include/kernel/transfer_list.h b/core/include/kernel/transfer_list.h
index ed813979f289ede1a78218a25c2fa10eb463b374..30e8a7397641266de045c935aaffe121d6179e16 100644
--- a/core/include/kernel/transfer_list.h
+++ b/core/include/kernel/transfer_list.h
@@ -22,7 +22,22 @@
  * Version of the register convention used.
  * Set to 1 for both AArch64 and AArch32 according to fw handoff spec v0.9
  */
-#define REG_CONVENTION_VER_MASK BIT(24)
+#define TL_REG_CONVENTION_VER_SHIFT_64	UL(32)
+#define TL_REG_CONVENTION_VER_SHIFT_32	UL(24)
+#define TL_REG_CONVENTION_VER_MASK	UL(0xff)
+#define TL_REG_CONVENTION_VER	UL(1)
+
+#define TL_HANDOFF_X1_VALUE(__version)	\
+	((TRANSFER_LIST_SIGNATURE &	\
+	((BIT64(TL_REG_CONVENTION_VER_SHIFT_64)) - 1)) |	\
+	(((__version) & TL_REG_CONVENTION_VER_MASK) <<	\
+	 TL_REG_CONVENTION_VER_SHIFT_64))
+
+#define TL_HANDOFF_R1_VALUE(__version)	\
+	((TRANSFER_LIST_SIGNATURE &	\
+	((BIT32(TL_REG_CONVENTION_VER_SHIFT_32)) - 1)) |	\
+	(((__version) & TL_REG_CONVENTION_VER_MASK) <<	\
+	 TL_REG_CONVENTION_VER_SHIFT_32))
 
 #define TL_FLAGS_HAS_CHECKSUM BIT(0)
 
diff --git a/core/include/kernel/user_mode_ctx_struct.h b/core/include/kernel/user_mode_ctx_struct.h
index 6c91f4eaac67934776427ce0cc897e1cc3ff6d00..c8812470ddb2e71d194466304a41925c3b144f2c 100644
--- a/core/include/kernel/user_mode_ctx_struct.h
+++ b/core/include/kernel/user_mode_ctx_struct.h
@@ -26,7 +26,6 @@
  * @ldelf_stack_ptr:	Stack pointer used for dumping address mappings and
  *			stack trace
  * @is_32bit:		True if 32-bit TS, false if 64-bit TS
- * @is_initializing:	True if TS is not fully loaded
  * @stack_ptr:		Stack pointer
  * @bbuf:		Bounce buffer for user buffers
  * @bbuf_size:		Size of bounce buffer
@@ -52,7 +51,6 @@ struct user_mode_ctx {
 	uaddr_t dl_entry_func;
 	uaddr_t ldelf_stack_ptr;
 	bool is_32bit;
-	bool is_initializing;
 	vaddr_t stack_ptr;
 	uint8_t *bbuf;
 	size_t bbuf_size;
diff --git a/core/include/kernel/user_ta.h b/core/include/kernel/user_ta.h
index 667122b5c675a2d09eaa1f91c248e3bc3a5f54cd..7ad4cfa62cf00fa7283669260d7214e155b9a3e5 100644
--- a/core/include/kernel/user_ta.h
+++ b/core/include/kernel/user_ta.h
@@ -28,7 +28,6 @@ SLIST_HEAD(load_seg_head, load_seg);
  * @cryp_states:	List of cryp states created by this TA
  * @objects:		List of storage objects opened by this TA
  * @storage_enums:	List of storage enumerators opened by this TA
- * @ta_time_offs:	Time reference used by the TA
  * @uctx:		Generic user mode context
  * @ctx:		Generic TA context
  */
@@ -37,7 +36,6 @@ struct user_ta_ctx {
 	struct tee_cryp_state_head cryp_states;
 	struct tee_obj_head objects;
 	struct tee_storage_enum_head storage_enums;
-	void *ta_time_offs;
 	struct user_mode_ctx uctx;
 	struct tee_ta_ctx ta_ctx;
 };
@@ -58,16 +56,33 @@ static inline struct user_ta_ctx *to_user_ta_ctx(struct ts_ctx *ctx)
 }
 
 #ifdef CFG_WITH_USER_TA
+/*
+ * Setup session context for a user TA
+ * @uuid: TA UUID
+ * @s: Session for which to setup a user TA context
+ *
+ * This function must be called with tee_ta_mutex locked.
+ */
 TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
-			struct tee_ta_session *s);
+				       struct tee_ta_session *s);
+
+/*
+ * Finalize session context initialization for a user TA
+ * @sess: Session for which to finalize user TA context
+ */
+TEE_Result tee_ta_complete_user_ta_session(struct tee_ta_session *s);
 #else
-static inline TEE_Result tee_ta_init_user_ta_session(
-			const TEE_UUID *uuid __unused,
-			struct tee_ta_session *s __unused)
+static inline TEE_Result
+tee_ta_init_user_ta_session(const TEE_UUID *uuid __unused,
+			    struct tee_ta_session *s __unused)
 {
 	return TEE_ERROR_ITEM_NOT_FOUND;
 }
-#endif
-
 
+static inline TEE_Result
+tee_ta_complete_user_ta_session(struct tee_ta_session *s __unused)
+{
+	return TEE_ERROR_GENERIC;
+}
+#endif /*CFG_WITH_USER_TA*/
 #endif /*__KERNEL_USER_TA_H*/
diff --git a/core/include/kernel/virtualization.h b/core/include/kernel/virtualization.h
index f14904e564d474e704356326a4fd29d49653c935..865899bb21ddfb5995eb658637970dd6d69b7c41 100644
--- a/core/include/kernel/virtualization.h
+++ b/core/include/kernel/virtualization.h
@@ -1,9 +1,13 @@
 /* SPDX-License-Identifier: BSD-2-Clause */
-/* Copyright (c) 2018, EPAM Systems. All rights reserved. */
+/*
+ * Copyright (c) 2018, EPAM Systems. All rights reserved.
+ * Copyright (c) 2024, Linaro Limited
+ */
 
 #ifndef __KERNEL_VIRTUALIZATION_H
 #define __KERNEL_VIRTUALIZATION_H
 
+#include <bitstring.h>
 #include <mm/core_mmu.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -11,6 +15,8 @@
 
 #define HYP_CLNT_ID 0
 
+struct guest_partition;
+
 #if defined(CFG_NS_VIRTUALIZATION)
 /**
  * virt_guest_created() - create new VM partition
@@ -69,27 +75,20 @@ void virt_on_stdcall(void);
 
 /**
  * virt_init_memory() - initialize memory for virtualization subsystem
- * @memory_map: current OP-TEE memory map
+ * @mem_map: current OP-TEE memory map
  * @secmem0_base: base of first secure memory range
  * @secmem0_size: size of first secure memory range
  * @secmem1_base: base of an eventual second secure memory range, 0 if unused
  * @secmem1_size: size of an eventual second secure memory range, 0 if unused
  */
-void virt_init_memory(struct tee_mmap_region *memory_map, paddr_t secmem0_base,
+void virt_init_memory(struct memory_map *mem_map, paddr_t secmem0_base,
 		      paddr_size_t secmem0_size, paddr_t secmem1_base,
 		      paddr_size_t secmem1_size);
 
 /**
  * virt_get_memory_map() - get current memory map
  */
-struct tee_mmap_region *virt_get_memory_map(void);
-
-/**
- * virt_get_ta_ram() - get TA RAM mapping for current VM
- * @start: beginning of TA RAM returned here
- * @end: end of TA RAM returned here
- */
-void virt_get_ta_ram(vaddr_t *start, vaddr_t *end);
+struct memory_map *virt_get_memory_map(void);
 
 /**
  * virt_get_current_guest_id() - return current guest ID
@@ -98,6 +97,90 @@ void virt_get_ta_ram(vaddr_t *start, vaddr_t *end);
  */
 uint16_t virt_get_current_guest_id(void);
 
+/**
+ * virt_get_guest_id() - return guest ID of a guest partition
+ * @prtn:       Guest partition
+ *
+ * Returns guest ID or 0 if @prtn is NULL
+ */
+uint16_t virt_get_guest_id(struct guest_partition *prtn);
+
+/*
+ * virt_next_guest() - iterate over guest partitions
+ * @prtn:       Guest partition to start from
+ *
+ * Iterates of the guest partitions, if @prtn is NULL the first partition
+ * is returned. If there are none or no next partition NULL is returned.
+ *
+ * The supplied @prtn has its reference counter decreased with
+ * virt_put_guest() before returning the next partition. A returned
+ * partition has its reference counter increased before being returned.
+ *
+ * If virt_next_guest() is called in sequence until it returns NULL, all
+ * reference counters are restored, but if the sequence is stopped earlier
+ * it's the callers responsibility to call virt_put_guest() on the last
+ * returned partition.
+ */
+struct guest_partition *virt_next_guest(struct guest_partition *prtn);
+
+/**
+ * virt_get_current_guest() - increase reference to current guest partition
+ *
+ * Each successful call to this function must be matched by a call to
+ * virt_put_guest() in order to decrease the reference counter again.
+ *
+ * Return a pointer to the guest partition on success or NULL on failure
+ */
+struct guest_partition *virt_get_current_guest(void);
+
+/**
+ * virt_get_guest() - increase reference to a guest partition
+ * @guest_id:     ID of the guest partition to find
+ *
+ * Each successful call to this function must be matched by a call to
+ * virt_put_guest() in order to decrease the reference counter again.
+ *
+ * Return a pointer to the guest partition on success or NULL on failure
+ */
+struct guest_partition *virt_get_guest(uint16_t guest_id);
+
+/**
+ * virt_put_guest() - decrease reference to a guest partition
+ * @prtn:       Guest partition
+ *
+ * Does nothing if @prtn is NULL.
+ */
+void virt_put_guest(struct guest_partition *prtn);
+
+/**
+ * virt_add_guest_spec_data() - add guest specific data
+ * @data_id:      assigned id for the guest specific data
+ * @data_size:    size of the guest specific data
+ * @data_destroy: function to destroy the guest specific data when the
+ *                guest is destroyed, does not free the data itself
+ *
+ * Assigns a new data ID returned in @data_id and records the associated
+ * @data_size size and destructor function @data_destroy.
+ *
+ * To keep things simple, this function is only to be called before exiting
+ * to the normal world for the first time, that is, while we're single
+ * threaded and only have one partition.
+ */
+TEE_Result virt_add_guest_spec_data(unsigned int *data_id, size_t data_size,
+				    void (*data_destroy)(void *data));
+
+/*
+ * virt_get_guest_spec_data() - get guest specific data
+ * @prtn: guest partition
+ * @data_id:  previously assigned ID for the data
+ *
+ * Returns the preallocated guest specific data of the partition with the
+ * ID of @guest_id, will only return NULL for an unrecognized @data_id or
+ * NULL @prtn.
+ */
+void *virt_get_guest_spec_data(struct guest_partition *prtn,
+			       unsigned int data_id);
+
 #else
 static inline TEE_Result virt_guest_created(uint16_t guest_id __unused)
 { return TEE_ERROR_NOT_SUPPORTED; }
@@ -110,22 +193,56 @@ static inline TEE_Result virt_set_guest(uint16_t guest_id __unused)
 
 static inline void virt_unset_guest(void) { }
 static inline void virt_on_stdcall(void) { }
-static inline struct tee_mmap_region *virt_get_memory_map(void) { return NULL; }
-static inline void
-virt_get_ta_ram(vaddr_t *start __unused, vaddr_t *end __unused) { }
-static inline void virt_init_memory(struct tee_mmap_region *memory_map __unused,
+static inline struct memory_map *virt_get_memory_map(void) { return NULL; }
+static inline void virt_init_memory(struct memory_map *mem_map __unused,
 				    paddr_t secmem0_base __unused,
 				    paddr_size_t secmem0_size __unused,
 				    paddr_t secmem1_base __unused,
 				    paddr_size_t secmem1_size __unused) { }
 static inline uint16_t virt_get_current_guest_id(void) { return 0; }
+static inline uint16_t virt_get_guest_id(struct guest_partition *prtn __unused)
+{
+	return 0;
+}
+static inline struct guest_partition *virt_get_current_guest(void)
+{
+	return NULL;
+}
+static inline struct guest_partition *virt_get_guest(uint16_t guest_id __unused)
+{
+	return NULL;
+}
+static inline struct guest_partition *
+virt_next_guest(struct guest_partition *prtn __unused)
+{
+	return NULL;
+}
+static inline void virt_put_guest(struct guest_partition *prtn __unused) { }
+static inline TEE_Result
+virt_add_guest_spec_data(unsigned int *data_id __unused,
+			 size_t data_size __unused,
+			 void (*data_destroy)(void *data) __unused)
+{
+	return TEE_ERROR_NOT_SUPPORTED;
+}
+
+static inline void *
+virt_get_guest_spec_data(struct guest_partition *prtn __unused,
+			 unsigned int data_id __unused)
+{
+	return NULL;
+}
+
 #endif /*CFG_NS_VIRTUALIZATION*/
 
 #if defined(CFG_CORE_SEL1_SPMC) && defined(CFG_NS_VIRTUALIZATION)
 TEE_Result virt_add_cookie_to_current_guest(uint64_t cookie);
 void virt_remove_cookie(uint64_t cookie);
 uint16_t virt_find_guest_by_cookie(uint64_t cookie);
+bitstr_t *virt_get_shm_bits(void);
 
+TEE_Result virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id,
+						    uint64_t cookie);
 #else
 static inline TEE_Result
 virt_add_cookie_to_current_guest(uint64_t cookie __unused)
@@ -133,6 +250,11 @@ virt_add_cookie_to_current_guest(uint64_t cookie __unused)
 static inline void virt_remove_cookie(uint64_t cookie __unused) { }
 static inline uint16_t virt_find_guest_by_cookie(uint64_t cookie __unused)
 { return 0; }
+static inline bitstr_t *virt_get_shm_bits(void) { return NULL; }
+static inline TEE_Result
+virt_reclaim_cookie_from_destroyed_guest(uint16_t guest_id __unused,
+					 uint64_t cookie __unused)
+{ return TEE_ERROR_NOT_SUPPORTED; }
 #endif
 
 #endif	/* __KERNEL_VIRTUALIZATION_H */
diff --git a/core/include/kernel/wait_queue.h b/core/include/kernel/wait_queue.h
index 20691e7fee0d17a05e92b9f0ada54293226177a4..e05adc9ac97978bb171800785acee693c1be9204 100644
--- a/core/include/kernel/wait_queue.h
+++ b/core/include/kernel/wait_queue.h
@@ -5,6 +5,7 @@
 #ifndef __KERNEL_WAIT_QUEUE_H
 #define __KERNEL_WAIT_QUEUE_H
 
+#include <tee_api_types.h>
 #include <types_ext.h>
 #include <sys/queue.h>
 
@@ -44,9 +45,10 @@ static inline void wq_wait_init(struct wait_queue *wq,
 	wq_wait_init_condvar(wq, wqe, NULL, wait_read);
 }
 
-/* Waits for the wait queue element to the awakened. */
-void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
-		   const void *sync_obj, const char *fname, int lineno);
+/* Waits for the wait queue element to be awakened or timed out */
+TEE_Result wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
+			 uint32_t timeout_ms, const void *sync_obj,
+			 const char *fname, int lineno);
 
 /* Wakes up the first wait queue element in the wait queue, if there is one */
 void wq_wake_next(struct wait_queue *wq, const void *sync_obj,
diff --git a/core/include/mm/core_memprot.h b/core/include/mm/core_memprot.h
index 428c827b270bbe9da0912829f2614381128c1df5..2f275fab80d2989ef670632055f543686b7e85e6 100644
--- a/core/include/mm/core_memprot.h
+++ b/core/include/mm/core_memprot.h
@@ -28,7 +28,6 @@ enum buf_is_attr {
 	CORE_MEM_NON_SEC,
 	CORE_MEM_SEC,
 	CORE_MEM_TEE_RAM,
-	CORE_MEM_TA_RAM,
 	CORE_MEM_SDP_MEM,
 	CORE_MEM_REG_SHM,
 };
@@ -90,6 +89,11 @@ void *phys_to_virt_io(paddr_t pa, size_t len);
  */
 paddr_t virt_to_phys(void *va);
 
+static inline paddr_t vaddr_to_phys(vaddr_t va)
+{
+	return virt_to_phys((void *)va);
+}
+
 /*
  * Return runtime usable address, irrespective of whether
  * the MMU is enabled or not. In case of MMU enabled also will be performed
@@ -97,8 +101,31 @@ paddr_t virt_to_phys(void *va);
  */
 vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len);
 
-/* Return true if @va relates to a unpaged section else false */
-bool is_unpaged(void *va);
+/*
+ * is_unpaged() - report unpaged status of an address
+ * @va:		virtual address
+ *
+ * Returns true if the @va is non-NULL and is in the unpaged area if paging
+ * is enabled, else false.
+ */
+#ifdef CFG_WITH_PAGER
+bool is_unpaged(const void *va);
+#else
+static inline bool is_unpaged(const void *va) { return va; }
+#endif
+
+/*
+ * is_nexus() - report nexus status of an address
+ * @va:		virtual address
+ *
+ * Returns true if the @va is non-NULL and is in the nexus memory area
+ * if ns-virtualization is enabled, else false.
+ */
+#ifdef CFG_NS_VIRTUALIZATION
+bool is_nexus(const void *va);
+#else
+static inline bool is_nexus(const void *va) { return va; }
+#endif
 
 struct io_pa_va {
 	paddr_t pa;
diff --git a/core/include/mm/core_mmu.h b/core/include/mm/core_mmu.h
index b239c6fbf65b9f62f79f976054962be31efc4a47..42fa12b64d5d0a9b5ea6637713b1b8ac6b8c6da4 100644
--- a/core/include/mm/core_mmu.h
+++ b/core/include/mm/core_mmu.h
@@ -10,6 +10,7 @@
 #include <assert.h>
 #include <compiler.h>
 #include <kernel/user_ta.h>
+#include <mm/tee_mm.h>
 #include <mm/tee_mmu_types.h>
 #include <types_ext.h>
 #include <util.h>
@@ -56,7 +57,6 @@
 #ifndef __ASSEMBLER__
 /*
  * Memory area type:
- * MEM_AREA_END:      Reserved, marks the end of a table of mapping areas.
  * MEM_AREA_TEE_RAM:  core RAM (read/write/executable, secure, reserved to TEE)
  * MEM_AREA_TEE_RAM_RX:  core private read-only/executable memory (secure)
  * MEM_AREA_TEE_RAM_RO:  core private read-only/non-executable memory (secure)
@@ -68,7 +68,6 @@
  * MEM_AREA_TEE_COHERENT: teecore coherent RAM (secure, reserved to TEE)
  * MEM_AREA_TEE_ASAN: core address sanitizer RAM (secure, reserved to TEE)
  * MEM_AREA_IDENTITY_MAP_RX: core identity mapped r/o executable memory (secure)
- * MEM_AREA_TA_RAM:   Secure RAM where teecore loads/exec TA instances.
  * MEM_AREA_NSEC_SHM: NonSecure shared RAM between NSec and TEE.
  * MEM_AREA_NEX_NSEC_SHM: nexus non-secure shared RAM between NSec and TEE.
  * MEM_AREA_RAM_NSEC: NonSecure RAM storing data
@@ -87,8 +86,7 @@
  * MEM_AREA_MAXTYPE:  lower invalid 'type' value
  */
 enum teecore_memtypes {
-	MEM_AREA_END = 0,
-	MEM_AREA_TEE_RAM,
+	MEM_AREA_TEE_RAM = 1,
 	MEM_AREA_TEE_RAM_RX,
 	MEM_AREA_TEE_RAM_RO,
 	MEM_AREA_TEE_RAM_RW,
@@ -99,7 +97,6 @@ enum teecore_memtypes {
 	MEM_AREA_TEE_COHERENT,
 	MEM_AREA_TEE_ASAN,
 	MEM_AREA_IDENTITY_MAP_RX,
-	MEM_AREA_TA_RAM,
 	MEM_AREA_NSEC_SHM,
 	MEM_AREA_NEX_NSEC_SHM,
 	MEM_AREA_RAM_NSEC,
@@ -123,7 +120,6 @@ enum teecore_memtypes {
 static inline const char *teecore_memtype_name(enum teecore_memtypes type)
 {
 	static const char * const names[] = {
-		[MEM_AREA_END] = "END",
 		[MEM_AREA_TEE_RAM] = "TEE_RAM_RWX",
 		[MEM_AREA_TEE_RAM_RX] = "TEE_RAM_RX",
 		[MEM_AREA_TEE_RAM_RO] = "TEE_RAM_RO",
@@ -135,7 +131,6 @@ static inline const char *teecore_memtype_name(enum teecore_memtypes type)
 		[MEM_AREA_TEE_ASAN] = "TEE_ASAN",
 		[MEM_AREA_IDENTITY_MAP_RX] = "IDENTITY_MAP_RX",
 		[MEM_AREA_TEE_COHERENT] = "TEE_COHERENT",
-		[MEM_AREA_TA_RAM] = "TA_RAM",
 		[MEM_AREA_NSEC_SHM] = "NSEC_SHM",
 		[MEM_AREA_NEX_NSEC_SHM] = "NEX_NSEC_SHM",
 		[MEM_AREA_RAM_NSEC] = "RAM_NSEC",
@@ -276,6 +271,12 @@ struct core_mmu_phys_mem {
 #define phys_mem_map_end \
 	SCATTERED_ARRAY_END(phys_mem_map, struct core_mmu_phys_mem)
 
+/* Virtual memory pool for core mappings */
+extern tee_mm_pool_t core_virt_mem_pool;
+
+/* Virtual memory pool for shared memory mappings */
+extern tee_mm_pool_t core_virt_shm_pool;
+
 #ifdef CFG_CORE_RESERVED_SHM
 /* Default NSec shared memory allocated from NSec world */
 extern unsigned long default_nsec_shm_paddr;
@@ -294,6 +295,11 @@ extern const unsigned long core_mmu_tee_load_pa;
 
 void core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg);
 void core_init_mmu_regs(struct core_mmu_config *cfg);
+/*
+ * Copy static memory map from temporary boot_mem to heap when CFG_BOOT_MEM
+ * is enabled.
+ */
+void core_mmu_save_mem_map(void);
 
 /* Arch specific function to help optimizing 1 MMU xlat table */
 bool core_mmu_prefer_tee_ram_at_top(paddr_t paddr);
@@ -544,12 +550,22 @@ void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages);
  */
 bool core_mmu_user_mapping_is_active(void);
 
+/*
+ * core_mmu_user_va_range_is_defined() - check if user va range is defined
+ * @returns true if a user VA space is defined, false if not.
+ */
+bool core_mmu_user_va_range_is_defined(void);
+
 /*
  * core_mmu_mattr_is_ok() - Check that supplied mem attributes can be used
  * @returns true if the attributes can be used, false if not.
  */
 bool core_mmu_mattr_is_ok(uint32_t mattr);
 
+TEE_Result core_mmu_for_each_map(void *ptr,
+				 TEE_Result (*fn)(struct tee_mmap_region *map,
+						  void *ptr));
+
 void core_mmu_get_mem_by_type(enum teecore_memtypes type, vaddr_t *s,
 			      vaddr_t *e);
 
@@ -615,7 +631,7 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start,
 #endif
 
 /* Initialize MMU partition */
-void core_init_mmu_prtn(struct mmu_partition *prtn, struct tee_mmap_region *mm);
+void core_init_mmu_prtn(struct mmu_partition *prtn, struct memory_map *mem_map);
 
 unsigned int asid_alloc(void);
 void asid_free(unsigned int asid);
@@ -634,12 +650,10 @@ void core_mmu_set_default_prtn(void);
 void core_mmu_set_default_prtn_tbl(void);
 #endif
 
-void core_mmu_init_virtualization(void);
+/* Initialize physical memory pool */
+void core_mmu_init_phys_mem(void);
 
-/* init some allocation pools */
-void core_mmu_init_ta_ram(void);
-
-void core_init_mmu(struct tee_mmap_region *mm);
+void core_init_mmu(struct memory_map *mem_map);
 
 void core_mmu_set_info_table(struct core_mmu_table_info *tbl_info,
 			     unsigned int level, vaddr_t va_base, void *table);
@@ -650,11 +664,6 @@ void core_mmu_map_region(struct mmu_partition *prtn,
 
 bool arch_va2pa_helper(void *va, paddr_t *pa);
 
-static inline bool core_mmap_is_end_of_table(const struct tee_mmap_region *mm)
-{
-	return mm->type == MEM_AREA_END;
-}
-
 static inline bool core_mmu_check_end_pa(paddr_t pa, size_t len)
 {
 	paddr_t end_pa = 0;
@@ -686,13 +695,6 @@ void core_mmu_set_secure_memory(paddr_t base, size_t size);
  */
 void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size);
 
-/*
- * core_mmu_get_ta_range() - get physical memory range reserved for TAs
- * @base: [out] range base address ref or NULL
- * @size: [out] range size ref or NULL
- */
-void core_mmu_get_ta_range(paddr_t *base, size_t *size);
-
 #endif /*__ASSEMBLER__*/
 
 #endif /* __MM_CORE_MMU_H */
diff --git a/core/include/mm/mobj.h b/core/include/mm/mobj.h
index 3b73b0008094d2043d7c800e8572c322b3ccdb31..452715817c90923909eac05d552f3211c506748e 100644
--- a/core/include/mm/mobj.h
+++ b/core/include/mm/mobj.h
@@ -39,7 +39,6 @@ struct mobj_ops {
 };
 
 extern struct mobj mobj_virt;
-extern struct mobj *mobj_sec_ddr;
 extern struct mobj *mobj_tee_ram_rx;
 extern struct mobj *mobj_tee_ram_rw;
 
diff --git a/core/include/mm/pgt_cache.h b/core/include/mm/pgt_cache.h
index 4f3e37e26c81974881de7494c8627d4f00344629..1e41ef44c7db0d0ddce0500c392e220849215a6d 100644
--- a/core/include/mm/pgt_cache.h
+++ b/core/include/mm/pgt_cache.h
@@ -5,6 +5,12 @@
 #ifndef __MM_PGT_CACHE_H
 #define __MM_PGT_CACHE_H
 
+#include <assert.h>
+#include <kernel/tee_ta_manager.h>
+#include <sys/queue.h>
+#include <types_ext.h>
+#include <util.h>
+
 #ifdef CFG_WITH_LPAE
 #define PGT_SIZE	(4 * 1024)
 #define PGT_NUM_PGT_PER_PAGE	1
@@ -13,12 +19,6 @@
 #define PGT_NUM_PGT_PER_PAGE	4
 #endif
 
-#include <assert.h>
-#include <kernel/tee_ta_manager.h>
-#include <sys/queue.h>
-#include <types_ext.h>
-#include <util.h>
-
 struct ts_ctx;
 
 struct pgt {
@@ -38,20 +38,6 @@ struct pgt {
 	SLIST_ENTRY(pgt) link;
 };
 
-/*
- * A proper value for PGT_CACHE_SIZE depends on many factors: CFG_WITH_LPAE,
- * CFG_TA_ASLR, size of TA, size of memrefs passed to TA, CFG_ULIBS_SHARED and
- * possibly others. The value is based on the number of threads as an indicator
- * on how large the system might be.
- */
-#if CFG_NUM_THREADS < 2
-#define PGT_CACHE_SIZE	4
-#elif (CFG_NUM_THREADS == 2 && !defined(CFG_WITH_LPAE))
-#define PGT_CACHE_SIZE	8
-#else
-#define PGT_CACHE_SIZE	ROUNDUP(CFG_NUM_THREADS * 2, PGT_NUM_PGT_PER_PAGE)
-#endif
-
 SLIST_HEAD(pgt_cache, pgt);
 struct user_mode_ctx;
 
diff --git a/core/include/mm/phys_mem.h b/core/include/mm/phys_mem.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ab037833f8442bc8fdfcc9084df18abbfef0e12
--- /dev/null
+++ b/core/include/mm/phys_mem.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#ifndef __MM_PHYS_MEM_H
+#define __MM_PHYS_MEM_H
+
+#include <mm/tee_mm.h>
+#include <types_ext.h>
+
+void nex_phys_mem_init(paddr_t core_base, paddr_size_t core_size,
+		       paddr_t ta_base, paddr_size_t ta_size);
+paddr_size_t nex_phys_mem_get_ta_size(void);
+paddr_t nex_phys_mem_get_ta_base(void);
+tee_mm_entry_t *nex_phys_mem_mm_find(paddr_t addr);
+tee_mm_entry_t *nex_phys_mem_core_alloc(size_t size);
+tee_mm_entry_t *nex_phys_mem_ta_alloc(size_t size);
+tee_mm_entry_t *nex_phys_mem_alloc2(paddr_t base, size_t size);
+void nex_phys_mem_partial_carve_out(paddr_t base, size_t size);
+#ifdef CFG_WITH_STATS
+void nex_phys_mem_stats(struct pta_stats_alloc *stats, bool reset);
+#endif
+
+#ifdef CFG_NS_VIRTUALIZATION
+void phys_mem_init(paddr_t core_base, paddr_size_t core_size,
+		   paddr_t ta_base, paddr_size_t ta_size);
+tee_mm_entry_t *phys_mem_mm_find(paddr_t addr);
+tee_mm_entry_t *phys_mem_core_alloc(size_t size);
+tee_mm_entry_t *phys_mem_ta_alloc(size_t size);
+tee_mm_entry_t *phys_mem_alloc2(paddr_t base, size_t size);
+#ifdef CFG_WITH_STATS
+void phys_mem_stats(struct pta_stats_alloc *stats, bool reset);
+#endif
+#else
+static inline void phys_mem_init(paddr_t core_base, paddr_size_t core_size,
+				 paddr_t ta_base, paddr_size_t ta_size)
+{
+	nex_phys_mem_init(core_base, core_size, ta_base, ta_size);
+}
+
+static inline tee_mm_entry_t *phys_mem_mm_find(paddr_t addr)
+{
+	return nex_phys_mem_mm_find(addr);
+}
+
+static inline tee_mm_entry_t *phys_mem_core_alloc(size_t size)
+{
+	return nex_phys_mem_core_alloc(size);
+}
+
+static inline tee_mm_entry_t *phys_mem_ta_alloc(size_t size)
+{
+	return nex_phys_mem_ta_alloc(size);
+}
+
+static inline tee_mm_entry_t *phys_mem_alloc2(paddr_t base, size_t size)
+{
+	return nex_phys_mem_alloc2(base, size);
+}
+
+#ifdef CFG_WITH_STATS
+static inline void phys_mem_stats(struct pta_stats_alloc *stats, bool reset)
+{
+	return nex_phys_mem_stats(stats, reset);
+}
+#endif
+#endif
+
+#endif /*__MM_PHYS_MEM_H*/
diff --git a/core/include/mm/tee_mm.h b/core/include/mm/tee_mm.h
index aae35f8717acc6b13f856f34367f21d838fe562d..3968d280fa9fc081ab4f33640cc940d0f8f5e637 100644
--- a/core/include/mm/tee_mm.h
+++ b/core/include/mm/tee_mm.h
@@ -38,15 +38,6 @@ struct _tee_mm_pool_t {
 };
 typedef struct _tee_mm_pool_t tee_mm_pool_t;
 
-/* Physical Secure DDR pool */
-extern tee_mm_pool_t tee_mm_sec_ddr;
-
-/* Virtual eSRAM pool */
-extern tee_mm_pool_t tee_mm_vcore;
-
-/* Shared memory pool */
-extern tee_mm_pool_t tee_mm_shm;
-
 /*
  * Returns a pointer to the mm covering the supplied address,
  * if no mm is found NULL is returned.
diff --git a/core/include/mm/tee_mmu_types.h b/core/include/mm/tee_mmu_types.h
index 2f495910f0eceb20c134459e20e948f3cfefc780..c78870c32b06c8229b92bffa9aff621ceac28e25 100644
--- a/core/include/mm/tee_mmu_types.h
+++ b/core/include/mm/tee_mmu_types.h
@@ -90,6 +90,12 @@ struct tee_mmap_region {
 	uint32_t attr; /* TEE_MATTR_* above */
 };
 
+struct memory_map {
+	size_t count;
+	size_t alloc_count;
+	struct tee_mmap_region *map;
+};
+
 struct vm_region {
 	struct mobj *mobj;
 	size_t offset;
diff --git a/core/include/optee_rpc_cmd.h b/core/include/optee_rpc_cmd.h
index 816f0a24fbe23ca476108ac02f85c8713dcd20d9..bfe453d1fe5b77235414b03f8eaabbc25f6794c5 100644
--- a/core/include/optee_rpc_cmd.h
+++ b/core/include/optee_rpc_cmd.h
@@ -65,10 +65,12 @@
  * Waiting on notification
  * [in]    value[0].a	    OPTEE_RPC_NOTIFICATION_WAIT
  * [in]    value[0].b	    notification value
+ * [in]    value[0].c	    timeout in millisecond or 0 if no timeout
  *
  * Sending a synchronous notification
  * [in]    value[0].a	    OPTEE_RPC_NOTIFICATION_SEND
  * [in]    value[0].b	    notification value
+ * [in]    value[0].c	    shall be 0, reserved for future evolution
  */
 #define OPTEE_RPC_CMD_NOTIFICATION	U(4)
 #define OPTEE_RPC_NOTIFICATION_WAIT	U(0)
@@ -178,6 +180,44 @@
 /* I2C master control flags */
 #define OPTEE_RPC_I2C_FLAGS_TEN_BIT	BIT(0)
 
+/*
+ * Reset RPMB probing
+ *
+ * Releases a possibly already used RPMB device and starts over searching
+ * for RPMB devices. Returns the kind of shared memory to use in subsequent
+ * OPTEE_RPC_CMD_RPMB_PROBE_NEXT and OPTEE_RPC_CMD_RPMB_FRAMES calls.
+ *
+ * [out]    value[0].a	    OPTEE_RPC_SHM_TYPE_*, the parameter for
+ *			    OPTEE_RPC_CMD_SHM_ALLOC
+ */
+#define OPTEE_RPC_CMD_RPMB_PROBE_RESET	U(22)
+
+/*
+ * Probe next RPMB device
+ *
+ * value[0].a indicates kind of RPMB device found, currently is only
+ * OPTEE_RPC_RPMB_EMMC supported. If another kind of RPMB device is found
+ * it will have a new unique value in value[0].a and the other
+ * out-parameters will be defined specifically for that device.
+ *
+ * If an eMMC/RPMB partition is found:
+ * [out]    value[0].a	    OPTEE_RPC_RPMB_EMMC
+ * [out]    value[0].b	    EXT CSD-slice 168 "RPMB Size"
+ * [out]    value[0].c	    EXT CSD-slice 222 "Reliable Write Sector Count"
+ * [out]    memref[1]       Buffer with the raw CID
+ */
+#define OPTEE_RPC_CMD_RPMB_PROBE_NEXT	U(23)
+
+#define OPTEE_RPC_RPMB_EMMC		U(0)
+
+/*
+ * Replay Protected Memory Block access
+ *
+ * [in]     memref[0]	    Frames to device
+ * [out]    memref[1]	    Frames from device
+ */
+#define OPTEE_RPC_CMD_RPMB_FRAMES	U(24)
+
 /*
  * Definition of protocol for command OPTEE_RPC_CMD_FS
  */
diff --git a/core/include/tee/tee_cryp_utl.h b/core/include/tee/tee_cryp_utl.h
index 7259cc3d6e93ef8fe55f6ac4ad18b2a631d09508..4851a4911c8e407d3d4e6b35931c21e41df69485 100644
--- a/core/include/tee/tee_cryp_utl.h
+++ b/core/include/tee/tee_cryp_utl.h
@@ -29,6 +29,12 @@ TEE_Result tee_do_cipher_update(void *ctx, uint32_t algo,
  */
 void plat_prng_add_jitter_entropy(enum crypto_rng_src sid, unsigned int *pnum);
 
+/*
+ * plat_rng_init() - Initialize RNG support.
+ * If not overridden with a platform implementation, the function defaults
+ * to __plat_rng_init() that implements a weak seeding of the RNG.
+ */
 void plat_rng_init(void);
+void __plat_rng_init(void);
 
 #endif
diff --git a/core/include/tee/tee_fs.h b/core/include/tee/tee_fs.h
index fce494c6bea3571b71d9bf6a71e5a192c00996cb..1f9e818f1e890f03386faece7fffcde24e3d362a 100644
--- a/core/include/tee/tee_fs.h
+++ b/core/include/tee/tee_fs.h
@@ -60,6 +60,7 @@ extern const struct tee_file_operations rpmb_fs_ops;
 
 TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create,
 				struct tee_file_handle **fh);
+TEE_Result tee_rpmb_reinit(void);
 
 /**
  * Weak function which can be overridden by platforms to indicate that the RPMB
@@ -67,6 +68,11 @@ TEE_Result tee_rpmb_fs_raw_open(const char *fname, bool create,
  * prevent a RPMB key write in the wrong state.
  */
 bool plat_rpmb_key_is_ready(void);
+#else
+static inline TEE_Result tee_rpmb_reinit(void)
+{
+	return TEE_ERROR_STORAGE_NOT_AVAILABLE;
+}
 #endif
 
 /*
diff --git a/core/kernel/boot.c b/core/kernel/boot.c
new file mode 100644
index 0000000000000000000000000000000000000000..08d36af56e8e572fca3390cd3a881eae6c176fd4
--- /dev/null
+++ b/core/kernel/boot.c
@@ -0,0 +1,195 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2015-2023, Linaro Limited
+ * Copyright (c) 2023, Arm Limited
+ */
+
+#include <kernel/boot.h>
+#include <kernel/dt.h>
+#include <libfdt.h>
+#include <mm/core_memprot.h>
+
+#ifdef CFG_CORE_DYN_SHM
+static uint64_t get_dt_val_and_advance(const void *data, size_t *offs,
+				       uint32_t cell_size)
+{
+	uint64_t rv = 0;
+
+	if (cell_size == 1) {
+		uint32_t v;
+
+		memcpy(&v, (const uint8_t *)data + *offs, sizeof(v));
+		*offs += sizeof(v);
+		rv = fdt32_to_cpu(v);
+	} else {
+		uint64_t v;
+
+		memcpy(&v, (const uint8_t *)data + *offs, sizeof(v));
+		*offs += sizeof(v);
+		rv = fdt64_to_cpu(v);
+	}
+
+	return rv;
+}
+
+/*
+ * Find all non-secure memory from DT. Memory marked inaccessible by Secure
+ * World is ignored since it could not be mapped to be used as dynamic shared
+ * memory.
+ */
+static int __maybe_unused get_nsec_memory_helper(void *fdt, struct core_mmu_phys_mem *mem)
+{
+	const uint8_t *prop = NULL;
+	uint64_t a = 0;
+	uint64_t l = 0;
+	size_t prop_offs = 0;
+	size_t prop_len = 0;
+	int elems_total = 0;
+	int addr_size = 0;
+	int len_size = 0;
+	int offs = 0;
+	size_t n = 0;
+	int len = 0;
+
+	addr_size = fdt_address_cells(fdt, 0);
+	if (addr_size < 0)
+		return 0;
+
+	len_size = fdt_size_cells(fdt, 0);
+	if (len_size < 0)
+		return 0;
+
+	while (true) {
+		offs = fdt_node_offset_by_prop_value(fdt, offs, "device_type",
+						     "memory",
+						     sizeof("memory"));
+		if (offs < 0)
+			break;
+
+		if (fdt_get_status(fdt, offs) != (DT_STATUS_OK_NSEC |
+						   DT_STATUS_OK_SEC))
+			continue;
+
+		prop = fdt_getprop(fdt, offs, "reg", &len);
+		if (!prop)
+			continue;
+
+		prop_len = len;
+		for (n = 0, prop_offs = 0; prop_offs < prop_len; n++) {
+			a = get_dt_val_and_advance(prop, &prop_offs, addr_size);
+			if (prop_offs >= prop_len) {
+				n--;
+				break;
+			}
+
+			l = get_dt_val_and_advance(prop, &prop_offs, len_size);
+			if (mem) {
+				mem->type = MEM_AREA_DDR_OVERALL;
+				mem->addr = a;
+				mem->size = l;
+				mem++;
+			}
+		}
+
+		elems_total += n;
+	}
+
+	return elems_total;
+}
+
+#ifdef CFG_DT
+static struct core_mmu_phys_mem *get_nsec_memory(void *fdt, size_t *nelems)
+{
+	struct core_mmu_phys_mem *mem = NULL;
+	int elems_total = 0;
+
+	elems_total = get_nsec_memory_helper(fdt, NULL);
+	if (elems_total <= 0)
+		return NULL;
+
+	mem = nex_calloc(elems_total, sizeof(*mem));
+	if (!mem)
+		panic();
+
+	elems_total = get_nsec_memory_helper(fdt, mem);
+	assert(elems_total > 0);
+
+	*nelems = elems_total;
+
+	return mem;
+}
+#else /*CFG_DT*/
+static struct core_mmu_phys_mem *get_nsec_memory(void *fdt __unused,
+						 size_t *nelems __unused)
+{
+	return NULL;
+}
+#endif /*!CFG_DT*/
+
+void discover_nsec_memory(void)
+{
+	struct core_mmu_phys_mem *mem;
+	const struct core_mmu_phys_mem *mem_begin = NULL;
+	const struct core_mmu_phys_mem *mem_end = NULL;
+	size_t nelems;
+	void *fdt = get_external_dt();
+
+	if (fdt) {
+		mem = get_nsec_memory(fdt, &nelems);
+		if (mem) {
+			core_mmu_set_discovered_nsec_ddr(mem, nelems);
+			return;
+		}
+
+		DMSG("No non-secure memory found in FDT");
+	}
+
+	mem_begin = phys_ddr_overall_begin;
+	mem_end = phys_ddr_overall_end;
+	nelems = mem_end - mem_begin;
+	if (nelems) {
+		/*
+		 * Platform cannot use both register_ddr() and the now
+		 * deprecated register_dynamic_shm().
+		 */
+		assert(phys_ddr_overall_compat_begin ==
+		       phys_ddr_overall_compat_end);
+	} else {
+		mem_begin = phys_ddr_overall_compat_begin;
+		mem_end = phys_ddr_overall_compat_end;
+		nelems = mem_end - mem_begin;
+		if (!nelems)
+			return;
+		DMSG("Warning register_dynamic_shm() is deprecated, "
+		     "please use register_ddr() instead");
+	}
+
+	mem = nex_calloc(nelems, sizeof(*mem));
+	if (!mem)
+		panic();
+
+	memcpy(mem, phys_ddr_overall_begin, sizeof(*mem) * nelems);
+	core_mmu_set_discovered_nsec_ddr(mem, nelems);
+}
+#else /*CFG_CORE_DYN_SHM*/
+void discover_nsec_memory(void)
+{
+}
+#endif /*!CFG_CORE_DYN_SHM*/
+
+#ifdef CFG_CORE_RESERVED_SHM
+int mark_static_shm_as_reserved(struct dt_descriptor *dt)
+{
+	vaddr_t shm_start;
+	vaddr_t shm_end;
+
+	core_mmu_get_mem_by_type(MEM_AREA_NSEC_SHM, &shm_start, &shm_end);
+	if (shm_start != shm_end)
+		return add_res_mem_dt_node(dt, "optee_shm",
+					   virt_to_phys((void *)shm_start),
+					   shm_end - shm_start);
+
+	DMSG("No SHM configured");
+	return -1;
+}
+#endif /*CFG_CORE_RESERVED_SHM*/
diff --git a/core/kernel/callout.c b/core/kernel/callout.c
new file mode 100644
index 0000000000000000000000000000000000000000..54d6a8c2f6cded4d74e93066cdc1129d9e444c49
--- /dev/null
+++ b/core/kernel/callout.c
@@ -0,0 +1,191 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <kernel/callout.h>
+#include <kernel/misc.h>
+#include <kernel/spinlock.h>
+#include <mm/core_memprot.h>
+
+TAILQ_HEAD(callout_head, callout);
+
+static unsigned int callout_sched_lock __nex_data = SPINLOCK_UNLOCK;
+static size_t callout_sched_core __nex_bss;
+static unsigned int callout_lock __nex_data = SPINLOCK_UNLOCK;
+static const struct callout_timer_desc *callout_desc __nex_bss;
+static struct callout_head callout_head __nex_data =
+	TAILQ_HEAD_INITIALIZER(callout_head);
+
+static void insert_callout(struct callout *co)
+{
+	struct callout *co2 = NULL;
+
+	TAILQ_FOREACH(co2, &callout_head, link) {
+		if (co->expiry_value < co2->expiry_value) {
+			TAILQ_INSERT_BEFORE(co2, co, link);
+			return;
+		}
+	}
+
+	TAILQ_INSERT_TAIL(&callout_head, co, link);
+}
+
+static void schedule_next_timeout(void)
+{
+	const struct callout_timer_desc *desc = callout_desc;
+	struct callout *co = TAILQ_FIRST(&callout_head);
+
+	if (co)
+		desc->set_next_timeout(desc, co->expiry_value);
+	else
+		desc->disable_timeout(desc);
+
+	if (desc->is_per_cpu) {
+		/*
+		 * Remember which core is supposed to receive the next
+		 * timer interrupt. This will not disable timers on other
+		 * CPUs, instead they will be ignored as a spurious call.
+		 */
+		cpu_spin_lock(&callout_sched_lock);
+		callout_sched_core = get_core_pos();
+		cpu_spin_unlock(&callout_sched_lock);
+	}
+}
+
+static bool callout_is_active(struct callout *co)
+{
+	struct callout *co2 = NULL;
+
+	TAILQ_FOREACH(co2, &callout_head, link)
+		if (co2 == co)
+			return true;
+
+	return false;
+}
+
+void callout_rem(struct callout *co)
+{
+	uint32_t state = 0;
+
+	state = cpu_spin_lock_xsave(&callout_lock);
+
+	if (callout_is_active(co)) {
+		TAILQ_REMOVE(&callout_head, co, link);
+		schedule_next_timeout();
+	}
+
+	cpu_spin_unlock_xrestore(&callout_lock, state);
+}
+
+void callout_add(struct callout *co, bool (*callback)(struct callout *co),
+		 uint32_t ms)
+{
+	const struct callout_timer_desc *desc = callout_desc;
+	uint32_t state = 0;
+
+	state = cpu_spin_lock_xsave(&callout_lock);
+
+	assert(is_nexus(co) && !callout_is_active(co) && is_unpaged(callback));
+	*co = (struct callout){ .callback = callback, };
+
+	if (desc) {
+		co->period = desc->ms_to_ticks(desc, ms);
+		co->expiry_value = desc->get_now(desc) + co->period;
+	} else {
+		/* This will be converted to ticks in callout_service_init(). */
+		co->period = ms;
+	}
+
+	insert_callout(co);
+	if (desc && co == TAILQ_FIRST(&callout_head))
+		schedule_next_timeout();
+
+	cpu_spin_unlock_xrestore(&callout_lock, state);
+}
+
+void callout_set_next_timeout(struct callout *co, uint32_t ms)
+{
+	co->period = callout_desc->ms_to_ticks(callout_desc, ms);
+}
+
+void callout_service_init(const struct callout_timer_desc *desc)
+{
+	struct callout_head tmp_head = TAILQ_HEAD_INITIALIZER(tmp_head);
+	struct callout *co = NULL;
+	uint32_t state = 0;
+	uint64_t now = 0;
+
+	state = cpu_spin_lock_xsave(&callout_lock);
+
+	assert(!callout_desc);
+	assert(is_nexus(desc) && is_unpaged(desc->disable_timeout) &&
+	       is_unpaged(desc->set_next_timeout) &&
+	       is_unpaged(desc->ms_to_ticks) && is_unpaged(desc->get_now));
+
+	callout_desc = desc;
+	now = desc->get_now(desc);
+
+	TAILQ_CONCAT(&tmp_head, &callout_head, link);
+	while (!TAILQ_EMPTY(&tmp_head)) {
+		co = TAILQ_FIRST(&tmp_head);
+		TAILQ_REMOVE(&tmp_head, co, link);
+
+		/*
+		 * Periods set before the timer descriptor are in
+		 * milliseconds since the frequency of the timer isn't
+		 * available at that point. So update it to ticks now.
+		 */
+		co->period = desc->ms_to_ticks(desc, co->period);
+		co->expiry_value = now + co->period;
+		insert_callout(co);
+	}
+	schedule_next_timeout();
+
+	cpu_spin_unlock_xrestore(&callout_lock, state);
+}
+
+void callout_service_cb(void)
+{
+	const struct callout_timer_desc *desc = callout_desc;
+	struct callout *co = NULL;
+	uint64_t now = 0;
+
+	if (desc->is_per_cpu) {
+		bool do_callout = false;
+
+		/*
+		 * schedule_next_timeout() saves the core it was last
+		 * called on. If there's a mismatch here it means that
+		 * another core has been scheduled for the next callout, so
+		 * there's no work to be done for this core and we can
+		 * disable the timeout on this CPU.
+		 */
+		cpu_spin_lock(&callout_sched_lock);
+		do_callout = (get_core_pos() == callout_sched_core);
+		if (!do_callout)
+			desc->disable_timeout(desc);
+		cpu_spin_unlock(&callout_sched_lock);
+		if (!do_callout)
+			return;
+	}
+
+	cpu_spin_lock(&callout_lock);
+
+	now = desc->get_now(desc);
+	while (!TAILQ_EMPTY(&callout_head)) {
+		co = TAILQ_FIRST(&callout_head);
+		if (co->expiry_value > now)
+			break;
+
+		TAILQ_REMOVE(&callout_head, co, link);
+
+		if (co->callback(co)) {
+			co->expiry_value += co->period;
+			insert_callout(co);
+		}
+	}
+	schedule_next_timeout();
+
+	cpu_spin_unlock(&callout_lock);
+}
diff --git a/core/kernel/console.c b/core/kernel/console.c
index 6291b2c39eef37bb0b74c60ba39890b71879ee84..3ce61f9eceac8fa5e75675bf82271d4111fac6c3 100644
--- a/core/kernel/console.c
+++ b/core/kernel/console.c
@@ -6,10 +6,11 @@
 #include <compiler.h>
 #include <console.h>
 #include <drivers/cbmem_console.h>
+#include <drivers/semihosting_console.h>
+#include <drivers/ffa_console.h>
 #include <drivers/serial.h>
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
-#include <kernel/boot.h>
 #include <kernel/panic.h>
 #include <libfdt.h>
 #include <stdlib.h>
@@ -18,6 +19,21 @@
 
 static struct serial_chip *serial_console __nex_bss;
 
+/* May be overridden by platform */
+__weak void plat_console_init(void)
+{
+}
+
+void console_init(void)
+{
+	if (IS_ENABLED(CFG_SEMIHOSTING_CONSOLE))
+		semihosting_console_init(CFG_SEMIHOSTING_CONSOLE_FILE);
+	else if (IS_ENABLED(CFG_FFA_CONSOLE))
+		ffa_console_init();
+	else
+		plat_console_init();
+}
+
 void __weak console_putc(int ch)
 {
 	if (!serial_console)
diff --git a/core/kernel/delay.c b/core/kernel/delay.c
index 1c404f939165938b70f0fd28d75daa1db79016a7..91d636ec43c2243939725fcaaa27084d3017bf98 100644
--- a/core/kernel/delay.c
+++ b/core/kernel/delay.c
@@ -32,6 +32,21 @@
 #include <kernel/misc.h>
 
 #ifdef CFG_CORE_HAS_GENERIC_TIMER
+int timeout_elapsed_us(uint64_t expire)
+{
+	int64_t diff = delay_cnt_read() - expire;
+
+	if (MUL_OVERFLOW(diff, 1000000, &diff) ||
+	    diff < INT_MIN || diff > INT_MAX) {
+		if (timeout_elapsed(expire))
+			return INT_MAX;
+		else
+			return INT_MIN;
+	}
+
+	return diff / delay_cnt_freq();
+}
+
 void udelay(uint32_t us)
 {
 	uint64_t target = timeout_init_us(us);
diff --git a/core/kernel/dt.c b/core/kernel/dt.c
index 722fabb7d2fd6b61f79f2c0ecb8c7e8ad07c0cb7..e3dc559ce6c4eca625f29f4e1b266c460a2ad48e 100644
--- a/core/kernel/dt.c
+++ b/core/kernel/dt.c
@@ -9,7 +9,6 @@
 #include <kernel/dt.h>
 #include <kernel/dt_driver.h>
 #include <kernel/interrupt.h>
-#include <kernel/linker.h>
 #include <libfdt.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
@@ -19,6 +18,10 @@
 
 static struct dt_descriptor external_dt __nex_bss;
 
+#if defined(CFG_CORE_FFA)
+static void *manifest_dt __nex_bss;
+#endif
+
 const struct dt_driver *dt_find_compatible_driver(const void *fdt, int offs)
 {
 	const struct dt_device_match *dm;
@@ -107,11 +110,7 @@ int dt_map_dev(const void *fdt, int offs, vaddr_t *base, size_t *size,
 	if (st == DT_STATUS_DISABLED)
 		return -1;
 
-	pbase = fdt_reg_base_address(fdt, offs);
-	if (pbase == DT_INFO_INVALID_REG)
-		return -1;
-	sz = fdt_reg_size(fdt, offs);
-	if (sz == DT_INFO_INVALID_REG_SIZE)
+	if (fdt_reg_info(fdt, offs, &pbase, &sz))
 		return -1;
 
 	switch (mapping) {
@@ -173,28 +172,6 @@ bad:
 
 }
 
-paddr_t fdt_reg_base_address(const void *fdt, int offs)
-{
-	const void *reg;
-	int ncells;
-	int len;
-	int parent;
-
-	parent = fdt_parent_offset(fdt, offs);
-	if (parent < 0)
-		return DT_INFO_INVALID_REG;
-
-	reg = fdt_getprop(fdt, offs, "reg", &len);
-	if (!reg)
-		return DT_INFO_INVALID_REG;
-
-	ncells = fdt_address_cells(fdt, parent);
-	if (ncells < 0)
-		return DT_INFO_INVALID_REG;
-
-	return fdt_read_paddr(reg, ncells);
-}
-
 static size_t fdt_read_size(const uint32_t *cell, int n)
 {
 	uint32_t sz = 0;
@@ -211,32 +188,72 @@ static size_t fdt_read_size(const uint32_t *cell, int n)
 	return sz;
 }
 
-size_t fdt_reg_size(const void *fdt, int offs)
+int fdt_reg_info(const void *fdt, int offs, paddr_t *base, size_t *size)
 {
-	const uint32_t *reg;
-	int n;
-	int len;
-	int parent;
-
-	parent = fdt_parent_offset(fdt, offs);
-	if (parent < 0)
-		return DT_INFO_INVALID_REG_SIZE;
+	const fdt32_t *reg = NULL;
+	int addr_ncells = 0;
+	int size_ncells = 0;
+	int parent = 0;
+	int len = 0;
 
 	reg = (const uint32_t *)fdt_getprop(fdt, offs, "reg", &len);
 	if (!reg)
-		return DT_INFO_INVALID_REG_SIZE;
+		return -FDT_ERR_NOTFOUND;
 
-	n = fdt_address_cells(fdt, parent);
-	if (n < 1 || n > 2)
-		return DT_INFO_INVALID_REG_SIZE;
+	if (fdt_find_cached_parent_reg_cells(fdt, offs, &addr_ncells,
+					     &size_ncells) != 0) {
+		parent = fdt_parent_offset(fdt, offs);
+		if (parent < 0)
+			return -FDT_ERR_NOTFOUND;
 
-	reg += n;
+		addr_ncells = fdt_address_cells(fdt, parent);
+		if (addr_ncells < 0)
+			return -FDT_ERR_NOTFOUND;
 
-	n = fdt_size_cells(fdt, parent);
-	if (n < 1 || n > 2)
+		size_ncells = fdt_size_cells(fdt, parent);
+		if (size_ncells < 0)
+			return -FDT_ERR_NOTFOUND;
+	}
+
+	if ((size_t)len < addr_ncells * sizeof(*reg))
+		return -FDT_ERR_BADSTRUCTURE;
+
+	if (base) {
+		*base = fdt_read_paddr(reg, addr_ncells);
+		if (*base == DT_INFO_INVALID_REG)
+			return -FDT_ERR_NOTFOUND;
+	}
+
+	if (size) {
+		if ((size_t)len < (addr_ncells + size_ncells) * sizeof(*reg))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		*size = fdt_read_size(reg + addr_ncells, size_ncells);
+		if (*size == DT_INFO_INVALID_REG_SIZE)
+			return -FDT_ERR_NOTFOUND;
+	}
+
+	return 0;
+}
+
+paddr_t fdt_reg_base_address(const void *fdt, int offs)
+{
+	paddr_t base = 0;
+
+	if (fdt_reg_info(fdt, offs, &base, NULL))
+		return DT_INFO_INVALID_REG;
+
+	return base;
+}
+
+size_t fdt_reg_size(const void *fdt, int offs)
+{
+	size_t size = 0;
+
+	if (fdt_reg_info(fdt, offs, NULL, &size))
 		return DT_INFO_INVALID_REG_SIZE;
 
-	return fdt_read_size(reg, n);
+	return size;
 }
 
 static bool is_okay(const char *st, int len)
@@ -281,10 +298,10 @@ void fdt_fill_device_info(const void *fdt, struct dt_node_info *info, int offs)
 		.reset = DT_INFO_INVALID_RESET,
 		.interrupt = DT_INFO_INVALID_INTERRUPT,
 	};
-	const fdt32_t *cuint;
+	const fdt32_t *cuint = NULL;
 
-	dinfo.reg = fdt_reg_base_address(fdt, offs);
-	dinfo.reg_size = fdt_reg_size(fdt, offs);
+	/* Intentionally discard fdt_reg_info() return value */
+	fdt_reg_info(fdt, offs, &dinfo.reg, &dinfo.reg_size);
 
 	cuint = fdt_getprop(fdt, offs, "clocks", NULL);
 	if (cuint) {
@@ -450,6 +467,9 @@ void *get_dt(void)
 	if (!fdt)
 		fdt = get_external_dt();
 
+	if (!fdt)
+		fdt = get_manifest_dt();
+
 	return fdt;
 }
 
@@ -460,10 +480,247 @@ void *get_secure_dt(void)
 	if (!fdt && IS_ENABLED(CFG_MAP_EXT_DT_SECURE))
 		fdt = get_external_dt();
 
+	if (!fdt)
+		fdt = get_manifest_dt();
+
 	return fdt;
 }
 
 #if defined(CFG_EMBED_DTB)
+#ifdef CFG_DT_CACHED_NODE_INFO
+/*
+ * struct cached_node - Cached information of a DT node
+ *
+ * @node_offset: Offset of the node in @cached_node_info_fdt
+ * @parent_offset: Offset of @node_offset parent node
+ * @address_cells: #address-cells property value of the parent node or 0
+ * @size_cells: #size-cells property value of the parent node or 0
+ * @phandle: Phandle associated to the node or 0 if none
+ */
+struct cached_node {
+	int node_offset;
+	int parent_offset;
+	int8_t address_cells;
+	int8_t size_cells;
+	uint32_t phandle;
+};
+
+/*
+ * struct dt_node_cache - Reference to cached information of DT nodes
+ *
+ * @array: Array of the cached node
+ * @count: Number of initialized cells in @array
+ * @alloced_count: Number of allocated cells in @array
+ * @fdt: Reference to the FDT for which node information are cached
+ */
+struct dt_node_cache {
+	struct cached_node *array;
+	size_t count;
+	size_t alloced_count;
+	const void *fdt;
+};
+
+static struct dt_node_cache *dt_node_cache;
+
+static bool fdt_node_info_are_cached(const void *fdt)
+{
+	return dt_node_cache && dt_node_cache->fdt == fdt;
+}
+
+static struct cached_node *find_cached_parent_node(const void *fdt,
+						   int node_offset)
+{
+	struct cached_node *cell = NULL;
+	size_t n = 0;
+
+	if (!fdt_node_info_are_cached(fdt))
+		return NULL;
+
+	for (n = 0; n < dt_node_cache->count; n++)
+		if (dt_node_cache->array[n].node_offset == node_offset)
+			cell = dt_node_cache->array + n;
+
+	return cell;
+}
+
+int fdt_find_cached_parent_node(const void *fdt, int node_offset,
+				int *parent_offset)
+{
+	struct cached_node *cell = NULL;
+
+	cell = find_cached_parent_node(fdt, node_offset);
+	if (!cell)
+		return -FDT_ERR_NOTFOUND;
+
+	*parent_offset = cell->parent_offset;
+
+	return 0;
+}
+
+int fdt_find_cached_parent_reg_cells(const void *fdt, int node_offset,
+				     int *address_cells, int *size_cells)
+{
+	struct cached_node *cell = NULL;
+	int rc = 0;
+
+	cell = find_cached_parent_node(fdt, node_offset);
+	if (!cell)
+		return -FDT_ERR_NOTFOUND;
+
+	if (address_cells) {
+		if (cell->address_cells >= 0)
+			*address_cells = cell->address_cells;
+		else
+			rc = -FDT_ERR_NOTFOUND;
+	}
+
+	if (size_cells) {
+		if (cell->size_cells >= 0)
+			*size_cells = cell->size_cells;
+		else
+			rc = -FDT_ERR_NOTFOUND;
+	}
+
+	return rc;
+}
+
+int fdt_find_cached_node_phandle(const void *fdt, uint32_t phandle,
+				 int *node_offset)
+{
+	struct cached_node *cell = NULL;
+	size_t n = 0;
+
+	if (!fdt_node_info_are_cached(fdt))
+		return -FDT_ERR_NOTFOUND;
+
+	for (n = 0; n < dt_node_cache->count; n++)
+		if (dt_node_cache->array[n].phandle == phandle)
+			cell = dt_node_cache->array + n;
+
+	if (!cell)
+		return -FDT_ERR_NOTFOUND;
+
+	*node_offset = cell->node_offset;
+
+	return 0;
+}
+
+static TEE_Result realloc_cached_node_array(void)
+{
+	assert(dt_node_cache);
+
+	if (dt_node_cache->count + 1 > dt_node_cache->alloced_count) {
+		size_t new_count = dt_node_cache->alloced_count * 2;
+		struct cached_node *new = NULL;
+
+		if (!new_count)
+			new_count = 4;
+
+		new = realloc(dt_node_cache->array,
+			      sizeof(*dt_node_cache->array) * new_count);
+		if (!new)
+			return TEE_ERROR_OUT_OF_MEMORY;
+
+		dt_node_cache->array = new;
+		dt_node_cache->alloced_count = new_count;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result add_cached_node(int parent_offset,
+				  int node_offset, int address_cells,
+				  int size_cells)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	res = realloc_cached_node_array();
+	if (res)
+		return res;
+
+	dt_node_cache->array[dt_node_cache->count] = (struct cached_node){
+		.node_offset = node_offset,
+		.parent_offset = parent_offset,
+		.address_cells = address_cells,
+		.size_cells = size_cells,
+		.phandle = fdt_get_phandle(dt_node_cache->fdt, node_offset),
+	};
+
+	dt_node_cache->count++;
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result add_cached_node_subtree(int node_offset)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+	const fdt32_t *cuint = NULL;
+	int subnode_offset = 0;
+	int8_t addr_cells = -1;
+	int8_t size_cells = -1;
+
+	cuint = fdt_getprop(dt_node_cache->fdt, node_offset, "#address-cells",
+			    NULL);
+	if (cuint)
+		addr_cells = (int)fdt32_to_cpu(*cuint);
+
+	cuint = fdt_getprop(dt_node_cache->fdt, node_offset, "#size-cells",
+			    NULL);
+	if (cuint)
+		size_cells = (int)fdt32_to_cpu(*cuint);
+
+	fdt_for_each_subnode(subnode_offset, dt_node_cache->fdt, node_offset) {
+		res = add_cached_node(node_offset, subnode_offset, addr_cells,
+				      size_cells);
+		if (res)
+			return res;
+
+		res = add_cached_node_subtree(subnode_offset);
+		if (res)
+			return res;
+	}
+
+	return TEE_SUCCESS;
+}
+
+static TEE_Result release_node_cache_info(void)
+{
+	if (dt_node_cache) {
+		free(dt_node_cache->array);
+		free(dt_node_cache);
+		dt_node_cache = NULL;
+	}
+
+	return TEE_SUCCESS;
+}
+
+release_init_resource(release_node_cache_info);
+
+static void init_node_cache_info(const void *fdt)
+{
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	assert(!dt_node_cache);
+
+	dt_node_cache = calloc(1, sizeof(*dt_node_cache));
+	if (dt_node_cache) {
+		dt_node_cache->fdt = fdt;
+		res = add_cached_node_subtree(0);
+	} else {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	if (res) {
+		EMSG("Error %#"PRIx32", disable DT cached info", res);
+		release_node_cache_info();
+	}
+}
+#else
+static void init_node_cache_info(const void *fdt __unused)
+{
+}
+#endif /* CFG_DT_CACHED_NODE_INFO */
+
 void *get_embedded_dt(void)
 {
 	static bool checked;
@@ -477,6 +734,8 @@ void *get_embedded_dt(void)
 			panic("Invalid embedded DTB");
 
 		checked = true;
+
+		init_node_cache_info(embedded_secure_dtb);
 	}
 
 	return embedded_secure_dtb;
@@ -495,7 +754,10 @@ static int add_dt_overlay_fragment(struct dt_descriptor *dt, int ioffs)
 	int offs = 0;
 	int ret = 0;
 
-	snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id);
+	ret = snprintf(frag, sizeof(frag), "fragment@%d", dt->frag_id);
+	if (ret < 0 || (size_t)ret >= sizeof(frag))
+		return -1;
+
 	offs = fdt_add_subnode(dt->blob, ioffs, frag);
 	if (offs < 0)
 		return offs;
@@ -740,3 +1002,69 @@ int add_res_mem_dt_node(struct dt_descriptor *dt, const char *name,
 	}
 	return 0;
 }
+
+#if defined(CFG_CORE_FFA)
+void init_manifest_dt(void *fdt)
+{
+	manifest_dt = fdt;
+}
+
+void reinit_manifest_dt(void)
+{
+	paddr_t pa = (unsigned long)manifest_dt;
+	void *fdt = NULL;
+	int ret = 0;
+
+	if (!pa) {
+		EMSG("No manifest DT found");
+		return;
+	}
+
+	fdt = core_mmu_add_mapping(MEM_AREA_MANIFEST_DT, pa, CFG_DTB_MAX_SIZE);
+	if (!fdt)
+		panic("Failed to map manifest DT");
+
+	manifest_dt = fdt;
+
+	ret = fdt_check_full(fdt, CFG_DTB_MAX_SIZE);
+	if (ret < 0) {
+		EMSG("Invalid manifest Device Tree at %#lx: error %d", pa, ret);
+		panic();
+	}
+
+	IMSG("manifest DT found");
+}
+
+void *get_manifest_dt(void)
+{
+	return manifest_dt;
+}
+
+static TEE_Result release_manifest_dt(void)
+{
+	if (!manifest_dt)
+		return TEE_SUCCESS;
+
+	if (core_mmu_remove_mapping(MEM_AREA_MANIFEST_DT, manifest_dt,
+				    CFG_DTB_MAX_SIZE))
+		panic("Failed to remove temporary manifest DT mapping");
+	manifest_dt = NULL;
+
+	return TEE_SUCCESS;
+}
+
+boot_final(release_manifest_dt);
+#else
+void init_manifest_dt(void *fdt __unused)
+{
+}
+
+void reinit_manifest_dt(void)
+{
+}
+
+void *get_manifest_dt(void)
+{
+	return NULL;
+}
+#endif /*CFG_CORE_FFA*/
diff --git a/core/kernel/dt_driver.c b/core/kernel/dt_driver.c
index 4597bf221a716139173525c271d894aac3818890..9d183a7806b0c8ab58a0a67a7df2b34168373593 100644
--- a/core/kernel/dt_driver.c
+++ b/core/kernel/dt_driver.c
@@ -112,6 +112,7 @@ static void assert_type_is_valid(enum dt_driver_type type)
 	case DT_DRIVER_INTERRUPT:
 	case DT_DRIVER_REGULATOR:
 	case DT_DRIVER_NVMEM:
+	case DT_DRIVER_FIREWALL:
 		return;
 	default:
 		assert(0);
@@ -134,13 +135,15 @@ TEE_Result dt_driver_register_provider(const void *fdt, int nodeoffset,
 
 	provider_cells = fdt_get_dt_driver_cells(fdt, nodeoffset, type);
 	if (provider_cells < 0) {
-		DMSG("Failed to find provider cells: %d", provider_cells);
+		DMSG("Failed to find provider cells: %d on node %s",
+		     provider_cells, fdt_get_name(fdt, nodeoffset, NULL));
 		return TEE_ERROR_GENERIC;
 	}
 
 	phandle = fdt_get_phandle(fdt, nodeoffset);
 	if (phandle == (uint32_t)-1) {
-		DMSG("Failed to find provide phandle");
+		DMSG("Failed to find provider phandle on node %s",
+		     fdt_get_name(fdt, nodeoffset, NULL));
 		return TEE_ERROR_GENERIC;
 	}
 
@@ -198,6 +201,9 @@ int fdt_get_dt_driver_cells(const void *fdt, int nodeoffset,
 	case DT_DRIVER_GPIO:
 		cells_name = "#gpio-cells";
 		break;
+	case DT_DRIVER_FIREWALL:
+		cells_name = "#access-controller-cells";
+		break;
 	case DT_DRIVER_I2C:
 	case DT_DRIVER_REGULATOR:
 		return 0;
@@ -252,7 +258,7 @@ dt_driver_get_provider_by_phandle(uint32_t phandle, enum dt_driver_type type)
 static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv,
 					    const void *fdt, int phandle_node,
 					    const uint32_t *prop,
-					    void *device_ref)
+					    void *device_ref, int consumer_node)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	struct dt_pargs *pargs = NULL;
@@ -266,8 +272,11 @@ static TEE_Result device_from_provider_prop(struct dt_driver_provider *prv,
 	pargs->fdt = fdt;
 	pargs->phandle_node = phandle_node;
 	pargs->args_count = prv->provider_cells;
-	for (n = 0; n < prv->provider_cells; n++)
+	pargs->consumer_node = consumer_node;
+	for (n = 0; n < prv->provider_cells; n++) {
+		assert(prop);
 		pargs->args[n] = fdt32_to_cpu(prop[n]);
+	}
 
 	res = prv->get_of_device(pargs, prv->priv_data, device_ref);
 
@@ -295,8 +304,8 @@ TEE_Result dt_driver_device_from_parent(const void *fdt, int nodeoffset,
 		return TEE_ERROR_DEFER_DRIVER_INIT;
 	}
 
-	return device_from_provider_prop(prv, fdt, nodeoffset, NULL,
-					 device_ref);
+	return device_from_provider_prop(prv, fdt, parent, NULL, device_ref,
+					 nodeoffset);
 }
 
 TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
@@ -308,8 +317,8 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
 						       void *device_ref)
 {
 	int len = 0;
+	int phandle_node = -1;
 	const uint32_t *prop = NULL;
-	int phandle_node_unused = -1;
 	struct dt_driver_provider *prv = NULL;
 
 	prop = fdt_getprop(fdt, nodeoffs, prop_name, &len);
@@ -332,8 +341,11 @@ TEE_Result dt_driver_device_from_node_idx_prop_phandle(const char *prop_name,
 	if ((prop_index + 1) * sizeof(*prop) > (size_t)len)
 		return TEE_ERROR_ITEM_NOT_FOUND;
 
-	return device_from_provider_prop(prv, fdt, phandle_node_unused,
-					 prop + prop_index, device_ref);
+	phandle_node = fdt_node_offset_by_phandle(fdt, phandle);
+
+	return device_from_provider_prop(prv, fdt, phandle_node,
+					 prop + prop_index, device_ref,
+					 nodeoffs);
 }
 
 TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
@@ -349,6 +361,7 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 	int phandle_node = -1;
 	uint32_t phandle = 0;
 	const uint32_t *prop = NULL;
+	int consumer_node = nodeoffset;
 	struct dt_driver_provider *prv = NULL;
 
 	prop = fdt_getprop(fdt, nodeoffset, prop_name, &len);
@@ -387,6 +400,8 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 			prv = dt_driver_get_provider_by_node(nodeoffset, type);
 		} else {
 			prv = dt_driver_get_provider_by_phandle(phandle, type);
+			if (prv)
+				phandle_node = prv->nodeoffset;
 		}
 
 		if (prv) {
@@ -428,7 +443,8 @@ TEE_Result dt_driver_device_from_node_idx_prop(const char *prop_name,
 		idx32++;
 
 		return device_from_provider_prop(prv, fdt, phandle_node,
-						 prop + idx32, device_ref);
+						 prop + idx32, device_ref,
+						 consumer_node);
 	}
 
 	return TEE_ERROR_ITEM_NOT_FOUND;
diff --git a/core/kernel/initcall.c b/core/kernel/initcall.c
index 148a1781f3dd72629c7eb130ae000952b34022f4..785c99c5a3d8a426781c035ad0df43dc1083786f 100644
--- a/core/kernel/initcall.c
+++ b/core/kernel/initcall.c
@@ -8,59 +8,78 @@
 #include <trace.h>
 #include <kernel/linker.h>
 
-/*
- * Note: this function is weak just to make it possible to exclude it from
- * the unpaged area.
- */
-void __weak call_preinitcalls(void)
+static void do_init_calls(const char *type __maybe_unused,
+			  const struct initcall *begin,
+			  const struct initcall *end)
 {
 	const struct initcall *call = NULL;
 	TEE_Result ret = TEE_SUCCESS;
 
-	for (call = preinitcall_begin; call < preinitcall_end; call++) {
-		DMSG("level %d %s()", call->level, call->func_name);
+	for (call = begin; call < end; call++) {
+		DMSG("%s level %d %s()", type, call->level, call->func_name);
 		ret = call->func();
-		if (ret != TEE_SUCCESS) {
-			EMSG("Preinitcall __text_start + 0x%08" PRIxVA
-			     " failed", (vaddr_t)call - VCORE_START_VA);
+		if (ret) {
+			EMSG("%s __text_start + 0x%08"PRIxVA" failed",
+			     type, (vaddr_t)call - VCORE_START_VA);
 		}
 	}
 }
 
+#define DO_INIT_CALLS(name) \
+	do_init_calls(#name, name##_begin, name##_end)
+
 /*
  * Note: this function is weak just to make it possible to exclude it from
  * the unpaged area.
  */
-void __weak call_initcalls(void)
+void __weak call_preinitcalls(void)
 {
-	const struct initcall *call = NULL;
-	TEE_Result ret = TEE_SUCCESS;
+	DO_INIT_CALLS(preinitcall);
+}
 
-	for (call = initcall_begin; call < initcall_end; call++) {
-		DMSG("level %d %s()", call->level, call->func_name);
-		ret = call->func();
-		if (ret != TEE_SUCCESS) {
-			EMSG("Initcall __text_start + 0x%08" PRIxVA
-			     " failed", (vaddr_t)call - VCORE_START_VA);
-		}
-	}
+/*
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+void __weak call_early_initcalls(void)
+{
+	DO_INIT_CALLS(early_initcall);
 }
 
 /*
  * Note: this function is weak just to make it possible to exclude it from
  * the unpaged area.
  */
-void __weak call_finalcalls(void)
+void __weak call_service_initcalls(void)
 {
-	const struct initcall *call = NULL;
-	TEE_Result ret = TEE_SUCCESS;
+	DO_INIT_CALLS(service_initcall);
+}
 
-	for (call = finalcall_begin; call < finalcall_end; call++) {
-		DMSG("level %d %s()", call->level, call->func_name);
-		ret = call->func();
-		if (ret != TEE_SUCCESS) {
-			EMSG("Finalcall __text_start + 0x%08" PRIxVA
-			     " failed", (vaddr_t)call - VCORE_START_VA);
-		}
-	}
+/*
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+void __weak call_driver_initcalls(void)
+{
+	DO_INIT_CALLS(driver_initcall);
+}
+
+/*
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+void __weak call_initcalls(void)
+{
+	call_early_initcalls();
+	call_service_initcalls();
+	call_driver_initcalls();
+}
+
+/*
+ * Note: this function is weak just to make it possible to exclude it from
+ * the unpaged area.
+ */
+void __weak call_finalcalls(void)
+{
+	DO_INIT_CALLS(finalcall);
 }
diff --git a/core/kernel/ldelf_loader.c b/core/kernel/ldelf_loader.c
index cf00f7d886ec4d2d9125963640431c4c01cdcbde..514a0196d89bc6f8f486b40b9bc4ffbc92e6bf99 100644
--- a/core/kernel/ldelf_loader.c
+++ b/core/kernel/ldelf_loader.c
@@ -31,7 +31,7 @@ static const bool is_32bit;
 static TEE_Result alloc_and_map_fobj(struct user_mode_ctx *uctx, size_t sz,
 				     uint32_t prot, uint32_t flags, vaddr_t *va)
 {
-	size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
+	size_t num_pgs = ROUNDUP_DIV(sz, SMALL_PAGE_SIZE);
 	struct fobj *fobj = fobj_ta_mem_alloc(num_pgs);
 	struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL,
 						 TEE_MATTR_MEM_TYPE_TAGGED);
diff --git a/core/kernel/mutex.c b/core/kernel/mutex.c
index 45028c43181d7a61313f23bde3451cb108418cc7..cbefc109ed410236b09a94c27243a623079fbfe1 100644
--- a/core/kernel/mutex.c
+++ b/core/kernel/mutex.c
@@ -4,6 +4,7 @@
  */
 
 #include <kernel/mutex.h>
+#include <kernel/mutex_pm_aware.h>
 #include <kernel/panic.h>
 #include <kernel/refcount.h>
 #include <kernel/spinlock.h>
@@ -60,7 +61,7 @@ static void __mutex_lock(struct mutex *m, const char *fname, int lineno)
 			 * Someone else is holding the lock, wait in normal
 			 * world for the lock to become available.
 			 */
-			wq_wait_final(&m->wq, &wqe, m, fname, lineno);
+			wq_wait_final(&m->wq, &wqe, 0, m, fname, lineno);
 		} else
 			return;
 	}
@@ -205,7 +206,7 @@ static void __mutex_read_lock(struct mutex *m, const char *fname, int lineno)
 			 * Someone else is holding the lock, wait in normal
 			 * world for the lock to become available.
 			 */
-			wq_wait_final(&m->wq, &wqe, m, fname, lineno);
+			wq_wait_final(&m->wq, &wqe, 0, m, fname, lineno);
 		} else
 			return;
 	}
@@ -342,6 +343,39 @@ unsigned int mutex_get_recursive_lock_depth(struct recursive_mutex *m)
 	return refcount_val(&m->lock_depth);
 }
 
+void mutex_pm_aware_init(struct mutex_pm_aware *m)
+{
+	*m = (struct mutex_pm_aware)MUTEX_PM_AWARE_INITIALIZER;
+}
+
+void mutex_pm_aware_destroy(struct mutex_pm_aware *m)
+{
+	mutex_destroy(&m->mutex);
+}
+
+void mutex_pm_aware_lock(struct mutex_pm_aware *m)
+{
+	if (thread_get_id_may_fail() == THREAD_ID_INVALID) {
+		if (!cpu_spin_trylock(&m->lock) || m->mutex.state)
+			panic();
+	} else {
+		mutex_lock(&m->mutex);
+		if (!thread_spin_trylock(&m->lock))
+			panic();
+	}
+}
+
+void mutex_pm_aware_unlock(struct mutex_pm_aware *m)
+{
+	if (thread_get_id_may_fail() == THREAD_ID_INVALID) {
+		assert(!m->mutex.state);
+		cpu_spin_unlock(&m->lock);
+	} else {
+		thread_spin_unlock(&m->lock);
+		mutex_unlock(&m->mutex);
+	}
+}
+
 void condvar_init(struct condvar *cv)
 {
 	*cv = (struct condvar)CONDVAR_INITIALIZER;
@@ -393,13 +427,15 @@ void condvar_broadcast(struct condvar *cv)
 }
 #endif /*CFG_MUTEX_DEBUG*/
 
-static void __condvar_wait(struct condvar *cv, struct mutex *m,
-			const char *fname, int lineno)
+static TEE_Result __condvar_wait_timeout(struct condvar *cv, struct mutex *m,
+					 uint32_t timeout_ms, const char *fname,
+					 int lineno)
 {
-	uint32_t old_itr_status;
-	struct wait_queue_elem wqe;
-	short old_state;
-	short new_state;
+	TEE_Result res = TEE_SUCCESS;
+	uint32_t old_itr_status = 0;
+	struct wait_queue_elem wqe = { };
+	short old_state = 0;
+	short new_state = 0;
 
 	mutex_unlock_check(m);
 
@@ -434,23 +470,38 @@ static void __condvar_wait(struct condvar *cv, struct mutex *m,
 	if (!new_state)
 		wq_wake_next(&m->wq, m, fname, lineno);
 
-	wq_wait_final(&m->wq, &wqe, m, fname, lineno);
+	res = wq_wait_final(&m->wq, &wqe, timeout_ms, m, fname, lineno);
 
 	if (old_state > 0)
 		mutex_read_lock(m);
 	else
 		mutex_lock(m);
+
+	return res;
 }
 
 #ifdef CFG_MUTEX_DEBUG
 void condvar_wait_debug(struct condvar *cv, struct mutex *m,
 			const char *fname, int lineno)
 {
-	__condvar_wait(cv, m, fname, lineno);
+	__condvar_wait_timeout(cv, m, 0, fname, lineno);
+}
+
+TEE_Result condvar_wait_timeout_debug(struct condvar *cv, struct mutex *m,
+				      uint32_t timeout_ms, const char *fname,
+				      int lineno)
+{
+	return __condvar_wait_timeout(cv, m, timeout_ms, fname, lineno);
 }
 #else
 void condvar_wait(struct condvar *cv, struct mutex *m)
 {
-	__condvar_wait(cv, m, NULL, -1);
+	__condvar_wait_timeout(cv, m, 0, NULL, -1);
+}
+
+TEE_Result condvar_wait_timeout(struct condvar *cv, struct mutex *m,
+				uint32_t timeout_ms)
+{
+	return __condvar_wait_timeout(cv, m, timeout_ms, NULL, -1);
 }
 #endif
diff --git a/core/kernel/notif.c b/core/kernel/notif.c
index d23b4fcd816b65ac471ade4da1575e716d5788ff..fa879e11d4b54a90ada0f5a84812a01ed44a0cf5 100644
--- a/core/kernel/notif.c
+++ b/core/kernel/notif.c
@@ -1,34 +1,58 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2021-2023, Linaro Limited
+ * Copyright (c) 2021-2024, Linaro Limited
  */
 
+#include <initcall.h>
 #include <kernel/mutex.h>
 #include <kernel/notif.h>
+#include <kernel/panic.h>
 #include <kernel/spinlock.h>
 #include <kernel/thread.h>
+#include <kernel/virtualization.h>
+#include <mm/core_memprot.h>
 #include <optee_rpc_cmd.h>
 #include <types_ext.h>
 
 #if defined(CFG_CORE_ASYNC_NOTIF)
+struct notif_data {
+	bool notif_started;
+};
+
 static struct mutex notif_mutex = MUTEX_INITIALIZER;
-static unsigned int notif_lock = SPINLOCK_UNLOCK;
-static bool notif_started;
+static unsigned int notif_lock __nex_data = SPINLOCK_UNLOCK;
+
+static struct notif_data default_notif_data;
+static unsigned int notif_data_id __nex_bss;
 
 SLIST_HEAD(notif_driver_head, notif_driver);
-static struct notif_driver_head notif_driver_head =
+static struct notif_driver_head notif_driver_head __nex_data =
 	SLIST_HEAD_INITIALIZER(&notif_driver_head);
 
+static struct notif_data *get_notif_data(struct guest_partition *prtn)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		assert(prtn);
+		return virt_get_guest_spec_data(prtn, notif_data_id);
+	}
+	return &default_notif_data;
+}
 
-bool notif_async_is_started(void)
+bool notif_async_is_started(uint16_t guest_id)
 {
+	struct guest_partition *prtn = virt_get_guest(guest_id);
 	uint32_t old_itr_status = 0;
 	bool ret = false;
 
-	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
-	ret = notif_started;
-	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
+	if (!IS_ENABLED(CFG_NS_VIRTUALIZATION) || prtn) {
+		struct notif_data *ndata = get_notif_data(prtn);
 
+		old_itr_status = cpu_spin_lock_xsave(&notif_lock);
+		ret = ndata->notif_started;
+		cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
+	}
+
+	virt_put_guest(prtn);
 	return ret;
 }
 
@@ -36,6 +60,8 @@ void notif_register_driver(struct notif_driver *ndrv)
 {
 	uint32_t old_itr_status = 0;
 
+	assert(is_nexus(ndrv) && is_unpaged(ndrv->atomic_cb));
+
 	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
 
 	SLIST_INSERT_HEAD(&notif_driver_head, ndrv, link);
@@ -54,31 +80,43 @@ void notif_unregister_driver(struct notif_driver *ndrv)
 	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
 }
 
-void notif_deliver_atomic_event(enum notif_event ev)
+void notif_deliver_atomic_event(enum notif_event ev, uint16_t guest_id)
 {
-	uint32_t old_itr_status = 0;
+	struct guest_partition *prtn = virt_get_guest(guest_id);
+	struct notif_data *ndata = get_notif_data(prtn);
 	struct notif_driver *nd = NULL;
-
-	assert(ev == NOTIF_EVENT_STARTED);
+	uint32_t old_itr_status = 0;
 
 	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
 
-	if (notif_started) {
-		DMSG("Already started");
-		goto out;
+	switch (ev) {
+	case NOTIF_EVENT_STARTED:
+		if (ndata->notif_started) {
+			DMSG("Already started");
+			goto out;
+		}
+		ndata->notif_started = true;
+		break;
+	case NOTIF_EVENT_SHUTDOWN:
+		break;
+	default:
+		EMSG("Unknown event %d", (int)ev);
+		panic();
 	}
-	notif_started = true;
 
 	SLIST_FOREACH(nd, &notif_driver_head, link)
 		if (nd->atomic_cb)
-			nd->atomic_cb(nd, ev);
+			nd->atomic_cb(nd, ev, guest_id);
 
 out:
 	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
+	virt_put_guest(prtn);
 }
 
 void notif_deliver_event(enum notif_event ev)
 {
+	struct guest_partition *prtn = virt_get_current_guest();
+	struct notif_data *ndata = get_notif_data(prtn);
 	uint32_t old_itr_status = 0;
 	struct notif_driver *nd = NULL;
 	struct notif_driver *nd_tmp = NULL;
@@ -89,13 +127,13 @@ void notif_deliver_event(enum notif_event ev)
 	mutex_lock(&notif_mutex);
 	old_itr_status = cpu_spin_lock_xsave(&notif_lock);
 
-	if (!notif_started) {
+	if (!ndata || !ndata->notif_started) {
 		DMSG("Not started ev %d", (int)ev);
 		goto out;
 	}
 
 	if (ev == NOTIF_EVENT_STOPPED)
-		notif_started = false;
+		ndata->notif_started = false;
 
 	SLIST_FOREACH_SAFE(nd, &notif_driver_head, link, nd_tmp) {
 		cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
@@ -105,7 +143,7 @@ void notif_deliver_event(enum notif_event ev)
 
 		old_itr_status = cpu_spin_lock_xsave(&notif_lock);
 
-		if (ev == NOTIF_EVENT_STOPPED && notif_started) {
+		if (ev == NOTIF_EVENT_STOPPED && ndata->notif_started) {
 			DMSG("Started again while stopping");
 			goto out;
 		}
@@ -114,22 +152,40 @@ void notif_deliver_event(enum notif_event ev)
 out:
 	cpu_spin_unlock_xrestore(&notif_lock, old_itr_status);
 	mutex_unlock(&notif_mutex);
+	virt_put_guest(prtn);
 }
+
+#ifdef CFG_NS_VIRTUALIZATION
+static TEE_Result nex_init_notif(void)
+{
+	return virt_add_guest_spec_data(&notif_data_id,
+					sizeof(struct notif_data), NULL);
+}
+nex_early_init(nex_init_notif);
+#endif
+
 #endif /*CFG_CORE_ASYNC_NOTIF*/
 
-static TEE_Result notif_rpc(uint32_t func, uint32_t value)
+static TEE_Result notif_rpc(uint32_t func, uint32_t value1, uint32_t value2)
 {
-	struct thread_param params = THREAD_PARAM_VALUE(IN, func, value, 0);
+	struct thread_param params =
+		THREAD_PARAM_VALUE(IN, func, value1, value2);
 
 	return thread_rpc_cmd(OPTEE_RPC_CMD_NOTIFICATION, 1, &params);
 }
 
 TEE_Result notif_wait(uint32_t value)
 {
-	return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value);
+	return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value, 0);
 }
 
 TEE_Result notif_send_sync(uint32_t value)
 {
-	return notif_rpc(OPTEE_RPC_NOTIFICATION_SEND, value);
+	return notif_rpc(OPTEE_RPC_NOTIFICATION_SEND, value, 0);
+}
+
+TEE_Result notif_wait_timeout(uint32_t value, uint32_t timeout_ms)
+{
+	return notif_rpc(OPTEE_RPC_NOTIFICATION_WAIT, value, timeout_ms);
 }
+
diff --git a/core/kernel/notif_default.c b/core/kernel/notif_default.c
index 85b156867d660116dd39736966bb634502ff1dbd..53de075fd0fce6aa9278ab27553941c298a2fa8a 100644
--- a/core/kernel/notif_default.c
+++ b/core/kernel/notif_default.c
@@ -1,98 +1,168 @@
 // SPDX-License-Identifier: BSD-2-Clause
 /*
- * Copyright (c) 2021-2023, Linaro Limited
+ * Copyright (c) 2021-2024, Linaro Limited
  */
 
 #include <assert.h>
 #include <bitstring.h>
+#include <config.h>
+#include <initcall.h>
 #include <kernel/interrupt.h>
 #include <kernel/notif.h>
 #include <kernel/spinlock.h>
+#include <kernel/virtualization.h>
 #include <trace.h>
 #include <types_ext.h>
 
-static bitstr_t bit_decl(notif_values, NOTIF_ASYNC_VALUE_MAX + 1);
-static bitstr_t bit_decl(notif_alloc_values, NOTIF_ASYNC_VALUE_MAX + 1);
+struct notif_vm_bitmap {
+	bool alloc_values_inited;
+	bitstr_t bit_decl(values, NOTIF_ASYNC_VALUE_MAX + 1);
+	bitstr_t bit_decl(alloc_values, NOTIF_ASYNC_VALUE_MAX + 1);
+};
+
 static unsigned int notif_default_lock = SPINLOCK_UNLOCK;
+/* Id used to look up the guest specific struct notif_vm_bitmap */
+static unsigned int notif_vm_bitmap_id __nex_bss;
+/* Notification state when ns-virtualization isn't enabled */
+static struct notif_vm_bitmap default_notif_vm_bitmap;
+
+static struct notif_vm_bitmap *get_notif_vm_bitmap(struct guest_partition *prtn)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		if (!prtn)
+			return NULL;
+		return virt_get_guest_spec_data(prtn, notif_vm_bitmap_id);
+	}
+	return &default_notif_vm_bitmap;
+}
 
 TEE_Result notif_alloc_async_value(uint32_t *val)
 {
-	static bool alloc_values_inited;
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
+	TEE_Result res = TEE_SUCCESS;
 	uint32_t old_itr_status = 0;
 	int bit = 0;
 
 	assert(interrupt_can_raise_pi(interrupt_get_main_chip()));
 
+	prtn = virt_get_current_guest();
+	nvb = get_notif_vm_bitmap(prtn);
+	if (!nvb) {
+		res = TEE_ERROR_BAD_PARAMETERS;
+		goto out;
+	}
+
 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
 
-	if (!alloc_values_inited) {
-		bit_set(notif_alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF);
-		alloc_values_inited = true;
+	if (!nvb->alloc_values_inited) {
+		bit_set(nvb->alloc_values, NOTIF_VALUE_DO_BOTTOM_HALF);
+		nvb->alloc_values_inited = true;
 	}
 
-	bit_ffc(notif_alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
-	if (bit >= 0) {
-		*val = bit;
-		bit_set(notif_alloc_values, bit);
+	bit_ffc(nvb->alloc_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+	if (bit < 0) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto out_unlock;
 	}
+	*val = bit;
+	bit_set(nvb->alloc_values, bit);
 
+out_unlock:
 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+out:
+	virt_put_guest(prtn);
 
-	if (bit < 0)
-		return TEE_ERROR_OUT_OF_MEMORY;
-
-	return TEE_SUCCESS;
+	return res;
 }
 
 void notif_free_async_value(uint32_t val)
 {
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t old_itr_status = 0;
 
+	prtn = virt_get_current_guest();
+	nvb = get_notif_vm_bitmap(prtn);
+	if (!nvb)
+		goto out;
+
 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
 
 	assert(val < NOTIF_ASYNC_VALUE_MAX);
-	assert(bit_test(notif_alloc_values, val));
-	bit_clear(notif_alloc_values, val);
+	assert(bit_test(nvb->alloc_values, val));
+	bit_clear(nvb->alloc_values, val);
 
 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+out:
+	virt_put_guest(prtn);
 }
 
 uint32_t notif_get_value(bool *value_valid, bool *value_pending)
 {
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t old_itr_status = 0;
 	uint32_t res = 0;
-	int bit = 0;
+	int bit = -1;
+
+	prtn = virt_get_current_guest();
+	nvb = get_notif_vm_bitmap(prtn);
+	if (!nvb) {
+		*value_valid = false;
+		goto out;
+	}
 
 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
 
-	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+	bit_ffs(nvb->values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
 	*value_valid = (bit >= 0);
-	if (!*value_valid) {
-		*value_pending = false;
-		goto out;
-	}
+	if (!*value_valid)
+		goto out_unlock;
 
 	res = bit;
-	bit_clear(notif_values, res);
-	bit_ffs(notif_values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
-	*value_pending = (bit >= 0);
-out:
+	bit_clear(nvb->values, res);
+	bit_ffs(nvb->values, (int)NOTIF_ASYNC_VALUE_MAX + 1, &bit);
+
+out_unlock:
 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+out:
+	virt_put_guest(prtn);
+	*value_pending = (bit >= 0);
 
 	return res;
 }
 
-void notif_send_async(uint32_t value)
+void notif_send_async(uint32_t value, uint16_t guest_id)
 {
+	struct guest_partition *prtn = NULL;
+	struct notif_vm_bitmap *nvb = NULL;
 	uint32_t old_itr_status = 0;
 	struct itr_chip *itr_chip = interrupt_get_main_chip();
 
 	assert(value <= NOTIF_ASYNC_VALUE_MAX);
+
+	prtn = virt_get_guest(guest_id);
+	nvb = get_notif_vm_bitmap(prtn);
+	if (!nvb)
+		goto out;
+
 	old_itr_status = cpu_spin_lock_xsave(&notif_default_lock);
 
-	DMSG("0x%"PRIx32, value);
-	bit_set(notif_values, value);
+	bit_set(nvb->values, value);
 	interrupt_raise_pi(itr_chip, CFG_CORE_ASYNC_NOTIF_GIC_INTID);
 
 	cpu_spin_unlock_xrestore(&notif_default_lock, old_itr_status);
+out:
+	virt_put_guest(prtn);
+}
+
+static TEE_Result notif_init(void)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION) &&
+	    virt_add_guest_spec_data(&notif_vm_bitmap_id,
+				     sizeof(struct notif_vm_bitmap), NULL))
+		panic("virt_add_guest_spec_data");
+	return TEE_SUCCESS;
 }
+nex_service_init(notif_init);
diff --git a/core/kernel/panic.c b/core/kernel/panic.c
index 9edef97d81b52cb76e179807f24d871c2a86e14d..17d4bb066c91ce1bb14bec3ce6f7021fe842e9f5 100644
--- a/core/kernel/panic.c
+++ b/core/kernel/panic.c
@@ -26,7 +26,7 @@ multi_core_panic_it_handler(struct itr_handler *hdl __unused)
 		cpu_idle();
 }
 
-static struct itr_handler multi_core_panic_handler = {
+static struct itr_handler multi_core_panic_handler __nex_data = {
 	.it = CFG_HALT_CORES_ON_PANIC_SGI,
 	.handler = multi_core_panic_it_handler,
 };
@@ -58,14 +58,14 @@ static TEE_Result init_multi_core_panic_handler(void)
 	return TEE_SUCCESS;
 }
 
-boot_final(init_multi_core_panic_handler);
+nex_driver_init_late(init_multi_core_panic_handler);
 
 void __do_panic(const char *file __maybe_unused,
 		const int line __maybe_unused,
 		const char *func __maybe_unused,
 		const char *msg __maybe_unused)
 {
-	/* disable prehemption */
+	/* disable preemption */
 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
 
 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
diff --git a/core/kernel/pm.c b/core/kernel/pm.c
index 4146464bd396114297559eda24fab03b6f9dde54..efd553f145c46d7c522330ee6f06d92912171f2c 100644
--- a/core/kernel/pm.c
+++ b/core/kernel/pm.c
@@ -6,6 +6,7 @@
 #include <keep.h>
 #include <kernel/panic.h>
 #include <kernel/pm.h>
+#include <kernel/spinlock.h>
 #include <malloc.h>
 #include <mm/core_memprot.h>
 #include <string.h>
@@ -13,6 +14,7 @@
 
 #define PM_FLAG_SUSPENDED	BIT(0)
 
+static unsigned int pm_list_lock = SPINLOCK_UNLOCK;
 static struct pm_callback_handle *pm_cb_ref;
 static size_t pm_cb_count;
 
@@ -35,6 +37,7 @@ void register_pm_cb(struct pm_callback_handle *pm_hdl)
 	struct pm_callback_handle *ref = NULL;
 	const char *name = pm_hdl->name;
 	size_t count = pm_cb_count;
+	uint32_t exceptions = 0;
 
 	verify_cb_args(pm_hdl);
 
@@ -47,6 +50,8 @@ void register_pm_cb(struct pm_callback_handle *pm_hdl)
 			panic();
 	}
 
+	exceptions = cpu_spin_lock_xsave(&pm_list_lock);
+
 	ref = realloc(pm_cb_ref, sizeof(*ref) * (count + 1));
 	if (!ref)
 		panic();
@@ -57,6 +62,30 @@ void register_pm_cb(struct pm_callback_handle *pm_hdl)
 
 	pm_cb_count = count + 1;
 	pm_cb_ref = ref;
+
+	cpu_spin_unlock_xrestore(&pm_list_lock, exceptions);
+}
+
+void unregister_pm_cb(struct pm_callback_handle *pm_hdl)
+{
+	uint32_t exceptions = 0;
+	size_t n = 0;
+
+	exceptions = cpu_spin_lock_xsave(&pm_list_lock);
+
+	for (n = 0; n < pm_cb_count; n++)
+		if (pm_cb_ref[n].callback == pm_hdl->callback &&
+		    pm_cb_ref[n].handle == pm_hdl->handle &&
+		    pm_cb_ref[n].order == pm_hdl->order)
+			break;
+
+	if (n < pm_cb_count) {
+		pm_cb_count--;
+		memmove(pm_cb_ref + n, pm_cb_ref + n + 1,
+			(pm_cb_count - n) * sizeof(*pm_cb_ref));
+	}
+
+	cpu_spin_unlock_xrestore(&pm_list_lock, exceptions);
 }
 
 static TEE_Result do_pm_callback(enum pm_op op, uint32_t pm_hint,
diff --git a/core/kernel/pseudo_ta.c b/core/kernel/pseudo_ta.c
index 828a1d844e6ef5ea61e9eb2fc4d0e42fb90557e8..587faa41a770919733dc1c9cf54717c076b73dd4 100644
--- a/core/kernel/pseudo_ta.c
+++ b/core/kernel/pseudo_ta.c
@@ -294,6 +294,12 @@ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
 	struct tee_ta_ctx *ctx;
 	const struct pseudo_ta_head *ta;
 
+	/*
+	 * Caller is expected to hold tee_ta_mutex for safe changes
+	 * in @s and registering of the context in tee_ctxes list.
+	 */
+	assert(mutex_is_locked(&tee_ta_mutex));
+
 	DMSG("Lookup pseudo TA %pUl", (void *)uuid);
 
 	ta = SCATTERED_ARRAY_BEGIN(pseudo_tas, struct pseudo_ta_head);
@@ -306,7 +312,6 @@ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
 		ta++;
 	}
 
-	/* Load a new TA and create a session */
 	DMSG("Open %s", ta->name);
 	stc = calloc(1, sizeof(struct pseudo_ta_ctx));
 	if (!stc)
@@ -319,10 +324,8 @@ TEE_Result tee_ta_init_pseudo_ta_session(const TEE_UUID *uuid,
 	ctx->ts_ctx.uuid = ta->uuid;
 	ctx->ts_ctx.ops = &pseudo_ta_ops;
 
-	mutex_lock(&tee_ta_mutex);
 	s->ts_sess.ctx = &ctx->ts_ctx;
 	TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link);
-	mutex_unlock(&tee_ta_mutex);
 
 	DMSG("%s : %pUl", stc->pseudo_ta->name, (void *)&ctx->ts_ctx.uuid);
 
diff --git a/core/kernel/ree_fs_ta.c b/core/kernel/ree_fs_ta.c
index 9550364380a55645011112807e6cd8b9fbc4e52f..a8ecb7c988fa5587eee4f892c8563e298f59866c 100644
--- a/core/kernel/ree_fs_ta.c
+++ b/core/kernel/ree_fs_ta.c
@@ -44,17 +44,17 @@
 #include <kernel/user_access.h>
 #include <mm/core_memprot.h>
 #include <mm/mobj.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_mm.h>
 #include <optee_rpc_cmd.h>
 #include <signed_hdr.h>
 #include <stdlib.h>
 #include <string.h>
-#include <tee_api_defines_extensions.h>
-#include <tee_api_types.h>
 #include <tee/tee_pobj.h>
-#include <tee/tee_svc_storage.h>
 #include <tee/tee_ta_enc_manager.h>
 #include <tee/uuid.h>
+#include <tee_api_defines_extensions.h>
+#include <tee_api_types.h>
 #include <utee_defines.h>
 
 struct ree_fs_ta_handle {
@@ -720,13 +720,13 @@ static TEE_Result buf_ta_open(const TEE_UUID *uuid,
 	if (res)
 		goto err;
 
-	handle->mm = tee_mm_alloc(&tee_mm_sec_ddr, handle->ta_size);
+	handle->mm = phys_mem_ta_alloc(handle->ta_size);
 	if (!handle->mm) {
 		res = TEE_ERROR_OUT_OF_MEMORY;
 		goto err;
 	}
 	handle->buf = phys_to_virt(tee_mm_get_smem(handle->mm),
-				   MEM_AREA_TA_RAM, handle->ta_size);
+				   MEM_AREA_SEC_RAM_OVERALL, handle->ta_size);
 	if (!handle->buf) {
 		res = TEE_ERROR_OUT_OF_MEMORY;
 		goto err;
diff --git a/core/kernel/scall.c b/core/kernel/scall.c
index 2dc92221f47a9c554cd68f4f0506f7a347c877e6..4d8869fd7682c2f60ae2bedfe98ae0bf19285e19 100644
--- a/core/kernel/scall.c
+++ b/core/kernel/scall.c
@@ -8,8 +8,6 @@
 #include <kernel/abort.h>
 #include <kernel/arch_scall.h>
 #include <kernel/ldelf_syscalls.h>
-#include <kernel/misc.h>
-#include <kernel/panic.h>
 #include <kernel/scall.h>
 #include <kernel/tee_ta_manager.h>
 #include <kernel/thread.h>
@@ -19,7 +17,6 @@
 #include <ldelf.h>
 #include <mm/vm.h>
 #include <speculation_barrier.h>
-#include <string.h>
 #include <tee/svc_cache.h>
 #include <tee_syscall_numbers.h>
 #include <tee/tee_svc_cryp.h>
diff --git a/core/kernel/semihosting.c b/core/kernel/semihosting.c
new file mode 100644
index 0000000000000000000000000000000000000000..83895ff240f768c9036031049fa32fd910bc3b2e
--- /dev/null
+++ b/core/kernel/semihosting.c
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024 Andes Technology Corporation
+ */
+
+#include <kernel/semihosting.h>
+#include <string.h>
+
+/*
+ * ARM and RISC-V have defined the standard way to perform
+ * the semihosting operations.
+ * - Operation codes and open modes are identical.
+ * - The implementation of the low-level __do_semihosting() call is
+ *   architecture-specific.
+ * - Arm semihosting interface:
+ *   https://developer.arm.com/documentation/dui0471/g/Semihosting/The-semihosting-interface
+ * - RISC-V semihosting interface:
+ *   https://github.com/riscv-non-isa/riscv-semihosting/blob/main/binary-interface.adoc
+ */
+
+/* An integer that specifies the file open mode */
+enum semihosting_open_mode {
+	SEMIHOSTING_OPEN_R = 0,
+	SEMIHOSTING_OPEN_RB = 1,
+	SEMIHOSTING_OPEN_RX = 2,
+	SEMIHOSTING_OPEN_RXB = 3,
+	SEMIHOSTING_OPEN_W = 4,
+	SEMIHOSTING_OPEN_WB = 5,
+	SEMIHOSTING_OPEN_WX = 6,
+	SEMIHOSTING_OPEN_WXB = 7,
+	SEMIHOSTING_OPEN_A = 8,
+	SEMIHOSTING_OPEN_AB = 9,
+	SEMIHOSTING_OPEN_AX = 10,
+	SEMIHOSTING_OPEN_AXB = 11,
+};
+
+enum semihosting_sys_ops {
+	/* Regular operations */
+	SEMIHOSTING_SYS_OPEN = 0x01,
+	SEMIHOSTING_SYS_CLOSE = 0x02,
+	SEMIHOSTING_SYS_WRITEC = 0x03,
+	SEMIHOSTING_SYS_WRITE = 0x05,
+	SEMIHOSTING_SYS_READ = 0x06,
+	SEMIHOSTING_SYS_READC = 0x07,
+};
+
+struct semihosting_param_t {
+	uintptr_t param0;
+	uintptr_t param1;
+	uintptr_t param2;
+};
+
+/**
+ * @brief Read one character byte from the semihosting host debug terminal
+ *
+ * @retval the character read from the semihosting host
+ */
+char semihosting_sys_readc(void)
+{
+	return __do_semihosting(SEMIHOSTING_SYS_READC, 0);
+}
+
+/**
+ * @brief Write one character byte to the semihosting host debug terminal
+ * @param c: the character to be written
+ */
+void semihosting_sys_writec(char c)
+{
+	__do_semihosting(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&c);
+}
+
+/**
+ * @brief Request the semihosting host to open a file on the host system
+ * @param fname: the path or name of the file
+ * @param flags: sys/fcntl.h standard flags to open the file with
+ *
+ * @retval nonzero if OK, or -1 if fails
+ */
+int semihosting_open(const char *fname, int flags)
+{
+	int semi_open_flags = 0;
+	const int flags_mask = O_RDONLY | O_WRONLY | O_RDWR |
+			       O_CREAT | O_TRUNC | O_APPEND;
+	struct semihosting_param_t arg = { };
+
+	/* Convert the flags to semihosting open. */
+	switch (flags & flags_mask) {
+	case O_RDONLY:				/* 'r' */
+		semi_open_flags = SEMIHOSTING_OPEN_R;
+		break;
+	case O_WRONLY | O_CREAT | O_TRUNC:	/* 'w' */
+		semi_open_flags = SEMIHOSTING_OPEN_W;
+		break;
+	case O_WRONLY | O_CREAT | O_APPEND:	/* 'a' */
+		semi_open_flags = SEMIHOSTING_OPEN_A;
+		break;
+	case O_RDWR:				/* 'r+' */
+		semi_open_flags = SEMIHOSTING_OPEN_RX;
+		break;
+	case O_RDWR | O_CREAT | O_TRUNC:	/* 'w+' */
+		semi_open_flags = SEMIHOSTING_OPEN_WX;
+		break;
+	case O_RDWR | O_CREAT | O_APPEND:	/* 'a+' */
+		semi_open_flags = SEMIHOSTING_OPEN_AX;
+		break;
+	default:
+		return -1;
+	}
+
+	arg.param0 = (uintptr_t)fname;
+	arg.param1 = semi_open_flags;
+	arg.param2 = strlen(fname);
+
+	return (int)__do_semihosting(SEMIHOSTING_SYS_OPEN, (uintptr_t)&arg);
+}
+
+/**
+ * @brief Read data from a file on the semihosting host system
+ * @param fd: a handle for a file previously opened
+ * @param ptr: pointer to a buffer
+ * @param len: the number of bytes to read to the buffer from the file
+ *
+ * @retval zero if OK, the same value as @len if fails, smaller value than @len
+ * for partial success
+ */
+size_t semihosting_read(int fd, void *ptr, size_t len)
+{
+	struct semihosting_param_t arg = {
+		.param0 = fd,
+		.param1 = (uintptr_t)ptr,
+		.param2 = len
+	};
+
+	return __do_semihosting(SEMIHOSTING_SYS_READ, (uintptr_t)&arg);
+}
+
+/**
+ * @brief Write data into a file on the semihosting host system
+ * @param fd: a handle for a file previously opened
+ * @param ptr: pointer to a buffer
+ * @param len: the number of bytes to be written from the buffer to the file
+ *
+ * @retval zero if OK, otherwise the number of bytes that are not written
+ */
+size_t semihosting_write(int fd, const void *ptr, size_t len)
+{
+	struct semihosting_param_t arg = {
+		.param0 = fd,
+		.param1 = (uintptr_t)ptr,
+		.param2 = len
+	};
+
+	return __do_semihosting(SEMIHOSTING_SYS_WRITE, (uintptr_t)&arg);
+}
+
+/**
+ * @brief Close a file on the semihosting host system
+ * @param fd: a handle for a file previously opened
+ *
+ * @retval zero if OK, -1 if fails
+ */
+int semihosting_close(int fd)
+{
+	struct semihosting_param_t arg = {
+		.param0 = fd,
+	};
+
+	return (int)__do_semihosting(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&arg);
+}
diff --git a/core/kernel/sub.mk b/core/kernel/sub.mk
index 3e81d5f8f124d914955d38e0d258cf71fac7a090..a8cdba2e88cba4e9e18bc650ddb6d75228ed05dc 100644
--- a/core/kernel/sub.mk
+++ b/core/kernel/sub.mk
@@ -1,10 +1,12 @@
 srcs-$(CFG_CORE_SANITIZE_KADDRESS) += asan.c
 cflags-remove-asan.c-y += $(cflags_kasan)
+cflags-remove-asan.c-y += $(finstrument-functions)
 srcs-$(CFG_TEE_CORE_DEBUG) += spin_lock_debug.c
 srcs-y += assert.c
 srcs-y += console.c
 srcs-$(CFG_DT) += dt.c
 srcs-$(CFG_DT) += dt_driver.c
+srcs-y += boot.c
 srcs-y += pm.c
 srcs-y += handle.c
 srcs-y += interrupt.c
@@ -54,6 +56,8 @@ srcs-y += pseudo_ta.c
 
 srcs-$(CFG_TRANSFER_LIST) += transfer_list.c
 
+srcs-$(CFG_SEMIHOSTING) += semihosting.c
+
 ifeq ($(CFG_SYSCALL_FTRACE),y)
 # We would not like to profile spin_lock_debug.c file as it provides
 # common APIs that are needed for ftrace framework to trace syscalls.
@@ -61,3 +65,4 @@ ifeq ($(CFG_SYSCALL_FTRACE),y)
 cflags-remove-spin_lock_debug.c-$(CFG_TEE_CORE_DEBUG) += -pg
 endif
 srcs-y += nv_counter.c
+srcs-$(CFG_CALLOUT) += callout.c
diff --git a/core/kernel/tee_misc.c b/core/kernel/tee_misc.c
index 240e7021870f278a0b8a0389ee0e1ab626a6de25..571ed18b8d5c4f794bd1ceb9567593f9f0b93b47 100644
--- a/core/kernel/tee_misc.c
+++ b/core/kernel/tee_misc.c
@@ -3,13 +3,11 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  */
 #include <kernel/cache_helpers.h>
-#include <kernel/chip_services.h>
 #include <kernel/tee_common_otp.h>
 #include <kernel/tee_common.h>
 #include <kernel/tee_misc.h>
 #include <malloc.h>
 #include <mm/core_memprot.h>
-#include <stdio.h>
 #include <trace.h>
 
 static uint8_t tee_b2hs_add_base(uint8_t in)
@@ -128,7 +126,7 @@ void *alloc_cache_aligned(size_t size)
 	uint32_t cacheline_size = 0;
 
 	cacheline_size = cache_get_max_line_size();
-	if (ROUNDUP_OVERFLOW(size, cacheline_size, &alloc_size))
+	if (ROUNDUP2_OVERFLOW(size, cacheline_size, &alloc_size))
 		return NULL;
 
 	ptr = memalign(cacheline_size, alloc_size);
diff --git a/core/kernel/tee_ta_manager.c b/core/kernel/tee_ta_manager.c
index 6117c3a01f5cb7105232653921975ee73afaa4f1..e47404688738cac8b1e048c45bed774495be17f5 100644
--- a/core/kernel/tee_ta_manager.c
+++ b/core/kernel/tee_ta_manager.c
@@ -22,14 +22,11 @@
 #include <mm/mobj.h>
 #include <mm/vm.h>
 #include <pta_stats.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <tee_api_types.h>
 #include <tee/entry_std.h>
 #include <tee/tee_obj.h>
-#include <tee/tee_svc_cryp.h>
-#include <tee/tee_svc_storage.h>
 #include <trace.h>
 #include <types_ext.h>
 #include <user_ta_header.h>
@@ -530,8 +527,7 @@ static TEE_Result tee_ta_init_session_with_context(struct tee_ta_session *s,
 		if (!ctx)
 			return TEE_ERROR_ITEM_NOT_FOUND;
 
-		if (!is_user_ta_ctx(&ctx->ts_ctx) ||
-		    !to_user_ta_ctx(&ctx->ts_ctx)->uctx.is_initializing)
+		if (!ctx->is_initializing)
 			break;
 		/*
 		 * Context is still initializing, wait here until it's
@@ -543,22 +539,22 @@ static TEE_Result tee_ta_init_session_with_context(struct tee_ta_session *s,
 	}
 
 	/*
-	 * If TA isn't single instance it should be loaded as new
-	 * instance instead of doing anything with this instance.
-	 * So tell the caller that we didn't find the TA it the
-	 * caller will load a new instance.
+	 * If the trusted service is not a single instance service (e.g. is
+	 * a multi-instance TA) it should be loaded as a new instance instead
+	 * of doing anything with this instance. So tell the caller that we
+	 * didn't find the TA it the caller will load a new instance.
 	 */
 	if ((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0)
 		return TEE_ERROR_ITEM_NOT_FOUND;
 
 	/*
-	 * The TA is single instance, if it isn't multi session we
+	 * The trusted service is single instance, if it isn't multi session we
 	 * can't create another session unless its reference is zero
 	 */
 	if (!(ctx->flags & TA_FLAG_MULTI_SESSION) && ctx->ref_count)
 		return TEE_ERROR_BUSY;
 
-	DMSG("Re-open TA %pUl", (void *)&ctx->ts_ctx.uuid);
+	DMSG("Re-open trusted service %pUl", (void *)&ctx->ts_ctx.uuid);
 
 	ctx->ref_count++;
 	s->ts_sess.ctx = &ctx->ts_ctx;
@@ -621,22 +617,33 @@ static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err,
 
 	/* Look for already loaded TA */
 	res = tee_ta_init_session_with_context(s, uuid);
-	mutex_unlock(&tee_ta_mutex);
-	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
+	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) {
+		mutex_unlock(&tee_ta_mutex);
 		goto out;
+	}
 
 	/* Look for secure partition */
 	res = stmm_init_session(uuid, s);
-	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
+	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) {
+		mutex_unlock(&tee_ta_mutex);
+		if (res == TEE_SUCCESS)
+			res = stmm_complete_session(s);
+
 		goto out;
+	}
 
 	/* Look for pseudo TA */
 	res = tee_ta_init_pseudo_ta_session(uuid, s);
-	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
+	if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND) {
+		mutex_unlock(&tee_ta_mutex);
 		goto out;
+	}
 
 	/* Look for user TA */
 	res = tee_ta_init_user_ta_session(uuid, s);
+	mutex_unlock(&tee_ta_mutex);
+	if (res == TEE_SUCCESS)
+		res = tee_ta_complete_user_ta_session(s);
 
 out:
 	if (!res) {
@@ -806,12 +813,11 @@ static TEE_Result dump_ta_memstats(struct tee_ta_session *s,
 	if (!ts_ctx)
 		return TEE_ERROR_ITEM_NOT_FOUND;
 
-	if (is_user_ta_ctx(ts_ctx) &&
-	    to_user_ta_ctx(ts_ctx)->uctx.is_initializing)
-		return TEE_ERROR_BAD_STATE;
-
 	ctx = ts_to_ta_ctx(ts_ctx);
 
+	if (ctx->is_initializing)
+		return TEE_ERROR_BAD_STATE;
+
 	if (tee_ta_try_set_busy(ctx)) {
 		if (!ctx->panicked) {
 			s->param = param;
diff --git a/core/kernel/tee_time.c b/core/kernel/tee_time.c
index e1a462b145b4901295f9008c9dbb8576d4ddbf3d..cc5bebc61438950e34479a5a887d82418726fa77 100644
--- a/core/kernel/tee_time.c
+++ b/core/kernel/tee_time.c
@@ -5,34 +5,11 @@
  */
 
 #include <compiler.h>
-#include <initcall.h>
 #include <kernel/tee_time.h>
 #include <kernel/thread.h>
-#include <kernel/time_source.h>
 #include <mm/core_mmu.h>
 #include <optee_rpc_cmd.h>
 #include <stdlib.h>
-#include <string.h>
-
-struct time_source _time_source;
-
-static TEE_Result register_time_source(void)
-{
-	time_source_init();
-
-	return TEE_SUCCESS;
-}
-early_init(register_time_source);
-
-TEE_Result tee_time_get_sys_time(TEE_Time *time)
-{
-	return _time_source.get_sys_time(time);
-}
-
-uint32_t tee_time_get_sys_time_protection_level(void)
-{
-	return _time_source.protection_level;
-}
 
 void tee_time_wait(uint32_t milliseconds_delay)
 {
diff --git a/core/kernel/tee_time_ree.c b/core/kernel/tee_time_ree.c
index 5e744add495ba03d4f14ab626a4f8e65492b8b5a..aa3a11d4abef962f8fa3e27867ecba515c1c5aa4 100644
--- a/core/kernel/tee_time_ree.c
+++ b/core/kernel/tee_time_ree.c
@@ -4,14 +4,13 @@
  */
 
 #include <kernel/tee_time.h>
-#include <kernel/time_source.h>
 #include <kernel/mutex.h>
 
 static TEE_Time prev;
 
 static struct mutex time_mu = MUTEX_INITIALIZER;
 
-static TEE_Result get_monotonic_ree_time(TEE_Time *time)
+TEE_Result tee_time_get_sys_time(TEE_Time *time)
 {
 	TEE_Result res;
 
@@ -31,10 +30,7 @@ static TEE_Result get_monotonic_ree_time(TEE_Time *time)
 	return res;
 }
 
-static const struct time_source ree_time_source = {
-	.name = "ree",
-	.protection_level = 100,
-	.get_sys_time = get_monotonic_ree_time,
-};
-
-REGISTER_TIME_SOURCE(ree_time_source)
+uint32_t tee_time_get_sys_time_protection_level(void)
+{
+	return 100;
+}
diff --git a/core/kernel/thread.c b/core/kernel/thread.c
index 2a1f22dce6351f5831c09ba1d01aa5435b2704cf..d7c319f504876b823d0f26d502e222cf3486ebc2 100644
--- a/core/kernel/thread.c
+++ b/core/kernel/thread.c
@@ -426,7 +426,7 @@ static void init_thread_stacks(void)
 		struct fobj *fobj = NULL;
 
 		/* Find vmem for thread stack and its protection gap */
-		mm = tee_mm_alloc(&tee_mm_vcore,
+		mm = tee_mm_alloc(&core_virt_mem_pool,
 				  SMALL_PAGE_SIZE + STACK_THREAD_SIZE);
 		assert(mm);
 
@@ -445,8 +445,7 @@ static void init_thread_stacks(void)
 		/* init effective stack */
 		sp = tee_mm_get_smem(mm) + tee_mm_get_bytes(mm);
 		asan_tag_access((void *)tee_mm_get_smem(mm), (void *)sp);
-		if (!thread_init_stack(n, sp))
-			panic("init stack failed");
+		threads[n].stack_va_end = sp;
 	}
 }
 #else
@@ -455,10 +454,8 @@ static void init_thread_stacks(void)
 	size_t n;
 
 	/* Assign the thread stacks */
-	for (n = 0; n < CFG_NUM_THREADS; n++) {
-		if (!thread_init_stack(n, GET_STACK_BOTTOM(stack_thread, n)))
-			panic("thread_init_stack failed");
-	}
+	for (n = 0; n < CFG_NUM_THREADS; n++)
+		threads[n].stack_va_end = GET_STACK_BOTTOM(stack_thread, n);
 }
 #endif /*CFG_WITH_PAGER*/
 
diff --git a/core/kernel/transfer_list.c b/core/kernel/transfer_list.c
index 1be1b849cf91dd68782536f3b868e5fe71092598..cf7793a2fec735227fd0c5521cb6d81a1713d222 100644
--- a/core/kernel/transfer_list.c
+++ b/core/kernel/transfer_list.c
@@ -388,9 +388,9 @@ bool transfer_list_set_data_size(struct transfer_list_header *tl,
 		 * of TL
 		 */
 		mov_dis = new_ev - old_ev;
-		if (ROUNDUP_OVERFLOW(mov_dis,
-				     TL_ALIGNMENT_FROM_ORDER(tl->alignment),
-				     &mov_dis) ||
+		if (ROUNDUP2_OVERFLOW(mov_dis,
+				      TL_ALIGNMENT_FROM_ORDER(tl->alignment),
+				      &mov_dis) ||
 		    tl->size + mov_dis > tl->max_size) {
 			return false;
 		}
@@ -401,8 +401,8 @@ bool transfer_list_set_data_size(struct transfer_list_header *tl,
 		 * Move distance should be rounded down to match the entry data
 		 * alignment.
 		 */
-		mov_dis = ROUNDDOWN(old_ev - new_ev,
-				    TL_ALIGNMENT_FROM_ORDER(tl->alignment));
+		mov_dis = ROUNDDOWN2(old_ev - new_ev,
+				     TL_ALIGNMENT_FROM_ORDER(tl->alignment));
 		r_new_ev = old_ev - mov_dis;
 		tl->size -= mov_dis;
 	}
@@ -537,7 +537,7 @@ transfer_list_add_with_align(struct transfer_list_header *tl, uint16_t tag_id,
 		 * alignment. Fill the gap with an empty transfer entry as a
 		 * placeholder before adding the desired transfer entry
 		 */
-		new_tl_ev = ROUNDUP(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) -
+		new_tl_ev = ROUNDUP2(ev, TL_ALIGNMENT_FROM_ORDER(alignment)) -
 			    sizeof(struct transfer_list_entry);
 		assert(new_tl_ev - tl_ev > sizeof(struct transfer_list_entry));
 		dummy_te_data_sz = new_tl_ev - tl_ev -
diff --git a/core/kernel/ubsan.c b/core/kernel/ubsan.c
index 04b016383d6ac73fd8c92059d2ec3d73327b26ca..5d62093cdb548e74b954029b091a88ad5fc840f8 100644
--- a/core/kernel/ubsan.c
+++ b/core/kernel/ubsan.c
@@ -63,6 +63,11 @@ struct nonnull_arg_data {
 	struct source_location loc;
 };
 
+struct invalid_builtin_data {
+	struct source_location loc;
+	unsigned char kind;
+};
+
 /*
  * When compiling with -fsanitize=undefined the compiler expects functions
  * with the following signatures. The functions are never called directly,
@@ -70,33 +75,30 @@ struct nonnull_arg_data {
  */
 void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
 				  unsigned long ptr);
-void __ubsan_handle_add_overflow(struct overflow_data *data,
-				  unsigned long lhs, unsigned long rhs);
-void __ubsan_handle_sub_overflow(struct overflow_data *data,
-				  unsigned long lhs, unsigned long rhs);
-void __ubsan_handle_mul_overflow(struct overflow_data *data,
-				  unsigned long lhs, unsigned long rhs);
-void __ubsan_handle_negate_overflow(struct overflow_data *data,
-				    unsigned long old_val);
-void __ubsan_handle_divrem_overflow(struct overflow_data *data,
-				    unsigned long lhs, unsigned long rhs);
-void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
-					unsigned long lhs, unsigned long rhs);
-void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
-				  unsigned long idx);
-void __ubsan_handle_unreachable(struct unreachable_data *data);
-void __ubsan_handle_missing_return(struct unreachable_data *data);
-void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
-					   unsigned long bound);
-void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
-				       unsigned long val);
-void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data
+void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr);
+void __ubsan_handle_add_overflow(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_sub_overflow(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_mul_overflow(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_negate_overflow(void *data_, void *old_val);
+void __ubsan_handle_divrem_overflow(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_pointer_overflow(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs, void *rhs);
+void __ubsan_handle_out_of_bounds(void *data_, void *idx);
+void __ubsan_handle_builtin_unreachable(void *data_);
+void __ubsan_handle_missing_return(void *data_);
+void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound);
+void __ubsan_handle_load_invalid_value(void *data_, void *val);
+void __ubsan_handle_nonnull_arg(void *data_
 #if __GCC_VERSION < 60000
 				, size_t arg_no
 #endif
 			       );
+void __ubsan_handle_invalid_builtin(void *data_);
 
-static void print_loc(const char *func, struct source_location *loc)
+static bool ubsan_panic = true;
+
+static void ubsan_handle_error(const char *func, struct source_location *loc,
+			       bool should_panic)
 {
 	const char *f = func;
 	const char func_prefix[] = "__ubsan_handle";
@@ -106,116 +108,130 @@ static void print_loc(const char *func, struct source_location *loc)
 
 	EMSG_RAW("Undefined behavior %s at %s:%" PRIu32 " col %" PRIu32,
 		 f, loc->file_name, loc->line, loc->column);
-}
-
 
-static volatile bool ubsan_panic = true;
+	if (should_panic)
+		panic();
+}
 
 void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
 				  unsigned long ptr __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_add_overflow(struct overflow_data *data,
-				 unsigned long lhs __unused,
-				 unsigned long rhs __unused)
+void __ubsan_handle_type_mismatch_v1(void *data_, void *ptr __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct type_mismatch_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_sub_overflow(struct overflow_data *data,
-				 unsigned long lhs __unused,
-				 unsigned long rhs __unused)
+void __ubsan_handle_add_overflow(void *data_, void *lhs __unused,
+				 void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_mul_overflow(struct overflow_data *data,
-				 unsigned long lhs __unused,
-				 unsigned long rhs __unused)
+void __ubsan_handle_sub_overflow(void *data_, void *lhs __unused,
+				 void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_negate_overflow(struct overflow_data *data,
-				    unsigned long old_val __unused)
+void __ubsan_handle_mul_overflow(void *data_, void *lhs __unused,
+				 void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_divrem_overflow(struct overflow_data *data,
-				    unsigned long lhs __unused,
-				    unsigned long rhs __unused)
+void __ubsan_handle_negate_overflow(void *data_, void *old_val __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data,
-					unsigned long lhs __unused,
-					unsigned long rhs __unused)
+void __ubsan_handle_divrem_overflow(void *data_, void *lhs __unused,
+				    void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data,
-				  unsigned long idx __unused)
+void __ubsan_handle_pointer_overflow(void *data_, void *lhs __unused,
+				     void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct overflow_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_unreachable(struct unreachable_data *data)
+void __ubsan_handle_shift_out_of_bounds(void *data_, void *lhs __unused,
+					void *rhs __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct shift_out_of_bounds_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
+}
+
+void __ubsan_handle_out_of_bounds(void *data_, void *idx __unused)
+{
+	struct out_of_bounds_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __noreturn __ubsan_handle_missing_return(struct unreachable_data *data)
+void __ubsan_handle_builtin_unreachable(void *data_)
 {
-	print_loc(__func__, &data->loc);
+	struct unreachable_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, false);
 	panic();
 }
 
-void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data,
-					   unsigned long bound __unused)
+void __noreturn __ubsan_handle_missing_return(void *data_)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct unreachable_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, false);
+	panic();
 }
 
-void __ubsan_handle_load_invalid_value(struct invalid_value_data *data,
-				       unsigned long val __unused)
+void __ubsan_handle_vla_bound_not_positive(void *data_, void *bound __unused)
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct vla_bound_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
+}
+
+void __ubsan_handle_load_invalid_value(void *data_, void *val __unused)
+{
+	struct invalid_value_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
 
-void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data
+void __ubsan_handle_nonnull_arg(void *data_
 #if __GCC_VERSION < 60000
 				, size_t arg_no __unused
 #endif
 			       )
 {
-	print_loc(__func__, &data->loc);
-	if (ubsan_panic)
-		panic();
+	struct nonnull_arg_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
+}
+
+void __ubsan_handle_invalid_builtin(void *data_)
+{
+	struct invalid_builtin_data *data = data_;
+
+	ubsan_handle_error(__func__, &data->loc, ubsan_panic);
 }
diff --git a/core/kernel/user_access.c b/core/kernel/user_access.c
index 3f229f985713741530a3ac6309f1ca749c9b4bb1..029330addbb24f0eb9733feb14a985a96710d04f 100644
--- a/core/kernel/user_access.c
+++ b/core/kernel/user_access.c
@@ -51,7 +51,7 @@ TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len)
 
 	uaddr = memtag_strip_tag_const(uaddr);
 	res = check_user_access(flags, uaddr, len);
-	if (!res) {
+	if (!res && kaddr && uaddr) {
 		enter_user_access();
 		memcpy(kaddr, uaddr, len);
 		exit_user_access();
@@ -67,7 +67,7 @@ TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len)
 
 	uaddr = memtag_strip_tag(uaddr);
 	res = check_user_access(flags, uaddr, len);
-	if (!res) {
+	if (!res && kaddr && uaddr) {
 		enter_user_access();
 		memcpy(uaddr, kaddr, len);
 		exit_user_access();
@@ -83,7 +83,7 @@ TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len)
 
 	uaddr = memtag_strip_tag_const(uaddr);
 	res = check_user_access(flags, uaddr, len);
-	if (!res) {
+	if (!res && kaddr && uaddr) {
 		enter_user_access();
 		memcpy(kaddr, uaddr, len);
 		exit_user_access();
@@ -99,7 +99,7 @@ TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len)
 
 	uaddr = memtag_strip_tag(uaddr);
 	res = check_user_access(flags, uaddr, len);
-	if (!res) {
+	if (!res && kaddr && uaddr) {
 		enter_user_access();
 		memcpy(uaddr, kaddr, len);
 		exit_user_access();
@@ -282,7 +282,7 @@ TEE_Result bb_strndup_user(const char *src, size_t maxlen, char **dst,
 	if (!d)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
-	if (l) {
+	if (l && src && d) {
 		enter_user_access();
 		memcpy(d, src, l);
 		exit_user_access();
diff --git a/core/kernel/user_ta.c b/core/kernel/user_ta.c
index 315f5f16e0f21028176f2c2f9d4b7cc8d7b08e2f..c96d369f1e5e4b826b5e508cf27834244d43f766 100644
--- a/core/kernel/user_ta.c
+++ b/core/kernel/user_ta.c
@@ -8,14 +8,12 @@
 #include <assert.h>
 #include <compiler.h>
 #include <crypto/crypto.h>
-#include <ctype.h>
 #include <initcall.h>
 #include <keep.h>
 #include <kernel/ldelf_loader.h>
 #include <kernel/linker.h>
 #include <kernel/panic.h>
 #include <kernel/scall.h>
-#include <kernel/tee_misc.h>
 #include <kernel/tee_ta_manager.h>
 #include <kernel/thread.h>
 #include <kernel/ts_store.h>
@@ -34,16 +32,12 @@
 #include <optee_rpc_cmd.h>
 #include <printk.h>
 #include <signed_hdr.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <sys/queue.h>
-#include <ta_pub_key.h>
 #include <tee/tee_cryp_utl.h>
 #include <tee/tee_obj.h>
 #include <tee/tee_svc_cryp.h>
-#include <tee/tee_svc.h>
 #include <tee/tee_svc_storage.h>
-#include <tee/uuid.h>
 #include <trace.h>
 #include <types_ext.h>
 #include <utee_defines.h>
@@ -229,11 +223,12 @@ out:
 	dec_recursion();
 out_clr_cancel:
 	/*
-	 * Clear the cancel state now that the user TA has returned. The next
+	 * Reset the cancel state now that the user TA has returned. The next
 	 * time the TA will be invoked will be with a new operation and should
 	 * not have an old cancellation pending.
 	 */
 	ta_sess->cancel = false;
+	ta_sess->cancel_mask = true;
 
 	return res;
 }
@@ -251,7 +246,7 @@ static TEE_Result user_ta_enter_invoke_cmd(struct ts_session *s, uint32_t cmd)
 static void user_ta_enter_close_session(struct ts_session *s)
 {
 	/* Only if the TA was fully initialized by ldelf */
-	if (!to_user_ta_ctx(s->ctx)->uctx.is_initializing)
+	if (!to_user_ta_ctx(s->ctx)->ta_ctx.is_initializing)
 		user_ta_enter(s, UTEE_ENTRY_FUNC_CLOSE_SESSION, 0);
 }
 
@@ -463,6 +458,12 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
 	TEE_Result res = TEE_SUCCESS;
 	struct user_ta_ctx *utc = NULL;
 
+	/*
+	 * Caller is expected to hold tee_ta_mutex for safe changes
+	 * in @s and registering of the context in tee_ctxes list.
+	 */
+	assert(mutex_is_locked(&tee_ta_mutex));
+
 	utc = calloc(1, sizeof(struct user_ta_ctx));
 	if (!utc)
 		return TEE_ERROR_OUT_OF_MEMORY;
@@ -482,15 +483,20 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
 
 	utc->ta_ctx.ts_ctx.uuid = *uuid;
 	res = vm_info_init(&utc->uctx, &utc->ta_ctx.ts_ctx);
-	if (res)
-		goto out;
-	utc->uctx.is_initializing = true;
+	if (res) {
+		condvar_destroy(&utc->ta_ctx.busy_cv);
+		free_utc(utc);
+		return res;
+	}
+
+	utc->ta_ctx.is_initializing = true;
 
 #ifdef CFG_TA_PAUTH
 	crypto_rng_read(&utc->uctx.keys, sizeof(utc->uctx.keys));
 #endif
 
-	mutex_lock(&tee_ta_mutex);
+	assert(!mutex_trylock(&tee_ta_mutex));
+
 	s->ts_sess.ctx = &utc->ta_ctx.ts_ctx;
 	s->ts_sess.handle_scall = s->ts_sess.ctx->ops->handle_scall;
 	/*
@@ -499,7 +505,14 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
 	 * handle single instance TAs.
 	 */
 	TAILQ_INSERT_TAIL(&tee_ctxes, &utc->ta_ctx, link);
-	mutex_unlock(&tee_ta_mutex);
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result tee_ta_complete_user_ta_session(struct tee_ta_session *s)
+{
+	struct user_ta_ctx *utc = to_user_ta_ctx(s->ts_sess.ctx);
+	TEE_Result res = TEE_SUCCESS;
 
 	/*
 	 * We must not hold tee_ta_mutex while allocating page tables as
@@ -516,10 +529,12 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
 	mutex_lock(&tee_ta_mutex);
 
 	if (!res) {
-		utc->uctx.is_initializing = false;
+		utc->ta_ctx.is_initializing = false;
 	} else {
 		s->ts_sess.ctx = NULL;
 		TAILQ_REMOVE(&tee_ctxes, &utc->ta_ctx, link);
+		condvar_destroy(&utc->ta_ctx.busy_cv);
+		free_utc(utc);
 	}
 
 	/* The state has changed for the context, notify eventual waiters. */
@@ -527,11 +542,5 @@ TEE_Result tee_ta_init_user_ta_session(const TEE_UUID *uuid,
 
 	mutex_unlock(&tee_ta_mutex);
 
-out:
-	if (res) {
-		condvar_destroy(&utc->ta_ctx.busy_cv);
-		free_utc(utc);
-	}
-
 	return res;
 }
diff --git a/core/kernel/wait_queue.c b/core/kernel/wait_queue.c
index 1326ef8ec1c80378f61d770c2490a16498b545e3..337697df50c57fe44fda51a25174ded0a734d86c 100644
--- a/core/kernel/wait_queue.c
+++ b/core/kernel/wait_queue.c
@@ -8,8 +8,6 @@
 #include <kernel/spinlock.h>
 #include <kernel/thread.h>
 #include <kernel/wait_queue.h>
-#include <optee_rpc_cmd.h>
-#include <string.h>
 #include <tee_api_defines.h>
 #include <trace.h>
 #include <types_ext.h>
@@ -22,10 +20,10 @@ void wq_init(struct wait_queue *wq)
 	*wq = (struct wait_queue)WAIT_QUEUE_INITIALIZER;
 }
 
-static void do_notif(TEE_Result (*fn)(uint32_t), int id,
-		     const char *cmd_str __maybe_unused,
-		     const void *sync_obj __maybe_unused,
-		     const char *fname, int lineno __maybe_unused)
+static TEE_Result do_notif(bool wait, int id, uint32_t timeout_ms,
+			   const char *cmd_str __maybe_unused,
+			   const void *sync_obj __maybe_unused,
+			   const char *fname, int lineno __maybe_unused)
 {
 	TEE_Result res = TEE_SUCCESS;
 
@@ -35,9 +33,15 @@ static void do_notif(TEE_Result (*fn)(uint32_t), int id,
 	else
 		DMSG("%s thread %d %p", cmd_str, id, sync_obj);
 
-	res = fn(id + NOTIF_SYNC_VALUE_BASE);
+	if (wait)
+		res = notif_wait_timeout(id + NOTIF_SYNC_VALUE_BASE,
+					 timeout_ms);
+	else
+		res = notif_send_sync(id + NOTIF_SYNC_VALUE_BASE);
 	if (res)
 		DMSG("%s thread %d res %#"PRIx32, cmd_str, id, res);
+
+	return res;
 }
 
 static void slist_add_tail(struct wait_queue *wq, struct wait_queue_elem *wqe)
@@ -71,24 +75,33 @@ void wq_wait_init_condvar(struct wait_queue *wq, struct wait_queue_elem *wqe,
 	cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status);
 }
 
-void wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
-		   const void *sync_obj, const char *fname, int lineno)
+static TEE_Result wq_wait_final_helper(struct wait_queue *wq,
+				       struct wait_queue_elem *wqe,
+				       uint32_t timeout_ms,
+				       const void *sync_obj, const char *fname,
+				       int lineno)
 {
-	uint32_t old_itr_status;
-	unsigned done;
+	uint32_t old_itr_status = 0;
 
-	do {
-		do_notif(notif_wait, wqe->handle,
-			 "sleep", sync_obj, fname, lineno);
+	do_notif(true, wqe->handle, timeout_ms, "sleep", sync_obj, fname,
+		 lineno);
 
-		old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock);
+	old_itr_status = cpu_spin_lock_xsave(&wq_spin_lock);
+	SLIST_REMOVE(wq, wqe, wait_queue_elem, link);
+	cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status);
 
-		done = wqe->done;
-		if (done)
-			SLIST_REMOVE(wq, wqe, wait_queue_elem, link);
+	if (wqe->done)
+		return TEE_SUCCESS;
+	else
+		return TEE_ERROR_TIMEOUT;
+}
 
-		cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status);
-	} while (!done);
+TEE_Result wq_wait_final(struct wait_queue *wq, struct wait_queue_elem *wqe,
+			 uint32_t timeout_ms, const void *sync_obj,
+			 const char *fname, int lineno)
+{
+	return wq_wait_final_helper(wq, wqe, timeout_ms, sync_obj, fname,
+				    lineno);
 }
 
 void wq_wake_next(struct wait_queue *wq, const void *sync_obj,
@@ -132,7 +145,7 @@ void wq_wake_next(struct wait_queue *wq, const void *sync_obj,
 		cpu_spin_unlock_xrestore(&wq_spin_lock, old_itr_status);
 
 		if (do_wakeup)
-			do_notif(notif_send_sync, handle,
+			do_notif(false, handle, 0,
 				 "wake ", sync_obj, fname, lineno);
 
 		if (!do_wakeup || !wake_read)
diff --git a/core/lib/libfdt/fdt_ro.c b/core/lib/libfdt/fdt_ro.c
index a5c2797cde6586595bc64c3c26e79dd26012bff7..e89003a613c9c3dd5b17a1b6321185e3bf15874b 100644
--- a/core/lib/libfdt/fdt_ro.c
+++ b/core/lib/libfdt/fdt_ro.c
@@ -6,6 +6,7 @@
 #include "libfdt_env.h"
 
 #include <fdt.h>
+#include <kernel/dt.h>	/* fdt_find_cached_xxx() */
 #include <libfdt.h>
 
 #include "libfdt_internal.h"
@@ -619,7 +620,13 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
 
 int fdt_parent_offset(const void *fdt, int nodeoffset)
 {
-	int nodedepth = fdt_node_depth(fdt, nodeoffset);
+	int parent_offset = 0;
+	int nodedepth = 0;
+
+	if (fdt_find_cached_parent_node(fdt, nodeoffset, &parent_offset) == 0)
+		return parent_offset;
+
+	nodedepth = fdt_node_depth(fdt, nodeoffset);
 
 	if (nodedepth < 0)
 		return nodedepth;
@@ -661,6 +668,9 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
+	if (fdt_find_cached_node_phandle(fdt, phandle, &offset) == 0)
+		return offset;
+
 	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
diff --git a/core/lib/libtomcrypt/aes.c b/core/lib/libtomcrypt/aes.c
index 3989140e710f4619cf56741c3cd36715d632d238..ecd9c61662d59a9af7dff41ff36bcb076f6fc7c9 100644
--- a/core/lib/libtomcrypt/aes.c
+++ b/core/lib/libtomcrypt/aes.c
@@ -10,6 +10,8 @@
 #include <tee_api_types.h>
 #include <tomcrypt_private.h>
 
+#define AES_ENC_KEY_LEN	(sizeof(ulong32) * 60)
+
 TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len,
 				     void *enc_key, size_t enc_keylen,
 				     unsigned int *rounds)
@@ -20,13 +22,13 @@ TEE_Result crypto_aes_expand_enc_key(const void *key, size_t key_len,
 #else
 	symmetric_key skey;
 
-	if (enc_keylen < sizeof(skey.rijndael.eK))
+	if (enc_keylen < AES_ENC_KEY_LEN)
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	if (aes_setup(key, key_len, 0, &skey))
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	memcpy(enc_key, skey.rijndael.eK, sizeof(skey.rijndael.eK));
+	memcpy(enc_key, skey.rijndael.eK, AES_ENC_KEY_LEN);
 	*rounds = skey.rijndael.Nr;
 #endif
 	return TEE_SUCCESS;
@@ -38,10 +40,11 @@ void crypto_aes_enc_block(const void *enc_key, size_t enc_keylen __maybe_unused,
 #ifdef _CFG_CORE_LTC_AES_ACCEL
 	crypto_accel_aes_ecb_enc(dst, src, enc_key, rounds, 1);
 #else
-	symmetric_key skey;
+	symmetric_key skey = { };
 
-	assert(enc_keylen >= sizeof(skey.rijndael.eK));
-	memcpy(skey.rijndael.eK, enc_key, sizeof(skey.rijndael.eK));
+	assert(enc_keylen >= AES_ENC_KEY_LEN);
+	skey.rijndael.eK = LTC_ALIGN_BUF(skey.rijndael.K, 16);
+	memcpy(skey.rijndael.eK, enc_key, AES_ENC_KEY_LEN);
 	skey.rijndael.Nr = rounds;
 	if (aes_ecb_encrypt(src, dst, &skey))
 		panic();
diff --git a/core/lib/libtomcrypt/aes_accel.c b/core/lib/libtomcrypt/aes_accel.c
index 0fb4bfc57e0ba9cb944830b1a0e4080b320d639a..cc667795afb7b831466aa7e6658351ce1695f579 100644
--- a/core/lib/libtomcrypt/aes_accel.c
+++ b/core/lib/libtomcrypt/aes_accel.c
@@ -49,6 +49,10 @@
 #include <crypto/crypto_accel.h>
 #include <tomcrypt_private.h>
 
+#define EXPANDED_AES_KEY_WORD_COUNT	60
+#define EXPANDED_AES_KEY_LEN		(EXPANDED_AES_KEY_WORD_COUNT * \
+					 sizeof(uint32_t))
+
 int rijndael_setup(const unsigned char *key, int keylen, int num_rounds,
 	      symmetric_key *skey)
 {
@@ -60,9 +64,12 @@ int rijndael_setup(const unsigned char *key, int keylen, int num_rounds,
 	if (keylen != 16 && keylen != 24 && keylen != 32)
 		return CRYPT_INVALID_KEYSIZE;
 
+	skey->rijndael.eK = LTC_ALIGN_BUF(skey->rijndael.K, 16);
+	skey->rijndael.dK = skey->rijndael.eK + EXPANDED_AES_KEY_WORD_COUNT;
+
 	if (crypto_accel_aes_expand_keys(key, keylen, skey->rijndael.eK,
 					 skey->rijndael.dK,
-					 sizeof(skey->rijndael.eK),
+					 EXPANDED_AES_KEY_LEN,
 					 &round_count))
 		return CRYPT_INVALID_ARG;
 
@@ -163,6 +170,7 @@ static int aes_cbc_decrypt_nblocks(const unsigned char *ct, unsigned char *pt,
 	return CRYPT_OK;
 }
 
+#ifdef LTC_CTR_MODE
 static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
 				   unsigned long blocks, unsigned char *IV,
 				   int mode, symmetric_key *skey)
@@ -182,6 +190,7 @@ static int aes_ctr_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
 
 	return CRYPT_OK;
 }
+#endif
 
 static int aes_xts_encrypt_nblocks(const unsigned char *pt, unsigned char *ct,
 				   unsigned long blocks, unsigned char *tweak,
@@ -238,7 +247,9 @@ const struct ltc_cipher_descriptor aes_desc = {
 	.accel_ecb_decrypt = aes_ecb_decrypt_nblocks,
 	.accel_cbc_encrypt = aes_cbc_encrypt_nblocks,
 	.accel_cbc_decrypt = aes_cbc_decrypt_nblocks,
+#ifdef LTC_CTR_MODE
 	.accel_ctr_encrypt = aes_ctr_encrypt_nblocks,
+#endif
 	.accel_xts_encrypt = aes_xts_encrypt_nblocks,
 	.accel_xts_decrypt = aes_xts_decrypt_nblocks,
 };
diff --git a/core/lib/libtomcrypt/ed25519.c b/core/lib/libtomcrypt/ed25519.c
index 763c0978afb4d3809d5e00e4a450eecd634be9a5..d04f1b9ba9f6b0796ef7a5e5666f0ed944a7c372 100644
--- a/core/lib/libtomcrypt/ed25519.c
+++ b/core/lib/libtomcrypt/ed25519.c
@@ -89,6 +89,11 @@ TEE_Result crypto_acipher_ed25519_sign(struct ed25519_keypair *key,
 	if (!key || !sig_len)
 		return TEE_ERROR_BAD_PARAMETERS;
 
+	if (*sig_len < UL(64)) {
+		*sig_len = UL(64);
+		return TEE_ERROR_SHORT_BUFFER;
+	}
+
 	siglen = *sig_len;
 
 	memcpy(private_key.priv, key->priv, sizeof(private_key.priv));
@@ -120,6 +125,11 @@ TEE_Result crypto_acipher_ed25519ctx_sign(struct ed25519_keypair *key,
 	if (!key || !sig_len)
 		return TEE_ERROR_BAD_PARAMETERS;
 
+	if (*sig_len < UL(64)) {
+		*sig_len = UL(64);
+		return TEE_ERROR_SHORT_BUFFER;
+	}
+
 	siglen = *sig_len;
 
 	memcpy(private_key.priv, key->priv, sizeof(private_key.priv));
diff --git a/core/lib/libtomcrypt/gcm.c b/core/lib/libtomcrypt/gcm.c
index b6848c72235e5b1ced8d4965250665b63ea848c7..bf1f02a3c75d82def2b4f9cf249378d125fda2f2 100644
--- a/core/lib/libtomcrypt/gcm.c
+++ b/core/lib/libtomcrypt/gcm.c
@@ -7,6 +7,7 @@
 #include <crypto/crypto.h>
 #include <crypto/crypto_impl.h>
 #include <stdlib.h>
+#include <string_ext.h>
 #include <string.h>
 #include <tee_api_types.h>
 #include <tomcrypt_private.h>
diff --git a/core/lib/libtomcrypt/mpi_desc.c b/core/lib/libtomcrypt/mpi_desc.c
index 791db1e136efb09b172d8ddb04148db76857615a..eebe4a10607fae417d600c7379ed7b5650625067 100644
--- a/core/lib/libtomcrypt/mpi_desc.c
+++ b/core/lib/libtomcrypt/mpi_desc.c
@@ -146,8 +146,7 @@ static ltc_mp_digit get_digit(void *a, int n)
 
 static int get_digit_count(void *a)
 {
-	return ROUNDUP(mbedtls_mpi_size(a), sizeof(mbedtls_mpi_uint)) /
-	       sizeof(mbedtls_mpi_uint);
+	return ROUNDUP_DIV(mbedtls_mpi_size(a), sizeof(mbedtls_mpi_uint));
 }
 
 static int compare(void *a, void *b)
diff --git a/core/lib/libtomcrypt/rsa.c b/core/lib/libtomcrypt/rsa.c
index f63bfe978f7b725337376a6be267000043e7c318..3a774e7dbb1b93fa3cda2e33df49266446140acf 100644
--- a/core/lib/libtomcrypt/rsa.c
+++ b/core/lib/libtomcrypt/rsa.c
@@ -30,6 +30,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 {
 	switch (algo) {
 #if defined(_CFG_CORE_LTC_SHA1_DESC)
+	case TEE_ALG_SHA1:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA1:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA1:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA1:
@@ -37,6 +38,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 		break;
 #endif
 #if defined(_CFG_CORE_LTC_MD5_DESC)
+	case TEE_ALG_MD5:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_MD5:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_MD5:
@@ -44,6 +46,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 		break;
 #endif
 #if defined(_CFG_CORE_LTC_SHA224_DESC)
+	case TEE_ALG_SHA224:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA224:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA224:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA224:
@@ -51,6 +54,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 		break;
 #endif
 #if defined(_CFG_CORE_LTC_SHA256_DESC)
+	case TEE_ALG_SHA256:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA256:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA256:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA256:
@@ -58,6 +62,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 		break;
 #endif
 #if defined(_CFG_CORE_LTC_SHA384_DESC)
+	case TEE_ALG_SHA384:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA384:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA384:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA384:
@@ -65,6 +70,7 @@ static TEE_Result tee_algo_to_ltc_hashindex(uint32_t algo, int *ltc_hashindex)
 		break;
 #endif
 #if defined(_CFG_CORE_LTC_SHA512_DESC)
+	case TEE_ALG_SHA512:
 	case TEE_ALG_RSASSA_PKCS1_V1_5_SHA512:
 	case TEE_ALG_RSASSA_PKCS1_PSS_MGF1_SHA512:
 	case TEE_ALG_RSAES_PKCS1_OAEP_MGF1_SHA512:
@@ -319,7 +325,9 @@ TEE_Result sw_crypto_acipher_rsanopad_decrypt(struct rsa_keypair *key,
 TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
 					struct rsa_keypair *key,
 					const uint8_t *label,
-					size_t label_len, const uint8_t *src,
+					size_t label_len,
+					uint32_t mgf_algo,
+					const uint8_t *src,
 					size_t src_len, uint8_t *dst,
 					size_t *dst_len)
 __weak __alias("sw_crypto_acipher_rsaes_decrypt");
@@ -327,14 +335,16 @@ __weak __alias("sw_crypto_acipher_rsaes_decrypt");
 TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 					   struct rsa_keypair *key,
 					   const uint8_t *label,
-					   size_t label_len, const uint8_t *src,
+					   size_t label_len,
+					   uint32_t mgf_algo,
+					   const uint8_t *src,
 					   size_t src_len, uint8_t *dst,
 					   size_t *dst_len)
 {
 	TEE_Result res = TEE_SUCCESS;
 	void *buf = NULL;
 	unsigned long blen;
-	int ltc_hashindex, ltc_res, ltc_stat, ltc_rsa_algo;
+	int ltc_hashindex, ltc_mgfindex, ltc_res, ltc_stat, ltc_rsa_algo;
 	size_t mod_size;
 	rsa_key ltc_key = { 0, };
 
@@ -353,9 +363,19 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 	/* Get the algorithm */
 	res = tee_algo_to_ltc_hashindex(algo, &ltc_hashindex);
 	if (res != TEE_SUCCESS) {
-		EMSG("tee_algo_to_ltc_hashindex() returned %d", (int)res);
+		EMSG("tee_algo_to_ltc_hashindex() returned %#"PRIx32, res);
 		goto out;
 	}
+	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
+		res = tee_algo_to_ltc_hashindex(mgf_algo, &ltc_mgfindex);
+		if (res != TEE_SUCCESS) {
+			EMSG("tee_algo_to_ltc_hashindex() returned %#"PRIx32"for mgf algo %#"PRIx32,
+				res, mgf_algo);
+			goto out;
+		}
+	} else {
+		ltc_mgfindex = -1;
+	}
 
 	/*
 	 * Use a temporary buffer since we don't know exactly how large
@@ -380,8 +400,8 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 
 	ltc_res = rsa_decrypt_key_ex(src, src_len, buf, &blen,
 				     ((label_len == 0) ? 0 : label), label_len,
-				     ltc_hashindex, ltc_rsa_algo, &ltc_stat,
-				     &ltc_key);
+				     ltc_mgfindex, ltc_hashindex, ltc_rsa_algo,
+				     &ltc_stat, &ltc_key);
 	switch (ltc_res) {
 	case CRYPT_PK_INVALID_PADDING:
 	case CRYPT_INVALID_PACKET:
@@ -424,7 +444,9 @@ out:
 TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
 					struct rsa_public_key *key,
 					const uint8_t *label,
-					size_t label_len, const uint8_t *src,
+					size_t label_len,
+					uint32_t mgf_algo,
+					const uint8_t *src,
 					size_t src_len, uint8_t *dst,
 					size_t *dst_len)
 __weak __alias("sw_crypto_acipher_rsaes_encrypt");
@@ -432,13 +454,15 @@ __weak __alias("sw_crypto_acipher_rsaes_encrypt");
 TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 					   struct rsa_public_key *key,
 					   const uint8_t *label,
-					   size_t label_len, const uint8_t *src,
+					   size_t label_len,
+					   uint32_t mgf_algo,
+					   const uint8_t *src,
 					   size_t src_len, uint8_t *dst,
 					   size_t *dst_len)
 {
 	TEE_Result res;
 	uint32_t mod_size;
-	int ltc_hashindex, ltc_res, ltc_rsa_algo;
+	int ltc_hashindex, ltc_mgfindex, ltc_res, ltc_rsa_algo;
 	rsa_key ltc_key = {
 		.type = PK_PUBLIC,
 		.e = key->e,
@@ -458,6 +482,14 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 	if (res != TEE_SUCCESS)
 		goto out;
 
+	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
+		res = tee_algo_to_ltc_hashindex(mgf_algo, &ltc_mgfindex);
+		if (res != TEE_SUCCESS)
+			goto out;
+	} else {
+		ltc_mgfindex = -1;
+	}
+
 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
 		ltc_rsa_algo = LTC_PKCS_1_V1_5;
 	else
@@ -466,7 +498,8 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 	ltc_res = rsa_encrypt_key_ex(src, src_len, dst,
 				     (unsigned long *)(dst_len), label,
 				     label_len, NULL, find_prng("prng_crypto"),
-				     ltc_hashindex, ltc_rsa_algo, &ltc_key);
+				     ltc_mgfindex, ltc_hashindex, ltc_rsa_algo,
+				     &ltc_key);
 	switch (ltc_res) {
 	case CRYPT_PK_INVALID_PADDING:
 	case CRYPT_INVALID_PACKET:
diff --git a/core/lib/libtomcrypt/src/ciphers/aes/aes.c b/core/lib/libtomcrypt/src/ciphers/aes/aes.c
index dd6f14e8eea8d9c2d1ba0b2b35b90f35137f4eec..3a5d0dbb8db31fac65ee22389ab9de4dac48effd 100644
--- a/core/lib/libtomcrypt/src/ciphers/aes/aes.c
+++ b/core/lib/libtomcrypt/src/ciphers/aes/aes.c
@@ -44,15 +44,6 @@ const struct ltc_cipher_descriptor rijndael_desc =
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-const struct ltc_cipher_descriptor aes_desc =
-{
-    "aes",
-    6,
-    16, 32, 16, 10,
-    SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-
 #else
 
 #define SETUP    rijndael_enc_setup
@@ -69,15 +60,6 @@ const struct ltc_cipher_descriptor rijndael_enc_desc =
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-const struct ltc_cipher_descriptor aes_enc_desc =
-{
-    "aes",
-    6,
-    16, 32, 16, 10,
-    SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
-
 #endif
 
 #define LTC_AES_TAB_C
@@ -114,7 +96,7 @@ static ulong32 setup_mix2(ulong32 temp)
 int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
 {
     int i;
-    ulong32 temp, *rk;
+    ulong32 temp, *rk, *K;
 #ifndef ENCRYPT_ONLY
     ulong32 *rrk;
 #endif
@@ -130,6 +112,10 @@ int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *s
     }
 
     skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
+    K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
+    skey->rijndael.eK = K;
+    K += 60;
+    skey->rijndael.dK = K;
 
     /* setup the forward key */
     i                 = 0;
diff --git a/core/lib/libtomcrypt/src/ciphers/aes/aes_desc.c b/core/lib/libtomcrypt/src/ciphers/aes/aes_desc.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b930a5e97339e9f840e43aa0373b60cf2b14dde
--- /dev/null
+++ b/core/lib/libtomcrypt/src/ciphers/aes/aes_desc.c
@@ -0,0 +1,254 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* Auto-detection of AES implementation by Steffen Jaeckel */
+/**
+  @file aes_desc.c
+  Run-time detection of correct AES implementation
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_RIJNDAEL)
+
+#ifndef ENCRYPT_ONLY
+
+#define AES_SETUP aes_setup
+#define AES_ENC   aes_ecb_encrypt
+#define AES_DEC   aes_ecb_decrypt
+#define AES_DONE  aes_done
+#define AES_TEST  aes_test
+#define AES_KS    aes_keysize
+
+const struct ltc_cipher_descriptor aes_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    AES_SETUP, AES_ENC, AES_DEC, AES_TEST, AES_DONE, AES_KS,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#else
+
+#define AES_SETUP aes_enc_setup
+#define AES_ENC   aes_enc_ecb_encrypt
+#define AES_DONE  aes_enc_done
+#define AES_TEST  aes_enc_test
+#define AES_KS    aes_enc_keysize
+
+const struct ltc_cipher_descriptor aes_enc_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    AES_SETUP, AES_ENC, NULL, NULL, AES_DONE, AES_KS,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#endif
+
+/* Code partially borrowed from https://software.intel.com/content/www/us/en/develop/articles/intel-sha-extensions.html */
+#if defined(LTC_HAS_AES_NI)
+static LTC_INLINE int s_aesni_is_supported(void)
+{
+   static int initialized = 0, is_supported = 0;
+
+   if (initialized == 0) {
+      int a, b, c, d;
+
+      /* Look for CPUID.1.0.ECX[25]
+       * EAX = 1, ECX = 0
+       */
+      a = 1;
+      c = 0;
+
+      asm volatile ("cpuid"
+           :"=a"(a), "=b"(b), "=c"(c), "=d"(d)
+           :"a"(a), "c"(c)
+          );
+
+      is_supported = ((c >> 25) & 1);
+      initialized = 1;
+   }
+
+   return is_supported;
+}
+
+#ifndef ENCRYPT_ONLY
+int aesni_is_supported(void)
+{
+   return s_aesni_is_supported();
+}
+#endif
+#endif
+
+ /**
+    Initialize the AES (Rijndael) block cipher
+    @param key The symmetric key you wish to pass
+    @param keylen The key length in bytes
+    @param num_rounds The number of rounds desired (0 for default)
+    @param skey The key in as scheduled by this function.
+    @return CRYPT_OK if successful
+ */
+int AES_SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+#ifdef LTC_HAS_AES_NI
+   if (s_aesni_is_supported()) {
+      return aesni_setup(key, keylen, num_rounds, skey);
+   }
+#endif
+   /* Last resort, software AES */
+   return rijndael_setup(key, keylen, num_rounds, skey);
+}
+
+/**
+  Encrypts a block of text with AES
+  @param pt The input plaintext (16 bytes)
+  @param ct The output ciphertext (16 bytes)
+  @param skey The key as scheduled
+  @return CRYPT_OK if successful
+*/
+int AES_ENC(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+#ifdef LTC_HAS_AES_NI
+   if (s_aesni_is_supported()) {
+      return aesni_ecb_encrypt(pt, ct, skey);
+   }
+#endif
+   return rijndael_ecb_encrypt(pt, ct, skey);
+}
+
+
+#ifndef ENCRYPT_ONLY
+/**
+  Decrypts a block of text with AES
+  @param ct The input ciphertext (16 bytes)
+  @param pt The output plaintext (16 bytes)
+  @param skey The key as scheduled
+  @return CRYPT_OK if successful
+*/
+int AES_DEC(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+#ifdef LTC_HAS_AES_NI
+   if (s_aesni_is_supported()) {
+      return aesni_ecb_decrypt(ct, pt, skey);
+   }
+#endif
+   return rijndael_ecb_decrypt(ct, pt, skey);
+}
+#endif /* ENCRYPT_ONLY */
+
+/**
+  Performs a self-test of the AES block cipher
+  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int AES_TEST(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else
+ int err;
+ static const struct {
+     int keylen;
+     unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+    { 16,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+        0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+    }, {
+      24,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+        0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+    }, {
+      32,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+        0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+    }
+ };
+
+  symmetric_key key;
+  unsigned char tmp[2][16];
+  int i;
+#ifndef ENCRYPT_ONLY
+  int y;
+#endif
+
+  for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+    zeromem(&key, sizeof(key));
+    if ((err = AES_SETUP(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+       return err;
+    }
+
+    AES_ENC(tests[i].pt, tmp[0], &key);
+    if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES Encrypt", i)) {
+        return CRYPT_FAIL_TESTVECTOR;
+    }
+#ifndef ENCRYPT_ONLY
+    AES_DEC(tmp[0], tmp[1], &key);
+    if (compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES Decrypt", i)) {
+        return CRYPT_FAIL_TESTVECTOR;
+    }
+
+    /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+    for (y = 0; y < 16; y++) tmp[0][y] = 0;
+    for (y = 0; y < 1000; y++) AES_ENC(tmp[0], tmp[0], &key);
+    for (y = 0; y < 1000; y++) AES_DEC(tmp[0], tmp[0], &key);
+    for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+#endif
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+
+/** Terminate the context
+   @param skey    The scheduled key
+*/
+void AES_DONE(symmetric_key *skey)
+{
+  LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+  Gets suitable key size
+  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
+  @return CRYPT_OK if the input key size is acceptable.
+*/
+int AES_KS(int *keysize)
+{
+   LTC_ARGCHK(keysize != NULL);
+
+   if (*keysize < 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   if (*keysize < 24) {
+      *keysize = 16;
+      return CRYPT_OK;
+   }
+   if (*keysize < 32) {
+      *keysize = 24;
+      return CRYPT_OK;
+   }
+   *keysize = 32;
+   return CRYPT_OK;
+}
+
+#endif
+
diff --git a/core/lib/libtomcrypt/src/ciphers/aes/aesni.c b/core/lib/libtomcrypt/src/ciphers/aes/aesni.c
new file mode 100644
index 0000000000000000000000000000000000000000..113aaf67629141429c555f880d43e3db14b2cdea
--- /dev/null
+++ b/core/lib/libtomcrypt/src/ciphers/aes/aesni.c
@@ -0,0 +1,371 @@
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* AES-NI implementation by Steffen Jaeckel */
+/**
+  @file aesni.c
+  Implementation of AES via the AES-NI instruction on x86_64
+*/
+
+#include "tomcrypt_private.h"
+
+#if defined(LTC_HAS_AES_NI)
+
+const struct ltc_cipher_descriptor aesni_desc =
+{
+    "aes",
+    6,
+    16, 32, 16, 10,
+    aesni_setup, aesni_ecb_encrypt, aesni_ecb_decrypt, aesni_test, aesni_done, aesni_keysize,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+#include <emmintrin.h>
+#include <smmintrin.h>
+#include <wmmintrin.h>
+
+#define setup_mix(t, c) _mm_extract_epi32(_mm_aeskeygenassist_si128(t, 0), c)
+#define temp_load(k) _mm_loadu_si128((__m128i*)(k))
+#define temp_update(t, k) _mm_insert_epi32(t, k, 3)
+#define temp_invert(k) _mm_aesimc_si128(*((__m128i*)(k)))
+
+
+static const ulong32 rcon[] = {
+    0x01UL, 0x02UL, 0x04UL, 0x08UL, 0x10UL, 0x20UL, 0x40UL, 0x80UL, 0x1BUL, 0x36UL
+};
+
+ /**
+    Initialize the AES (Rijndael) block cipher
+    @param key The symmetric key you wish to pass
+    @param keylen The key length in bytes
+    @param num_rounds The number of rounds desired (0 for default)
+    @param skey The key in as scheduled by this function.
+    @return CRYPT_OK if successful
+ */
+int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   int i;
+   __m128i temp;
+   ulong32 *rk, *K;
+   ulong32 *rrk;
+   LTC_ARGCHK(key != NULL);
+   LTC_ARGCHK(skey != NULL);
+
+   if (keylen != 16 && keylen != 24 && keylen != 32) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+
+   if (num_rounds != 0 && num_rounds != (keylen / 4 + 6)) {
+      return CRYPT_INVALID_ROUNDS;
+   }
+
+   skey->rijndael.Nr = keylen / 4 + 6;
+   K = LTC_ALIGN_BUF(skey->rijndael.K, 16);
+   skey->rijndael.eK = K;
+   K += 60;
+   skey->rijndael.dK = K;
+
+   /* setup the forward key */
+   i = 0;
+   rk = skey->rijndael.eK;
+   LOAD32L(rk[0], key);
+   LOAD32L(rk[1], key + 4);
+   LOAD32L(rk[2], key + 8);
+   LOAD32L(rk[3], key + 12);
+   if (keylen == 16) {
+      temp = temp_load(key);
+      for (;;) {
+         rk[4] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+         rk[5] = rk[1] ^ rk[4];
+         rk[6] = rk[2] ^ rk[5];
+         rk[7] = rk[3] ^ rk[6];
+         if (++i == 10) {
+            break;
+         }
+         temp = temp_update(temp, rk[7]);
+         rk += 4;
+      }
+   } else if (keylen == 24) {
+      LOAD32L(rk[4], key + 16);
+      LOAD32L(rk[5], key + 20);
+      temp = temp_load(key + 8);
+      for (;;) {
+         rk[6] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+         rk[7] = rk[1] ^ rk[6];
+         rk[8] = rk[2] ^ rk[7];
+         rk[9] = rk[3] ^ rk[8];
+         if (++i == 8) {
+            break;
+         }
+         rk[10] = rk[4] ^ rk[9];
+         rk[11] = rk[5] ^ rk[10];
+         temp = temp_update(temp, rk[11]);
+         rk += 6;
+      }
+   } else if (keylen == 32) {
+      LOAD32L(rk[4], key + 16);
+      LOAD32L(rk[5], key + 20);
+      LOAD32L(rk[6], key + 24);
+      LOAD32L(rk[7], key + 28);
+      temp = temp_load(key + 16);
+      for (;;) {
+         rk[8] = rk[0] ^ setup_mix(temp, 3) ^ rcon[i];
+         rk[9] = rk[1] ^ rk[8];
+         rk[10] = rk[2] ^ rk[9];
+         rk[11] = rk[3] ^ rk[10];
+         if (++i == 7) {
+            break;
+         }
+         temp = temp_update(temp, rk[11]);
+         rk[12] = rk[4] ^ setup_mix(temp, 2);
+         rk[13] = rk[5] ^ rk[12];
+         rk[14] = rk[6] ^ rk[13];
+         rk[15] = rk[7] ^ rk[14];
+         temp = temp_update(temp, rk[15]);
+         rk += 8;
+      }
+   } else {
+      /* this can't happen */
+      /* coverity[dead_error_line] */
+      return CRYPT_ERROR;
+   }
+
+   /* setup the inverse key now */
+   rk = skey->rijndael.dK;
+   rrk = skey->rijndael.eK + skey->rijndael.Nr * 4;
+
+   /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+   /* copy first */
+   *rk++ = *rrk++;
+   *rk++ = *rrk++;
+   *rk++ = *rrk++;
+   *rk = *rrk;
+   rk -= 3;
+   rrk -= 3;
+
+   for (i = 1; i < skey->rijndael.Nr; i++) {
+      rrk -= 4;
+      rk += 4;
+      temp = temp_invert(rk);
+      *((__m128i*) rk) = temp_invert(rrk);
+   }
+
+   /* copy last */
+   rrk -= 4;
+   rk += 4;
+   *rk++ = *rrk++;
+   *rk++ = *rrk++;
+   *rk++ = *rrk++;
+   *rk = *rrk;
+
+   return CRYPT_OK;
+}
+
+/**
+  Encrypts a block of text with AES
+  @param pt The input plaintext (16 bytes)
+  @param ct The output ciphertext (16 bytes)
+  @param skey The key as scheduled
+  @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#else
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+#endif
+{
+   int Nr, r;
+   const __m128i *skeys;
+   __m128i block;
+
+   LTC_ARGCHK(pt != NULL);
+   LTC_ARGCHK(ct != NULL);
+   LTC_ARGCHK(skey != NULL);
+
+   Nr = skey->rijndael.Nr;
+
+   if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS;
+
+   skeys = (__m128i*) skey->rijndael.eK;
+   block = _mm_loadu_si128((const __m128i*) (pt));
+
+   block = _mm_xor_si128(block, skeys[0]);
+   for (r = 1; r < Nr - 1; r += 2) {
+      block = _mm_aesenc_si128(block, skeys[r]);
+      block = _mm_aesenc_si128(block, skeys[r + 1]);
+   }
+   block = _mm_aesenc_si128(block, skeys[Nr - 1]);
+   block = _mm_aesenclast_si128(block, skeys[Nr]);
+
+   _mm_storeu_si128((__m128i*) ct, block);
+
+   return CRYPT_OK;
+}
+
+#ifdef LTC_CLEAN_STACK
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey)
+{
+   int err = s_aesni_ecb_encrypt(pt, ct, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+   return err;
+}
+#endif
+
+
+/**
+  Decrypts a block of text with AES
+  @param ct The input ciphertext (16 bytes)
+  @param pt The output plaintext (16 bytes)
+  @param skey The key as scheduled
+  @return CRYPT_OK if successful
+*/
+#ifdef LTC_CLEAN_STACK
+static int s_aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#else
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+#endif
+{
+   int Nr, r;
+   const __m128i *skeys;
+   __m128i block;
+
+   LTC_ARGCHK(pt != NULL);
+   LTC_ARGCHK(ct != NULL);
+   LTC_ARGCHK(skey != NULL);
+
+   Nr = skey->rijndael.Nr;
+
+   if (Nr < 2 || Nr > 16) return CRYPT_INVALID_ROUNDS;
+
+   skeys = (__m128i*) skey->rijndael.dK;
+   block = _mm_loadu_si128((const __m128i*) (ct));
+
+   block = _mm_xor_si128(block, skeys[0]);
+   for (r = 1; r < Nr - 1; r += 2) {
+      block = _mm_aesdec_si128(block, skeys[r]);
+      block = _mm_aesdec_si128(block, skeys[r + 1]);
+   }
+   block = _mm_aesdec_si128(block, skeys[Nr - 1]);
+   block = _mm_aesdeclast_si128(block, skeys[Nr]);
+
+   _mm_storeu_si128((__m128i*) pt, block);
+
+   return CRYPT_OK;
+}
+
+
+#ifdef LTC_CLEAN_STACK
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey)
+{
+   int err = s_aesni_ecb_decrypt(ct, pt, skey);
+   burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
+   return err;
+}
+#endif
+
+/**
+  Performs a self-test of the AES block cipher
+  @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
+*/
+int aesni_test(void)
+{
+ #ifndef LTC_TEST
+    return CRYPT_NOP;
+ #else
+ int err;
+ static const struct {
+     int keylen;
+     unsigned char key[32], pt[16], ct[16];
+ } tests[] = {
+    { 16,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
+        0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
+    }, {
+      24,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
+        0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
+    }, {
+      32,
+      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+        0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
+      { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+        0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
+      { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
+        0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
+    }
+ };
+
+  symmetric_key key;
+  unsigned char tmp[2][16];
+  int i, y;
+
+  for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
+    zeromem(&key, sizeof(key));
+    if ((err = aesni_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
+       return err;
+    }
+
+    aesni_ecb_encrypt(tests[i].pt, tmp[0], &key);
+    aesni_ecb_decrypt(tmp[0], tmp[1], &key);
+    if (compare_testvector(tmp[0], 16, tests[i].ct, 16, "AES-NI Encrypt", i) ||
+          compare_testvector(tmp[1], 16, tests[i].pt, 16, "AES-NI Decrypt", i)) {
+        return CRYPT_FAIL_TESTVECTOR;
+    }
+
+    /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
+    for (y = 0; y < 16; y++) tmp[0][y] = 0;
+    for (y = 0; y < 1000; y++) aesni_ecb_encrypt(tmp[0], tmp[0], &key);
+    for (y = 0; y < 1000; y++) aesni_ecb_decrypt(tmp[0], tmp[0], &key);
+    for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
+  }
+  return CRYPT_OK;
+ #endif
+}
+
+
+/** Terminate the context
+   @param skey    The scheduled key
+*/
+void aesni_done(symmetric_key *skey)
+{
+  LTC_UNUSED_PARAM(skey);
+}
+
+
+/**
+  Gets suitable key size
+  @param keysize [in/out] The length of the recommended key (in bytes).  This function will store the suitable size back in this variable.
+  @return CRYPT_OK if the input key size is acceptable.
+*/
+int aesni_keysize(int *keysize)
+{
+   LTC_ARGCHK(keysize != NULL);
+
+   if (*keysize < 16) {
+      return CRYPT_INVALID_KEYSIZE;
+   }
+   if (*keysize < 24) {
+      *keysize = 16;
+      return CRYPT_OK;
+   }
+   if (*keysize < 32) {
+      *keysize = 24;
+      return CRYPT_OK;
+   }
+   *keysize = 32;
+   return CRYPT_OK;
+}
+
+#endif
+
diff --git a/core/lib/libtomcrypt/src/ciphers/aes/sub.mk b/core/lib/libtomcrypt/src/ciphers/aes/sub.mk
deleted file mode 100644
index ac7b50712e10492d032421c576fd0f9efa81bf21..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/ciphers/aes/sub.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-cflags-y += -Wno-unused-parameter
-
-ifneq ($(_CFG_CORE_LTC_AES_ACCEL),y)
-srcs-$(_CFG_CORE_LTC_AES_DESC) += aes.c
-endif
diff --git a/core/lib/libtomcrypt/src/ciphers/sub.mk b/core/lib/libtomcrypt/src/ciphers/sub.mk
deleted file mode 100644
index 78cf037bd17d4ae06a94129e8bc61b7bd0602b8a..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/ciphers/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-subdirs-$(call cfg-one-enabled, _CFG_CORE_LTC_AES _CFG_CORE_LTC_AES_DESC) += aes
-srcs-$(_CFG_CORE_LTC_DES) += des.c
diff --git a/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c b/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c
index be8133d4f7dd22f0dafdea844007de3c811062ff..7b5ad3f52a9d51f8f0ce2af6738716280e008606 100644
--- a/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c
+++ b/core/lib/libtomcrypt/src/encauth/ccm/ccm_memory.c
@@ -161,6 +161,10 @@ int ccm_memory(int cipher,
        PAD[x++] = 0;
    }
    for (; y < L; y++) {
+       if (x >= sizeof(PAD)) {
+          err = CRYPT_INVALID_ARG;
+          goto error;
+       }
        PAD[x++] = (unsigned char)((len >> 24) & 255);
        len <<= 8;
    }
diff --git a/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c b/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c
index fee2c6b2decaf57ac65674921f1ad5abc007dcf4..114e8d7a8f15b313517b0d3d2f0289fcd8398e01 100644
--- a/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c
+++ b/core/lib/libtomcrypt/src/encauth/ccm/ccm_test.c
@@ -215,14 +215,14 @@ int ccm_test(void)
             XMEMCPY(tag3, tests[x].tag, tests[x].taglen);
             tag3[0] ^= 0xff; /* set the tag to the wrong value */
             taglen = tests[x].taglen;
-            if ((err = ccm_memory(idx,
-                                  tests[x].key, 16,
-                                  NULL,
-                                  tests[x].nonce, tests[x].noncelen,
-                                  tests[x].header, tests[x].headerlen,
-                                  buf2, tests[x].ptlen,
-                                  buf,
-                                  tag3, &taglen, 1   )) != CRYPT_ERROR) {
+            if (ccm_memory(idx,
+                           tests[x].key, 16,
+                           NULL,
+                           tests[x].nonce, tests[x].noncelen,
+                           tests[x].header, tests[x].headerlen,
+                           buf2, tests[x].ptlen,
+                           buf,
+                           tag3, &taglen, 1   ) != CRYPT_ERROR) {
                return CRYPT_FAIL_TESTVECTOR;
             }
             if (compare_testvector(buf2, tests[x].ptlen, zero, tests[x].ptlen, "CCM decrypt wrong tag", x)) {
diff --git a/core/lib/libtomcrypt/src/encauth/ccm/sub.mk b/core/lib/libtomcrypt/src/encauth/ccm/sub.mk
deleted file mode 100644
index 8f4306051d6552b2d0f36a636927bd3d618595d8..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/encauth/ccm/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += ccm_init.c
-srcs-y += ccm_add_nonce.c
-srcs-y += ccm_add_aad.c
-srcs-y += ccm_process.c
-srcs-y += ccm_done.c
-srcs-y += ccm_reset.c
diff --git a/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c b/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c
index 4ae0960df4ff41a2b4ed2522943ba6c6f8f337f7..bd3ee3b9a20842c2977ef3886377c153c49e9d23 100644
--- a/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c
+++ b/core/lib/libtomcrypt/src/encauth/gcm/gcm_memory.c
@@ -70,9 +70,7 @@ int gcm_memory(      int           cipher,
     * but again it's only for SSE2 anyways, so who cares?
     */
 #ifdef LTC_GCM_TABLES_SSE2
-   if ((unsigned long)gcm & 15) {
-      gcm = (gcm_state *)((unsigned long)gcm + (16 - ((unsigned long)gcm & 15)));
-   }
+    gcm = LTC_ALIGN_BUF(gcm, 16);
 #endif
 
     if ((err = gcm_init(gcm, cipher, key, keylen)) != CRYPT_OK) {
@@ -106,6 +104,7 @@ int gcm_memory(      int           cipher,
        err = CRYPT_INVALID_ARG;
     }
 LTC_ERR:
+    gcm_reset(gcm);
     XFREE(orig);
     return err;
 }
diff --git a/core/lib/libtomcrypt/src/encauth/gcm/sub.mk b/core/lib/libtomcrypt/src/encauth/gcm/sub.mk
deleted file mode 100644
index 6720c3fcee54ab72010ddc79932a091997f87f99..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/encauth/gcm/sub.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-srcs-y += gcm_add_aad.c
-srcs-y += gcm_add_iv.c
-srcs-y += gcm_done.c
-srcs-y += gcm_gf_mult.c
-srcs-y += gcm_init.c
-srcs-y += gcm_memory.c
-ifeq ($(_CFG_CORE_LTC_CE),y)
-srcs-y += gcm_mult_h_arm_ce.c
-else
-srcs-y += gcm_mult_h.c
-endif
-srcs-y += gcm_process.c
-srcs-y += gcm_reset.c
diff --git a/core/lib/libtomcrypt/src/encauth/sub.mk b/core/lib/libtomcrypt/src/encauth/sub.mk
deleted file mode 100644
index 6ef940545e56ccfc65947cfae85867aa50a59a3e..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/encauth/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-subdirs-$(_CFG_CORE_LTC_CCM) += ccm
-subdirs-$(_CFG_CORE_LTC_GCM) += gcm
diff --git a/core/lib/libtomcrypt/src/hashes/helper/sub.mk b/core/lib/libtomcrypt/src/hashes/helper/sub.mk
deleted file mode 100644
index c01be6ddcdb6f5b716239277bd506e715a69e12d..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/hashes/helper/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-cflags-y += -Wno-unused-parameter
-
-srcs-y += hash_memory.c
-srcs-y += hash_memory_multi.c
diff --git a/core/lib/libtomcrypt/src/hashes/sha2/sub.mk b/core/lib/libtomcrypt/src/hashes/sha2/sub.mk
deleted file mode 100644
index cd701ec1aeca1a10c58695d0b0cc36ebea56c0db..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/hashes/sha2/sub.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-srcs-$(_CFG_CORE_LTC_SHA224_DESC) += sha224.c
-
-ifneq ($(_CFG_CORE_LTC_SHA256_ACCEL),y)
-srcs-$(_CFG_CORE_LTC_SHA256_DESC) += sha256.c
-endif
-
-srcs-$(_CFG_CORE_LTC_SHA384_DESC) += sha384.c
-
-ifneq ($(_CFG_CORE_LTC_SHA512_ACCEL),y)
-srcs-$(_CFG_CORE_LTC_SHA512_DESC) += sha512.c
-endif
-
-srcs-$(_CFG_CORE_LTC_SHA512_256) += sha512_256.c
diff --git a/core/lib/libtomcrypt/src/hashes/sub.mk b/core/lib/libtomcrypt/src/hashes/sub.mk
deleted file mode 100644
index 6a35fe2b81929b36e50d2033ec9bcdabbe108f3c..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/hashes/sub.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-srcs-$(_CFG_CORE_LTC_MD5_DESC) += md5.c
-
-ifeq ($(_CFG_CORE_LTC_SHA1_DESC),y)
-ifneq ($(_CFG_CORE_LTC_SHA1_ACCEL),y)
-srcs-y += sha1.c
-endif
-endif
-
-ifneq ($(_CFG_CORE_LTC_SHA3_ACCEL),y)
-srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3.c
-endif
-srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3_test.c
-subdirs-y += helper
-subdirs-y += sha2
diff --git a/core/lib/libtomcrypt/src/hashes/tiger.c b/core/lib/libtomcrypt/src/hashes/tiger.c
index 8ca2d54f2f8bcc7914566d54cf95f2f851c4d9eb..145bf28c0b26e292ef60bcb5e4895e245e8718af 100644
--- a/core/lib/libtomcrypt/src/hashes/tiger.c
+++ b/core/lib/libtomcrypt/src/hashes/tiger.c
@@ -28,6 +28,24 @@ const struct ltc_hash_descriptor tiger_desc =
     NULL
 };
 
+const struct ltc_hash_descriptor tiger2_desc =
+{
+    "tiger2",
+    33,
+    24,
+    64,
+
+    /* OID ... does not exist */
+   { 0 },
+   0,
+
+    &tiger2_init,
+    &tiger_process,
+    &tiger_done,
+    &tiger2_test,
+    NULL
+};
+
 #define t1 (table)
 #define t2 (table+256)
 #define t3 (table+256*2)
@@ -601,7 +619,7 @@ static int ss_tiger_compress(hash_state *md, const unsigned char *buf)
 static int  s_tiger_compress(hash_state *md, const unsigned char *buf)
 #endif
 {
-    ulong64 a, b, c, x[8];
+    ulong64 a, b, c, x[8], t;
     unsigned long i;
 
     /* load words */
@@ -617,6 +635,11 @@ static int  s_tiger_compress(hash_state *md, const unsigned char *buf)
     s_pass(&c,&a,&b,x,7);
     s_key_schedule(x);
     s_pass(&b,&c,&a,x,9);
+    for (i = 3; i < md->tiger.passes; ++i) {
+       s_key_schedule(x);
+       s_pass(&a,&b,&c,x,9);
+       t = a; a = c; c = b; b = t;
+   }
 
     /* store state */
     md->tiger.state[0] = a ^ md->tiger.state[0];
@@ -649,6 +672,57 @@ int tiger_init(hash_state *md)
     md->tiger.state[2] = CONST64(0xF096A5B4C3B2E187);
     md->tiger.curlen = 0;
     md->tiger.length = 0;
+    md->tiger.passes = 3;
+    md->tiger.pad = 0x01u;
+    return CRYPT_OK;
+}
+
+/**
+   Initialize the hash state (extended version)
+   @param md       The hash state you wish to initialize
+   @param passes   The number of passes that should be executed
+                   when the compress function is called.
+   @return CRYPT_OK if successful
+*/
+int tiger_init_ex(hash_state *md, unsigned long passes)
+{
+    int err;
+    if ((err = tiger_init(md) != CRYPT_OK)) {
+        return err;
+    }
+    md->tiger.passes = passes;
+    return CRYPT_OK;
+}
+
+/**
+   Initialize the hash state (extended version)
+   @param md       The hash state you wish to initialize
+   @return CRYPT_OK if successful
+*/
+int tiger2_init(hash_state *md)
+{
+    int err;
+    if ((err = tiger_init(md) != CRYPT_OK)) {
+       return err;
+    }
+    md->tiger.pad = 0x80u;
+    return CRYPT_OK;
+}
+
+/**
+   Initialize the hash state (extended version)
+   @param md       The hash state you wish to initialize
+   @param passes   The number of passes that should be executed
+                   when the compress function is called.
+   @return CRYPT_OK if successful
+*/
+int tiger2_init_ex(hash_state *md, unsigned long passes)
+{
+    int err;
+    if ((err = tiger2_init(md) != CRYPT_OK)) {
+        return err;
+    }
+    md->tiger.passes = passes;
     return CRYPT_OK;
 }
 
@@ -679,8 +753,8 @@ int tiger_done(hash_state * md, unsigned char *out)
     /* increase the length of the message */
     md->tiger.length += md->tiger.curlen * 8;
 
-    /* append the '1' bit */
-    md->tiger.buf[md->tiger.curlen++] = (unsigned char)0x01;
+    /* append the padding bit */
+    md->tiger.buf[md->tiger.curlen++] = md->tiger.pad;
 
     /* if the length is currently above 56 bytes we append zeros
      * then compress.  Then we can fall back to padding zeros and length
@@ -717,51 +791,77 @@ int tiger_done(hash_state * md, unsigned char *out)
   Self-test the hash
   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
 */
-int  tiger_test(void)
+int s_tiger_test(unsigned int idx)
 {
  #ifndef LTC_TEST
     return CRYPT_NOP;
  #else
   static const struct {
       const char *msg;
-      unsigned char hash[24];
+      unsigned char hash[2][24];
   } tests[] = {
     { "",
-     { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
-       0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
-       0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 }
+      {
+        { 0x32, 0x93, 0xac, 0x63, 0x0c, 0x13, 0xf0, 0x24,
+          0x5f, 0x92, 0xbb, 0xb1, 0x76, 0x6e, 0x16, 0x16,
+          0x7a, 0x4e, 0x58, 0x49, 0x2d, 0xde, 0x73, 0xf3 },
+        { 0x44, 0x41, 0xbe, 0x75, 0xf6, 0x01, 0x87, 0x73,
+          0xc2, 0x06, 0xc2, 0x27, 0x45, 0x37, 0x4b, 0x92,
+          0x4a, 0xa8, 0x31, 0x3f, 0xef, 0x91, 0x9f, 0x41 },
+      },
     },
     { "abc",
-     { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2,
-       0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52,
-       0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 }
+      {
+        { 0x2a, 0xab, 0x14, 0x84, 0xe8, 0xc1, 0x58, 0xf2,
+          0xbf, 0xb8, 0xc5, 0xff, 0x41, 0xb5, 0x7a, 0x52,
+          0x51, 0x29, 0x13, 0x1c, 0x95, 0x7b, 0x5f, 0x93 },
+        { 0xf6, 0x8d, 0x7b, 0xc5, 0xaf, 0x4b, 0x43, 0xa0,
+          0x6e, 0x04, 0x8d, 0x78, 0x29, 0x56, 0x0d, 0x4a,
+          0x94, 0x15, 0x65, 0x8b, 0xb0, 0xb1, 0xf3, 0xbf },
+      },
     },
     { "Tiger",
-     { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f,
-       0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27,
-       0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 }
+      {
+        { 0xdd, 0x00, 0x23, 0x07, 0x99, 0xf5, 0x00, 0x9f,
+          0xec, 0x6d, 0xeb, 0xc8, 0x38, 0xbb, 0x6a, 0x27,
+          0xdf, 0x2b, 0x9d, 0x6f, 0x11, 0x0c, 0x79, 0x37 },
+        { 0xfe, 0x40, 0x79, 0x8b, 0x8e, 0xb9, 0x37, 0xfd,
+          0x97, 0x76, 0x08, 0x93, 0x05, 0x48, 0xd6, 0xa8,
+          0x94, 0xc2, 0x0b, 0x04, 0xcb, 0xef, 0x7a, 0x42 },
+      },
     },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
-     { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87,
-       0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47,
-       0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 }
+      {
+        { 0xf7, 0x1c, 0x85, 0x83, 0x90, 0x2a, 0xfb, 0x87,
+          0x9e, 0xdf, 0xe6, 0x10, 0xf8, 0x2c, 0x0d, 0x47,
+          0x86, 0xa3, 0xa5, 0x34, 0x50, 0x44, 0x86, 0xb5 },
+        { 0x15, 0x9b, 0x38, 0x0a, 0xb7, 0x92, 0x94, 0xe0,
+          0xda, 0x19, 0xf1, 0x62, 0x82, 0xce, 0x6d, 0xce,
+          0x0f, 0x84, 0xd3, 0x4f, 0x72, 0x9d, 0xbe, 0xa3 },
+      },
     },
     { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
-     { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00,
-       0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76,
-       0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 }
+      {
+        { 0xc5, 0x40, 0x34, 0xe5, 0xb4, 0x3e, 0xb8, 0x00,
+          0x58, 0x48, 0xa7, 0xe0, 0xae, 0x6a, 0xac, 0x76,
+          0xe4, 0xff, 0x59, 0x0a, 0xe7, 0x15, 0xfd, 0x25 },
+        { 0x01, 0xef, 0x91, 0x0b, 0x9b, 0xb2, 0xcb, 0x4c,
+          0x6c, 0x47, 0x49, 0x5c, 0x86, 0xb3, 0x64, 0x1a,
+          0xff, 0x14, 0xfb, 0xf7, 0x79, 0x40, 0x9c, 0x0e },
+      },
     },
   };
+  int (*init[2])(hash_state *hash) = { tiger_init, tiger2_init };
 
   int i;
   unsigned char tmp[24];
   hash_state md;
 
   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
-      tiger_init(&md);
+      init[idx](&md);
       tiger_process(&md, (unsigned char *)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
       tiger_done(&md, tmp);
-      if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "TIGER", i)) {
+      if (compare_testvector(tmp, sizeof(tmp), tests[i].hash[idx], sizeof(tests[i].hash[idx]), !idx ? "TIGER": "TIGER2", i)) {
           return CRYPT_FAIL_TESTVECTOR;
       }
   }
@@ -769,6 +869,24 @@ int  tiger_test(void)
   #endif
 }
 
+/**
+  Self-test the hash
+  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int tiger_test(void)
+{
+   return s_tiger_test(0);
+}
+
+/**
+  Self-test the hash
+  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
+*/
+int tiger2_test(void)
+{
+   return s_tiger_test(1);
+}
+
 #endif
 
 /*
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt.h b/core/lib/libtomcrypt/src/headers/tomcrypt.h
index c310a8ce4627844b39b0483f5513cc15bc5a5cee..8efdc8a98d3a15c74b2e244cd5eeb7966c5fa0b5 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt.h
@@ -28,7 +28,7 @@ extern "C" {
 
 #ifndef TAB_SIZE
 /* descriptor table size */
-#define TAB_SIZE      34
+#define TAB_SIZE      48
 #endif
 
 /* error codes [will be expanded in future releases] */
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h b/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h
index 3dad4667c6f2ed948c0e8ebb8f38b471a32104ab..3d90d03ccaa6560be5bdaacf9f8b44e36d26b16f 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_cfg.h
@@ -79,18 +79,23 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
  * The x86 platforms allow this but some others [ARM for instance] do not.  On those platforms you **MUST**
  * use the portable [slower] macros.
  */
-/* detect x86/i386 32bit */
-#if defined(__i386__) || defined(__i386) || defined(_M_IX86)
+/* detect x86/i386/ARM 32bit */
+#if defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_ARM)
    #define ENDIAN_LITTLE
    #define ENDIAN_32BITWORD
    #define LTC_FAST
 #endif
 
-/* detect amd64/x64 */
-#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64)
+/* detect amd64/x64/arm64 */
+#if defined(__x86_64__) || defined(_M_X64) || defined(_M_AMD64) || defined(_M_ARM64)
    #define ENDIAN_LITTLE
    #define ENDIAN_64BITWORD
    #define LTC_FAST
+   #if defined(__SSE4_1__)
+      #if __SSE4_1__ == 1
+         #define LTC_AMD64_SSE4_1
+      #endif
+   #endif
 #endif
 
 /* detect PPC32 */
@@ -190,7 +195,8 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
       defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || \
       defined(__LITTLE_ENDIAN__) || \
       defined(__ARMEL__) || defined(__THUMBEL__) || defined(__AARCH64EL__) || \
-      defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__)
+      defined(_MIPSEL) || defined(__MIPSEL) || defined(__MIPSEL__) || \
+      defined(_M_ARM) || defined(_M_ARM64)
     #define ENDIAN_LITTLE
   #else
     #error Cannot detect endianness
@@ -203,7 +209,7 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
    typedef unsigned __int64 ulong64;
    typedef __int64 long64;
 #else
-   #define CONST64(n) n ## ULL
+   #define CONST64(n) n ## uLL
    typedef unsigned long long ulong64;
    typedef long long long64;
 #endif
@@ -214,7 +220,7 @@ LTC_EXPORT int   LTC_CALL XSTRCMP(const char *s1, const char *s2);
     defined(__s390x__) || defined(__arch64__) || defined(__aarch64__) || \
     defined(__sparcv9) || defined(__sparc_v9__) || defined(__sparc64__) || \
     defined(__ia64) || defined(__ia64__) || defined(__itanium__) || defined(_M_IA64) || \
-    defined(__LP64__) || defined(_LP64) || defined(__64BIT__)
+    defined(__LP64__) || defined(_LP64) || defined(__64BIT__) || defined(_M_ARM64)
    typedef unsigned ulong32;
    #if !defined(ENDIAN_64BITWORD) && !defined(ENDIAN_32BITWORD)
      #define ENDIAN_64BITWORD
@@ -295,6 +301,21 @@ typedef unsigned long ltc_mp_digit;
    #define LTC_ALIGN(n)
 #endif
 
+/* Choose Windows Vista as minimum Version if we're compiling with at least VS2019
+ * This is done in order to test the bcrypt RNG and can still be overridden by the user. */
+#if defined(_MSC_VER) && _MSC_VER >= 1920
+#   ifndef _WIN32_WINNT
+#      define _WIN32_WINNT 0x0600
+#   endif
+#   ifndef WINVER
+#      define WINVER 0x0600
+#   endif
+#endif
+
+#if defined(_MSC_VER) && defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 && !defined(LTC_WIN32_BCRYPT)
+#   define LTC_WIN32_BCRYPT
+#endif
+
 /* Define `LTC_NO_NULL_TERMINATION_CHECK` in the user code
  * before including `tomcrypt.h` to disable this functionality.
  */
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h b/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h
index 17a099491406a70f7f37f4e787a690ad71619efc..aa94698deff40a2422c5a26cb4044a92288d9448 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_cipher.h
@@ -35,7 +35,9 @@ struct saferp_key {
 
 #ifdef LTC_RIJNDAEL
 struct rijndael_key {
-   ulong32 eK[60], dK[60];
+   unsigned char K[(60 + 60 + 4) * sizeof(ulong32)];
+   ulong32 *eK;
+   ulong32 *dK;
    int Nr;
 };
 #endif
@@ -127,24 +129,24 @@ struct khazad_key {
 
 #ifdef LTC_ANUBIS
 struct anubis_key {
-   int keyBits;
-   int R;
    ulong32 roundKeyEnc[18 + 1][4];
    ulong32 roundKeyDec[18 + 1][4];
+   int keyBits;
+   int R;
 };
 #endif
 
 #ifdef LTC_MULTI2
 struct multi2_key {
-    int N;
     ulong32 uk[8];
+    int N;
 };
 #endif
 
 #ifdef LTC_CAMELLIA
 struct camellia_key {
-    int R;
     ulong64 kw[4], k[24], kl[6];
+    int R;
 };
 #endif
 
@@ -245,60 +247,60 @@ typedef union Symmetric_key {
 #ifdef LTC_ECB_MODE
 /** A block cipher ECB structure */
 typedef struct {
+   /** The scheduled key */
+   symmetric_key       key;
    /** The index of the cipher chosen */
    int                 cipher,
    /** The block size of the given cipher */
                        blocklen;
-   /** The scheduled key */
-   symmetric_key       key;
 } symmetric_ECB;
 #endif
 
 #ifdef LTC_CFB_MODE
 /** A block cipher CFB structure */
 typedef struct {
-   /** The index of the cipher chosen */
-   int                 cipher,
-   /** The block size of the given cipher */
-                       blocklen,
-   /** The padding offset */
-                       padlen;
    /** The current IV */
    unsigned char       IV[MAXBLOCKSIZE],
    /** The pad used to encrypt/decrypt */
                        pad[MAXBLOCKSIZE];
    /** The scheduled key */
    symmetric_key       key;
+   /** The index of the cipher chosen */
+   int                 cipher,
+   /** The block size of the given cipher */
+                       blocklen,
+   /** The padding offset */
+                       padlen;
 } symmetric_CFB;
 #endif
 
 #ifdef LTC_OFB_MODE
 /** A block cipher OFB structure */
 typedef struct {
+   /** The current IV */
+   unsigned char       IV[MAXBLOCKSIZE];
+   /** The scheduled key */
+   symmetric_key       key;
    /** The index of the cipher chosen */
    int                 cipher,
    /** The block size of the given cipher */
                        blocklen,
    /** The padding offset */
                        padlen;
-   /** The current IV */
-   unsigned char       IV[MAXBLOCKSIZE];
-   /** The scheduled key */
-   symmetric_key       key;
 } symmetric_OFB;
 #endif
 
 #ifdef LTC_CBC_MODE
 /** A block cipher CBC structure */
 typedef struct {
-   /** The index of the cipher chosen */
-   int                 cipher,
-   /** The block size of the given cipher */
-                       blocklen;
    /** The current IV */
    unsigned char       IV[MAXBLOCKSIZE];
    /** The scheduled key */
    symmetric_key       key;
+   /** The index of the cipher chosen */
+   int                 cipher,
+   /** The block size of the given cipher */
+                       blocklen;
 } symmetric_CBC;
 #endif
 
@@ -306,6 +308,13 @@ typedef struct {
 #ifdef LTC_CTR_MODE
 /** A block cipher CTR structure */
 typedef struct {
+   /** The counter */
+   unsigned char       ctr[MAXBLOCKSIZE];
+   /** The pad used to encrypt/decrypt */
+   unsigned char       pad[MAXBLOCKSIZE];
+   /** The scheduled key */
+   symmetric_key       key;
+
    /** The index of the cipher chosen */
    int                 cipher,
    /** The block size of the given cipher */
@@ -316,13 +325,6 @@ typedef struct {
                        mode,
    /** counter width */
                        ctrlen;
-
-   /** The counter */
-   unsigned char       ctr[MAXBLOCKSIZE];
-   /** The pad used to encrypt/decrypt */
-   unsigned char       pad[MAXBLOCKSIZE] LTC_ALIGN(16);
-   /** The scheduled key */
-   symmetric_key       key;
 } symmetric_CTR;
 #endif
 
@@ -330,9 +332,6 @@ typedef struct {
 #ifdef LTC_LRW_MODE
 /** A LRW structure */
 typedef struct {
-    /** The index of the cipher chosen (must be a 128-bit block cipher) */
-    int               cipher;
-
     /** The current IV */
     unsigned char     IV[16],
 
@@ -349,25 +348,28 @@ typedef struct {
     /** The pre-computed multiplication table */
     unsigned char     PC[16][256][16];
 #endif
+
+    /** The index of the cipher chosen (must be a 128-bit block cipher) */
+    int               cipher;
 } symmetric_LRW;
 #endif
 
 #ifdef LTC_F8_MODE
 /** A block cipher F8 structure */
 typedef struct {
+   /** The current IV */
+   unsigned char       IV[MAXBLOCKSIZE],
+                       MIV[MAXBLOCKSIZE];
+   /** The scheduled key */
+   symmetric_key       key;
    /** The index of the cipher chosen */
    int                 cipher,
    /** The block size of the given cipher */
                        blocklen,
    /** The padding offset */
                        padlen;
-   /** The current IV */
-   unsigned char       IV[MAXBLOCKSIZE],
-                       MIV[MAXBLOCKSIZE];
    /** Current block count */
    ulong32             blockcnt;
-   /** The scheduled key */
-   symmetric_key       key;
 } symmetric_F8;
 #endif
 
@@ -688,18 +690,20 @@ extern const struct ltc_cipher_descriptor safer_k64_desc, safer_k128_desc, safer
 #endif
 
 #ifdef LTC_RIJNDAEL
-
-/* make aes an alias */
-#define aes_setup           rijndael_setup
-#define aes_ecb_encrypt     rijndael_ecb_encrypt
-#define aes_ecb_decrypt     rijndael_ecb_decrypt
-#define aes_test            rijndael_test
-#define aes_done            rijndael_done
-#define aes_keysize         rijndael_keysize
-
-#define aes_enc_setup           rijndael_enc_setup
-#define aes_enc_ecb_encrypt     rijndael_enc_ecb_encrypt
-#define aes_enc_keysize         rijndael_enc_keysize
+/* declare aes properly now */
+int aes_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aes_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aes_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int aes_test(void);
+void aes_done(symmetric_key *skey);
+int aes_keysize(int *keysize);
+int aes_enc_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aes_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aes_enc_test(void);
+void aes_enc_done(symmetric_key *skey);
+int aes_enc_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor aes_desc;
+extern const struct ltc_cipher_descriptor aes_enc_desc;
 
 int rijndael_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
 int rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
@@ -711,8 +715,19 @@ int rijndael_enc_setup(const unsigned char *key, int keylen, int num_rounds, sym
 int rijndael_enc_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
 void rijndael_enc_done(symmetric_key *skey);
 int rijndael_enc_keysize(int *keysize);
-extern const struct ltc_cipher_descriptor rijndael_desc, aes_desc;
-extern const struct ltc_cipher_descriptor rijndael_enc_desc, aes_enc_desc;
+extern const struct ltc_cipher_descriptor rijndael_desc;
+extern const struct ltc_cipher_descriptor rijndael_enc_desc;
+#endif
+
+#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1)
+int aesni_is_supported(void);
+int aesni_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey);
+int aesni_ecb_encrypt(const unsigned char *pt, unsigned char *ct, const symmetric_key *skey);
+int aesni_ecb_decrypt(const unsigned char *ct, unsigned char *pt, const symmetric_key *skey);
+int aesni_test(void);
+void aesni_done(symmetric_key *skey);
+int aesni_keysize(int *keysize);
+extern const struct ltc_cipher_descriptor aesni_desc;
 #endif
 
 #ifdef LTC_XTEA
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h b/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h
index 62eab007b590408c72220543fb0e3e7bb08a3e3b..8b01d3c2e4b65d3554f033946ab6670a73a83e9d 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_custom.h
@@ -179,6 +179,9 @@
 #define LTC_RC6
 #define LTC_SAFERP
 #define LTC_RIJNDAEL
+#ifndef LTC_NO_AES_NI
+   #define LTC_AES_NI
+#endif
 #define LTC_XTEA
 /* _TABLES tells it to use tables during setup, _SMALL means to use the smaller scheduled key format
  * (saves 4KB of ram), _ALL_TABLES enables all tables during setup */
@@ -332,11 +335,14 @@
 /* Greg's SOBER128 stream cipher based PRNG */
 #define LTC_SOBER128
 
+#if !defined(_WIN32) && !defined(_WIN32_WCE)
 /* the *nix style /dev/random device */
 #define LTC_DEVRANDOM
 /* try /dev/urandom before trying /dev/random
  * are you sure you want to disable this? http://www.2uo.de/myths-about-urandom/ */
 #define LTC_TRY_URANDOM_FIRST
+#endif /* not Windows */
+
 /* rng_get_bytes() */
 #define LTC_RNG_GET_BYTES
 /* rng_make_prng() */
@@ -369,9 +375,9 @@
 
 /* with non-glibc or glibc 2.17+ prefer clock_gettime over gettimeofday */
 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
-#if __GLIBC_PREREQ(2, 17)
-  #define LTC_CLOCK_GETTIME
-#endif
+   #if __GLIBC_PREREQ(2, 17)
+      #define LTC_CLOCK_GETTIME
+   #endif
 #elif defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L
   #define LTC_CLOCK_GETTIME
 #endif
@@ -401,6 +407,11 @@
 #define LTC_FORTUNA_POOLS 32
 #endif
 
+/* at compile time you can decide whether fortuna uses the regular AES APIs
+ * or whether it will use the 'encrypt_only' variants.
+ * This is useful for custom builds of libtomcrypt for size-constrained targets. */
+/* #define LTC_FORTUNA_USE_ENCRYPT_ONLY */
+
 #endif /* LTC_FORTUNA */
 
 
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h b/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h
index bc18b6304b1be39fe02229550b5f57a7ce6ad343..a29d482da60a12cdf71f150abeda58727afd9cce 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_hash.h
@@ -57,8 +57,8 @@ struct md4_state {
 #ifdef LTC_TIGER
 struct tiger_state {
     ulong64 state[3], length;
-    unsigned long curlen;
-    unsigned char buf[64];
+    unsigned long curlen, passes;
+    unsigned char buf[64], pad;
 };
 #endif
 
@@ -440,10 +440,16 @@ extern const struct ltc_hash_descriptor md2_desc;
 
 #ifdef LTC_TIGER
 int tiger_init(hash_state * md);
+int tiger_init_ex(hash_state *md, unsigned long passes);
 int tiger_process(hash_state * md, const unsigned char *in, unsigned long inlen);
 int tiger_done(hash_state * md, unsigned char *out);
 int tiger_test(void);
-extern const struct ltc_hash_descriptor tiger_desc;
+int tiger2_init(hash_state *md);
+int tiger2_init_ex(hash_state *md, unsigned long passes);
+#define tiger2_process(m, i, l) tiger_process(m, i, l)
+#define tiger2_done(m, o)       tiger_done(m, o)
+int tiger2_test(void);
+extern const struct ltc_hash_descriptor tiger_desc, tiger2_desc;
 #endif
 
 #ifdef LTC_RIPEMD128
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h b/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h
index c8f4a322780fcc79a62a6d465140776326bb5457..f6738f69774f02bd2975faa311efdb1f19869669 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_mac.h
@@ -358,10 +358,10 @@ typedef struct {
    unsigned char     aSum_current[MAXBLOCKSIZE],    /* AAD related helper variable */
                      aOffset_current[MAXBLOCKSIZE], /* AAD related helper variable */
                      adata_buffer[MAXBLOCKSIZE];    /* AAD buffer */
-   int               adata_buffer_bytes;            /* bytes in AAD buffer */
-   unsigned long     ablock_index;                  /* index # for current adata (AAD) block */
 
    symmetric_key     key;                     /* scheduled key for cipher */
+   int               adata_buffer_bytes;            /* bytes in AAD buffer */
+   unsigned long     ablock_index;                  /* index # for current adata (AAD) block */
    unsigned long     block_index;             /* index # for current data block */
    int               cipher,                  /* cipher idx */
                      tag_len,                 /* length of tag */
@@ -407,7 +407,12 @@ int ocb3_test(void);
 #define CCM_DECRYPT LTC_DECRYPT
 
 typedef struct {
+   unsigned char       PAD[16],              /* flags | Nonce N | l(m) */
+                       ctr[16],
+                       CTRPAD[16];
+
    symmetric_key       K;
+
    int                 cipher,               /* which cipher */
                        taglen,               /* length of the tag (encoded in M value) */
                        x;                    /* index in PAD */
@@ -419,10 +424,7 @@ typedef struct {
                        current_aadlen,       /* length of the currently provided add */
                        noncelen;             /* length of the nonce */
 
-   unsigned char       PAD[16],              /* flags | Nonce N | l(m) */
-                       ctr[16],
-                       CTRPAD[16],
-                       CTRlen;
+   unsigned char       CTRlen;
 } ccm_state;
 
 int ccm_init(ccm_state *ccm, int cipher,
@@ -478,13 +480,18 @@ extern const unsigned char gcm_shift_table[];
 #define LTC_GCM_MODE_TEXT  2
 
 typedef struct {
-   symmetric_key       K;
    unsigned char       H[16],        /* multiplier */
                        X[16],        /* accumulator */
                        Y[16],        /* counter */
                        Y_0[16],      /* initial counter */
                        buf[16];      /* buffer for stuff */
 
+#ifdef LTC_GCM_TABLES
+   unsigned char       PC[16][256][16];  /* 16 tables of 8x128 */
+#endif
+
+   symmetric_key       K;
+
    int                 cipher,       /* which cipher */
                        ivmode,       /* Which mode is the IV in? */
                        mode,         /* mode the GCM code is in */
@@ -492,14 +499,6 @@ typedef struct {
 
    ulong64             totlen,       /* 64-bit counter used for IV and AAD */
                        pttotlen;     /* 64-bit counter for the PT */
-
-#ifdef LTC_GCM_TABLES
-   unsigned char       PC[16][256][16]  /* 16 tables of 8x128 */
-#ifdef LTC_GCM_TABLES_SSE2
-LTC_ALIGN(16)
-#endif
-;
-#endif
 } gcm_state;
 
 void gcm_mult_h(const gcm_state *gcm, unsigned char *I);
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h b/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h
index 94aa7c32d20fd737fd5eafe070ce68b200b93a64..257f523831b1b161b6886e9b657f3930411bf212 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_macros.h
@@ -1,6 +1,11 @@
 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
 /* SPDX-License-Identifier: Unlicense */
 
+
+#define LTC_TMPVAR__(n, l) n ## l
+#define LTC_TMPVAR_(n, l) LTC_TMPVAR__(n, l)
+#define LTC_TMPVAR(n) LTC_TMPVAR_(LTC_ ## n ## _, __LINE__)
+
 /* ---- HELPER MACROS ---- */
 #ifdef ENDIAN_NEUTRAL
 
@@ -275,20 +280,20 @@ static inline ulong32 ROR(ulong32 word, int i)
 #ifndef LTC_NO_ROLC
 
 #define ROLc(word,i) ({ \
-   ulong32 ROLc_tmp = (word); \
+   ulong32 LTC_TMPVAR(ROLc) = (word); \
    __asm__ ("roll %2, %0" : \
-            "=r" (ROLc_tmp) : \
-            "0" (ROLc_tmp), \
+            "=r" (LTC_TMPVAR(ROLc)) : \
+            "0" (LTC_TMPVAR(ROLc)), \
             "I" (i)); \
-            ROLc_tmp; \
+            LTC_TMPVAR(ROLc); \
    })
 #define RORc(word,i) ({ \
-   ulong32 RORc_tmp = (word); \
+   ulong32 LTC_TMPVAR(RORc) = (word); \
    __asm__ ("rorl %2, %0" : \
-            "=r" (RORc_tmp) : \
-            "0" (RORc_tmp), \
+            "=r" (LTC_TMPVAR(RORc)) : \
+            "0" (LTC_TMPVAR(RORc)), \
             "I" (i)); \
-            RORc_tmp; \
+            LTC_TMPVAR(RORc); \
    })
 
 #else
@@ -393,20 +398,20 @@ static inline ulong64 ROR64(ulong64 word, int i)
 #ifndef LTC_NO_ROLC
 
 #define ROL64c(word,i) ({ \
-   ulong64 ROL64c_tmp = word; \
+   ulong64 LTC_TMPVAR(ROL64c) = word; \
    __asm__ ("rolq %2, %0" : \
-            "=r" (ROL64c_tmp) : \
-            "0" (ROL64c_tmp), \
+            "=r" (LTC_TMPVAR(ROL64c)) : \
+            "0" (LTC_TMPVAR(ROL64c)), \
             "J" (i)); \
-            ROL64c_tmp; \
+            LTC_TMPVAR(ROL64c); \
    })
 #define ROR64c(word,i) ({ \
-   ulong64 ROR64c_tmp = word; \
+   ulong64 LTC_TMPVAR(ROR64c) = word; \
    __asm__ ("rorq %2, %0" : \
-            "=r" (ROR64c_tmp) : \
-            "0" (ROR64c_tmp), \
+            "=r" (LTC_TMPVAR(ROR64c)) : \
+            "0" (LTC_TMPVAR(ROR64c)), \
             "J" (i)); \
-            ROR64c_tmp; \
+            LTC_TMPVAR(ROR64c); \
    })
 
 #else /* LTC_NO_ROLC */
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h b/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h
index 0ee3ac8d141e476c85f1bd87325106cd13f6b70d..60c57784c167903e27959b6d17172c436374de96 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_pk.h
@@ -57,10 +57,10 @@ void rsa_free(rsa_key *key);
 
 /* These use PKCS #1 v2.0 padding */
 #define rsa_encrypt_key(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, key) \
-  rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, LTC_PKCS_1_OAEP, key)
+  rsa_encrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, prng, prng_idx, hash_idx, -1, LTC_PKCS_1_OAEP, key)
 
 #define rsa_decrypt_key(in, inlen, out, outlen, lparam, lparamlen, hash_idx, stat, key) \
-  rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, LTC_PKCS_1_OAEP, stat, key)
+  rsa_decrypt_key_ex(in, inlen, out, outlen, lparam, lparamlen, hash_idx, -1, LTC_PKCS_1_OAEP, stat, key)
 
 #define rsa_sign_hash(in, inlen, out, outlen, prng, prng_idx, hash_idx, saltlen, key) \
   rsa_sign_hash_ex(in, inlen, out, outlen, LTC_PKCS_1_PSS, prng, prng_idx, hash_idx, saltlen, key)
@@ -76,13 +76,15 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
                              unsigned char *out,      unsigned long *outlen,
                        const unsigned char *lparam,   unsigned long  lparamlen,
                              prng_state    *prng,     int            prng_idx,
-                             int            hash_idx, int            padding,
+                             int            mgf_hash, int            lparam_hash,
+                             int            padding,
                        const rsa_key       *key);
 
 int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen,
                              unsigned char *out,            unsigned long *outlen,
                        const unsigned char *lparam,         unsigned long  lparamlen,
-                             int            hash_idx,       int            padding,
+                             int            mgf_hash,       int            lparam_hash,
+                             int            padding,
                              int           *stat,     const rsa_key       *key);
 
 int rsa_sign_hash_ex(const unsigned char *in,       unsigned long  inlen,
@@ -548,43 +550,43 @@ typedef struct ltc_asn1_list_ {
    struct ltc_asn1_list_ *prev, *next, *child, *parent;
 } ltc_asn1_list;
 
-#define LTC_SET_ASN1(list, index, Type, Data, Size)  \
-   do {                                              \
-      int LTC_MACRO_temp            = (index);       \
-      ltc_asn1_list *LTC_MACRO_list = (list);        \
-      LTC_MACRO_list[LTC_MACRO_temp].type = (Type);  \
-      LTC_MACRO_list[LTC_MACRO_temp].data = (void*)(Data);  \
-      LTC_MACRO_list[LTC_MACRO_temp].size = (Size);  \
-      LTC_MACRO_list[LTC_MACRO_temp].used = 0;       \
-      LTC_MACRO_list[LTC_MACRO_temp].optional = 0;   \
-      LTC_MACRO_list[LTC_MACRO_temp].klass = 0;      \
-      LTC_MACRO_list[LTC_MACRO_temp].pc = 0;         \
-      LTC_MACRO_list[LTC_MACRO_temp].tag = 0;        \
+#define LTC_SET_ASN1(list, index, Type, Data, Size)               \
+   do {                                                           \
+      int LTC_TMPVAR(SA)            = (index);                    \
+      ltc_asn1_list *LTC_TMPVAR(SA_list) = (list);                \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].type = (Type);          \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].data = (void*)(Data);   \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].size = (Size);          \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].used = 0;               \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].optional = 0;           \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].klass = 0;              \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].pc = 0;                 \
+      LTC_TMPVAR(SA_list)[LTC_TMPVAR(SA)].tag = 0;                \
    } while (0)
 
-#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag)      \
-   do {                                                           \
-      int LTC_MACRO_temp            = (index);                    \
-      ltc_asn1_list *LTC_MACRO_list = (list);                     \
-      LTC_MACRO_list[LTC_MACRO_temp].type = LTC_ASN1_CUSTOM_TYPE; \
-      LTC_MACRO_list[LTC_MACRO_temp].klass = (Class);             \
-      LTC_MACRO_list[LTC_MACRO_temp].pc = (Pc);                   \
-      LTC_MACRO_list[LTC_MACRO_temp].tag = (Tag);                 \
+#define LTC_SET_ASN1_IDENTIFIER(list, index, Class, Pc, Tag)               \
+   do {                                                                    \
+      int LTC_TMPVAR(SAI)       = (index);                                 \
+      ltc_asn1_list *LTC_TMPVAR(SAI_list) = (list);                        \
+      LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].type = LTC_ASN1_CUSTOM_TYPE;   \
+      LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].klass = (Class);               \
+      LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].pc = (Pc);                     \
+      LTC_TMPVAR(SAI_list)[LTC_TMPVAR(SAI)].tag = (Tag);                   \
    } while (0)
 
-#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data)    \
-   do {                                                           \
-      int LTC_MACRO_temp##__LINE__ = (index);                     \
-      LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, 1);   \
-      LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_CONSTRUCTED, Tag);       \
+#define LTC_SET_ASN1_CUSTOM_CONSTRUCTED(list, index, Class, Tag, Data)                       \
+   do {                                                                                      \
+      int LTC_TMPVAR(SACC) = (index);                                                        \
+      LTC_SET_ASN1(list, LTC_TMPVAR(SACC), LTC_ASN1_CUSTOM_TYPE, Data, 1);                   \
+      LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACC), Class, LTC_ASN1_PC_CONSTRUCTED, Tag);  \
    } while (0)
 
-#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size)    \
-   do {                                                           \
-      int LTC_MACRO_temp##__LINE__ = (index);                     \
-      LTC_SET_ASN1(list, LTC_MACRO_temp##__LINE__, LTC_ASN1_CUSTOM_TYPE, Data, Size);   \
-      LTC_SET_ASN1_IDENTIFIER(list, LTC_MACRO_temp##__LINE__, Class, LTC_ASN1_PC_PRIMITIVE, Tag);       \
-      list[LTC_MACRO_temp##__LINE__].used = (int)(Type);       \
+#define LTC_SET_ASN1_CUSTOM_PRIMITIVE(list, index, Class, Tag, Type, Data, Size)          \
+   do {                                                                                   \
+      int LTC_TMPVAR(SACP) = (index);                                                     \
+      LTC_SET_ASN1(list, LTC_TMPVAR(SACP), LTC_ASN1_CUSTOM_TYPE, Data, Size);             \
+      LTC_SET_ASN1_IDENTIFIER(list, LTC_TMPVAR(SACP), Class, LTC_ASN1_PC_PRIMITIVE, Tag); \
+      list[LTC_TMPVAR(SACP)].used = (int)(Type);                                          \
    } while (0)
 
 extern const char*          der_asn1_class_to_string_map[];
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h b/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h
index a0aa8920423801cdce092d240164052e821018ce..cca013c0730f28c0c9f48f6ae7c4504d37c540b7 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_pkcs.h
@@ -49,12 +49,14 @@ int pkcs_1_v1_5_decode(const unsigned char *msg,
 int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
                        const unsigned char *lparam, unsigned long lparamlen,
                              unsigned long modulus_bitlen, prng_state *prng,
-                             int           prng_idx,         int  hash_idx,
+                             int           prng_idx,
+                             int           mgf_hash, int lparam_hash,
                              unsigned char *out,    unsigned long *outlen);
 
 int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
                        const unsigned char *lparam, unsigned long lparamlen,
-                             unsigned long modulus_bitlen, int hash_idx,
+                             unsigned long modulus_bitlen,
+                             int           mgf_hash, int          lparam_hash,
                              unsigned char *out,    unsigned long *outlen,
                              int           *res);
 
diff --git a/core/lib/libtomcrypt/src/headers/tomcrypt_private.h b/core/lib/libtomcrypt/src/headers/tomcrypt_private.h
index a65c83ec39c9fcaafd66da11d8ee9c9155fc06b3..53d63555b059948a18b411c37d344db11fdaa3af 100644
--- a/core/lib/libtomcrypt/src/headers/tomcrypt_private.h
+++ b/core/lib/libtomcrypt/src/headers/tomcrypt_private.h
@@ -6,9 +6,30 @@
 /*
  * Internal Macros
  */
+/* Static assertion */
+#define LTC_STATIC_ASSERT(msg, cond) typedef char ltc_static_assert_##msg[(cond) ? 1 : -1];
 
 #define LTC_PAD_MASK       (0xF000U)
 
+#if defined(ENDIAN_64BITWORD)
+   #define CONSTPTR(n) CONST64(n)
+#else
+   #define CONSTPTR(n) n ## uL
+#endif
+
+LTC_STATIC_ASSERT(correct_CONSTPTR_size, sizeof(CONSTPTR(1)) == sizeof(void*))
+
+/* Poor-man's `uintptr_t` since we can't use stdint.h
+ * c.f. https://github.com/DCIT/perl-CryptX/issues/95#issuecomment-1745280962 */
+typedef size_t ltc_uintptr;
+
+LTC_STATIC_ASSERT(correct_ltc_uintptr_size, sizeof(ltc_uintptr) == sizeof(void*))
+
+/* Aligns a `unsigned char` buffer `buf` to `n` bytes and returns that aligned address.
+ * Make sure that the buffer that is passed is huge enough.
+ */
+#define LTC_ALIGN_BUF(buf, n) ((void*)((ltc_uintptr)&((unsigned char*)(buf))[n - 1] & (~(CONSTPTR(n) - CONSTPTR(1)))))
+
 /* `NULL` as defined by the standard is not guaranteed to be of a pointer
  * type. In order to make sure that in vararg API's a pointer type is used,
  * define our own version and use that one internally.
@@ -77,6 +98,10 @@ typedef struct
 
 /* tomcrypt_cipher.h */
 
+#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1)
+#define LTC_HAS_AES_NI
+#endif
+
 void blowfish_enc(ulong32 *data, unsigned long blocks, const symmetric_key *skey);
 int blowfish_expand(const unsigned char *key, int keylen,
                     const unsigned char *data, int datalen,
diff --git a/core/lib/libtomcrypt/src/mac/hmac/sub.mk b/core/lib/libtomcrypt/src/mac/hmac/sub.mk
deleted file mode 100644
index 2b8702f2dd6249bfc2a7eab4af5ddc461a3aebb7..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/mac/hmac/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-cflags-y += -Wno-unused-parameter
-
-srcs-y += hmac_done.c
-srcs-y += hmac_init.c
-srcs-y += hmac_memory.c
-srcs-y += hmac_memory_multi.c
-srcs-y += hmac_process.c
diff --git a/core/lib/libtomcrypt/src/mac/omac/sub.mk b/core/lib/libtomcrypt/src/mac/omac/sub.mk
deleted file mode 100644
index c0de70b228df7c1b72baa9234cee8210670509ae..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/mac/omac/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-cflags-y += -Wno-unused-parameter
-
-srcs-y += omac_done.c
-srcs-y += omac_init.c
-srcs-y += omac_memory.c
-srcs-y += omac_memory_multi.c
-srcs-y += omac_process.c
diff --git a/core/lib/libtomcrypt/src/mac/sub.mk b/core/lib/libtomcrypt/src/mac/sub.mk
deleted file mode 100644
index e8690abcc828a2376f4ecfcc4cf69e308616f8d2..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/mac/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-subdirs-$(_CFG_CORE_LTC_HMAC) += hmac
-subdirs-$(_CFG_CORE_LTC_CMAC) += omac
diff --git a/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c b/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c
index 37cee9f970005a958bfc0b60148365a48f175786..9be2ebf16763ae7cd84b31ad6e8caf5d23e7faa2 100644
--- a/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c
+++ b/core/lib/libtomcrypt/src/math/fp/ltc_ecc_fp_mulmod.c
@@ -1430,8 +1430,8 @@ int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen)
     */
    cache_entry = XCALLOC(FP_ENTRIES*(2*(1U<<FP_LUT)+4)+3, sizeof(ltc_asn1_list));
    if (cache_entry == NULL) {
-      err = CRYPT_MEM;
-      goto save_err;
+      LTC_MUTEX_UNLOCK(&ltc_ecc_fp_lock);
+      return CRYPT_MEM;
    }
    j = 1;   /* handle the zero'th element later */
 
diff --git a/core/lib/libtomcrypt/src/math/fp/sub.mk b/core/lib/libtomcrypt/src/math/fp/sub.mk
deleted file mode 100644
index fe7965693d5531cff1650abd8fae15593b8795c0..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/math/fp/sub.mk
+++ /dev/null
@@ -1 +0,0 @@
-srcs-$(_CFG_CORE_LTC_ECC) += ltc_ecc_fp_mulmod.c
diff --git a/core/lib/libtomcrypt/src/math/sub.mk b/core/lib/libtomcrypt/src/math/sub.mk
deleted file mode 100644
index 4a38a3216ee3cb4f56d5db35d79a7736df14f78b..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/math/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-subdirs-y += fp
-srcs-y += multi.c
-srcs-y += rand_prime.c
-srcs-y += rand_bn.c
diff --git a/core/lib/libtomcrypt/src/misc/base64/sub.mk b/core/lib/libtomcrypt/src/misc/base64/sub.mk
deleted file mode 100644
index 91916905a57735779ea4e39596da9bc3808f012c..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/base64/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += base64_decode.c
-srcs-y += base64_encode.c
diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt.c b/core/lib/libtomcrypt/src/misc/crypt/crypt.c
index 14576fa7da659bb4a81bf9720f0b12ccb9759849..81f00dbf9061ca67d76defa52b32f9ac5052ea52 100644
--- a/core/lib/libtomcrypt/src/misc/crypt/crypt.c
+++ b/core/lib/libtomcrypt/src/misc/crypt/crypt.c
@@ -315,15 +315,21 @@ const char *crypt_build_settings =
 #if defined(LTC_FORTUNA)
     "   Fortuna (" NAME_VALUE(LTC_FORTUNA_POOLS) ", "
 #if defined(LTC_FORTUNA_RESEED_RATELIMIT_TIMED)
-    "LTC_FORTUNA_RESEED_RATELIMIT_TIMED, "
+    "LTC_FORTUNA_RESEED_RATELIMIT_TIMED"
 #else
     "LTC_FORTUNA_RESEED_RATELIMIT_STATIC, " NAME_VALUE(LTC_FORTUNA_WD)
+#endif
+#if defined(LTC_FORTUNA_USE_ENCRYPT_ONLY)
+    ", LTC_FORTUNA_USE_ENCRYPT_ONLY"
 #endif
     ")\n"
 #endif
 #if defined(LTC_SOBER128)
     "   SOBER128\n"
 #endif
+#if defined(LTC_WIN32_BCRYPT)
+    "   WIN32_BCRYPT\n"
+#endif
 
     "\nPK Crypto:\n"
 #if defined(LTC_MRSA)
@@ -416,6 +422,9 @@ const char *crypt_build_settings =
 #if defined(LTC_ADLER32)
     " ADLER32 "
 #endif
+#if defined(LTC_AES_NI) && defined(LTC_AMD64_SSE4_1)
+    " AES-NI "
+#endif
 #if defined(LTC_BASE64)
     " BASE64 "
 #endif
diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c
index bb2b873e2600ab1eb1e9e2a19bdd1d354735f1a7..bfed2e68d110da7894d95ba783f46487cf5fc20c 100644
--- a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c
+++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_ciphers.c
@@ -16,6 +16,7 @@
 int register_all_ciphers(void)
 {
 #ifdef LTC_RIJNDAEL
+   /* `aesni_desc` is explicitely not registered, since it's handled from within the `aes_desc` */
 #ifdef ENCRYPT_ONLY
    /* alternative would be
     * register_cipher(&rijndael_enc_desc);
diff --git a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c
index 68a64aed6cee1d8c6c62bcb320c2747ff843586e..328e84a6c005606cde5cb55030f166420273d1d9 100644
--- a/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c
+++ b/core/lib/libtomcrypt/src/misc/crypt/crypt_register_all_hashes.c
@@ -17,6 +17,7 @@ int register_all_hashes(void)
 {
 #ifdef LTC_TIGER
    REGISTER_HASH(&tiger_desc);
+   REGISTER_HASH(&tiger2_desc);
 #endif
 #ifdef LTC_MD2
    REGISTER_HASH(&md2_desc);
diff --git a/core/lib/libtomcrypt/src/misc/crypt/sub.mk b/core/lib/libtomcrypt/src/misc/crypt/sub.mk
deleted file mode 100644
index 9880a9be98ce8aefe4dce28ffbcef75a2eea121e..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/crypt/sub.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-srcs-y += crypt.c
-srcs-y += crypt_cipher_descriptor.c
-srcs-y += crypt_cipher_is_valid.c
-srcs-y += crypt_find_cipher_any.c
-srcs-y += crypt_find_cipher.c
-srcs-y += crypt_find_cipher_id.c
-srcs-y += crypt_find_hash_any.c
-srcs-y += crypt_find_hash.c
-srcs-y += crypt_find_hash_id.c
-srcs-y += crypt_find_hash_oid.c
-srcs-y += crypt_find_prng.c
-srcs-y += crypt_fsa.c
-srcs-y += crypt_hash_descriptor.c
-srcs-y += crypt_hash_is_valid.c
-srcs-y += crypt_prng_descriptor.c
-srcs-y += crypt_prng_is_valid.c
-srcs-y += crypt_register_cipher.c
-srcs-y += crypt_register_hash.c
-srcs-y += crypt_register_prng.c
-srcs-y += crypt_unregister_cipher.c
-srcs-y += crypt_unregister_hash.c
-srcs-y += crypt_unregister_prng.c
diff --git a/core/lib/libtomcrypt/src/misc/pbes/sub.mk b/core/lib/libtomcrypt/src/misc/pbes/sub.mk
deleted file mode 100644
index 46557aaa21e22d641cc0afe09c93028fdfe4f15b..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/pbes/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += pbes.c
-srcs-y += pbes1.c
-srcs-y += pbes2.c
diff --git a/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk b/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk
deleted file mode 100644
index 92f782e485c2f84ed57bf6245ed0d25bac8dd8e3..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/pkcs12/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += pkcs12_kdf.c
-srcs-y += pkcs12_utf8_to_utf16.c
diff --git a/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c
index 73bc4a1ad8b92c1606252afc03ce79a5eb6193fd..f90c0eef1223feef3b51607728e298199781bf47 100644
--- a/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c
+++ b/core/lib/libtomcrypt/src/misc/pkcs5/pkcs_5_test.c
@@ -169,6 +169,7 @@ int pkcs_5_test (void)
                               (unsigned char*)cases_5_2[i].S, cases_5_2[i].S_len,
                               cases_5_2[i].c, hash,
                               DK, &dkLen)) != CRYPT_OK) {
+            LTC_UNUSED_PARAM(err);
 #ifdef LTC_TEST_DBG
             printf("\npkcs_5_alg2() #%d: Failed/1 (%s)\n", i, error_to_string(err));
 #endif
@@ -186,6 +187,7 @@ int pkcs_5_test (void)
                               (unsigned char*)cases_5_1[i].S,
                               cases_5_1[i].c, hash,
                               DK, &dkLen)) != CRYPT_OK) {
+            LTC_UNUSED_PARAM(err);
 #ifdef LTC_TEST_DBG
             printf("\npkcs_5_alg1() #%d: Failed/1 (%s)\n", i, error_to_string(err));
 #endif
@@ -203,6 +205,7 @@ int pkcs_5_test (void)
                                        (unsigned char*)cases_5_1o[i].S,
                                        cases_5_1o[i].c, hash,
                                        DK, &dkLen)) != CRYPT_OK) {
+            LTC_UNUSED_PARAM(err);
 #ifdef LTC_TEST_DBG
             printf("\npkcs_5_alg1_openssl() #%d: Failed/1 (%s)\n", i, error_to_string(err));
 #endif
diff --git a/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk b/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk
deleted file mode 100644
index 7f8ccfe714f4863fc147189acadc6bb6b1559153..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/pkcs5/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += pkcs_5_1.c
-srcs-y += pkcs_5_2.c
diff --git a/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c b/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c
index c65402c70c8fdd52f084a6ccae1cc74ef9298a2d..d8a49aa27042b1c40d8baef6a88fe1c1df5c36a1 100644
--- a/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c
+++ b/core/lib/libtomcrypt/src/misc/ssh/ssh_encode_sequence_multi.c
@@ -135,7 +135,7 @@ int ssh_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
                   STORE32H(size, out);
                   out += 4;
                }
-               if ((err = mp_to_unsigned_bin(vdata, out)) != CRYPT_OK) {
+               if (mp_to_unsigned_bin(vdata, out) != CRYPT_OK) {
                   err = CRYPT_ERROR;
                   goto error;
                }
diff --git a/core/lib/libtomcrypt/src/misc/ssh/sub.mk b/core/lib/libtomcrypt/src/misc/ssh/sub.mk
deleted file mode 100644
index b10fb7ca7719d255dd8103689be0ebd50f0de812..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/ssh/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += ssh_decode_sequence_multi.c
-srcs-y += ssh_encode_sequence_multi.c
diff --git a/core/lib/libtomcrypt/src/misc/sub.mk b/core/lib/libtomcrypt/src/misc/sub.mk
deleted file mode 100644
index fc55c8e931386628eca36b0c501f96554357937d..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/misc/sub.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-srcs-y += burn_stack.c
-srcs-y += error_to_string.c
-srcs-y += mem_neq.c
-srcs-y += zeromem.c
-subdirs-y += base64
-subdirs-y += crypt
-subdirs-y += pkcs5
-subdirs-y += pkcs12
-subdirs-y += ssh
diff --git a/core/lib/libtomcrypt/src/modes/cbc/sub.mk b/core/lib/libtomcrypt/src/modes/cbc/sub.mk
deleted file mode 100644
index 1ce3e771b30e23fd7f891381d3ccb3f03c9f784e..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/cbc/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += cbc_decrypt.c
-srcs-y += cbc_done.c
-srcs-y += cbc_encrypt.c
-srcs-y += cbc_getiv.c
-srcs-y += cbc_setiv.c
-srcs-y += cbc_start.c
diff --git a/core/lib/libtomcrypt/src/modes/cfb/sub.mk b/core/lib/libtomcrypt/src/modes/cfb/sub.mk
deleted file mode 100644
index 7a92b019559ba94917215488651fafe9390b1bc3..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/cfb/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += cfb_decrypt.c
-srcs-y += cfb_done.c
-srcs-y += cfb_encrypt.c
-srcs-y += cfb_getiv.c
-srcs-y += cfb_setiv.c
-srcs-y += cfb_start.c
diff --git a/core/lib/libtomcrypt/src/modes/ctr/sub.mk b/core/lib/libtomcrypt/src/modes/ctr/sub.mk
deleted file mode 100644
index 154150123ebaf705d161338601c2b99080427605..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/ctr/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += ctr_decrypt.c
-srcs-y += ctr_done.c
-srcs-y += ctr_encrypt.c
-srcs-y += ctr_getiv.c
-srcs-y += ctr_setiv.c
-srcs-y += ctr_start.c
diff --git a/core/lib/libtomcrypt/src/modes/ecb/sub.mk b/core/lib/libtomcrypt/src/modes/ecb/sub.mk
deleted file mode 100644
index c47c061e69e2cf5ee8775dc46c9dd0e166e811f6..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/ecb/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-srcs-y += ecb_decrypt.c
-srcs-y += ecb_done.c
-srcs-y += ecb_encrypt.c
-srcs-y += ecb_start.c
diff --git a/core/lib/libtomcrypt/src/modes/f8/sub.mk b/core/lib/libtomcrypt/src/modes/f8/sub.mk
deleted file mode 100644
index 32e13814f64f505b2fb379f61c695f28f224a1ab..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/f8/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += f8_decrypt.c
-srcs-y += f8_done.c
-srcs-y += f8_encrypt.c
-srcs-y += f8_getiv.c
-srcs-y += f8_setiv.c
-srcs-y += f8_start.c
diff --git a/core/lib/libtomcrypt/src/modes/lrw/sub.mk b/core/lib/libtomcrypt/src/modes/lrw/sub.mk
deleted file mode 100644
index b464c41bb2c10c5fc8e07a04f56de1dd5e875cbb..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/lrw/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-srcs-y += lrw_decrypt.c
-srcs-y += lrw_done.c
-srcs-y += lrw_encrypt.c
-srcs-y += lrw_getiv.c
-srcs-y += lrw_process.c
-srcs-y += lrw_setiv.c
-srcs-y += lrw_start.c
diff --git a/core/lib/libtomcrypt/src/modes/ofb/sub.mk b/core/lib/libtomcrypt/src/modes/ofb/sub.mk
deleted file mode 100644
index f1fceeb9f2e2de0931614ef05577194c43a75ca6..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/ofb/sub.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-srcs-y += ofb_decrypt.c
-srcs-y += ofb_done.c
-srcs-y += ofb_encrypt.c
-srcs-y += ofb_getiv.c
-srcs-y += ofb_setiv.c
-srcs-y += ofb_start.c
diff --git a/core/lib/libtomcrypt/src/modes/sub.mk b/core/lib/libtomcrypt/src/modes/sub.mk
deleted file mode 100644
index 45b14a893460214f2000b729e5d7cbb509a0d336..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-subdirs-$(_CFG_CORE_LTC_CBC) += cbc
-subdirs-$(_CFG_CORE_LTC_CTR) += ctr
-subdirs-$(_CFG_CORE_LTC_ECB) += ecb
-subdirs-$(_CFG_CORE_LTC_XTS) += xts
diff --git a/core/lib/libtomcrypt/src/modes/xts/sub.mk b/core/lib/libtomcrypt/src/modes/xts/sub.mk
deleted file mode 100644
index d8d9f1865347deebdb994e507f10bc2af732b58b..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/modes/xts/sub.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-srcs-y += xts_decrypt.c
-srcs-y += xts_done.c
-srcs-y += xts_encrypt.c
-srcs-y += xts_init.c
-srcs-y += xts_mult_x.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk
deleted file mode 100644
index 4cf829e50bd866765c0e708e7ece81746d244d0d..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/bit/sub.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-srcs-y += der_decode_bit_string.c
-srcs-y += der_encode_bit_string.c
-srcs-y += der_length_bit_string.c
-srcs-y += der_decode_raw_bit_string.c
-srcs-y += der_encode_raw_bit_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk
deleted file mode 100644
index 3761249314095ca416922013e58ba8edc4043faa..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/boolean/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_boolean.c
-srcs-y += der_encode_boolean.c
-srcs-y += der_length_boolean.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c b/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c
index 7ff7809e0f0b9d670dc3f36dfedb3c6e9a6ef516..4c786b4868b6a3b3b8e5511608280e4f97cdb2b8 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c
@@ -65,7 +65,7 @@ int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
 
            case LTC_ASN1_SHORT_INTEGER:
                if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
-                  if (der_length_short_integer(size, &z) == CRYPT_OK) {
+                  if (der_length_short_integer(*(unsigned long*)data, &z) == CRYPT_OK) {
                       list[x].used = 1;
                       *inlen       = z;
                       return CRYPT_OK;
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk
deleted file mode 100644
index d3b95ec89e16cdb290c6415b64acad003fc7558f..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/choice/sub.mk
+++ /dev/null
@@ -1 +0,0 @@
-srcs-y += der_decode_choice.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c b/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c
index f5cc93e39e7198b94f5963e25b747e3f65488eb9..412502ef99c0e7fb09977e9ad2958b27da78d544 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/der_encode_custom_type.c
@@ -36,7 +36,7 @@ int der_encode_custom_type(const ltc_asn1_list *root,
 
    /* get size of output that will be required */
    y = 0; z = 0;
-   if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+   if (der_length_custom_type(root, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG;
 
    /* too big ? */
    if (*outlen < y) {
@@ -46,7 +46,7 @@ int der_encode_custom_type(const ltc_asn1_list *root,
    }
 
    /* get length of the identifier, so we know the offset where to start writing */
-   if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+   if (der_length_asn1_identifier(root, &id_len) != CRYPT_OK) return CRYPT_INVALID_ARG;
    x = id_len;
 
 
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk
deleted file mode 100644
index 5ba17b7c6abfbf7cef835ff449b891e5e867adbc..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/custom_type/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_custom_type.c
-srcs-y += der_encode_custom_type.c
-srcs-y += der_length_custom_type.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk
deleted file mode 100644
index 63de0efbd5835c1beb1106c32fbf24f6806ae717..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/general/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-srcs-y += der_asn1_maps.c
-srcs-y += der_decode_asn1_length.c
-srcs-y += der_decode_asn1_identifier.c
-srcs-y += der_encode_asn1_identifier.c
-srcs-y += der_encode_asn1_length.c
-srcs-y += der_length_asn1_identifier.c
-srcs-y += der_length_asn1_length.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk
deleted file mode 100644
index 312e613cfc225d53a1c1f15bbbac6dcbfa2bee10..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/generalizedtime/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_encode_generalizedtime.c
-srcs-y += der_decode_generalizedtime.c
-srcs-y += der_length_generalizedtime.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk
deleted file mode 100644
index dc32a5d0e7957aeadb61f9c3b26800e006cc9396..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/ia5/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_ia5_string.c
-srcs-y += der_encode_ia5_string.c
-srcs-y += der_length_ia5_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk
deleted file mode 100644
index d319f91aaaca04f3d90b4440ae6a702220052fdd..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/integer/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_integer.c
-srcs-y += der_encode_integer.c
-srcs-y += der_length_integer.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk
deleted file mode 100644
index b56efb04287508eebb66aaba8702bfe3a0943e8c..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/object_identifier/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_object_identifier.c
-srcs-y += der_encode_object_identifier.c
-srcs-y += der_length_object_identifier.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk
deleted file mode 100644
index 04607eed5024384d87d8e935cd5ab7992bc5c6cf..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/octet/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_octet_string.c
-srcs-y += der_encode_octet_string.c
-srcs-y += der_length_octet_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk
deleted file mode 100644
index b509209aea32903d584aee62439d83e101c71d8b..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/printable_string/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_printable_string.c
-srcs-y += der_encode_printable_string.c
-srcs-y += der_length_printable_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c
index 2a0841d963536d44e24d224aae21774efbcbf744..35886cf8857720bcfd8f4744eea3c16cbd30ebf4 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c
@@ -268,7 +268,7 @@ static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *i
             }
             l->size = len;
 
-            if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
+            if ((l->data = XCALLOC(l->size, sizeof(wchar_t))) == NULL) {
                err = CRYPT_MEM;
                goto error;
             }
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c
index 429b5407e939048f86b9a1c2cbb2934ec779949e..d5283fad210f1b6e7f834a034b8b00f13fb03a4f 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_multi.c
@@ -78,7 +78,7 @@ static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen
       return CRYPT_NOP;
    }
 
-   list = XCALLOC(sizeof(*list), x);
+   list = XCALLOC(x, sizeof(*list));
    if (list == NULL) {
       return CRYPT_MEM;
    }
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c
index d7f3c8844ed15e158203269a08bbab81e56bb817..f5bd74f123483f6f7129d6eb97da89572086c82d 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_ex.c
@@ -33,7 +33,7 @@ int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
 
    /* get size of output that will be required */
    y = 0; z = 0;
-   if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
+   if (der_length_sequence_ex(list, inlen, &y, &z) != CRYPT_OK) return CRYPT_INVALID_ARG;
 
    /* too big ? */
    if (*outlen < y) {
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c
index a0877fc19c5462f1ebf84116c42c40dbc0c8e9c9..0d3c7d1356bbc9252386023b5367e59106d56bfb 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/der_encode_sequence_multi.c
@@ -81,7 +81,7 @@ int der_encode_sequence_multi(unsigned char *out, unsigned long *outlen, ...)
       return CRYPT_NOP;
    }
 
-   list = XCALLOC(sizeof(*list), x);
+   list = XCALLOC(x, sizeof(*list));
    if (list == NULL) {
       return CRYPT_MEM;
    }
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk
deleted file mode 100644
index d44420b0df88a0f3cf8810c31a2cf93f6c32f524..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sequence/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-srcs-y += der_decode_sequence_ex.c
-srcs-y += der_decode_sequence_flexi.c
-srcs-y += der_decode_sequence_multi.c
-srcs-y += der_encode_sequence_ex.c
-srcs-y += der_encode_sequence_multi.c
-srcs-y += der_length_sequence.c
-srcs-y += der_sequence_free.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk
deleted file mode 100644
index 52525d6076935a1d390b2b857685fd5cee8be6f2..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/set/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += der_encode_set.c
-srcs-y += der_encode_setof.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk
deleted file mode 100644
index fae1f08d1adb5f8315e8fde50b202ad040fca291..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/short_integer/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_short_integer.c
-srcs-y += der_encode_short_integer.c
-srcs-y += der_length_short_integer.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk
deleted file mode 100644
index 2951f19c2f732a850ce508786db6fba906e624bb..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/sub.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-subdirs-y += bit
-subdirs-y += boolean
-subdirs-y += choice
-subdirs-y += custom_type
-subdirs-y += general
-subdirs-y += generalizedtime
-subdirs-y += ia5
-subdirs-y += integer
-subdirs-y += object_identifier
-subdirs-y += octet
-subdirs-y += printable_string
-subdirs-y += sequence
-subdirs-y += set
-subdirs-y += short_integer
-subdirs-y += utctime
-subdirs-y += utf8
-subdirs-y += teletex_string
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk
deleted file mode 100644
index 8f47f074bc67e615d903bf9e9da80931eb90977c..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/teletex_string/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += der_decode_teletex_string.c
-srcs-y += der_length_teletex_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk
deleted file mode 100644
index afb3e1bacb361b2fb7ef11640da8e4750e064784..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/utctime/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += der_decode_utctime.c
-srcs-y += der_encode_utctime.c
-srcs-y += der_length_utctime.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c
index 93a5e5ed23316b38b8b1291492e66ab78bf5b806..ee543ddb09449b9caed7316c0628ad42ab720b02 100644
--- a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c
+++ b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/der_decode_utf8_string.c
@@ -56,7 +56,8 @@ int der_decode_utf8_string(const unsigned char *in,  unsigned long inlen,
 
         https://tools.ietf.org/html/rfc3629#section-3
     */
-   for (y = 0; x < inlen; ) {
+   len += x;
+   for (y = 0; x < len; ) {
       /* read first byte */
       tmp = in[x++];
 
@@ -87,7 +88,7 @@ int der_decode_utf8_string(const unsigned char *in,  unsigned long inlen,
       /* now update z so it equals the number of additional bytes to read */
       if (z > 0) { --z; }
 
-      if (x + z > inlen) {
+      if (x + z > len) {
          return CRYPT_INVALID_PACKET;
       }
 
diff --git a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk
deleted file mode 100644
index 353892996c38fa8bc2443dcbd83db41ebba0093f..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/der/utf8/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-cflags-remove-y += -Wextra
-srcs-y += der_decode_utf8_string.c
-srcs-y += der_encode_utf8_string.c
-srcs-y += der_length_utf8_string.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk
deleted file mode 100644
index 867ffad5afcab467772783b6dd1de4a63b83134f..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/oid/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-srcs-y += pk_oid_cmp.c
-srcs-y += pk_oid_str.c
diff --git a/core/lib/libtomcrypt/src/pk/asn1/sub.mk b/core/lib/libtomcrypt/src/pk/asn1/sub.mk
deleted file mode 100644
index 86d77d413a5a0052354e9ccdd190792816959e1f..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/asn1/sub.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-subdirs-y += der
-subdirs-y += oid
diff --git a/core/lib/libtomcrypt/src/pk/dh/sub.mk b/core/lib/libtomcrypt/src/pk/dh/sub.mk
deleted file mode 100644
index 86f2d763b164ee7b7c9daae35eeb22bb338d4118..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/dh/sub.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-srcs-y += dh.c
-cflags-dh.c-y += -Wno-unused-variable
-srcs-y += dh_check_pubkey.c
-srcs-y += dh_export.c
-srcs-y += dh_export_key.c
-srcs-y += dh_free.c
-srcs-y += dh_generate_key.c
-srcs-y += dh_import.c
-srcs-y += dh_make_key.c
-srcs-y += dh_set.c
-srcs-y += dh_set_pg_dhparam.c
-srcs-y += dh_shared_secret.c
-
diff --git a/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c b/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c
index 995e0d22559ed8c9c60350103e32f7e3d1cfbf8a..b5660d39830f942e4edb2f951a245b13c7a33e64 100644
--- a/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c
+++ b/core/lib/libtomcrypt/src/pk/dsa/dsa_import.c
@@ -72,14 +72,14 @@ int dsa_import(const unsigned char *in, unsigned long inlen, dsa_key *key)
        }
    }
    /* get key type */
-   if ((err = der_decode_sequence_multi(in, inlen,
-                          LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
-                          LTC_ASN1_INTEGER,      1UL, key->p,
-                          LTC_ASN1_INTEGER,      1UL, key->q,
-                          LTC_ASN1_INTEGER,      1UL, key->g,
-                          LTC_ASN1_INTEGER,      1UL, key->y,
-                          LTC_ASN1_INTEGER,      1UL, key->x,
-                          LTC_ASN1_EOL,          0UL, NULL)) == CRYPT_OK) {
+   if (der_decode_sequence_multi(in, inlen,
+                                 LTC_ASN1_SHORT_INTEGER, 1UL, &zero,
+                                 LTC_ASN1_INTEGER,       1UL, key->p,
+                                 LTC_ASN1_INTEGER,       1UL, key->q,
+                                 LTC_ASN1_INTEGER,       1UL, key->g,
+                                 LTC_ASN1_INTEGER,       1UL, key->y,
+                                 LTC_ASN1_INTEGER,       1UL, key->x,
+                                 LTC_ASN1_EOL,           0UL, NULL) == CRYPT_OK) {
 
        key->type = PK_PRIVATE;
    } else { /* public */
diff --git a/core/lib/libtomcrypt/src/pk/dsa/sub.mk b/core/lib/libtomcrypt/src/pk/dsa/sub.mk
deleted file mode 100644
index d0b29e5c8e33f91789a4bfd734fad6787d42c66e..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/dsa/sub.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-srcs-y += dsa_decrypt_key.c
-srcs-y += dsa_encrypt_key.c
-srcs-y += dsa_export.c
-srcs-y += dsa_free.c
-srcs-y += dsa_generate_key.c
-srcs-y += dsa_generate_pqg.c
-srcs-y += dsa_import.c
-srcs-y += dsa_make_key.c
-srcs-y += dsa_shared_secret.c
-srcs-y += dsa_sign_hash.c
-srcs-y += dsa_verify_hash.c
-srcs-y += dsa_verify_key.c
diff --git a/core/lib/libtomcrypt/src/pk/ec25519/sub.mk b/core/lib/libtomcrypt/src/pk/ec25519/sub.mk
deleted file mode 100644
index 5040c391ce0e38ec9a80e0d31fd7229afa259b88..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/ec25519/sub.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-srcs-y += ec25519_crypto_ctx.c
-srcs-y += ec25519_export.c
-srcs-y += tweetnacl.c
diff --git a/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c b/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c
index ad0a7c656307a0aa56da1b6dde9ebb6e9e9cca5e..64e21f1df2a1131f6fa73e92b0e480f8902f79c3 100644
--- a/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c
+++ b/core/lib/libtomcrypt/src/pk/ec25519/tweetnacl.c
@@ -47,7 +47,7 @@ sv set25519(gf r, const gf a)
 sv car25519(gf o)
 {
   int i;
-  i64 c;
+  u64 c;
   FOR(i,16) {
     o[i]+=(1LL<<16);
     c=o[i]>>16;
@@ -109,7 +109,7 @@ static u8 par25519(const gf a)
 sv unpack25519(gf o, const u8 *n)
 {
   int i;
-  FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
+  FOR(i,16) o[i]=n[2*i]+((u64)n[2*i+1]<<8);
   o[15]&=0x7fff;
 }
 
@@ -348,7 +348,8 @@ static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6,
 
 sv modL(u8 *r,i64 x[64])
 {
-  i64 carry,i,j;
+  i64 i,j;
+  u64 carry;
   for (i = 63;i >= 32;--i) {
     carry = 0;
     for (j = i - 32;j < i - 12;++j) {
diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c
index d30fd06822c25f160da2b323191331a2ca9b39be..891a741363656828fc65a97b5af260dfc3f62ef3 100644
--- a/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c
+++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_get_key.c
@@ -33,8 +33,11 @@ int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_k
    }
    else if (type == PK_PRIVATE) {
       if (key->type != PK_PRIVATE)                                                return CRYPT_PK_TYPE_MISMATCH;
+      if (size > *outlen) {
+         *outlen = size;
+         return CRYPT_BUFFER_OVERFLOW;
+      }
       *outlen = size;
-      if (size > *outlen)                                                         return CRYPT_BUFFER_OVERFLOW;
       if ((ksize = mp_unsigned_bin_size(key->k)) > size)                          return CRYPT_BUFFER_OVERFLOW;
       /* pad and store k */
       if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK)   return err;
diff --git a/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c b/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c
index a6fd7bfbb791bc3b2b162409970ed77c1e12c9f1..81ac6ed6b0496b46988402d9414b7c2270db5f32 100644
--- a/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c
+++ b/core/lib/libtomcrypt/src/pk/ecc/ecc_import_pkcs8.c
@@ -64,7 +64,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
    if (err != CRYPT_OK) return err;
 
 
-   if ((err = pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l)) == CRYPT_OK) {
+   if (pkcs8_decode_flexi(in, inlen, pwd, pwdlen, &l) == CRYPT_OK) {
 
       /* Setup for basic structure */
       n=0;
@@ -73,7 +73,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
       LTC_SET_DER_FLEXI_CHECK(flexi_should, n++, LTC_ASN1_OCTET_STRING, &priv_key);
       LTC_SET_DER_FLEXI_CHECK(flexi_should, n, LTC_ASN1_EOL, NULL);
 
-      if (((err = s_der_flexi_sequence_cmp(l, flexi_should)) == CRYPT_OK) &&
+      if ((s_der_flexi_sequence_cmp(l, flexi_should) == CRYPT_OK) &&
             (pk_oid_cmp_with_asn1(pka_ec_oid, seq->child) == CRYPT_OK)) {
          ltc_asn1_list *version, *field, *point, *point_g, *order, *p_cofactor;
 
@@ -154,7 +154,7 @@ int ecc_import_pkcs8(const unsigned char *in, unsigned long inlen,
 
          /* load private key value 'k' */
          len = priv_key->size;
-         if ((err = der_decode_sequence_flexi(priv_key->data, &len, &p)) == CRYPT_OK) {
+         if (der_decode_sequence_flexi(priv_key->data, &len, &p) == CRYPT_OK) {
             if (p->type == LTC_ASN1_SEQUENCE &&
                 LTC_ASN1_IS_TYPE(p->child, LTC_ASN1_INTEGER) &&
                 LTC_ASN1_IS_TYPE(p->child->next, LTC_ASN1_OCTET_STRING)) {
diff --git a/core/lib/libtomcrypt/src/pk/ecc/sub.mk b/core/lib/libtomcrypt/src/pk/ecc/sub.mk
deleted file mode 100644
index 8567283a09555bd636f8b9919f974f6c62664110..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/ecc/sub.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-srcs-y += ecc.c
-srcs-y += ecc_find_curve.c
-srcs-y += ecc_free.c
-srcs-y += ecc_get_oid_str.c
-srcs-y += ecc_make_key.c
-srcs-y += ecc_set_curve.c
-srcs-y += ecc_set_curve_internal.c
-srcs-y += ecc_shared_secret.c
-srcs-y += ecc_sign_hash.c
-srcs-y += ecc_ssh_ecdsa_encode_name.c
-srcs-y += ecc_verify_hash.c
-srcs-y += ltc_ecc_is_point.c
-srcs-y += ltc_ecc_is_point_at_infinity.c
-srcs-y += ltc_ecc_map.c
-srcs-y += ltc_ecc_mulmod.c
-srcs-y += ltc_ecc_mulmod_timing.c
-srcs-y += ltc_ecc_mul2add.c
-srcs-y += ltc_ecc_points.c
-srcs-y += ltc_ecc_projective_add_point.c
-srcs-y += ltc_ecc_projective_dbl_point.c
diff --git a/core/lib/libtomcrypt/src/pk/ed25519/sub.mk b/core/lib/libtomcrypt/src/pk/ed25519/sub.mk
deleted file mode 100644
index cb2206dabeccb43d14345cb82b6ef918a344ec9f..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/ed25519/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-srcs-y += ed25519_export.c
-srcs-y += ed25519_import.c
-srcs-y += ed25519_import_pkcs8.c
-srcs-y += ed25519_import_x509.c
-srcs-y += ed25519_make_key.c
-srcs-y += ed25519_sign.c
-srcs-y += ed25519_verify.c
diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
index 5bb3918e12c08cea87111d7e267055f27e8da159..2c5f52062c22038947e521fc122708956cc7dfe2 100644
--- a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
+++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c
@@ -16,7 +16,8 @@
    @param lparam           The session or system data (can be NULL)
    @param lparamlen        The length of the lparam
    @param modulus_bitlen   The bit length of the RSA modulus
-   @param hash_idx         The index of the hash desired
+   @param mgf_hash         The hash algorithm used for the MGF
+   @param lparam_hash      The hash algorithm used when hashing the lparam (can be -1)
    @param out              [out] Destination of decoding
    @param outlen           [in/out] The max size and resulting size of the decoding
    @param res              [out] Result of decoding, 1==valid, 0==invalid
@@ -24,13 +25,14 @@
 */
 int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
                        const unsigned char *lparam, unsigned long lparamlen,
-                             unsigned long modulus_bitlen, int hash_idx,
+                             unsigned long modulus_bitlen,
+                             int mgf_hash, int lparam_hash,
                              unsigned char *out,    unsigned long *outlen,
                              int           *res)
 {
    unsigned char *DB, *seed, *mask;
    unsigned long hLen, x, y, modulus_len;
-   int           err, ret;
+   int           err, ret, lparam_hash_used;
 
    LTC_ARGCHK(msg    != NULL);
    LTC_ARGCHK(out    != NULL);
@@ -41,10 +43,18 @@ int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
    *res = 0;
 
    /* test valid hash */
-   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+   if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
       return err;
    }
-   hLen        = hash_descriptor[hash_idx]->hashsize;
+   if (lparam_hash != -1) {
+      if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
+         return err;
+      }
+      lparam_hash_used = lparam_hash;
+   } else {
+      lparam_hash_used = mgf_hash;
+   }
+   hLen        = hash_descriptor[lparam_hash_used]->hashsize;
    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
    /* test hash/message size */
@@ -94,7 +104,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
    x += modulus_len - hLen - 1;
 
    /* compute MGF1 of maskedDB (hLen) */
-   if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+   if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
       goto LBL_ERR;
    }
 
@@ -104,7 +114,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
    }
 
    /* compute MGF1 of seed (k - hlen - 1) */
-   if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+   if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
       goto LBL_ERR;
    }
 
@@ -118,12 +128,12 @@ int pkcs_1_oaep_decode(const unsigned char *msg,    unsigned long msglen,
    /* compute lhash and store it in seed [reuse temps!] */
    x = modulus_len;
    if (lparam != NULL) {
-      if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
+      if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, seed, &x)) != CRYPT_OK) {
          goto LBL_ERR;
       }
    } else {
       /* can't pass hash_memory a NULL so use DB with zero length */
-      if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) {
+      if ((err = hash_memory(lparam_hash_used, DB, 0, seed, &x)) != CRYPT_OK) {
          goto LBL_ERR;
       }
    }
diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c
index 93ee1db27d685da14186cf4d78bdf5dd0cf14680..a9c93422807f8a8dda485d0daf58c868b00a2b79 100644
--- a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c
+++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_encode.c
@@ -26,28 +26,37 @@
 int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
                        const unsigned char *lparam, unsigned long lparamlen,
                              unsigned long modulus_bitlen, prng_state *prng,
-                             int           prng_idx,         int  hash_idx,
+                             int           prng_idx,
+                             int           mgf_hash, int lparam_hash,
                              unsigned char *out,    unsigned long *outlen)
 {
    unsigned char *DB, *seed, *mask;
    unsigned long hLen, x, y, modulus_len;
-   int           err;
+   int           err, lparam_hash_used;
 
-   LTC_ARGCHK(msg    != NULL);
+   LTC_ARGCHK((msglen == 0) || (msg != NULL));
    LTC_ARGCHK(out    != NULL);
    LTC_ARGCHK(outlen != NULL);
 
    /* test valid hash */
-   if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+   if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
       return err;
    }
+   if (lparam_hash != -1) {
+      if ((err = hash_is_valid(lparam_hash)) != CRYPT_OK) {
+         return err;
+      }
+      lparam_hash_used = lparam_hash;
+   } else {
+      lparam_hash_used = mgf_hash;
+   }
 
    /* valid prng */
    if ((err = prng_is_valid(prng_idx)) != CRYPT_OK) {
       return err;
    }
 
-   hLen        = hash_descriptor[hash_idx]->hashsize;
+   hLen        = hash_descriptor[lparam_hash_used]->hashsize;
    modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
 
    /* test message size */
@@ -76,12 +85,12 @@ int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
    /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */
    x = modulus_len;
    if (lparam != NULL) {
-      if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
+      if ((err = hash_memory(lparam_hash_used, lparam, lparamlen, DB, &x)) != CRYPT_OK) {
          goto LBL_ERR;
       }
    } else {
       /* can't pass hash_memory a NULL so use DB with zero length */
-      if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) {
+      if ((err = hash_memory(lparam_hash_used, DB, 0, DB, &x)) != CRYPT_OK) {
          goto LBL_ERR;
       }
    }
@@ -95,9 +104,11 @@ int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
    /* 0x01 byte */
    DB[x++] = 0x01;
 
-   /* message (length = msglen) */
-   XMEMCPY(DB+x, msg, msglen);
-   x += msglen;
+   if (msglen != 0) {
+      /* message (length = msglen) */
+      XMEMCPY(DB+x, msg, msglen);
+      x += msglen;
+   }
 
    /* now choose a random seed */
    if (prng_descriptor[prng_idx]->read(seed, hLen, prng) != hLen) {
@@ -106,7 +117,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
    }
 
    /* compute MGF1 of seed (k - hlen - 1) */
-   if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
+   if ((err = pkcs_1_mgf1(mgf_hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) {
       goto LBL_ERR;
    }
 
@@ -116,7 +127,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg,    unsigned long msglen,
    }
 
    /* compute MGF1 of maskedDB (hLen) */
-   if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
+   if ((err = pkcs_1_mgf1(mgf_hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) {
       goto LBL_ERR;
    }
 
diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c
index 517242593c3de847cdd27bc53ad356155d277795..6cb3c67d3a445d7f29dd18ce75dba56b508a89b9 100644
--- a/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c
+++ b/core/lib/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c
@@ -35,6 +35,10 @@ int pkcs_1_v1_5_encode(const unsigned char *msg,
   unsigned char *ps;
   int result;
 
+  LTC_ARGCHK((msglen == 0) || (msg != NULL));
+  LTC_ARGCHK(out    != NULL);
+  LTC_ARGCHK(outlen != NULL);
+
   /* valid block_type? */
   if ((block_type != LTC_PKCS_1_EMSA) &&
       (block_type != LTC_PKCS_1_EME)) {
@@ -88,7 +92,9 @@ int pkcs_1_v1_5_encode(const unsigned char *msg,
   out[0]          = 0x00;
   out[1]          = (unsigned char)block_type;  /* block_type 1 or 2 */
   out[2 + ps_len] = 0x00;
-  XMEMCPY(&out[2 + ps_len + 1], msg, msglen);
+  if (msglen != 0) {
+    XMEMCPY(&out[2 + ps_len + 1], msg, msglen);
+  }
   *outlen = modulus_len;
 
   result  = CRYPT_OK;
diff --git a/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk b/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk
deleted file mode 100644
index 43f96b96e94c17c94652663aa058ac36a5d49784..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/pkcs1/sub.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-srcs-y += pkcs_1_i2osp.c
-srcs-y += pkcs_1_mgf1.c
-srcs-y += pkcs_1_oaep_decode.c
-srcs-y += pkcs_1_oaep_encode.c
-srcs-y += pkcs_1_os2ip.c
-srcs-y += pkcs_1_pss_decode.c
-srcs-y += pkcs_1_pss_encode.c
-srcs-y += pkcs_1_v1_5_decode.c
-srcs-y += pkcs_1_v1_5_encode.c
diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
index 34a11f918002b0e0556f94cf29ce5edfd46cc6d3..ea1ec99f53c36c1a89340502e0674ed856a5e6c0 100644
--- a/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
+++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_decrypt_key.c
@@ -17,7 +17,8 @@
    @param outlen      [in/out] The max size and resulting size of the plaintext (octets)
    @param lparam      The system "lparam" value
    @param lparamlen   The length of the lparam value (octets)
-   @param hash_idx    The index of the hash desired
+   @param mgf_hash    The hash algorithm used for the MGF
+   @param lparam_hash The hash algorithm used when hashing the lparam (can be -1)
    @param padding     Type of padding (LTC_PKCS_1_OAEP or LTC_PKCS_1_V1_5)
    @param stat        [out] Result of the decryption, 1==valid, 0==invalid
    @param key         The corresponding private RSA key
@@ -26,13 +27,15 @@
 int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen,
                              unsigned char *out,            unsigned long *outlen,
                        const unsigned char *lparam,         unsigned long  lparamlen,
-                             int            hash_idx,       int            padding,
+                             int            mgf_hash,       int            lparam_hash,
+                             int            padding,
                              int           *stat,     const rsa_key       *key)
 {
   unsigned long modulus_bitlen, modulus_bytelen, x;
   int           err;
   unsigned char *tmp;
 
+  LTC_ARGCHK(in     != NULL);
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);
   LTC_ARGCHK(key    != NULL);
@@ -42,7 +45,6 @@ int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen
   *stat = 0;
 
   /* valid padding? */
-
   if ((padding != LTC_PKCS_1_V1_5) &&
       (padding != LTC_PKCS_1_OAEP)) {
     return CRYPT_PK_INVALID_PADDING;
@@ -50,7 +52,7 @@ int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen
 
   if (padding == LTC_PKCS_1_OAEP) {
     /* valid hash ? */
-    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+    if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
        return err;
     }
   }
@@ -79,8 +81,8 @@ int rsa_decrypt_key_ex(const unsigned char *in,             unsigned long  inlen
 
   if (padding == LTC_PKCS_1_OAEP) {
     /* now OAEP decode the packet */
-    err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx,
-                             out, outlen, stat);
+    err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, mgf_hash,
+                             lparam_hash, out, outlen, stat);
   } else {
     /* now PKCS #1 v1.5 depad the packet */
     err = pkcs_1_v1_5_decode(tmp, x, LTC_PKCS_1_EME, modulus_bitlen, out, outlen, stat);
diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
index 66942608ab18c8551fb68c5259c24b33f1936ffa..8739bb277c51b95a79fb090fe92e7f5ec08530a6 100644
--- a/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
+++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_encrypt_key.c
@@ -28,13 +28,14 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
                              unsigned char *out,      unsigned long *outlen,
                        const unsigned char *lparam,   unsigned long  lparamlen,
                              prng_state    *prng,     int            prng_idx,
-                             int            hash_idx, int            padding,
+                             int            mgf_hash, int            lparam_hash,
+                             int            padding,
                        const rsa_key       *key)
 {
   unsigned long modulus_bitlen, modulus_bytelen, x;
   int           err;
 
-  LTC_ARGCHK(in     != NULL);
+  LTC_ARGCHK((inlen == 0) || (in != NULL));
   LTC_ARGCHK(out    != NULL);
   LTC_ARGCHK(outlen != NULL);
   LTC_ARGCHK(key    != NULL);
@@ -52,7 +53,7 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
 
   if (padding == LTC_PKCS_1_OAEP) {
     /* valid hash? */
-    if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) {
+    if ((err = hash_is_valid(mgf_hash)) != CRYPT_OK) {
        return err;
     }
   }
@@ -71,8 +72,8 @@ int rsa_encrypt_key_ex(const unsigned char *in,       unsigned long  inlen,
     /* OAEP pad the key */
     x = *outlen;
     if ((err = pkcs_1_oaep_encode(in, inlen, lparam,
-                                  lparamlen, modulus_bitlen, prng, prng_idx, hash_idx,
-                                  out, &x)) != CRYPT_OK) {
+                                  lparamlen, modulus_bitlen, prng, prng_idx, mgf_hash,
+                                  lparam_hash, out, &x)) != CRYPT_OK) {
        return err;
     }
   } else {
diff --git a/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c b/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
index f035f6f6a5b035ea1b72a895824f3b7efa6ef033..492a5932547c377a850354d348160c269e1d2253 100644
--- a/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
+++ b/core/lib/libtomcrypt/src/pk/rsa/rsa_verify_hash.c
@@ -146,7 +146,7 @@ int rsa_verify_hash_ex(const unsigned char *sig,            unsigned long  sigle
       LTC_SET_ASN1(siginfo,    0, LTC_ASN1_SEQUENCE,          digestinfo,                    2);
       LTC_SET_ASN1(siginfo,    1, LTC_ASN1_OCTET_STRING,      tmpbuf,                        siglen);
 
-      if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
+      if (der_decode_sequence_strict(out, outlen, siginfo, 2) != CRYPT_OK) {
          /* fallback to Legacy:missing NULL */
          LTC_SET_ASN1(siginfo, 0, LTC_ASN1_SEQUENCE,          digestinfo,                    1);
          if ((err = der_decode_sequence_strict(out, outlen, siginfo, 2)) != CRYPT_OK) {
diff --git a/core/lib/libtomcrypt/src/pk/rsa/sub.mk b/core/lib/libtomcrypt/src/pk/rsa/sub.mk
deleted file mode 100644
index f0b8975bb8365d296a67bcc5f93178ff165bcef3..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/rsa/sub.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-srcs-y += rsa_decrypt_key.c
-srcs-y += rsa_encrypt_key.c
-srcs-y += rsa_export.c
-srcs-y += rsa_exptmod.c
-srcs-y += rsa_import.c
-srcs-y += rsa_key.c
-srcs-y += rsa_make_key.c
-srcs-y += rsa_sign_hash.c
-srcs-y += rsa_verify_hash.c
diff --git a/core/lib/libtomcrypt/src/pk/sub.mk b/core/lib/libtomcrypt/src/pk/sub.mk
deleted file mode 100644
index dca26a50a05fef92ce4a6ff64b6a13ed82a8bb07..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/sub.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-subdirs-$(_CFG_CORE_LTC_ASN1) += asn1
-subdirs-$(_CFG_CORE_LTC_DSA) += dsa
-# PKCS1 paddings are used with RSA only
-subdirs-$(_CFG_CORE_LTC_RSA) += pkcs1
-subdirs-$(_CFG_CORE_LTC_RSA) += rsa
-subdirs-$(_CFG_CORE_LTC_DH) += dh
-subdirs-$(_CFG_CORE_LTC_ECC) += ecc
-subdirs-$(_CFG_CORE_LTC_X25519) += ec25519
-subdirs-$(_CFG_CORE_LTC_X25519) += x25519
-subdirs-$(_CFG_CORE_LTC_ED25519) += ec25519
-subdirs-$(_CFG_CORE_LTC_ED25519) += ed25519
diff --git a/core/lib/libtomcrypt/src/pk/x25519/sub.mk b/core/lib/libtomcrypt/src/pk/x25519/sub.mk
deleted file mode 100644
index 853371ed615ecbeed3702d3fab8ab4b09d8cd025..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/pk/x25519/sub.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-srcs-y += x25519_export.c
-srcs-y += x25519_import.c
-srcs-y += x25519_make_key.c
-srcs-y += x25519_shared_secret.c
diff --git a/core/lib/libtomcrypt/src/prngs/fortuna.c b/core/lib/libtomcrypt/src/prngs/fortuna.c
index 6f500986c5f8a685369aada3e0187cd0492829b2..9c92595e9be0fc2ee4a2996c2fb20e6e742f474b 100644
--- a/core/lib/libtomcrypt/src/prngs/fortuna.c
+++ b/core/lib/libtomcrypt/src/prngs/fortuna.c
@@ -39,6 +39,18 @@ we reseed automatically when len(pool0) >= 64 or every LTC_FORTUNA_WD calls to t
    #error LTC_FORTUNA_POOLS must be in [4..32]
 #endif
 
+#ifdef LTC_FORTUNA_USE_ENCRYPT_ONLY
+#define AES_SETUP aes_enc_setup
+#define AES_ENC   aes_enc_ecb_encrypt
+#define AES_DONE  aes_enc_done
+#define AES_TEST  aes_enc_test
+#else
+#define AES_SETUP aes_setup
+#define AES_ENC   aes_ecb_encrypt
+#define AES_DONE  aes_done
+#define AES_TEST  aes_test
+#endif
+
 const struct ltc_prng_descriptor fortuna_desc = {
     "fortuna",
     64,
@@ -146,7 +158,7 @@ static int s_fortuna_reseed(prng_state *prng)
    if ((err = sha256_done(&md, prng->u.fortuna.K)) != CRYPT_OK) {
       return err;
    }
-   if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
+   if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
       return err;
    }
    s_fortuna_update_iv(prng);
@@ -236,7 +248,7 @@ int fortuna_start(prng_state *prng)
 
    /* reset bufs */
    zeromem(prng->u.fortuna.K, 32);
-   if ((err = rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
+   if ((err = AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey)) != CRYPT_OK) {
       for (x = 0; x < LTC_FORTUNA_POOLS; x++) {
           sha256_done(&prng->u.fortuna.pool[x], tmp);
       }
@@ -395,7 +407,7 @@ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state
    /* handle whole blocks without the extra XMEMCPY */
    while (outlen >= 16) {
       /* encrypt the IV and store it */
-      rijndael_ecb_encrypt(prng->u.fortuna.IV, out, &prng->u.fortuna.skey);
+      AES_ENC(prng->u.fortuna.IV, out, &prng->u.fortuna.skey);
       out += 16;
       outlen -= 16;
       s_fortuna_update_iv(prng);
@@ -403,19 +415,19 @@ unsigned long fortuna_read(unsigned char *out, unsigned long outlen, prng_state
 
    /* left over bytes? */
    if (outlen > 0) {
-      rijndael_ecb_encrypt(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey);
+      AES_ENC(prng->u.fortuna.IV, tmp, &prng->u.fortuna.skey);
       XMEMCPY(out, tmp, outlen);
       s_fortuna_update_iv(prng);
    }
 
    /* generate new key */
-   rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K   , &prng->u.fortuna.skey);
+   AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K   , &prng->u.fortuna.skey);
    s_fortuna_update_iv(prng);
 
-   rijndael_ecb_encrypt(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey);
+   AES_ENC(prng->u.fortuna.IV, prng->u.fortuna.K+16, &prng->u.fortuna.skey);
    s_fortuna_update_iv(prng);
 
-   if (rijndael_setup(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) {
+   if (AES_SETUP(prng->u.fortuna.K, 32, 0, &prng->u.fortuna.skey) != CRYPT_OK) {
       tlen = 0;
    }
 
@@ -512,7 +524,7 @@ int fortuna_test(void)
    if ((err = sha256_test()) != CRYPT_OK) {
       return err;
    }
-   return rijndael_test();
+   return AES_TEST();
 #endif
 }
 
diff --git a/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c b/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c
index b07238ec7676f2187ae0890fd7d428b43341bc73..9a122102176b7bc102dc707ba798bb916f137973 100644
--- a/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c
+++ b/core/lib/libtomcrypt/src/prngs/rng_get_bytes.c
@@ -82,12 +82,27 @@ static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len,
 
 /* Try the Microsoft CSP */
 #if defined(_WIN32) || defined(_WIN32_WCE)
+#if defined(LTC_WIN32_BCRYPT)
+
+#include <windows.h>
+#include <bcrypt.h>
+#pragma comment(lib, "bcrypt.lib")
+
+static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
+                               void (*callback)(void))
+{
+   LTC_UNUSED_PARAM(callback);
+
+   return BCRYPT_SUCCESS(BCryptGenRandom(NULL, (PUCHAR)buf, (ULONG)len, BCRYPT_USE_SYSTEM_PREFERRED_RNG)) ? len : 0;
+}
+
+#else
+
 #ifndef _WIN32_WINNT
-  #define _WIN32_WINNT 0x0400
+  #define _WIN32_WINNT 0x0501
 #endif
-#ifdef _WIN32_WCE
-   #define UNDER_CE
-   #define ARM
+#ifndef WINVER
+  #define WINVER 0x0501
 #endif
 
 #define WIN32_LEAN_AND_MEAN
@@ -97,23 +112,23 @@ static unsigned long s_rng_ansic(unsigned char *buf, unsigned long len,
 static unsigned long s_rng_win32(unsigned char *buf, unsigned long len,
                                void (*callback)(void))
 {
-   HCRYPTPROV hProv = 0;
    LTC_UNUSED_PARAM(callback);
-   if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
-                            (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
-       !CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
-                            CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
-      return 0;
-
-   if (CryptGenRandom(hProv, len, buf) == TRUE) {
-      CryptReleaseContext(hProv, 0);
-      return len;
-   } else {
-      CryptReleaseContext(hProv, 0);
-      return 0;
+
+   static HCRYPTPROV hProv = 0;
+   if (hProv == 0) {
+      HCRYPTPROV h = 0;
+      if (!CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
+                                (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
+          !CryptAcquireContextW(&h, NULL, MS_DEF_PROV_W, PROV_RSA_FULL,
+                                CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
+         return 0;
+      }
+      hProv = h;
    }
-}
 
+   return CryptGenRandom(hProv, (DWORD)len, (BYTE *)buf) == TRUE ? len : 0;
+}
+#endif /* Old WIN32 versions */
 #endif /* WIN32 */
 
 /**
diff --git a/core/lib/libtomcrypt/src/prngs/sub.mk b/core/lib/libtomcrypt/src/prngs/sub.mk
deleted file mode 100644
index d8a8e51e0b9f54eb2840821cbac5743f3261f695..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/prngs/sub.mk
+++ /dev/null
@@ -1,7 +0,0 @@
-cflags-y += -Wno-unused-parameter -Wno-unused-variable
-
-srcs-y += rng_get_bytes.c
-srcs-y += rng_make_prng.c
-srcs-y += sprng.c
-srcs-y += rc4.c
-srcs-$(_CFG_CORE_LTC_FORTUNA_PRNG) += fortuna.c
diff --git a/core/lib/libtomcrypt/src/sub.mk b/core/lib/libtomcrypt/src/sub.mk
deleted file mode 100644
index d622204fe1f378f497be52c8d3e4712c42b0378b..0000000000000000000000000000000000000000
--- a/core/lib/libtomcrypt/src/sub.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-subdirs-$(_CFG_CORE_LTC_CIPHER) += ciphers
-subdirs-$(_CFG_CORE_LTC_AUTHENC) += encauth
-subdirs-y += hashes
-subdirs-$(_CFG_CORE_LTC_MAC) += mac
-subdirs-$(_CFG_CORE_LTC_ACIPHER) += math
-subdirs-y += misc
-subdirs-y += modes
-subdirs-$(_CFG_CORE_LTC_ACIPHER) += pk
-subdirs-$(_CFG_CORE_LTC_EC25519) += pk
diff --git a/core/lib/libtomcrypt/sub.mk b/core/lib/libtomcrypt/sub.mk
index de11cccd847c6fd6f97b4af002947533bf2773be..a2a153062c1c6058978561452b9dc927eaf6cf43 100644
--- a/core/lib/libtomcrypt/sub.mk
+++ b/core/lib/libtomcrypt/sub.mk
@@ -1,155 +1,369 @@
 global-incdirs-y += include
 global-incdirs-y += src/headers
 
-cflags-lib-y += -Wno-declaration-after-statement
-
 cppflags-lib-y += -DARGTYPE=4  # Make LTC_ARGCHK() return on error
 cppflags-lib-y += -DLTC_NO_TEST -DLTC_NO_PROTOTYPES
 cppflags-lib-y += -DLTC_NO_TABLES -DLTC_HASH_HELPERS
 cppflags-lib-y += -DLTC_NO_MISC
 cppflags-lib-y += -DLTC_HMAC
 cppflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -DLTC_SMALL_CODE
-
 cppflags-lib-y += -DLTC_NO_CIPHERS
-
-ifeq ($(_CFG_CORE_LTC_AES_DESC),y)
-	cppflags-lib-y += -DLTC_RIJNDAEL
-endif
-ifeq ($(_CFG_CORE_LTC_DES),y)
-	cppflags-lib-y += -DLTC_DES
-endif
-
 cppflags-lib-y += -DLTC_NO_MODES
+cppflags-lib-y += -DLTC_NO_HASHES
+cppflags-lib-y += -DLTC_NO_MACS
+cppflags-lib-y += -DLTC_NO_PK
+cppflags-lib-y += -DLTC_NO_PRNGS -DLTC_FORTUNA
+cflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -Os
 
-ifeq ($(_CFG_CORE_LTC_ECB),y)
-	cppflags-lib-y += -DLTC_ECB_MODE
-endif
-ifeq ($(_CFG_CORE_LTC_CBC),y)
-	cppflags-lib-y += -DLTC_CBC_MODE
-endif
-ifeq ($(_CFG_CORE_LTC_CTR),y)
-	cppflags-lib-y += -DLTC_CTR_MODE
-endif
-ifeq ($(_CFG_CORE_LTC_XTS),y)
-	cppflags-lib-y += -DLTC_XTS_MODE
+srcs-y += tomcrypt.c
+srcs-y += src/misc/burn_stack.c
+srcs-y += src/misc/error_to_string.c
+srcs-y += src/misc/mem_neq.c
+srcs-y += src/misc/zeromem.c
+srcs-y += src/misc/base64/base64_decode.c
+srcs-y += src/misc/base64/base64_encode.c
+srcs-y += src/misc/crypt/crypt.c
+srcs-y += src/misc/crypt/crypt_cipher_descriptor.c
+srcs-y += src/misc/crypt/crypt_cipher_is_valid.c
+srcs-y += src/misc/crypt/crypt_find_cipher_any.c
+srcs-y += src/misc/crypt/crypt_find_cipher.c
+srcs-y += src/misc/crypt/crypt_find_cipher_id.c
+srcs-y += src/misc/crypt/crypt_find_hash_any.c
+srcs-y += src/misc/crypt/crypt_find_hash.c
+srcs-y += src/misc/crypt/crypt_find_hash_id.c
+srcs-y += src/misc/crypt/crypt_find_hash_oid.c
+srcs-y += src/misc/crypt/crypt_find_prng.c
+srcs-y += src/misc/crypt/crypt_fsa.c
+srcs-y += src/misc/crypt/crypt_hash_descriptor.c
+srcs-y += src/misc/crypt/crypt_hash_is_valid.c
+srcs-y += src/misc/crypt/crypt_prng_descriptor.c
+srcs-y += src/misc/crypt/crypt_prng_is_valid.c
+srcs-y += src/misc/crypt/crypt_register_cipher.c
+srcs-y += src/misc/crypt/crypt_register_hash.c
+srcs-y += src/misc/crypt/crypt_register_prng.c
+srcs-y += src/misc/crypt/crypt_unregister_cipher.c
+srcs-y += src/misc/crypt/crypt_unregister_hash.c
+srcs-y += src/misc/crypt/crypt_unregister_prng.c
+srcs-y += src/misc/pkcs12/pkcs12_kdf.c
+srcs-y += src/misc/pkcs12/pkcs12_utf8_to_utf16.c
+srcs-y += src/misc/pkcs5/pkcs_5_1.c
+srcs-y += src/misc/pkcs5/pkcs_5_2.c
+srcs-y += src/misc/ssh/ssh_decode_sequence_multi.c
+srcs-y += src/misc/ssh/ssh_encode_sequence_multi.c
+
+cppflags-lib-$(_CFG_CORE_LTC_AES_DESC) += -DLTC_RIJNDAEL
+srcs-$(_CFG_CORE_LTC_AES) += aes.c
+ifeq ($(_CFG_CORE_LTC_AES_ACCEL),y)
+srcs-$(_CFG_CORE_LTC_AES_DESC) += aes_accel.c
+else
+srcs-$(_CFG_CORE_LTC_AES_DESC) += src/ciphers/aes/aes.c
+srcs-$(_CFG_CORE_LTC_AES_DESC) += src/ciphers/aes/aes_desc.c
 endif
 
-cppflags-lib-y += -DLTC_NO_HASHES
+cppflags-lib-$(_CFG_CORE_LTC_DES) += -DLTC_DES
+srcs-$(_CFG_CORE_LTC_DES) += src/ciphers/des.c
 
-ifeq ($(_CFG_CORE_LTC_MD5_DESC),y)
-	cppflags-lib-y += -DLTC_MD5
-endif
-ifeq ($(_CFG_CORE_LTC_SHA1_DESC),y)
-	cppflags-lib-y += -DLTC_SHA1
-endif
-ifeq ($(_CFG_CORE_LTC_SHA224_DESC),y)
-	cppflags-lib-y += -DLTC_SHA224
-endif
-ifeq ($(_CFG_CORE_LTC_SHA256_DESC),y)
-	cppflags-lib-y += -DLTC_SHA256
-endif
-ifeq ($(_CFG_CORE_LTC_SHA384_DESC),y)
-	cppflags-lib-y += -DLTC_SHA384
-endif
-ifeq ($(_CFG_CORE_LTC_SHA512_DESC),y)
-	cppflags-lib-y += -DLTC_SHA512
-endif
-ifeq ($(_CFG_CORE_LTC_SHA512_256),y)
-	cppflags-lib-y += -DLTC_SHA512_256
+cppflags-lib-$(_CFG_CORE_LTC_CCM) += -DLTC_CCM_MODE
+srcs-$(_CFG_CORE_LTC_CCM) += ccm.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_init.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_add_nonce.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_add_aad.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_process.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_done.c
+srcs-$(_CFG_CORE_LTC_CCM) += src/encauth/ccm/ccm_reset.c
+
+cppflags-lib-$(_CFG_CORE_LTC_GCM) += -DLTC_GCM_MODE
+srcs-$(_CFG_CORE_LTC_GCM) += gcm.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_add_aad.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_add_iv.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_done.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_gf_mult.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_init.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_memory.c
+ifeq ($(_CFG_CORE_LTC_CE),y)
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_mult_h_arm_ce.c
+else
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_mult_h.c
 endif
-cppflags-lib-$(_CFG_CORE_LTC_SHA3_DESC) += -DLTC_SHA3
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_process.c
+srcs-$(_CFG_CORE_LTC_GCM) += src/encauth/gcm/gcm_reset.c
 
+srcs-$(_CFG_CORE_LTC_HASH) += hash.c
+srcs-$(_CFG_CORE_LTC_HASH) += src/hashes/helper/hash_memory.c
+srcs-$(_CFG_CORE_LTC_HASH) += src/hashes/helper/hash_memory_multi.c
 
-cppflags-lib-y += -DLTC_NO_MACS
+cppflags-lib-$(_CFG_CORE_LTC_MD5_DESC) += -DLTC_MD5
+srcs-$(_CFG_CORE_LTC_MD5_DESC) += src/hashes/md5.c
 
-ifeq ($(_CFG_CORE_LTC_HMAC),y)
-	cppflags-lib-y += -DLTC_HMAC
-endif
-ifeq ($(_CFG_CORE_LTC_CMAC),y)
-	cppflags-lib-y += -DLTC_OMAC
-endif
-ifeq ($(_CFG_CORE_LTC_CCM),y)
-	cppflags-lib-y += -DLTC_CCM_MODE
+cppflags-lib-$(_CFG_CORE_LTC_SHA1_DESC) += -DLTC_SHA1
+ifeq ($(_CFG_CORE_LTC_SHA1_ACCEL),y)
+srcs-$(_CFG_CORE_LTC_SHA1_DESC) += sha1_accel.c
+else
+srcs-$(_CFG_CORE_LTC_SHA1_DESC) += src/hashes/sha1.c
 endif
-ifeq ($(_CFG_CORE_LTC_GCM),y)
-	cppflags-lib-y += -DLTC_GCM_MODE
+
+cppflags-lib-$(_CFG_CORE_LTC_SHA3_DESC) += -DLTC_SHA3
+ifeq ($(_CFG_CORE_LTC_SHA3_ACCEL),y)
+srcs-$(_CFG_CORE_LTC_SHA3_DESC) += sha3_accel.c
+else
+srcs-$(_CFG_CORE_LTC_SHA3_DESC) += src/hashes/sha3.c
 endif
+srcs-$(_CFG_CORE_LTC_SHA3_DESC) += src/hashes/sha3_test.c
+srcs-$(_CFG_CORE_LTC_SHA3_DESC) += shake.c
 
-cppflags-lib-y += -DLTC_NO_PK
+cppflags-lib-$(_CFG_CORE_LTC_SHA224_DESC) += -DLTC_SHA224
+srcs-$(_CFG_CORE_LTC_SHA224_DESC) += src/hashes/sha2/sha224.c
 
-ifeq ($(_CFG_CORE_LTC_RSA),y)
-   cppflags-lib-y += -DLTC_MRSA
-endif
-ifeq ($(_CFG_CORE_LTC_DSA),y)
-   cppflags-lib-y += -DLTC_MDSA
-endif
-ifeq ($(_CFG_CORE_LTC_DH),y)
-   cppflags-lib-y += -DLTC_MDH
+cppflags-lib-$(_CFG_CORE_LTC_SHA256_DESC) += -DLTC_SHA256
+ifeq ($(_CFG_CORE_LTC_SHA256_ACCEL),y)
+srcs-$(_CFG_CORE_LTC_SHA256_DESC) += sha256_accel.c
+else
+srcs-$(_CFG_CORE_LTC_SHA256_DESC) += src/hashes/sha2/sha256.c
 endif
-ifeq ($(_CFG_CORE_LTC_ECC),y)
-   cppflags-lib-y += -DLTC_MECC
-
-   # use Shamir's trick for point mul (speeds up signature verification)
-   cppflags-lib-y += -DLTC_ECC_SHAMIR
 
-   cppflags-lib-y += -DLTC_ECC192
-   cppflags-lib-y += -DLTC_ECC224
-   cppflags-lib-y += -DLTC_ECC256
-   cppflags-lib-y += -DLTC_ECC384
-   cppflags-lib-y += -DLTC_ECC521
-   cppflags-lib-y += -DLTC_CURVE25519
+cppflags-lib-$(_CFG_CORE_LTC_SHA384_DESC) += -DLTC_SHA384
+srcs-$(_CFG_CORE_LTC_SHA384_DESC) += src/hashes/sha2/sha384.c
 
-   # ECC 521 bits is the max supported key size
-   cppflags-lib-y += -DLTC_MAX_ECC=521
-endif
-ifneq (,$(filter y,$(_CFG_CORE_LTC_SM2_DSA) $(_CFG_CORE_LTC_SM2_PKE)))
-   cppflags-lib-y += -DLTC_ECC_SM2
+cppflags-lib-$(_CFG_CORE_LTC_SHA512_DESC) += -DLTC_SHA512
+ifeq ($(_CFG_CORE_LTC_SHA512_ACCEL),y)
+srcs-$(_CFG_CORE_LTC_SHA512_DESC) += sha512_accel.c
+else
+srcs-$(_CFG_CORE_LTC_SHA512_DESC) += src/hashes/sha2/sha512.c
 endif
 
-cppflags-lib-$(_CFG_CORE_LTC_X25519) += -DLTC_CURVE25519
-cppflags-lib-$(_CFG_CORE_LTC_ED25519) += -DLTC_CURVE25519
+cppflags-lib-$(_CFG_CORE_LTC_SHA512_256) += -DLTC_SHA512_256
+srcs-$(_CFG_CORE_LTC_SHA512_256) += src/hashes/sha2/sha512_256.c
 
-cppflags-lib-y += -DLTC_NO_PRNGS -DLTC_FORTUNA
+cppflags-lib-$(_CFG_CORE_LTC_HMAC) += -DLTC_HMAC
+srcs-$(_CFG_CORE_LTC_HMAC) += hmac.c
+srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_done.c
+srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_init.c
+srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_memory.c
+srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_memory_multi.c
+srcs-$(_CFG_CORE_LTC_HMAC) += src/mac/hmac/hmac_process.c
 
-cflags-lib-$(_CFG_CORE_LTC_SIZE_OPTIMIZATION) += -Os
+cppflags-lib-$(_CFG_CORE_LTC_CMAC) += -DLTC_OMAC
+srcs-$(_CFG_CORE_LTC_CMAC) += cmac.c
+srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_done.c
+srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_init.c
+srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_memory.c
+srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_memory_multi.c
+srcs-$(_CFG_CORE_LTC_CMAC) += src/mac/omac/omac_process.c
 
-subdirs-y += src
+srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/multi.c
+srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/rand_prime.c
+srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/rand_bn.c
+ifeq ($(_CFG_CORE_LTC_ECC),y)
+srcs-$(_CFG_CORE_LTC_ACIPHER) += src/math/fp/ltc_ecc_fp_mulmod.c
+endif
 
-srcs-$(_CFG_CORE_LTC_HASH) += hash.c
-srcs-$(_CFG_CORE_LTC_HMAC) += hmac.c
-srcs-$(_CFG_CORE_LTC_CMAC) += cmac.c
-srcs-$(_CFG_CORE_LTC_ECB) += ecb.c
+
+cppflags-lib-$(_CFG_CORE_LTC_CBC) += -DLTC_CBC_MODE
 srcs-$(_CFG_CORE_LTC_CBC) += cbc.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_decrypt.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_done.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_encrypt.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_getiv.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_setiv.c
+srcs-$(_CFG_CORE_LTC_CBC) += src/modes/cbc/cbc_start.c
+
+cppflags-lib-$(_CFG_CORE_LTC_CTR) += -DLTC_CTR_MODE
 srcs-$(_CFG_CORE_LTC_CTR) += ctr.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_decrypt.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_done.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_encrypt.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_getiv.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_setiv.c
+srcs-$(_CFG_CORE_LTC_CTR) += src/modes/ctr/ctr_start.c
+
+cppflags-lib-$(_CFG_CORE_LTC_ECB) += -DLTC_ECB_MODE
+srcs-$(_CFG_CORE_LTC_ECB) += ecb.c
+srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_decrypt.c
+srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_done.c
+srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_encrypt.c
+srcs-$(_CFG_CORE_LTC_ECB) += src/modes/ecb/ecb_start.c
+
+cppflags-lib-$(_CFG_CORE_LTC_XTS) += -DLTC_XTS_MODE
 srcs-$(_CFG_CORE_LTC_XTS) += xts.c
-srcs-$(_CFG_CORE_LTC_CCM) += ccm.c
-srcs-$(_CFG_CORE_LTC_GCM) += gcm.c
+srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_decrypt.c
+srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_done.c
+srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_encrypt.c
+srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_init.c
+srcs-$(_CFG_CORE_LTC_XTS) += src/modes/xts/xts_mult_x.c
+
+srcs-$(_CFG_CORE_LTC_ACIPHER) += mpi_desc.c
+cflags-mpi_desc.c-y += -Wno-declaration-after-statement
+cppflags-mpi_desc.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS
+
+ifeq ($(_CFG_CORE_LTC_ASN1),y)
+srcs-y += src/pk/asn1/der/bit/der_decode_bit_string.c
+srcs-y += src/pk/asn1/der/bit/der_encode_bit_string.c
+srcs-y += src/pk/asn1/der/bit/der_length_bit_string.c
+srcs-y += src/pk/asn1/der/bit/der_decode_raw_bit_string.c
+srcs-y += src/pk/asn1/der/bit/der_encode_raw_bit_string.c
+srcs-y += src/pk/asn1/der/boolean/der_decode_boolean.c
+srcs-y += src/pk/asn1/der/boolean/der_encode_boolean.c
+srcs-y += src/pk/asn1/der/boolean/der_length_boolean.c
+srcs-y += src/pk/asn1/der/choice/der_decode_choice.c
+srcs-y += src/pk/asn1/der/custom_type/der_decode_custom_type.c
+srcs-y += src/pk/asn1/der/custom_type/der_encode_custom_type.c
+srcs-y += src/pk/asn1/der/custom_type/der_length_custom_type.c
+srcs-y += src/pk/asn1/der/general/der_asn1_maps.c
+srcs-y += src/pk/asn1/der/general/der_decode_asn1_length.c
+srcs-y += src/pk/asn1/der/general/der_decode_asn1_identifier.c
+srcs-y += src/pk/asn1/der/general/der_encode_asn1_identifier.c
+srcs-y += src/pk/asn1/der/general/der_encode_asn1_length.c
+srcs-y += src/pk/asn1/der/general/der_length_asn1_identifier.c
+srcs-y += src/pk/asn1/der/general/der_length_asn1_length.c
+srcs-y += src/pk/asn1/der/generalizedtime/der_encode_generalizedtime.c
+srcs-y += src/pk/asn1/der/generalizedtime/der_decode_generalizedtime.c
+srcs-y += src/pk/asn1/der/generalizedtime/der_length_generalizedtime.c
+srcs-y += src/pk/asn1/der/ia5/der_decode_ia5_string.c
+srcs-y += src/pk/asn1/der/ia5/der_encode_ia5_string.c
+srcs-y += src/pk/asn1/der/ia5/der_length_ia5_string.c
+srcs-y += src/pk/asn1/der/integer/der_decode_integer.c
+srcs-y += src/pk/asn1/der/integer/der_encode_integer.c
+srcs-y += src/pk/asn1/der/integer/der_length_integer.c
+srcs-y += src/pk/asn1/der/object_identifier/der_decode_object_identifier.c
+srcs-y += src/pk/asn1/der/object_identifier/der_encode_object_identifier.c
+srcs-y += src/pk/asn1/der/object_identifier/der_length_object_identifier.c
+srcs-y += src/pk/asn1/der/octet/der_decode_octet_string.c
+srcs-y += src/pk/asn1/der/octet/der_encode_octet_string.c
+srcs-y += src/pk/asn1/der/octet/der_length_octet_string.c
+srcs-y += src/pk/asn1/der/printable_string/der_decode_printable_string.c
+srcs-y += src/pk/asn1/der/printable_string/der_encode_printable_string.c
+srcs-y += src/pk/asn1/der/printable_string/der_length_printable_string.c
+srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_ex.c
+srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_flexi.c
+srcs-y += src/pk/asn1/der/sequence/der_decode_sequence_multi.c
+srcs-y += src/pk/asn1/der/sequence/der_encode_sequence_ex.c
+srcs-y += src/pk/asn1/der/sequence/der_encode_sequence_multi.c
+srcs-y += src/pk/asn1/der/sequence/der_length_sequence.c
+srcs-y += src/pk/asn1/der/sequence/der_sequence_free.c
+srcs-y += src/pk/asn1/der/set/der_encode_set.c
+srcs-y += src/pk/asn1/der/set/der_encode_setof.c
+srcs-y += src/pk/asn1/der/short_integer/der_decode_short_integer.c
+srcs-y += src/pk/asn1/der/short_integer/der_encode_short_integer.c
+srcs-y += src/pk/asn1/der/short_integer/der_length_short_integer.c
+srcs-y += src/pk/asn1/der/utctime/der_decode_utctime.c
+srcs-y += src/pk/asn1/der/utctime/der_encode_utctime.c
+srcs-y += src/pk/asn1/der/utctime/der_length_utctime.c
+srcs-y += src/pk/asn1/der/utf8/der_decode_utf8_string.c
+srcs-y += src/pk/asn1/der/utf8/der_encode_utf8_string.c
+srcs-y += src/pk/asn1/der/utf8/der_length_utf8_string.c
+srcs-y += src/pk/asn1/der/teletex_string/der_decode_teletex_string.c
+srcs-y += src/pk/asn1/der/teletex_string/der_length_teletex_string.c
+srcs-y += src/pk/asn1/oid/pk_oid_cmp.c
+srcs-y += src/pk/asn1/oid/pk_oid_str.c
+endif
+
+cppflags-lib-$(_CFG_CORE_LTC_DSA) += -DLTC_MDSA
 srcs-$(_CFG_CORE_LTC_DSA) += dsa.c
-srcs-$(_CFG_CORE_LTC_ECC) += ecc.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_decrypt_key.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_encrypt_key.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_export.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_free.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_generate_key.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_generate_pqg.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_import.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_make_key.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_shared_secret.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_sign_hash.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_verify_hash.c
+srcs-$(_CFG_CORE_LTC_DSA) += src/pk/dsa/dsa_verify_key.c
+
+cppflags-lib-$(_CFG_CORE_LTC_RSA) += -DLTC_MRSA
 srcs-$(_CFG_CORE_LTC_RSA) += rsa.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_i2osp.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_mgf1.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_oaep_decode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_oaep_encode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_os2ip.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_pss_decode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_pss_encode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_v1_5_decode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/pkcs1/pkcs_1_v1_5_encode.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_decrypt_key.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_encrypt_key.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_export.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_exptmod.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_import.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_key.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_make_key.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_sign_hash.c
+srcs-$(_CFG_CORE_LTC_RSA) += src/pk/rsa/rsa_verify_hash.c
+
+cppflags-lib-$(_CFG_CORE_LTC_DH) += -DLTC_MDH
 srcs-$(_CFG_CORE_LTC_DH) += dh.c
-srcs-$(_CFG_CORE_LTC_AES) += aes.c
-srcs-$(_CFG_CORE_LTC_AES_ACCEL) += aes_accel.c
-srcs-$(_CFG_CORE_LTC_SHA1_ACCEL) += sha1_accel.c
-ifeq ($(_CFG_CORE_LTC_SHA256_DESC),y)
-srcs-$(_CFG_CORE_LTC_SHA256_ACCEL) += sha256_accel.c
-endif
-ifeq ($(_CFG_CORE_LTC_SHA512_DESC),y)
-srcs-$(_CFG_CORE_LTC_SHA512_ACCEL) += sha512_accel.c
-endif
-ifeq ($(_CFG_CORE_LTC_SHA3_DESC),y)
-srcs-y += shake.c
-srcs-$(_CFG_CORE_LTC_SHA3_ACCEL) += sha3_accel.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_check_pubkey.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_export.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_export_key.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_free.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_generate_key.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_import.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_make_key.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_set.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_set_pg_dhparam.c
+srcs-$(_CFG_CORE_LTC_DH) += src/pk/dh/dh_shared_secret.c
+
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_MECC
+# use Shamir's trick for point mul (speeds up signature verification)
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC_SHAMIR
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC192
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC224
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC256
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC384
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_ECC521
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_CURVE25519
+# ECC 521 bits is the max supported key size
+cppflags-lib-$(_CFG_CORE_LTC_ECC) += -DLTC_MAX_ECC=521
+srcs-$(_CFG_CORE_LTC_ECC) += ecc.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_find_curve.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_free.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_get_oid_str.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_make_key.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_set_curve.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_set_curve_internal.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_shared_secret.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_sign_hash.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_ssh_ecdsa_encode_name.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ecc_verify_hash.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_is_point.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_is_point_at_infinity.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_map.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mulmod.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mulmod_timing.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_mul2add.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_points.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_projective_add_point.c
+srcs-$(_CFG_CORE_LTC_ECC) += src/pk/ecc/ltc_ecc_projective_dbl_point.c
+
+ifneq (,$(filter y,$(_CFG_CORE_LTC_SM2_DSA) $(_CFG_CORE_LTC_SM2_PKE)))
+   cppflags-lib-y += -DLTC_ECC_SM2
 endif
 srcs-$(_CFG_CORE_LTC_SM2_DSA) += sm2-dsa.c
 srcs-$(_CFG_CORE_LTC_SM2_PKE) += sm2-pke.c
 srcs-$(_CFG_CORE_LTC_SM2_KEP) += sm2-kep.c
-srcs-$(_CFG_CORE_LTC_X25519) += x25519.c
-srcs-$(_CFG_CORE_LTC_ED25519) += ed25519.c
-ifeq ($(_CFG_CORE_LTC_ACIPHER),y)
-srcs-y += mpi_desc.c
-cppflags-mpi_desc.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS
-endif
 
-srcs-y += tomcrypt.c
+cppflags-lib-$(_CFG_CORE_LTC_EC25519) += -DLTC_CURVE25519
+srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/ec25519_crypto_ctx.c
+srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/ec25519_export.c
+srcs-$(_CFG_CORE_LTC_EC25519) += src/pk/ec25519/tweetnacl.c
 
+srcs-$(_CFG_CORE_LTC_ED25519) += ed25519.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_export.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import_pkcs8.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_import_x509.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_make_key.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_sign.c
+srcs-$(_CFG_CORE_LTC_ED25519) += src/pk/ed25519/ed25519_verify.c
+
+srcs-$(_CFG_CORE_LTC_X25519) += x25519.c
+cflags-x25519.c-y += -Wno-declaration-after-statement
+srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_export.c
+srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_import.c
+srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_make_key.c
+srcs-$(_CFG_CORE_LTC_X25519) += src/pk/x25519/x25519_shared_secret.c
diff --git a/core/lib/qcbor/LICENSE b/core/lib/qcbor/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..bf7753f1369a065bfadeddeed488b23a4916be3c
--- /dev/null
+++ b/core/lib/qcbor/LICENSE
@@ -0,0 +1,36 @@
+QCBOR is available under what is essentially the 3-Clause BSD License.
+
+Files created inside Qualcomm and open-sourced through CAF (The Code
+Aurora Forum) have a slightly modified 3-Clause BSD License. The
+modification additionally disclaims NON-INFRINGEMENT.
+
+Files created after release to CAF use the standard 3-Clause BSD
+License with no modification. These files have the SPDX license
+identifier, "SPDX-License-Identifier: BSD-3-Clause" in them.
+
+
+BSD 3-Clause License
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+
diff --git a/core/lib/qcbor/README.md b/core/lib/qcbor/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..708a3a69d359b84b90f0dd997270da734ac2c62a
--- /dev/null
+++ b/core/lib/qcbor/README.md
@@ -0,0 +1,581 @@
+![QCBOR Logo](https://github.com/laurencelundblade/qdv/blob/master/logo.png?raw=true)
+
+**QCBOR** is a powerful, commercial-quality CBOR encoder-decoder that
+implements these RFCs:
+
+* [RFC8949](https://tools.ietf.org/html/rfc8949) The CBOR Standard. (Nearly everything
+except sorting of encoded maps)
+* [RFC7049](https://tools.ietf.org/html/rfc7049) The previous CBOR standard.
+Replaced by RFC 8949.
+* [RFC8742](https://tools.ietf.org/html/rfc8742) CBOR Sequences
+* [RFC8943](https://tools.ietf.org/html/rfc8943) CBOR Dates
+
+## QCBOR Characteristics
+
+**Implemented in C with minimal dependency** – Dependent only
+ on C99, <stdint.h>, <stddef.h>, <stdbool.h> and <string.h> making
+  it highly portable. <math.h> and <fenv.h> are used too, but their
+  use can disabled. No #ifdefs or compiler options need to be set for
+  QCBOR to run correctly.
+
+**Focused on C / native data representation** – Careful conversion of
+  CBOR data types in to C data types,  handling over and
+  underflow, strict typing and such so the caller doesn't have to
+  worry so much about this and so code using QCBOR passes static
+  analyzers easier.  Simpler code because there is no support for
+  encoding/decoding to/from JSON, pretty printing, diagnostic
+  notation... Only encoding from native C representations and decoding
+  to native C representations is supported.
+
+**Small simple memory model** – Malloc is not needed. The encode
+  context is 176 bytes, decode context is 312 bytes and the
+  description of decoded data item is 56 bytes. Stack use is light and
+  there is no recursion. The caller supplies the memory to hold the
+  encoded CBOR and encode/decode contexts so caller has full control
+  of memory usage making it good for embedded implementations that
+  have to run in small fixed memory.
+
+**Easy decoding of maps** – The "spiffy decode" functions allow
+  fetching map items directly by label. Detection of duplicate map
+  items is automatically performed. This makes decoding of complex
+  protocols much simpler, say when compared to TinyCBOR.
+
+**Supports most of RFC 8949** – With some size limits, all data types
+  and formats in the specification are supported. Map sorting is main
+  CBOR feature that is not supported.  The same decoding API supports
+  both definite and indefinite-length map and array decoding. Decoding
+  indefinite length strings is supported but requires a string
+  allocator be set up. Encoding of indefinite length strings is
+  planned, but not yet supported.
+
+**Extensible and general** – Provides a way to handle data types that
+  are not directly supported.
+
+**Secure coding style** – Uses a construct called UsefulBuf as a
+  discipline for very safe coding and handling of binary data.
+
+**Small code size** – In the smallest configuration the object
+  code is less than 4KB on 64-bit x86 CPUs. The design is such that
+  object code for QCBOR APIs not used is not referenced.
+
+**Clear documented public interface** – The public interface is
+  separated from the implementation. It can be put to use without
+  reading the source.
+
+**Comprehensive test suite** – Easy to verify on a new platform or OS
+  with the test suite. The test suite dependencies are minimal and the
+  same as the library's.
+
+## Spiffy Decode
+
+These are functions to decode particular data types. They are an
+alternative to and built on top of QCBORDecode_GetNext(). They do type
+checking and in some cases sophisticated type conversion.
+
+Spiffy decode supports easier map and array decoding. A map can be
+descended into with QCBORDecode_EnterMap(). When a map has been
+entered, members can be retrieved by label.  Detection of duplicate
+map labels, an error, is automatically performed.
+
+An internal error state is maintained. This simplifies the decode
+implementation as an error check is only needed at the end of the
+decode, rather than on every function.
+
+An outcome is that decoding implementations are simple and involve
+many fewer lines of code. They also tend to parallel the encoding
+implementations as seen in the following example.
+
+     /* Encode */
+     QCBOREncode_Init(&EncodeCtx, Buffer);
+     QCBOREncode_OpenMap(&EncodeCtx);
+     QCBOREncode_AddTextToMap(&EncodeCtx, "Manufacturer", pE->Manufacturer);
+     QCBOREncode_AddInt64ToMap(&EncodeCtx, "Displacement", pE->uDisplacement);
+     QCBOREncode_AddInt64ToMap(&EncodeCtx, "Horsepower", pE->uHorsePower);
+     QCBOREncode_CloseMap(&EncodeCtx);
+     uErr = QCBOREncode_Finish(&EncodeCtx, &EncodedEngine);
+
+     /* Decode */
+     QCBORDecode_Init(&DecodeCtx, EncodedEngine, QCBOR_DECODE_MODE_NORMAL);
+     QCBORDecode_EnterMap(&DecodeCtx);
+     QCBORDecode_GetTextStringInMapSZ(&DecodeCtx, "Manufacturer", &(pE->Manufacturer));
+     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Displacement", &(pE->uDisplacement));
+     QCBORDecode_GetInt64InMapSZ(&DecodeCtx, "Horsepower", &(pE->uHorsePower));
+     QCBORDecode_ExitMap(&DecodeCtx);
+     uErr = QCBORDecode_Finish(&DecodeCtx);
+
+The spiffy decode functions will handle definite and indefinite length
+maps and arrays without the caller having to do anything. This
+includes mixed definite and indefinte maps and arrays. (Some work
+remains to support map searching with indefinite length strings.)
+
+## Comparison to TinyCBOR
+
+TinyCBOR is a popular widely used implementation. Like QCBOR,
+it is a solid, well-maintained commercial quality implementation. This
+section is for folks trying to understand the difference in
+the approach between QCBOR and TinyCBOR.
+
+TinyCBOR's API is more minimalist and closer to the CBOR
+encoding mechanics than QCBOR's. QCBOR's API is at a somewhat higher
+level of abstraction.
+
+QCBOR really does implement just about everything described in
+RFC 8949. The main part missing is sorting of maps when encoding.
+TinyCBOR implements a smaller part of the standard.
+
+No detailed code size comparison has been made, but in a spot check
+that encodes and decodes a single integer shows QCBOR about 25%
+larger.  QCBOR encoding is actually smaller, but QCBOR decoding is
+larger. This includes the code to call the library, which is about the
+same for both libraries, and the code linked from the libraries. QCBOR
+is a bit more powerful, so you get value for the extra code brought
+in, especially when decoding more complex protocols.
+
+QCBOR tracks encoding and decoding errors internally so the caller
+doesn't have to check the return code of every call to an encode or
+decode function. In many cases the error check is only needed as the
+last step or an encode or decode. TinyCBOR requires an error check on
+each call.
+
+QCBOR provides a substantial feature that allows searching for data
+items in a map by label. It works for integer and text string labels
+(and at some point byte-string labels). This includes detection of
+items with duplicate labels. This makes the code for decoding CBOR
+simpler, similar to the encoding code and easier to read. TinyCBOR
+supports search by string, but no integer, nor duplicate detection.
+
+QCBOR provides explicit support many of the registered CBOR tags. For
+example, QCBOR supports big numbers and decimal fractions including
+their conversion to floats, uint64_t and such.
+
+Generally, QCBOR supports safe conversion of most CBOR number formats
+into number formats supported in C. For example, a data item can be
+fetched and converted to a C uint64_t whether the input CBOR is an
+unsigned 64-bit integer, signed 64-bit integer, floating-point number,
+big number, decimal fraction or a big float. The conversion is
+performed with full proper error detection of overflow and underflow.
+
+QCBOR has a special feature for decoding byte-string wrapped CBOR. It
+treats this similar to entering an array with one item. This is
+particularly use for CBOR protocols like COSE that make use of
+byte-string wrapping.  The implementation of these protocols is
+simpler and uses less memory.
+
+QCBOR's test suite is written in the same portable C that QCBOR is
+where TinyCBOR requires Qt for its test. QCBOR's test suite is
+designed to be able to run on small embedded devices the same as
+QCBOR.
+
+## Code Status
+
+The official current release is version 1.4.1 Changes over the last few
+years have been only minor bug fixes, minor feature additions and
+documentation improvements. QCBOR 1.x is highly stable.
+
+Work on some larger feature additions is ongoing in "dev" branch.
+This includes more explicit support for preferred serialization and
+CDE (CBOR Deterministic Encoding).  It will eventually be release as
+QCBOR 2.x.
+
+QCBOR was originally developed by Qualcomm. It was [open sourced
+through CAF](https://source.codeaurora.org/quic/QCBOR/QCBOR/) with a
+permissive Linux license, September 2018 (thanks Qualcomm!).
+
+## Building
+
+There is a simple makefile for the UNIX style command line binary that
+compiles everything to run the tests. CMake is also available, please read
+the "Building with CMake" section for more information.
+
+These eleven files, the contents of the src and inc directories, make
+up the entire implementation.
+
+* inc
+   * UsefulBuf.h
+   * qcbor_private.h
+   * qcbor_common.h
+   * qcbor_encode.h
+   * qcbor_decode.h
+   * qcbor_spiffy_decode.h
+* src
+   * UsefulBuf.c
+   * qcbor_encode.c
+   * qcbor_decode.c
+   * ieee754.h
+   * ieee754.c
+
+For most use cases you should just be able to add them to your
+project. Hopefully the easy portability of this implementation makes
+this work straight away, whatever your development environment is.
+
+The test directory includes the tests that are nearly as portable as
+the main implementation.  If your development environment doesn't
+support UNIX style command line and make, you should be able to make a
+simple project and add the test files to it.  Then just call
+RunTests() to invoke them all.
+
+While this code will run fine without configuration, there are several
+C pre processor macros that can be #defined in order to:
+
+ * use a more efficient implementation
+ * to reduce code size
+ * to improve performance (a little)
+ * remove features to reduce code size
+
+See the comment sections on "Configuration" in inc/UsefulBuf.h and
+the pre processor defines that start with QCBOR_DISABLE_XXX.
+
+### Building with CMake
+
+CMake can also be used to build QCBOR and the test application. Having the root
+`CMakeLists.txt` file, QCBOR can be easily integrated with your project's
+existing CMake environment. The result of the build process is a static library,
+to build a shared library instead you must add the
+`-DBUILD_SHARED_LIBS=ON` option at the CMake configuration step.
+The tests can be built into a simple command line application to run them as it
+was mentioned before; or it can be built as a library to be integrated with your
+development environment.
+The `BUILD_QCBOR_TEST` CMake option can be used for building the tests, it can
+have three values: `APP`, `LIB` or `OFF` (default, test are not included in the
+build).
+
+Building the QCBOR library:
+
+```bash
+cd <QCBOR_base_folder>
+# Configuring the project and generating a native build system
+cmake -S . -B <build_folder>
+# Building the project
+cmake --build <build_folder>
+```
+
+Building and running the QCBOR test app:
+```bash
+cd <QCBOR_base_folder>
+# Configuring the project and generating a native build system
+cmake -S . -B <build_folder> -DBUILD_QCBOR_TEST=APP
+# Building the project
+cmake --build <build_folder>
+# Running the test app
+.<build_folder>/test/qcbortest
+```
+
+To enable all the compiler warnings that are used in the QCBOR release process
+you can use the `BUILD_QCBOR_WARN` option at the CMake configuration step:
+```bash
+cmake -S . -B <build_folder> -DBUILD_QCBOR_WARN=ON
+```
+
+### Floating Point Support & Configuration
+
+By default, all QCBOR floating-point features are enabled:
+
+* Encoding and decoding of basic float types, single and double-precision
+* Encoding and decoding of half-precision with conversion to/from single
+  and double-precision
+* Preferred serialization of floating-point
+* Floating point dates
+* Methods that can convert big numbers, decimal fractions and other numbers
+  to/from floating-point
+
+If full floating-point is not needed, the following #defines can be
+used to reduce object code size and dependency.
+
+See discussion in qcbor_encode.h for other details.
+
+#### #define QCBOR_DISABLE_FLOAT_HW_USE
+
+This removes dependency on:
+
+* Floating-point hardware and floating-point instructions
+* `<math.h>` and `<fenv.h>`
+* The math library (libm, -lm)
+
+For most limited environments, this removes enough floating-point
+dependencies to be able to compile and run QCBOR.
+
+Note that this does not remove use of the types double and float from
+QCBOR, but it limits QCBOR's use of them to converting the encoded
+byte stream to them and copying them. Converting and copying them
+usually don't require any hardware, libraries or includes. The C
+compiler takes care of it on its own.
+
+QCBOR uses its own implementation of half-precision float-pointing
+that doesn't depend on math libraries. It uses masks and shifts
+instead. Thus, even with this define, half-precision encoding and
+decoding works.
+
+When this is defined, the QCBOR functionality lost is minimal and only
+for decoding:
+
+* Decoding floating-point format dates are not handled
+* There is no conversion between floats and integers when decoding. For
+  example, QCBORDecode_GetUInt64ConvertAll() will be unable to convert
+  to and from float-point.
+* Floats will be unconverted to double when decoding.
+
+No interfaces are disabled or removed with this define.  If input that
+requires floating-point conversion or functions are called that
+request floating-point conversion, an error code like
+`QCBOR_ERR_HW_FLOAT_DISABLED` will be returned.
+
+This saves only a small amount of object code. The primary purpose for
+defining this is to remove dependency on floating point hardware and
+libraries.
+
+#### #define QCBOR_DISABLE_PREFERRED_FLOAT
+
+This eliminates support for half-precision
+and CBOR preferred serialization by disabling
+QCBOR's shift and mask based implementation of
+half-precision floating-point.
+
+With this defined, single and double-precision floating-point
+numbers can still be encoded and decoded. Conversion
+of floating-point to and from integers, big numbers and
+such is also supported. Floating-point dates are still
+supported.
+
+The primary reason to define this is to save object code.
+Roughly 900 bytes are saved, though about half of this
+can be saved just by not calling any functions that
+encode floating-point numbers.
+
+#### #define USEFULBUF_DISABLE_ALL_FLOAT
+
+This eliminates floating point support completely (along with related function
+headers). This is useful if the compiler options deny the usage of floating
+point operations completely, and the usage soft floating point ABI is not
+possible.
+
+#### Compiler options
+
+Compilers support a number of options that control
+which float-point related code is generated. For example,
+it is usually possible to give options to the compiler to avoid all
+floating-point hardware and instructions, to use software
+and replacement libraries instead. These are usually
+bigger and slower, but these options may still be useful
+in getting QCBOR to run in some environments in
+combination with `QCBOR_DISABLE_FLOAT_HW_USE`.
+In particular, `-mfloat-abi=soft`, disables use of
+ hardware instructions for the float and double
+ types in C for some architectures.
+
+#### CMake options
+
+If you are using CMake, it can also be used to configure the floating-point
+support. These options can be enabled by adding them to the CMake configuration
+step and setting their value to 'ON' (True). The following table shows the
+available options and the associated #defines.
+
+    | CMake option                      | #define                       |
+    |-----------------------------------|-------------------------------|
+    | QCBOR_OPT_DISABLE_FLOAT_HW_USE    | QCBOR_DISABLE_FLOAT_HW_USE    |
+    | QCBOR_OPT_DISABLE_FLOAT_PREFERRED | QCBOR_DISABLE_PREFERRED_FLOAT |
+    | QCBOR_OPT_DISABLE_FLOAT_ALL       | USEFULBUF_DISABLE_ALL_FLOAT   |
+
+## Code Size
+
+These are approximate sizes on a 64-bit x86 CPU with the -Os optimization.
+All QCBOR_DISABLE_XXX are set and compiler stack frame checking is disabled
+for smallest but not for largest. Smallest is the library functions for a
+protocol with strings, integers, arrays, maps and Booleans, but not floats
+and standard tag types.
+
+    |               | smallest | largest |
+    |---------------|----------|---------|
+    | encode only   |      850 |    2200 |
+    | decode only   |     1550 |   13300 |
+    | combined      |     2500 |   15500 |
+
+ From the table above, one can see that the amount of code pulled in
+ from the QCBOR library varies a lot, ranging from 1KB to 15KB.  The
+ main factor is the number of QCBOR functions called and
+ which ones they are. QCBOR minimizes internal
+ interdependency so only code necessary for the called functions is
+ brought in.
+
+ Encoding is simpler and smaller. An encode-only implementation may
+ bring in only 1KB of code.
+
+ Encoding of floating-point brings in a little more code as does
+ encoding of tagged types and encoding of bstr wrapping.
+
+ Basic decoding using QCBORDecode_GetNext() brings in 3KB.
+
+ Use of the supplied MemPool by calling  QCBORDecode_SetMemPool() to
+ setup to decode indefinite-length strings adds 0.5KB.
+
+ Basic use of spiffy decode to brings in about 3KB. Using more spiffy
+ decode functions, such as those for tagged types bstr wrapping brings
+ in more code.
+
+ Finally, use of all of the integer conversion functions will bring in
+ about 5KB, though you can use the simpler ones like
+ QCBORDecode_GetInt64() without bringing in very much code.
+
+ In addition to using fewer QCBOR functions, the following are some
+ ways to make the code smaller.
+
+ The gcc compiler output is usually smaller than llvm because stack
+ guards are off by default (be sure you actually have gcc and not llvm
+ installed to be invoked by the gcc command). You can also turn off
+ stack gaurds with llvm. It is safe to turn off stack gaurds with this
+ code because Usefulbuf provides similar defenses and this code was
+ carefully written to be defensive.
+
+ If QCBOR is installed as a shared library, then of course only one
+ copy of the code is in memory no matter how many applications use it.
+
+### Disabling Features
+
+Here's the list of all features that can be disabled to save object
+code. The amount saved is an approximation.
+
+    | #define                                 | Saves |
+    | ----------------------------------------| ------|
+    | QCBOR_DISABLE_ENCODE_USAGE_GUARDS       |   150 |
+    | QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS |   400 |
+    | QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS  |   200 |
+    | QCBOR_DISABLE_UNCOMMON_TAGS             |   100 |
+    | QCBOR_DISABLE_EXP_AND_MANTISSA          |   400 |
+    | QCBOR_DISABLE_PREFERRED_FLOAT           |   900 |
+    | QCBOR_DISABLE_FLOAT_HW_USE              |    50 |
+    | QCBOR_DISABLE_TAGS                      |   400 |
+    | QCBOR_DISABLE_NON_INTEGER_LABELS        |   140 |
+    | USEFULBUF_DISABLE_ALL_FLOAT             |   950 |
+
+QCBOR_DISABLE_ENCODE_USAGE_GUARDS affects encoding only.  It doesn't
+disable any encoding features, just some error checking.  Disable it
+when you are confident that an encoding implementation is complete and
+correct.
+
+Indefinite lengths are a feature of CBOR that makes encoding simpler
+and the decoding more complex. They allow the encoder to not have to
+know the length of a string, map or array when they start encoding
+it. Their main use is when encoding has to be done on a very
+constrained device.  Conversely when decoding on a very constrained
+device, it is good to prohibit use of indefinite lengths so the
+decoder can be smaller.
+
+The QCBOR decode API processes both definite and indefinite lengths
+with the same API, except to decode indefinite-length strings a
+storage allocator must be configured.
+
+To reduce the size of the decoder define
+QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS particularly if you are not
+configuring a storage allocator.
+
+Further reduction can be by defining
+QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS which will result in an error
+when an indefinite-length map or array arrives for decoding.
+
+QCBOR_DISABLE_UNCOMMON_TAGS disables the decoding of explicit tags for
+base 64, regex, UUID and MIME data. This just disables the automatic
+recognition of these from a major type 6 tag.
+
+QCBOR_DISABLE_EXP_AND_MANTISSA disables the decoding of decimal
+fractions and big floats.
+
+QCBOR_DISABLE_TAGS disables all decoding of CBOR tags. If the input has
+a single tag, the error is unrecoverable so it is suitable only for protocols that
+have no tags. "Borrowed" tag content formats (e.g. an epoch-based date
+without the tag number), can still be processed.
+
+QCBOR_DISABLE_NON_INTEGER_LABELS causes any label that doesn't
+fit in an int64_t to result in a QCBOR_ERR_MAP_LABEL_TYPE error.
+This also disables QCBOR_DECODE_MODE_MAP_AS_ARRAY and 
+QCBOR_DECODE_MODE_MAP_STRINGS_ONLY. It is fairly common for CBOR-based
+protocols to use only small integers as labels.
+
+See the discussion above on floating-point.
+
+ ### Size of spiffy decode
+
+ When creating a decode implementation, there is a choice of whether
+ or not to use spiffy decode features or to just use
+ QCBORDecode_GetNext().
+
+ The implementation using spiffy decode will be simpler resulting in
+ the calling code being smaller, but the amount of code brought in
+ from the QCBOR library will be larger. Basic use of spiffy decode
+ brings in about 2KB of object code.  If object code size is not a
+ concern, then it is probably better to use spiffy decode because it
+ is less work, there is less complexity and less testing to worry
+ about.
+
+ If code size is a concern, then use of QCBORDecode_GetNext() will
+ probably result in smaller overall code size for simpler CBOR
+ protocols. However, if the CBOR protocol is complex then use of
+ spiffy decode may reduce overall code size.  An example of a complex
+ protocol is one that involves decoding a lot of maps or maps that
+ have many data items in them.  The overall code may be smaller
+ because the general purpose spiffy decode map processor is the one
+ used for all the maps.
+
+
+## Other Software Using QCBOR
+
+* [t_cose](https://github.com/laurencelundblade/t_cose) implements enough of
+[COSE, RFC 8152](https://tools.ietf.org/html/rfc8152) to support
+[CBOR Web Token (CWT)](https://tools.ietf.org/html/rfc8392) and
+[Entity Attestation Token (EAT)](https://tools.ietf.org/html/draft-ietf-rats-eat-06).
+Specifically it supports signing and verification of the COSE_Sign1 message.
+
+* [ctoken](https://github.com/laurencelundblade/ctoken) is an implementation of
+EAT and CWT.
+
+## Credits
+* Ganesh Kanike for porting to QSEE
+* Mark Bapst for sponsorship and release as open source by Qualcomm
+* Sachin Sharma for release through CAF
+* Tamas Ban for porting to TF-M and 32-bit ARM
+* Michael Eckel for Makefile improvements
+* Jan Jongboom for indefinite length encoding
+* Peter Uiterwijk for error strings and other
+* Michael Richarson for CI set up and fixing some compiler warnings
+* Máté Tóth-Pál for float-point disabling and other
+* Dave Thaler for portability to Windows
+
+## Copyright and License
+
+QCBOR is available under what is essentially the 3-Clause BSD License.
+
+Files created inside Qualcomm and open-sourced through CAF (The Code
+Aurora Forum) have a slightly modified 3-Clause BSD License. The
+modification additionally disclaims NON-INFRINGEMENT.
+
+Files created after release to CAF use the standard 3-Clause BSD
+License with no modification. These files have the SPDX license
+identifier, "SPDX-License-Identifier: BSD-3-Clause" in them.
+
+### BSD-3-Clause license
+
+* Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+### Copyright for this README
+
+Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
+Copyright (c) 2021-2023, Arm Limited. All rights reserved.
diff --git a/core/lib/qcbor/inc/UsefulBuf.h b/core/lib/qcbor/inc/UsefulBuf.h
new file mode 100644
index 0000000000000000000000000000000000000000..d2eda83d2c5adbf666b99b82ba35c011569fea29
--- /dev/null
+++ b/core/lib/qcbor/inc/UsefulBuf.h
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: BSD-3-Clause
+#include "qcbor/UsefulBuf.h"
diff --git a/core/lib/qcbor/inc/qcbor.h b/core/lib/qcbor/inc/qcbor.h
new file mode 100644
index 0000000000000000000000000000000000000000..760a9fa4aed023bec1e75d96ab12ab304bc1c899
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor.h
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: BSD-3-Clause
+#include "qcbor/qcbor.h"
diff --git a/core/lib/qcbor/inc/qcbor/UsefulBuf.h b/core/lib/qcbor/inc/qcbor/UsefulBuf.h
new file mode 100644
index 0000000000000000000000000000000000000000..009ae82d37bc2fbf683c7bcc833458afd264688f
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/UsefulBuf.h
@@ -0,0 +1,2507 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* =========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+/*============================================================================
+ FILE:  UsefulBuf.h
+
+ DESCRIPTION:  General purpose input and output buffers
+
+ EDIT HISTORY FOR FILE:
+
+ This section contains comments describing changes made to the module.
+ Notice that changes are listed in reverse chronological order.
+
+ when         who             what, where, why
+ --------     ----            --------------------------------------------------
+ 10/05/2024   llundblade      Add Xxx_OffsetToPointer.
+ 19/12/2022   llundblade      Document that adding empty data is allowed.
+ 4/11/2022    llundblade      Add GetOutPlace and Advance to UsefulOutBuf.
+ 9/21/2021    llundbla        Clarify UsefulOutBuf size calculation mode
+ 8/8/2021     dthaler/llundbla Work with C++ without compiler extensions
+ 5/11/2021    llundblade      Improve comments and comment formatting.
+ 3/6/2021     mcr/llundblade  Fix warnings related to --Wcast-qual
+ 2/17/2021    llundblade      Add method to go from a pointer to an offset.
+ 1/25/2020    llundblade      Add some casts so static anlyzers don't complain.
+ 5/21/2019    llundblade      #define configs for efficient endianness handling.
+ 5/16/2019    llundblade      Add UsefulOutBuf_IsBufferNULL().
+ 3/23/2019    llundblade      Big documentation & style update. No interface
+                              change.
+ 3/6/2019     llundblade      Add UsefulBuf_IsValue()
+ 12/17/2018   llundblade      Remove const from UsefulBuf and UsefulBufC .len
+ 12/13/2018   llundblade      Documentation improvements
+ 09/18/2018   llundblade      Cleaner distinction between UsefulBuf and
+                              UsefulBufC.
+ 02/02/18     llundbla        Full support for integers in and out; fix pointer
+                              alignment bug. Incompatible change: integers
+                              in/out are now in network byte order.
+ 08/12/17     llundbla        Added UsefulOutBuf_AtStart and UsefulBuf_Find
+ 06/27/17     llundbla        Fix UsefulBuf_Compare() bug. Only affected
+                              comparison for < or > for unequal length buffers.
+                              Added UsefulBuf_Set() function.
+ 05/30/17     llundbla        Functions for NULL UsefulBufs and const / unconst
+ 11/13/16     llundbla        Initial Version.
+
+ =============================================================================*/
+
+#ifndef _UsefulBuf_h
+#define _UsefulBuf_h
+
+
+/*
+ * Endianness Configuration
+ *
+ * This code is written so it will work correctly on big- and
+ * little-endian CPUs without configuration or any auto-detection of
+ * endianness. All code here will run correctly regardless of the
+ * endianness of the CPU it is running on.
+ *
+ * There are four C preprocessor macros that can be set with #define
+ * to explicitly configure endianness handling. Setting them can
+ * reduce code size a little and improve efficiency a little.
+ *
+ * Note that most of QCBOR is unaffected by this configuration.  Its
+ * endianness handling is integrated with the code that handles
+ * alignment and preferred serialization. This configuration does
+ * affect QCBOR's (planned) implementation of integer arrays (tagged
+ * arrays) and use of the functions here to serialize or deserialize
+ * integers and floating-point values.
+ *
+ * Following is the recipe for configuring the endianness-related
+ * #defines.
+ *
+ * The first option is to not define anything. This will work fine
+ * with all CPUs, OS's and compilers. The code for encoding integers
+ * may be a little larger and slower.
+ *
+ * If your CPU is big-endian then define
+ * USEFULBUF_CONFIG_BIG_ENDIAN. This will give the most efficient code
+ * for big-endian CPUs. It will be small and efficient because there
+ * will be no byte swapping.
+ *
+ * Try defining USEFULBUF_CONFIG_HTON. This will work on most CPUs,
+ * OS's and compilers, but not all. On big-endian CPUs this should
+ * give the most efficient code, the same as
+ * USEFULBUF_CONFIG_BIG_ENDIAN does. On little-endian CPUs it should
+ * call the system-defined byte swapping method which is presumably
+ * implemented efficiently. In some cases, this will be a dedicated
+ * byte swap instruction like Intel's bswap.
+ *
+ * If USEFULBUF_CONFIG_HTON works and you know your CPU is
+ * little-endian, it is also good to define
+ * USEFULBUF_CONFIG_LITTLE_ENDIAN.
+ *
+ * if USEFULBUF_CONFIG_HTON doesn't work and you know your system is
+ * little-endian, try defining both USEFULBUF_CONFIG_LITTLE_ENDIAN and
+ * USEFULBUF_CONFIG_BSWAP. This should call the most efficient
+ * system-defined byte swap method. However, note
+ * https://hardwarebug.org/2010/01/14/beware-the-builtins/.  Perhaps
+ * this is fixed now. Often hton() and ntoh() will call the built-in
+ * __builtin_bswapXX()() function, so this size issue could affect
+ * USEFULBUF_CONFIG_HTON.
+ *
+ * Last, run the tests. They must all pass.
+ *
+ * These #define config options affect the inline implementation of
+ * UsefulOutBuf_InsertUint64() and UsefulInputBuf_GetUint64().  They
+ * also affect the 16-, 32-bit, float and double versions of these
+ * functions. Since they are inline, the size effect is not in the
+ * UsefulBuf object code, but in the calling code.
+ *
+ * Summary:
+ *   USEFULBUF_CONFIG_BIG_ENDIAN -- Force configuration to big-endian.
+ *   USEFULBUF_CONFIG_LITTLE_ENDIAN -- Force to little-endian.
+ *   USEFULBUF_CONFIG_HTON -- Use hton(), htonl(), ntohl()... to
+ *     handle big and little-endian with system option.
+ *   USEFULBUF_CONFIG_BSWAP -- With USEFULBUF_CONFIG_LITTLE_ENDIAN,
+ *     use __builtin_bswapXX().
+ *
+ * It is possible to run this code in environments where using floating point is
+ * not allowed. Defining USEFULBUF_DISABLE_ALL_FLOAT will disable all the code
+ * that is related to handling floating point types, along with related
+ * interfaces. This makes it possible to compile the code with the compile
+ * option -mgeneral-regs-only.
+ */
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) && defined(USEFULBUF_CONFIG_LITTLE_ENDIAN)
+#error "Cannot define both USEFULBUF_CONFIG_BIG_ENDIAN and USEFULBUF_CONFIG_LITTLE_ENDIAN"
+#endif
+
+
+#include <stdint.h> /* for uint8_t, uint16_t.... */
+#include <string.h> /* for strlen, memcpy, memmove, memset */
+#include <stddef.h> /* for size_t */
+
+
+#ifdef USEFULBUF_CONFIG_HTON
+#include <arpa/inet.h> /* for htons, htonl, htonll, ntohs... */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* Keep editor indention formatting happy */
+#endif
+#endif
+
+/**
+ * @file UsefulBuf.h
+ *
+ * The goal of this code is to make buffer and pointer manipulation
+ * easier and safer when working with binary data.
+ *
+ * The @ref UsefulBuf, @ref UsefulOutBuf and @ref UsefulInputBuf
+ * structures are used to represent buffers rather than ad hoc
+ * pointers and lengths.
+ *
+ * With these it is possible to write code that does little or no
+ * direct pointer manipulation for copying and formatting data. For
+ * example, the QCBOR encoder was written using these and has less
+ * pointer manipulation.
+ *
+ * While it is true that object code using these functions will be a
+ * little larger and slower than a white-knuckle clever use of
+ * pointers might be, but not by that much or enough to have an effect
+ * for most use cases. For security-oriented code this is highly
+ * worthwhile. Clarity, simplicity, reviewability and are more
+ * important.
+ *
+ * There are some extra sanity and double checks in this code to help
+ * catch coding errors and simple memory corruption. They are helpful,
+ * but not a substitute for proper code review, input validation and
+ * such.
+ *
+ * This code consists of a lot of inline functions and a few that are
+ * not.  It should not generate very much object code, especially with
+ * the optimizer turned up to @c -Os or @c -O3.
+ */
+
+
+/**
+ * @ref UsefulBufC and @ref UsefulBuf are simple data structures to
+ * hold a pointer and length for binary data.  In C99 this data
+ * structure can be passed on the stack making a lot of code cleaner
+ * than carrying around a pointer and length as two parameters.
+ *
+ * This is also conducive to secure coding practice as the length is
+ * always carried with the pointer and the convention for handling a
+ * pointer and a length is clear.
+ *
+ * While it might be possible to write buffer and pointer code more
+ * efficiently in some use cases, the thought is that unless there is
+ * an extreme need for performance (e.g., you are building a
+ * gigabit-per-second IP router), it is probably better to have
+ * cleaner code you can be most certain about the security of.
+ *
+ * The non-const @ref UsefulBuf is usually used to refer an empty
+ * buffer to be filled in.  The length is the size of the buffer.
+ *
+ * The const @ref UsefulBufC is usually used to refer to some data
+ * that has been filled in. The length is amount of valid data pointed
+ * to.
+ *
+ * A common use mode is to pass a @ref UsefulBuf to a function, the
+ * function puts some data in it, then the function returns a @ref
+ * UsefulBufC refering to the data. The @ref UsefulBuf is a non-const
+ * "in" parameter and the @ref UsefulBufC is a const "out" parameter
+ * so the constness stays correct. There is no single "in,out"
+ * parameter (if there was, it would have to be non-const).  Note that
+ * the pointer returned in the @ref UsefulBufC usually ends up being
+ * the same pointer passed in as a @ref UsefulBuf, though this is not
+ * striclty required.
+ *
+ * A @ref UsefulBuf is null, it has no value, when @c ptr in it is
+ * @c NULL.
+ *
+ * There are functions and macros for the following:
+ *  - Initializing
+ *  - Create initialized const @ref UsefulBufC from compiler literals
+ *  - Create initialized const @ref UsefulBufC from NULL-terminated string
+ *  - Make an empty @ref UsefulBuf on the stack
+ *  - Checking whether a @ref UsefulBuf is null, empty or both
+ *  - Copying, copying with offset, copying head or tail
+ *  - Comparing and finding substrings
+ *
+ * See also @ref UsefulOutBuf. It is a richer structure that has both
+ * the size of the valid data and the size of the buffer.
+ *
+ * @ref UsefulBuf is only 16 or 8 bytes on a 64- or 32-bit machine so
+ * it can go on the stack and be a function parameter or return value.
+ *
+ * Another way to look at it is this. C has the NULL-terminated string
+ * as a means for handling text strings, but no means or convention
+ * for binary strings. Other languages do have such means, Rust, an
+ * efficient compiled language, for example.
+ *
+ * @ref UsefulBuf is kind of like the Useful Pot Pooh gave Eeyore on
+ * his birthday.  Eeyore's balloon fits beautifully, "it goes in and
+ * out like anything".
+ */
+typedef struct q_useful_buf_c {
+    const void *ptr;
+    size_t      len;
+} UsefulBufC;
+
+
+/**
+ * This non-const @ref UsefulBuf is typically used for some allocated
+ * memory that is to be filled in. The @c len is the amount of memory,
+ * not the length of the valid data in the buffer.
+ */
+typedef struct q_useful_buf {
+   void  *ptr;
+   size_t len;
+} UsefulBuf;
+
+
+/**
+ * A null @ref UsefulBufC is one that has no value in the same way a
+ * @c NULL pointer has no value.  A @ref UsefulBufC is @c NULL when
+ * the @c ptr field is @c NULL. It doesn't matter what @c len is.  See
+ * UsefulBuf_IsEmpty() for the distinction between null and empty.
+ */
+/*
+ * NULLUsefulBufC and few other macros have to be
+ * definied differently in C than C++ because there
+ * is no common construct for a literal structure.
+ *
+ * In C compound literals are used.
+ *
+ * In C++ list initalization is used. This only works
+ * in C++11 and later.
+ *
+ * Note that some popular C++ compilers can handle compound
+ * literals with on-by-default extensions, however
+ * this code aims for full correctness with strict
+ * compilers so they are not used.
+ */
+#ifdef __cplusplus
+#define NULLUsefulBufC {NULL, 0}
+#else
+#define NULLUsefulBufC ((UsefulBufC) {NULL, 0})
+#endif
+
+/**
+ * A null @ref UsefulBuf is one that has no memory associated the same
+ * way @c NULL points to nothing. It does not matter what @c len is.
+ **/
+#ifdef __cplusplus
+#define NULLUsefulBuf  {NULL, 0}
+#else
+#define NULLUsefulBuf  ((UsefulBuf) {NULL, 0})
+#endif
+
+
+/**
+ * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or not.
+ *
+ * @param[in] UB The UsefulBuf to check.
+ *
+ * @return 1 if it is @ref NULLUsefulBuf, 0 if not.
+ */
+static inline int UsefulBuf_IsNULL(UsefulBuf UB);
+
+
+/**
+ * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or not.
+ *
+ * @param[in] UB The @ref UsefulBufC to check.
+ *
+ * @return 1 if it is @c NULLUsefulBufC, 0 if not.
+ */
+static inline int UsefulBuf_IsNULLC(UsefulBufC UB);
+
+
+/**
+ * @brief Check if a @ref UsefulBuf is empty or not.
+ *
+ * @param[in] UB The @ref UsefulBuf to check.
+ *
+ * @return 1 if it is empty, 0 if not.
+ *
+ * An "empty" @ref UsefulBuf is one that has a value and can be
+ * considered to be set, but that value is of zero length.  It is
+ * empty when @c len is zero. It doesn't matter what the @c ptr is.
+ *
+ * Many uses will not need to clearly distinguish a @c NULL @ref
+ * UsefulBuf from an empty one and can have the @c ptr @c NULL and the
+ * @c len 0.  However if a use of @ref UsefulBuf needs to make a
+ * distinction then @c ptr should not be @c NULL when the @ref
+ * UsefulBuf is considered empty, but not @c NULL.
+ */
+static inline int UsefulBuf_IsEmpty(UsefulBuf UB);
+
+
+/**
+ * @brief Check if a @ref UsefulBufC is empty or not.
+ *
+ * @param[in] UB The @ref UsefulBufC to check.
+ *
+ * @return 1 if it is empty, 0 if not.
+ */
+static inline int UsefulBuf_IsEmptyC(UsefulBufC UB);
+
+
+/**
+ * @brief Check if a @ref UsefulBuf is @ref NULLUsefulBuf or empty.
+ *
+ * @param[in] UB The @ref UsefulBuf to check.
+ *
+ * @return 1 if it is either @ref NULLUsefulBuf or empty, 0 if not.
+ */
+static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB);
+
+
+/**
+ * @brief Check if a @ref UsefulBufC is @ref NULLUsefulBufC or empty.
+ *
+ * @param[in] UB The @ref UsefulBufC to check.
+ *
+ * @return 1 if it is either @ref NULLUsefulBufC or empty, 0 if not.
+ */
+static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB);
+
+
+/**
+ * @brief Convert a non-const @ref UsefulBuf to a const @ref UsefulBufC.
+ *
+ * @param[in] UB The @ref UsefulBuf to convert.
+ *
+ * @return A @ref UsefulBufC struct.
+ */
+static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB);
+
+
+/**
+ * @brief Convert a const @ref UsefulBufC to a non-const @ref UsefulBuf.
+ *
+ * @param[in] UBC The @ref UsefulBuf to convert.
+ *
+ * @return A non-const @ref UsefulBuf struct.
+ *
+ * Use of this is not necessary for the intended use mode of @ref
+ * UsefulBufC and @ref UsefulBuf.  In that mode, the @ref UsefulBuf is
+ * created to describe a buffer that has not had any data put in
+ * it. Then the data is put in it.  Then a @ref UsefulBufC is create
+ * to describe the part with the data in it. This goes from non-const
+ * to const, so this function is not needed.
+ *
+ * If the -Wcast-qual warning is enabled, this function can be used to
+ * avoid that warning.
+ */
+static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC);
+
+
+/**
+ * Convert a literal string to a @ref UsefulBufC.
+ *
+ * @c szString must be a literal string that @c sizeof() works on.
+ * This is better for literal strings than UsefulBuf_FromSZ() because
+ * it generates less code. It will not work on non-literal strings.
+ *
+ * The terminating \0 (NULL) is NOT included in the length!
+ */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_SZ_LITERAL(szString)  {(szString), sizeof(szString)-1}
+#else
+#define UsefulBuf_FROM_SZ_LITERAL(szString) \
+    ((UsefulBufC) {(szString), sizeof(szString)-1})
+#endif
+
+
+/**
+ * Convert a literal byte array to a @ref UsefulBufC.
+ *
+ * @c pBytes must be a literal string that @c sizeof() works on.  It
+ * will not work on non-literal arrays.
+ */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)  {(pBytes), sizeof(pBytes)}
+#else
+#define UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes) \
+   ((UsefulBufC) {(pBytes), sizeof(pBytes)})
+#endif
+
+/**
+ * Make an automatic variable named @c name of type @ref UsefulBuf and
+ * point it to a stack variable of the given @c size.
+ */
+#define  UsefulBuf_MAKE_STACK_UB(name, size) \
+    uint8_t    __pBuf##name[(size)];\
+    UsefulBuf  name = {__pBuf##name , sizeof( __pBuf##name )}
+
+
+/**
+ * Make a byte array in to a @ref UsefulBuf. This is usually used on
+ * stack variables or static variables.  Also see @ref
+ * UsefulBuf_MAKE_STACK_UB.
+ */
+#ifdef __cplusplus
+#define UsefulBuf_FROM_BYTE_ARRAY(pBytes)  {(pBytes), sizeof(pBytes)}
+#else
+#define UsefulBuf_FROM_BYTE_ARRAY(pBytes) \
+   ((UsefulBuf) {(pBytes), sizeof(pBytes)})
+#endif
+
+
+/**
+ * @brief Convert a NULL-terminated string to a @ref UsefulBufC.
+ *
+ * @param[in] szString The string to convert.
+ *
+ * @return A @ref UsefulBufC struct.
+ *
+ * @c UsefulBufC.ptr points to the string so its lifetime must be
+ * maintained.
+ *
+ * The terminating \0 (NULL) is NOT included in the length.
+ */
+static inline UsefulBufC UsefulBuf_FromSZ(const char *szString);
+
+
+/**
+ * @brief Copy one @ref UsefulBuf into another at an offset.
+ *
+ * @param[in] Dest     Destination buffer to copy into.
+ * @param[in] uOffset  The byte offset in @c Dest at which to copy to.
+ * @param[in] Src      The bytes to copy.
+ *
+ * @return Pointer and length of the copy or @ref NULLUsefulBufC.
+ *
+ * This fails and returns @ref NULLUsefulBufC if @c offset is beyond the
+ * size of @c Dest.
+ *
+ * This fails and returns @ref NULLUsefulBufC if the @c Src length
+ * plus @c uOffset is greater than the length of @c Dest.
+ *
+ * The results are undefined if @c Dest and @c Src overlap.
+ *
+ * This assumes that there is valid data in @c Dest up to @c
+ * uOffset. The @ref UsefulBufC returned starts at the beginning of @c
+ * Dest and goes to @c Src.len @c + @c uOffset.
+ */
+UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src);
+
+
+/**
+ * @brief Copy one @ref UsefulBuf into another.
+ *
+ * @param[in] Dest  The destination buffer to copy into.
+ * @param[out] Src  The source to copy from.
+ *
+ * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
+ *         on failure.
+ *
+ * This fails if @c Src.len is greater than @c Dest.len.
+ *
+ * Note that like @c memcpy(), the pointers are not checked and this
+ * will crash rather than return @ref NULLUsefulBufC if they are @c
+ * NULL or invalid.
+ *
+ * The results are undefined if @c Dest and @c Src overlap.
+ */
+static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src);
+
+
+/**
+ * @brief Set all bytes in a @ref UsefulBuf to a value, for example to 0.
+ *
+ * @param[in] pDest  The destination buffer to copy into.
+ * @param[in] value  The value to set the bytes to.
+ *
+ * Note that like @c memset(), the pointer in @c pDest is not checked
+ * and this will crash if @c NULL or invalid.
+ */
+static inline UsefulBufC UsefulBuf_Set(UsefulBuf pDest, uint8_t value);
+
+
+/**
+ * @brief Copy a pointer into a @ref UsefulBuf.
+ *
+ * @param[in,out] Dest  The destination buffer to copy into.
+ * @param[in] ptr       The source to copy from.
+ * @param[in] uLen      Length of the source; amount to copy.
+ *
+ * @return Filled in @ref UsefulBufC on success, @ref NULLUsefulBufC
+ *         on failure.
+ *
+ * This fails and returns @ref NULLUsefulBufC if @c uLen is greater
+ * than @c pDest->len.
+ *
+ * Note that like @c memcpy(), the pointers are not checked and this
+ * will crash, rather than return 1 if they are @c NULL or invalid.
+ */
+static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest,
+                                           const void *ptr,
+                                           size_t uLen);
+
+
+/**
+ *  @brief Returns a truncation of a @ref UsefulBufC.
+ *
+ *  @param[in] UB       The buffer to get the head of.
+ *  @param[in] uAmount  The number of bytes in the head.
+ *
+ *  @return A @ref UsefulBufC that is the head of UB.
+ */
+static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount);
+
+
+/**
+ * @brief  Returns bytes from the end of a @ref UsefulBufC.
+ *
+ * @param[in] UB       The buffer to get the tail of.
+ * @param[in] uAmount  The offset from the start where the tail is to begin.
+ *
+ * @return A @ref UsefulBufC that is the tail of @c UB or @ref NULLUsefulBufC
+ *         if @c uAmount is greater than the length of the @ref UsefulBufC.
+ *
+ * If @c UB.ptr is @c NULL, but @c UB.len is not zero, then the result will
+ * be a @ref UsefulBufC with a @c NULL @c ptr and @c len with the length
+ * of the tail.
+ */
+static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount);
+
+
+/**
+ * @brief Compare one @ref UsefulBufC to another.
+ *
+ * @param[in] UB1  The first buffer to compare.
+ * @param[in] UB2  The second buffer to compare.
+ *
+ * @return 0, positive or negative value.
+ *
+ * Returns a negative value if @c UB1 if is less than @c UB2. @c UB1 is
+ * less than @c UB2 if it is shorter or the first byte that is not the
+ * same is less.
+ *
+ * Returns 0 if the inputs are the same.
+ *
+ * Returns a positive value if @c UB2 is less than @c UB1.
+ *
+ * All that is of significance is that the result is positive, negative
+ * or 0. (This doesn't return the difference between the first
+ * non-matching byte like @c memcmp() ).
+ */
+int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2);
+
+
+/**
+ * @brief Find first byte that is not a particular byte value.
+ *
+ * @param[in] UB     The destination buffer for byte comparison.
+ * @param[in] uValue The byte value to compare to.
+ *
+ * @return  Offset of first byte that isn't @c uValue or
+ *          @c SIZE_MAX if all bytes are @c uValue.
+ *
+ * Note that unlike most comparison functions, 0
+ * does not indicate a successful comparison, so the
+ * test for match is:
+ *
+ *      UsefulBuf_IsValue(...) == SIZE_MAX
+ *
+ * If @c UB is null or empty, there is no match
+ * and 0 is returned.
+ */
+size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue);
+
+
+/**
+ * @brief Find one @ref UsefulBufC in another.
+ *
+ * @param[in] BytesToSearch  Buffer to search through.
+ * @param[in] BytesToFind    Buffer with bytes to be found.
+ *
+ * @return Position of found bytes or @c SIZE_MAX if not found.
+ */
+size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind);
+
+
+/**
+ * @brief Convert a pointer to an offset with bounds checking.
+ *
+ * @param[in] UB  A UsefulBuf.
+ * @param[in] p   Pointer to convert to offset.
+ *
+ * @return SIZE_MAX if @c p is out of range, the byte offset if not.
+*/
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p);
+
+
+/**
+ * @brief Convert an offset to a pointer with bounds checking.
+ *
+ * @param[in] UB       A UsefulBuf.
+ * @param[in] uOffset  Offset in @c pUInBuf.
+ *
+ * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
+ */
+static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset);
+
+
+#ifndef USEFULBUF_DISABLE_DEPRECATED
+/** Deprecated macro; use @ref UsefulBuf_FROM_SZ_LITERAL instead */
+#define SZLiteralToUsefulBufC(szString)  UsefulBuf_FROM_SZ_LITERAL(szString)
+
+/** Deprecated macro; use UsefulBuf_MAKE_STACK_UB instead */
+#define  MakeUsefulBufOnStack(name, size) \
+    uint8_t    __pBuf##name[(size)];\
+    UsefulBuf  name = {__pBuf##name , sizeof( __pBuf##name )}
+
+/** Deprecated macro; use @ref UsefulBuf_FROM_BYTE_ARRAY_LITERAL instead */
+#define ByteArrayLiteralToUsefulBufC(pBytes) \
+   UsefulBuf_FROM_BYTE_ARRAY_LITERAL(pBytes)
+
+/** Deprecated function; use UsefulBuf_Unconst() instead */
+static inline UsefulBuf UsefulBufC_Unconst(const UsefulBufC UBC)
+{
+   UsefulBuf UB;
+
+   /* See UsefulBuf_Unconst() implementation for comment */
+   UB.ptr = (void *)(uintptr_t)UBC.ptr;
+
+   UB.len = UBC.len;
+
+   return UB;
+}
+#endif /* USEFULBUF_DISABLE_DEPRECATED */
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Copy a @c float to a @c uint32_t.
+ *
+ * @param[in] f  Float value to copy.
+ *
+ * @return  A @c uint32_t with the float bits.
+ *
+ * Convenience function to avoid type punning, compiler warnings and
+ * such. The optimizer usually reduces this to a simple assignment.  This
+ * is a crusty corner of C.
+ */
+static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f);
+
+
+/**
+ * @brief Copy a @c double to a @c uint64_t.
+ *
+ * @param[in] d  Double value to copy.
+ *
+ * @return  A @c uint64_t with the double bits.
+ *
+ * Convenience function to avoid type punning, compiler warnings and
+ * such. The optimizer usually reduces this to a simple assignment.  This
+ * is a crusty corner of C.
+ */
+static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d);
+
+
+/**
+ * @brief Copy a @c uint32_t to a @c float.
+ *
+ * @param[in] u32  Integer value to copy.
+ *
+ * @return  The value as a @c float.
+ *
+ * Convenience function to avoid type punning, compiler warnings and
+ * such. The optimizer usually reduces this to a simple assignment.  This
+ * is a crusty corner of C.
+ */
+static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32);
+
+
+/**
+ * @brief Copy a @c uint64_t to a @c double.
+ *
+ * @param[in] u64  Integer value to copy.
+ *
+ * @return  The value as a @c double.
+ *
+ * Convenience function to avoid type punning, compiler warnings and
+ * such. The optimizer usually reduces this to a simple assignment.  This
+ * is a crusty corner of C.
+ */
+static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+/**
+ * UsefulOutBuf is a structure and functions (an object) for
+ * serializing data into a buffer to encode for a network protocol or
+ * write data to a file.
+ *
+ * The main idea is that all the pointer manipulation is performed by
+ * @ref UsefulOutBuf functions so the caller doesn't have to do any
+ * pointer manipulation.  The pointer manipulation is centralized.
+ * This code has been reviewed and written carefully so it
+ * spares the caller of much of this work and results in safer code
+ * with less effort.
+ *
+ * The @ref UsefulOutBuf methods that add data to the output buffer
+ * always check the length and will never write off the end of the
+ * output buffer. If an attempt to add data that will not fit is made,
+ * an internal error flag will be set and further attempts to add data
+ * will not do anything.
+ *
+ * There is no way to ever write off the end of that buffer when
+ * calling the @c UsefulOutBuf_AddXxx() and
+ * @c UsefulOutBuf_InsertXxx() functions.
+ *
+ * The functions to add data do not report success of failure. The
+ * caller only needs to check for an error in the final call, either
+ * UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to get the
+ * result. This makes the calling code cleaner.
+ *
+ * There is a utility function to get the error status anytime along
+ * the way for a special circumstance. There are functions to see how
+ * much room is left and see if some data will fit too, but their use
+ * is generally unnecessary.
+ *
+ * The general call flow is:
+ *
+ *    - Initialize by calling @ref UsefulOutBuf_Init(). The output
+ *      buffer given to it can be from the heap, stack or
+ *      otherwise. @ref UsefulOutBuf_MakeOnStack is a convenience
+ *      macro that makes a buffer on the stack and initializes it.
+ *
+ *    - Call methods like UsefulOutBuf_InsertString(),
+ *      UsefulOutBuf_AppendUint32() and UsefulOutBuf_InsertUsefulBuf()
+ *      to output data. The append calls add data to the end of the
+ *      valid data. The insert calls take a position argument.
+ *
+ *    - Call UsefulOutBuf_OutUBuf() or UsefulOutBuf_CopyOut() to see
+ *      there were no errors and to get the serialized output bytes.
+ *
+ * @ref UsefulOutBuf can be used in a mode to calculate the size of
+ * what would be output without actually outputting anything.  This is
+ * useful to calculate the size of a buffer that is to be allocated to
+ * hold the output. See @ref SizeCalculateUsefulBuf.
+ *
+ * Methods like UsefulOutBuf_InsertUint64() always output in network
+ * byte order (big endian).
+ *
+ * The possible errors are:
+ *
+ *  - The @ref UsefulOutBuf was not initialized or was corrupted.
+ *
+ *  - An attempt was made to add data that will not fit.
+ *
+ *  - An attempt was made to insert data at a position beyond the end of
+ *    the buffer.
+ *
+ *  - An attempt was made to insert data at a position beyond the valid
+ *    data in the buffer.
+ *
+ * Some inexpensive simple sanity checks are performed before every
+ * data addition to guard against use of an uninitialized or corrupted
+ * UsefulOutBuf.
+ *
+ * @ref UsefulOutBuf has been used to create a CBOR encoder. The CBOR
+ * encoder has almost no pointer manipulation in it, is easier to
+ * read, and easier to review.
+ *
+ * A @ref UsefulOutBuf is small and can go on the stack:
+ *   - 32 bytes (27 bytes plus alignment padding) on a 64-bit CPU
+ *   - 16 bytes (15 bytes plus alignment padding) on a 32-bit CPU
+ */
+typedef struct useful_out_buf {
+   /* PRIVATE DATA STRUCTURE */
+   UsefulBuf  UB;       /* Memory that is being output to */
+   size_t     data_len; /* length of the valid data, the insertion point */
+   uint16_t   magic;    /* Used to detect corruption and lack
+                         * of initialization */
+   uint8_t    err;
+} UsefulOutBuf;
+
+
+/**
+ * This is a @ref UsefulBuf value that can be passed to
+ * UsefulOutBuf_Init() to have it calculate the size of the output
+ * buffer needed. Pass this for @c Storage, call all the append and
+ * insert functions normally, then call UsefulOutBuf_OutUBuf(). The
+ * returned @ref UsefulBufC has the size.
+ *
+ * As one can see, this is just a NULL pointer and very large size.
+ * The NULL pointer tells UsefulOutputBuf to not copy any data.
+ */
+#ifdef __cplusplus
+#define SizeCalculateUsefulBuf {NULL, SIZE_MAX}
+#else
+#define SizeCalculateUsefulBuf ((UsefulBuf) {NULL, SIZE_MAX})
+#endif
+
+
+/**
+ * @brief Initialize and supply the actual output buffer.
+ *
+ * @param[out] pUOutBuf  The @ref UsefulOutBuf to initialize.
+ * @param[in] Storage    Buffer to output into.
+ *
+ * This initializes the @ref UsefulOutBuf with storage, sets the
+ * current position to the beginning of the buffer and clears the
+ * error state.
+ *
+ * See @ref SizeCalculateUsefulBuf for instructions on how to
+ * initialize a @ref UsefulOutBuf to calculate the size that would be
+ * output without actually outputting.
+ *
+ * This must be called before the @ref UsefulOutBuf is used.
+ */
+void UsefulOutBuf_Init(UsefulOutBuf *pUOutBuf, UsefulBuf Storage);
+
+
+/**
+ * Convenience macro to make a @ref UsefulOutBuf on the stack and
+ * initialize it with a stack buffer of the given size. The variable
+ * will be named @c name.
+ */
+#define  UsefulOutBuf_MakeOnStack(name, size) \
+   uint8_t       __pBuf##name[(size)];\
+   UsefulOutBuf  name;\
+   UsefulOutBuf_Init(&(name), (UsefulBuf){__pBuf##name, (size)});
+
+
+/**
+ * @brief Reset a @ref UsefulOutBuf for re use.
+ *
+ * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf
+ *
+ * This sets the amount of data in the output buffer to none and
+ * clears the error state.
+ *
+ * The output buffer is still the same one and size as from the
+ * UsefulOutBuf_Init() call.
+ *
+ * This doesn't zero the data, just resets to 0 bytes of valid data.
+ */
+static inline void UsefulOutBuf_Reset(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Returns position of end of data in the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ *
+ * @return position of end of data.
+ *
+ * On a freshly initialized @ref UsefulOutBuf with no data added, this
+ * will return 0. After 10 bytes have been added, it will return 10
+ * and so on.
+ *
+ * Generally, there is no need to call this for most uses of @ref
+ * UsefulOutBuf.
+ */
+static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Returns whether any data has been added to the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ *
+ * @return 1 if output position is at start, 0 if not.
+ */
+static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Inserts bytes into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] NewData   The bytes to insert.
+ * @param[in] uPos      Index in output buffer at which to insert.
+ *
+ * @c NewData is the pointer and length for the bytes to be added to
+ * the output buffer. There must be room in the output buffer for all
+ * of @c NewData or an error will occur.
+ *
+ * The insertion point must be between 0 and the current valid
+ * data. If not, an error will occur. Appending data to the output
+ * buffer is achieved by inserting at the end of the valid data. This
+ * can be retrieved by calling UsefulOutBuf_GetEndPosition().
+ *
+ * When insertion is performed, the bytes between the insertion point
+ * and the end of data previously added to the output buffer are slid
+ * to the right to make room for the new data.
+ *
+ * Overlapping buffers are OK. @c NewData can point to data in the
+ * output buffer.
+ *
+ * NewData.len may be 0 in which case nothing will be inserted.
+ *
+ * If an error occurs, an error state is set in the @ref
+ * UsefulOutBuf. No error is returned.  All subsequent attempts to add
+ * data will do nothing.
+ *
+ * The intended use is that all additions are made without checking
+ * for an error. The error will be taken into account when
+ * UsefulOutBuf_OutUBuf() returns @c NullUsefulBufC.
+ * UsefulOutBuf_GetError() can also be called to check for an error.
+ */
+void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pUOutBuf,
+                                  UsefulBufC NewData,
+                                  size_t uPos);
+
+
+/**
+ * @brief Insert a data buffer into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] pBytes    Pointer to the bytes to insert
+ * @param[in] uLen      Length of the bytes to insert
+ * @param[in] uPos      Index in output buffer at which to insert
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same with
+ * the difference being a pointer and length is passed in rather than an
+ * @ref UsefulBufC.
+ */
+static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pUOutBuf,
+                                           const void *pBytes,
+                                           size_t uLen,
+                                           size_t uPos);
+
+
+/**
+ * @brief Insert a NULL-terminated string into the UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] szString  NULL-terminated string to insert.
+ * @param[in] uPos      Index in output buffer at which to insert.
+ */
+static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pUOutBuf,
+                                             const char *szString,
+                                             size_t uPos);
+
+
+/**
+ * @brief Insert a byte into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the UsefulOutBuf.
+ * @param[in] byte      Bytes to insert.
+ * @param[in] uPos      Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being a single byte is to be inserted.
+ */
+static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *pUOutBuf,
+                                           uint8_t byte,
+                                           size_t uPos);
+
+
+/**
+ * @brief Insert a 16-bit integer into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger16  Integer to insert.
+ * @param[in] uPos        Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being a two-byte integer is to be inserted.
+ *
+ * The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *pUOutBuf,
+                                             uint16_t uInteger16,
+                                             size_t uPos);
+
+
+/**
+ * @brief Insert a 32-bit integer into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger32  Integer to insert.
+ * @param[in] uPos        Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being a four-byte integer is to be inserted.
+ *
+ * The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pUOutBuf,
+                                             uint32_t uInteger32,
+                                             size_t uPos);
+
+
+/**
+ * @brief Insert a 64-bit integer into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger64  Integer to insert.
+ * @param[in] uPos        Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being an eight-byte integer is to be inserted.
+ *
+ * The integer will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pUOutBuf,
+                                             uint64_t uInteger64,
+                                             size_t uPos);
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Insert a @c float into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] f         @c float to insert.
+ * @param[in] uPos      Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being a @c float is to be inserted.
+ *
+ * The @c float will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pUOutBuf,
+                                            float f,
+                                            size_t uPos);
+
+
+/**
+ * @brief Insert a @c double into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] d         @c double  to insert.
+ * @param[in] uPos      Index in output buffer at which to insert.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This is the same
+ * with the difference being a @c double is to be inserted.
+ *
+ * The @c double will be inserted in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pUOutBuf,
+                                             double d,
+                                             size_t uPos);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+/**
+ * @brief Append a @ref UsefulBuf into the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] NewData   The @ref UsefulBuf with the bytes to append.
+ *
+ * See UsefulOutBuf_InsertUsefulBuf() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ */
+static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pUOutBuf,
+                                                UsefulBufC NewData);
+
+
+/**
+ * @brief Append bytes to the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] pBytes    Pointer to bytes to append.
+ * @param[in] uLen      Length of @c pBytes to append.
+ *
+ * See UsefulOutBuf_InsertData() for details. This does the same with
+ * the insertion point at the end of the valid data.
+ */
+static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pUOutBuf,
+                                           const void *pBytes,
+                                           size_t uLen);
+
+
+/**
+ * @brief Append a NULL-terminated string to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] szString  NULL-terminated string to append.
+ */
+static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pUOutBuf,
+                                             const char *szString);
+
+
+/**
+ * @brief Append a byte to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] byte      Bytes to append.
+ *
+ * See UsefulOutBuf_InsertByte() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ */
+static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pUOutBuf,
+                                           uint8_t byte);
+
+
+/**
+ * @brief Append an integer to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger16  Integer to append.
+ *
+ * See UsefulOutBuf_InsertUint16() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ *
+ * The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pUOutBuf,
+                                             uint16_t uInteger16);
+
+
+/**
+ * @brief Append an integer to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger32  Integer to append.
+ *
+ * See UsefulOutBuf_InsertUint32() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ *
+ * The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pUOutBuf,
+                                             uint32_t uInteger32);
+
+
+/**
+ * @brief Append an integer to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf    Pointer to the @ref UsefulOutBuf.
+ * @param[in] uInteger64  Integer to append.
+ *
+ * See UsefulOutBuf_InsertUint64() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ *
+ * The integer will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pUOutBuf,
+                                             uint64_t uInteger64);
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Append a @c float to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] f         @c float to append.
+ *
+ * See UsefulOutBuf_InsertFloat() for details. This does the same with
+ * the insertion point at the end of the valid data.
+ *
+ * The float will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pUOutBuf,
+                                            float f);
+
+
+/**
+ * @brief Append a @c double to the @ref UsefulOutBuf
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] d         @c double to append.
+ *
+ * See UsefulOutBuf_InsertDouble() for details. This does the same
+ * with the insertion point at the end of the valid data.
+ *
+ * The double will be appended in network byte order (big endian).
+ */
+static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pUOutBuf,
+                                             double d);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+/**
+ * @brief Returns the current error status.
+ *
+ * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
+ *
+ * @return 0 if all OK, 1 on error.
+ *
+ * This returns the error status since a call to either
+ * UsefulOutBuf_Reset() of UsefulOutBuf_Init().  Once a @ref UsefulOutBuf
+ * goes into the error state, it will stay until one of those
+ * functions is called.
+ *
+ * Possible error conditions are:
+ *   - bytes to be inserted will not fit
+ *   - insertion point is out of buffer or past valid data
+ *   - current position is off end of buffer (probably corrupted or uninitialized)
+ *   - detect corruption / uninitialized by bad magic number
+ */
+static inline int UsefulOutBuf_GetError(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Returns number of bytes unused used in the output buffer.
+ *
+ * @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
+ *
+ * @return Number of unused bytes or zero.
+ *
+ * Because of the error handling strategy and checks in
+ * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
+ * this.
+ */
+static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ *@brief Returns 1 if some number of bytes will fit in the @ref UsefulOutBuf.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf
+ * @param[in] uLen      Number of bytes for which to check
+ *
+ * @return 1 if @c uLen bytes will fit, 0 if not.
+ *
+ * Because of the error handling strategy and checks in
+ * UsefulOutBuf_InsertUsefulBuf() it is usually not necessary to use
+ * this.
+ */
+static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pUOutBuf, size_t uLen);
+
+
+ /**
+  * @brief Returns 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
+  *
+  * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf
+  *
+  * @return 1 if buffer given to UsefulOutBuf_Init() was @c NULL.
+  *
+  * Giving a @c NULL output buffer to UsefulOutBuf_Init() is used when
+  * just calculating the length of the encoded data.
+  */
+static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Returns pointer and length of the output buffer not yet used.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ *
+ * @return pointer and length of output buffer not used.
+ *
+ * This is an escape that allows the caller to write directly
+ * to the output buffer without any checks. This doesn't
+ * change the output buffer or state. It just returns a pointer
+ * and length of the bytes remaining.
+ *
+ * This is useful to avoid having the bytes to be added all
+ * in a contiguous buffer. Its use can save memory. A good
+ * example is in the COSE encrypt implementation where
+ * the output of the symmetric cipher can go directly
+ * into the output buffer, rather than having to go into
+ * an intermediate buffer.
+ *
+ * See UsefulOutBuf_Advance() which is used to tell
+ * UsefulOutBuf how much was written.
+ *
+ * Warning: this bypasses the buffer safety provided by
+ * UsefulOutBuf!
+ */
+static inline UsefulBuf
+UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Advance the amount output assuming it was written by the caller.
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[in] uAmount  The amount to advance.
+ *
+ * This advances the position in the output buffer
+ * by \c uAmount. This assumes that the
+ * caller has written \c uAmount to the pointer obtained
+ * with UsefulOutBuf_GetOutPlace().
+ *
+ * Warning: this bypasses the buffer safety provided by
+ * UsefulOutBuf!
+ */
+void
+UsefulOutBuf_Advance(UsefulOutBuf *pUOutBuf, size_t uAmount);
+
+
+/**
+ *  @brief Returns the resulting valid data in a UsefulOutBuf
+ *
+ *  @param[in] pUOutBuf Pointer to the @ref UsefulOutBuf.
+ *
+ *  @return The valid data in @ref UsefulOutBuf or
+ *           @ref NULLUsefulBufC if there was an error adding data.
+ *
+ *  The storage for the returned data is the @c Storage parameter
+ *  passed to UsefulOutBuf_Init(). See also UsefulOutBuf_CopyOut().
+ *
+ *  This can be called anytime and many times to get intermediate
+ *  results. It doesn't change the data or reset the current position,
+ *  so further data can be added.
+ */
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pUOutBuf);
+
+
+/**
+ * @brief Copies the valid data into a supplied buffer
+ *
+ * @param[in] pUOutBuf  Pointer to the @ref UsefulOutBuf.
+ * @param[out] Dest     The destination buffer to copy into.
+ *
+ * @return Pointer and length of copied data or @c NULLUsefulBufC
+ *         if it will not fit in the @c Dest buffer or the error
+ *         state was entered.
+ *
+ * This is the same as UsefulOutBuf_OutUBuf() except it copies the
+ * data to @c Dest.
+ */
+UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pUOutBuf, UsefulBuf Dest);
+
+
+
+
+/**
+ * @ref UsefulInputBuf is the counterpart to @ref UsefulOutBuf. It is
+ * for parsing data received.  Initialize it with the data from the
+ * network. Then use the functions like UsefulInputBuf_GetBytes() to
+ * get data chunks of various types. A position cursor is maintained
+ * internally.
+ *
+ * As long as the functions here are used, there will never be any
+ * reference off the end of the given buffer (except
+ * UsefulInputBuf_SetBufferLength()). This is true even if they are
+ * called incorrectly, an attempt is made to seek off the end of the
+ * buffer or such. This makes it easier to write safe and correct
+ * code.  For example, the QCBOR decoder implementation is safer and
+ * easier to review through its use of @ref UsefulInputBuf.
+ *
+ * @ref UsefulInputBuf maintains an internal error state.  The
+ * intended use is fetching data chunks without any error checks until
+ * the end.  If there was any error, such as an attempt to fetch data
+ * off the end, the error state is entered and no further data will be
+ * returned. In the error state the @c UsefulInputBuf_GetXxxx()
+ * functions return 0, or @c NULL or @ref NULLUsefulBufC. As long as
+ * null is not dereferenced, the error check can be put off until the
+ * end, simplifying the calling code.
+ *
+ * The integer and float parsing expects network byte order (big
+ * endian).  Network byte order is what is used by TCP/IP, CBOR and
+ * most internet protocols.
+ *
+ * Lots of inline functions are used to keep code size down. The
+ * optimizer, particularly with the @c -Os or @c -O3, also reduces
+ * code size a lot. The only non-inline code is
+ * UsefulInputBuf_GetBytes().  It is less than 100 bytes so use of
+ * @ref UsefulInputBuf doesn't add much code for all the messy
+ * hard-to-get right issues with parsing binary protocols in C that it
+ * solves.
+ *
+ * The parse context size is:
+ *   - 64-bit machine: 16 + 8 + 2 + 1 (+ 5 bytes padding to align) = 32 bytes
+ *   - 32-bit machine: 8 + 4 + 2 + 1 (+ 1 byte padding to align) = 16 bytes
+ */
+typedef struct useful_input_buf {
+   /* PRIVATE DATA STRUCTURE */
+   UsefulBufC UB;     /* Data being parsed */
+   size_t     cursor; /* Current offset in data being parse */
+   uint16_t   magic;  /* Check for corrupted or uninitialized UsefulInputBuf */
+   uint8_t    err;    /* Set request goes off end or magic number is bad */
+} UsefulInputBuf;
+
+#define UIB_MAGIC (0xB00F)
+
+
+/**
+ * @brief Initialize the @ref UsefulInputBuf structure before use.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] UB       The data to parse.
+ */
+static inline void UsefulInputBuf_Init(UsefulInputBuf *pUInBuf, UsefulBufC UB);
+
+
+/**
+ * @brief Returns current position in input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return Integer position of the cursor.
+ *
+ * The position that the next bytes will be returned from.
+ */
+static size_t UsefulInputBuf_Tell(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Sets the current position in input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uPos     Position to set to.
+ *
+ * If the position is off the end of the input buffer, the error state
+ * is entered.
+ *
+ * Seeking to a valid position in the buffer will not reset the error
+ * state. Only re-initialization will do that.
+ */
+static void UsefulInputBuf_Seek(UsefulInputBuf *pUInBuf, size_t uPos);
+
+
+/**
+ * @brief Returns the number of bytes from the cursor to the end of the buffer,
+ * the unconsumed bytes.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return Number of bytes unconsumed or 0 on error.
+ *
+ * Returns 0 if the cursor is invalid or corruption of the
+ * @ref UsefulInputBuf structure is detected.
+ */
+static size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Check if there are unconsumed bytes.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uLen     Number of bytes to check availability for.
+ *
+ * @return 1 if @c uLen bytes are available after the cursor, and 0 if not.
+ */
+static int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pUInBuf, size_t uLen);
+
+
+/**
+ * @brief Convert a pointer to an offset with bounds checking.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] p        Pointer to convert to offset.
+ *
+ * @return SIZE_MAX if @c p is out of range, the byte offset if not.
+ */
+static size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p);
+
+
+/**
+ * @brief Convert an offset to a pointer with bounds checking.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uOffset  Offset in @c pUInBuf.
+ *
+ * @return @c NULL if @c uOffset is out of range, a pointer into the buffer if not.
+ */
+static const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset);
+
+
+/**
+ * @brief Get pointer to bytes out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uNum     Number of bytes to get.
+ *
+ * @return Pointer to bytes.
+ *
+ * This consumes @c uNum bytes from the input buffer. This returns a
+ * pointer to the start of the @c uNum bytes.
+ *
+ * If there are not @c uNum bytes in the input buffer, @c NULL will be
+ * returned and the error state is entered.
+ *
+ * This advances the position cursor by @c uNum bytes.
+ */
+const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pUInBuf, size_t uNum);
+
+
+/**
+ * @brief Get @ref UsefulBuf out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uNum     Number of bytes to get.
+ *
+ * @return A @ref UsefulBufC with ptr and length of bytes consumed.
+ *
+ * This consumes @c uNum bytes from the input buffer and returns the
+ * pointer and length for them as a @ref UsefulBufC. The length
+ * returned will always be @c uNum. The position cursor is advanced by
+ * @c uNum bytes.
+ *
+ * If there are not @c uNum bytes in the input buffer, @ref
+ * NULLUsefulBufC will be returned and the error state is entered.
+ */
+static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pUInBuf, size_t uNum);
+
+
+/**
+ * @brief Get a byte out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The byte.
+ *
+ * This consumes 1 byte from the input buffer, returns it and advances
+ * the position cursor by 1.
+ *
+ * If there is not 1 byte in the buffer, 0 will be returned for the
+ * byte and the error state is entered. To know if the 0 returned was
+ * in error or the real value, the error state must be checked.  If
+ * possible, put this off until all values are retrieved to have
+ * smaller and simpler code, but if not possible
+ * UsefulInputBuf_GetError() can be called. Also, in the error state
+ * UsefulInputBuf_GetBytes() returns @c NULL *or the @c ptr from
+ * UsefulInputBuf_GetUsefulBuf() is @c NULL.
+ */
+static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Get a @c uint16_t out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The @c uint16_t.
+ *
+ * See UsefulInputBuf_GetByte(). This works the same, except it returns
+ * a @c uint16_t and two bytes are consumed.
+ *
+ * The input bytes are interpreted in network order (big endian).
+ */
+static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Get a @c uint32_t out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The @c uint32_t.
+ *
+ * See UsefulInputBuf_GetByte(). This works the same, except it
+ * returns a @c uint32_t and four bytes are consumed.
+ *
+ * The input bytes are interpreted in network order (big endian).
+ */
+static uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Get a @c uint64_t out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The uint64_t.
+ *
+ * See UsefulInputBuf_GetByte(). This works the same, except it returns
+ * a @c uint64_t and eight bytes are consumed.
+ *
+ * The input bytes are interpreted in network order (big endian).
+ */
+static uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pUInBuf);
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Get a float out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The float.
+ *
+ * See UsefulInputBuf_GetByte(). This works the same, except it
+ * returns a float and four bytes are consumed.
+ *
+ * The input bytes are interpreted in network order (big endian).
+ */
+static float UsefulInputBuf_GetFloat(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Get a double out of the input buffer.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The double.
+ *
+ * See UsefulInputBuf_GetByte(). This works the same, except it
+ * returns a double and eight bytes are consumed.
+ *
+ * The input bytes are interpreted in network order (big endian).
+ */
+static double UsefulInputBuf_GetDouble(UsefulInputBuf *pUInBuf);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+/**
+ * @brief Get the error status.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return 0 if not in the error state, 1 if in the error state.
+ *
+ * This returns whether the @ref UsefulInputBuf is in the
+ * error state or not.
+ *
+ * The error state is entered for one of these reasons:
+ * - Attempt to fetch data past the end of the buffer
+ * - Attempt to seek to a position past the end of the buffer
+ * - Attempt to get data from an uninitialized  or corrupt instance
+ *   of @ref UsefulInputBuf
+ *
+ * Once in the error state, it can only be cleared by calling
+ * UsefulInputBuf_Init().
+ *
+ * For many use cases, it is possible to only call this once after all
+ * the @c UsefulInputBuf_GetXxxx() calls have been made.  This is
+ * possible if no reference to the data returned are needed before the
+ * error state is checked.
+ *
+ * In some cases UsefulInputBuf_GetUsefulBuf() or
+ * UsefulInputBuf_GetBytes() can stand in for this because they return
+ * @c NULL if the error state has been entered. (The others can't stand
+ * in because they don't return a clearly distinct error value.)
+ */
+static int UsefulInputBuf_GetError(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Gets the input buffer length.
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ *
+ * @return The length of the input buffer.
+ *
+ * This returns the length of the input buffer set by
+ * UsefulInputBuf_Init() or UsefulInputBuf_SetBufferLength().
+ */
+static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pUInBuf);
+
+
+/**
+ * @brief Alters the input buffer length (use with caution).
+ *
+ * @param[in] pUInBuf  Pointer to the @ref UsefulInputBuf.
+ * @param[in] uNewLen  The new length of the input buffer.
+ *
+ * This alters the internal remembered length of the input buffer set
+ * when UsefulInputBuf_Init() was called.
+ *
+ * The new length given here should always be equal to or less than
+ * the length given when UsefulInputBuf_Init() was called. Making it
+ * larger allows @ref UsefulInputBuf to run off the input buffer.
+ *
+ * The typical use is to set a length shorter than that when
+ * initialized to constrain parsing. If
+ * UsefulInputBuf_GetBufferLength() was called before this, then the
+ * original length can be restored with another call to this.
+ *
+ * This should be used with caution. It is the only
+ * @ref UsefulInputBuf method that can violate the safety of input
+ * buffer parsing.
+ */
+static void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pUInBuf, size_t uNewLen);
+
+
+
+
+/*----------------------------------------------------------
+ Inline implementations.
+ */
+static inline int UsefulBuf_IsNULL(UsefulBuf UB)
+{
+   return !UB.ptr;
+}
+
+
+static inline int UsefulBuf_IsNULLC(UsefulBufC UB)
+{
+   return !UB.ptr;
+}
+
+
+static inline int UsefulBuf_IsEmpty(UsefulBuf UB)
+{
+   return !UB.len;
+}
+
+
+static inline int UsefulBuf_IsEmptyC(UsefulBufC UB)
+{
+   return !UB.len;
+}
+
+
+static inline int UsefulBuf_IsNULLOrEmpty(UsefulBuf UB)
+{
+   return UsefulBuf_IsEmpty(UB) || UsefulBuf_IsNULL(UB);
+}
+
+
+static inline int UsefulBuf_IsNULLOrEmptyC(UsefulBufC UB)
+{
+   return UsefulBuf_IsEmptyC(UB) || UsefulBuf_IsNULLC(UB);
+}
+
+
+static inline UsefulBufC UsefulBuf_Const(const UsefulBuf UB)
+{
+   UsefulBufC UBC;
+   UBC.ptr = UB.ptr;
+   UBC.len = UB.len;
+
+   return UBC;
+}
+
+static inline UsefulBuf UsefulBuf_Unconst(const UsefulBufC UBC)
+{
+   UsefulBuf UB;
+
+   /* -Wcast-qual is a good warning flag to use in general. This is
+    * the one place in UsefulBuf where it needs to be quieted.
+    */
+   UB.ptr = (void *)(uintptr_t)UBC.ptr;
+
+   UB.len = UBC.len;
+
+   return UB;
+}
+
+
+static inline UsefulBufC UsefulBuf_FromSZ(const char *szString)
+{
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+   return UBC;
+}
+
+
+static inline UsefulBufC UsefulBuf_Copy(UsefulBuf Dest, const UsefulBufC Src)
+{
+   return UsefulBuf_CopyOffset(Dest, 0, Src);
+}
+
+
+static inline UsefulBufC UsefulBuf_Set(UsefulBuf Dest, uint8_t value)
+{
+   memset(Dest.ptr, value, Dest.len);
+
+   UsefulBufC UBC;
+   UBC.ptr = Dest.ptr;
+   UBC.len = Dest.len;
+
+   return UBC;
+}
+
+
+static inline UsefulBufC UsefulBuf_CopyPtr(UsefulBuf Dest, const void *ptr, size_t len)
+{
+   UsefulBufC UBC;
+   UBC.ptr = ptr;
+   UBC.len = len;
+   return UsefulBuf_Copy(Dest, UBC);
+}
+
+
+static inline UsefulBufC UsefulBuf_Head(UsefulBufC UB, size_t uAmount)
+{
+   if(uAmount > UB.len) {
+      return NULLUsefulBufC;
+   }
+   UsefulBufC UBC;
+
+   UBC.ptr = UB.ptr;
+   UBC.len = uAmount;
+
+   return UBC;
+}
+
+
+static inline UsefulBufC UsefulBuf_Tail(UsefulBufC UB, size_t uAmount)
+{
+   UsefulBufC ReturnValue;
+
+   if(uAmount > UB.len) {
+      ReturnValue = NULLUsefulBufC;
+   } else if(UB.ptr == NULL) {
+      ReturnValue.ptr = NULL;
+      ReturnValue.len = UB.len - uAmount;
+   } else {
+      ReturnValue.ptr = (const uint8_t *)UB.ptr + uAmount;
+      ReturnValue.len = UB.len - uAmount;
+   }
+
+   return ReturnValue;
+}
+
+
+static inline size_t UsefulBuf_PointerToOffset(UsefulBufC UB, const void *p)
+{
+   if(UB.ptr == NULL) {
+      return SIZE_MAX;
+   }
+
+   if(p < UB.ptr) {
+      /* given pointer is before start of buffer */
+      return SIZE_MAX;
+   }
+
+   /* Cast to size_t (from ptrdiff_t) is OK because of check above */
+   const size_t uOffset = (size_t)((const uint8_t *)p - (const uint8_t *)UB.ptr);
+
+    if(uOffset >= UB.len) {
+      /* given pointer is off the end of the buffer */
+      return SIZE_MAX;
+   }
+
+   return uOffset;
+}
+
+
+static inline const void *UsefulBuf_OffsetToPointer(UsefulBufC UB, size_t uOffset)
+{
+   if(UsefulBuf_IsNULLC(UB) || uOffset >= UB.len) {
+      return NULL;
+   }
+
+   return (const uint8_t *)UB.ptr + uOffset;
+}
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+static inline uint32_t UsefulBufUtil_CopyFloatToUint32(float f)
+{
+   uint32_t u32;
+   memcpy(&u32, &f, sizeof(uint32_t));
+   return u32;
+}
+
+static inline uint64_t UsefulBufUtil_CopyDoubleToUint64(double d)
+{
+   uint64_t u64;
+   memcpy(&u64, &d, sizeof(uint64_t));
+   return u64;
+}
+
+static inline double UsefulBufUtil_CopyUint64ToDouble(uint64_t u64)
+{
+   double d;
+   memcpy(&d, &u64, sizeof(uint64_t));
+   return d;
+}
+
+static inline float UsefulBufUtil_CopyUint32ToFloat(uint32_t u32)
+{
+   float f;
+   memcpy(&f, &u32, sizeof(uint32_t));
+   return f;
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+static inline void UsefulOutBuf_Reset(UsefulOutBuf *pMe)
+{
+   pMe->data_len = 0;
+   pMe->err      = 0;
+}
+
+
+static inline size_t UsefulOutBuf_GetEndPosition(UsefulOutBuf *pMe)
+{
+   return pMe->data_len;
+}
+
+
+static inline int UsefulOutBuf_AtStart(UsefulOutBuf *pMe)
+{
+   return 0 == pMe->data_len;
+}
+
+
+static inline void UsefulOutBuf_InsertData(UsefulOutBuf *pMe,
+                                           const void *pBytes,
+                                           size_t uLen,
+                                           size_t uPos)
+{
+   UsefulBufC Data = {pBytes, uLen};
+   UsefulOutBuf_InsertUsefulBuf(pMe, Data, uPos);
+}
+
+
+static inline void UsefulOutBuf_InsertString(UsefulOutBuf *pMe,
+                                             const char *szString,
+                                             size_t uPos)
+{
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+
+   UsefulOutBuf_InsertUsefulBuf(pMe, UBC, uPos);
+}
+
+
+static inline void UsefulOutBuf_InsertByte(UsefulOutBuf *me,
+                                           uint8_t byte,
+                                           size_t uPos)
+{
+   UsefulOutBuf_InsertData(me, &byte, 1, uPos);
+}
+
+
+static inline void UsefulOutBuf_InsertUint16(UsefulOutBuf *me,
+                                             uint16_t uInteger16,
+                                             size_t uPos)
+{
+   /* See UsefulOutBuf_InsertUint64() for comments on this code */
+
+   const void *pBytes;
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   pBytes = &uInteger16;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   uint16_t uTmp = htons(uInteger16);
+   pBytes        = &uTmp;
+
+#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
+   uint16_t uTmp = __builtin_bswap16(uInteger16);
+   pBytes = &uTmp;
+
+#else
+   uint8_t aTmp[2];
+
+   aTmp[0] = (uint8_t)((uInteger16 & 0xff00) >> 8);
+   aTmp[1] = (uint8_t)(uInteger16 & 0xff);
+
+   pBytes = aTmp;
+#endif
+
+   UsefulOutBuf_InsertData(me, pBytes, 2, uPos);
+}
+
+
+static inline void UsefulOutBuf_InsertUint32(UsefulOutBuf *pMe,
+                                             uint32_t uInteger32,
+                                             size_t uPos)
+{
+   /* See UsefulOutBuf_InsertUint64() for comments on this code */
+
+   const void *pBytes;
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   pBytes = &uInteger32;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   uint32_t uTmp = htonl(uInteger32);
+   pBytes = &uTmp;
+
+#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
+   uint32_t uTmp = __builtin_bswap32(uInteger32);
+
+   pBytes = &uTmp;
+
+#else
+   uint8_t aTmp[4];
+
+   aTmp[0] = (uint8_t)((uInteger32 & 0xff000000) >> 24);
+   aTmp[1] = (uint8_t)((uInteger32 & 0xff0000) >> 16);
+   aTmp[2] = (uint8_t)((uInteger32 & 0xff00) >> 8);
+   aTmp[3] = (uint8_t)(uInteger32 & 0xff);
+
+   pBytes = aTmp;
+#endif
+
+   UsefulOutBuf_InsertData(pMe, pBytes, 4, uPos);
+}
+
+static inline void UsefulOutBuf_InsertUint64(UsefulOutBuf *pMe,
+                                             uint64_t      uInteger64,
+                                             size_t        uPos)
+{
+   const void *pBytes;
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   /* We have been told explicitly we are running on a big-endian
+    * machine. Network byte order is big endian, so just copy.  There
+    * is no issue with alignment here because uInteger64 is always
+    * aligned (and it doesn't matter if pBytes is aligned).
+    */
+   pBytes = &uInteger64;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   /* Use system function to handle big- and little-endian. This works
+    * on both big- and little-endian machines, but hton() is not
+    * always available or in a standard place so it is not used by
+    * default. With some compilers and CPUs the code for this is very
+    * compact through use of a special swap instruction and on
+    * big-endian machines hton() will reduce to nothing.
+    */
+   uint64_t uTmp = htonll(uInteger64);
+
+   pBytes = &uTmp;
+
+#elif defined(USEFULBUF_CONFIG_LITTLE_ENDIAN) && defined(USEFULBUF_CONFIG_BSWAP)
+   /* Use built-in function for byte swapping. This usually compiles
+    * to an efficient special byte swap instruction. Unlike hton() it
+    * does not do this conditionally on the CPU endianness, so this
+    * code is also conditional on USEFULBUF_CONFIG_LITTLE_ENDIAN
+    */
+   uint64_t uTmp = __builtin_bswap64(uInteger64);
+
+   pBytes = &uTmp;
+
+#else
+   /* Default which works on every CPU with no dependency on anything
+    * from the CPU, compiler, libraries or OS.  This always works, but
+    * it is usually a little larger and slower than hton().
+    */
+   uint8_t aTmp[8];
+
+   aTmp[0] = (uint8_t)((uInteger64 & 0xff00000000000000) >> 56);
+   aTmp[1] = (uint8_t)((uInteger64 & 0xff000000000000) >> 48);
+   aTmp[2] = (uint8_t)((uInteger64 & 0xff0000000000) >> 40);
+   aTmp[3] = (uint8_t)((uInteger64 & 0xff00000000) >> 32);
+   aTmp[4] = (uint8_t)((uInteger64 & 0xff000000) >> 24);
+   aTmp[5] = (uint8_t)((uInteger64 & 0xff0000) >> 16);
+   aTmp[6] = (uint8_t)((uInteger64 & 0xff00) >> 8);
+   aTmp[7] = (uint8_t)(uInteger64 & 0xff);
+
+   pBytes = aTmp;
+#endif
+
+   /* Do the insert */
+   UsefulOutBuf_InsertData(pMe, pBytes, sizeof(uint64_t), uPos);
+}
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+static inline void UsefulOutBuf_InsertFloat(UsefulOutBuf *pMe,
+                                            float f,
+                                            size_t uPos)
+{
+   UsefulOutBuf_InsertUint32(pMe, UsefulBufUtil_CopyFloatToUint32(f), uPos);
+}
+
+
+static inline void UsefulOutBuf_InsertDouble(UsefulOutBuf *pMe,
+                                             double d,
+                                             size_t uPos)
+{
+   UsefulOutBuf_InsertUint64(pMe, UsefulBufUtil_CopyDoubleToUint64(d), uPos);
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+static inline void UsefulOutBuf_AppendUsefulBuf(UsefulOutBuf *pMe,
+                                                UsefulBufC NewData)
+{
+   /* An append is just a insert at the end */
+   UsefulOutBuf_InsertUsefulBuf(pMe, NewData, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+
+static inline void UsefulOutBuf_AppendData(UsefulOutBuf *pMe,
+                                           const void *pBytes,
+                                           size_t uLen)
+{
+   UsefulBufC Data = {pBytes, uLen};
+   UsefulOutBuf_AppendUsefulBuf(pMe, Data);
+}
+
+
+static inline void UsefulOutBuf_AppendString(UsefulOutBuf *pMe,
+                                             const char *szString)
+{
+   UsefulBufC UBC;
+   UBC.ptr = szString;
+   UBC.len = strlen(szString);
+
+   UsefulOutBuf_AppendUsefulBuf(pMe, UBC);
+}
+
+
+static inline void UsefulOutBuf_AppendByte(UsefulOutBuf *pMe,
+                                           uint8_t byte)
+{
+   UsefulOutBuf_AppendData(pMe, &byte, 1);
+}
+
+
+static inline void UsefulOutBuf_AppendUint16(UsefulOutBuf *pMe,
+                                             uint16_t uInteger16)
+{
+   UsefulOutBuf_InsertUint16(pMe, uInteger16, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+static inline void UsefulOutBuf_AppendUint32(UsefulOutBuf *pMe,
+                                             uint32_t uInteger32)
+{
+   UsefulOutBuf_InsertUint32(pMe, uInteger32, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+
+static inline void UsefulOutBuf_AppendUint64(UsefulOutBuf *pMe,
+                                             uint64_t uInteger64)
+{
+   UsefulOutBuf_InsertUint64(pMe, uInteger64, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+static inline void UsefulOutBuf_AppendFloat(UsefulOutBuf *pMe,
+                                            float f)
+{
+   UsefulOutBuf_InsertFloat(pMe, f, UsefulOutBuf_GetEndPosition(pMe));
+}
+
+
+static inline void UsefulOutBuf_AppendDouble(UsefulOutBuf *pMe,
+                                             double d)
+{
+   UsefulOutBuf_InsertDouble(pMe, d, UsefulOutBuf_GetEndPosition(pMe));
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+static inline int UsefulOutBuf_GetError(UsefulOutBuf *pMe)
+{
+   return pMe->err;
+}
+
+
+static inline size_t UsefulOutBuf_RoomLeft(UsefulOutBuf *pMe)
+{
+   return pMe->UB.len - pMe->data_len;
+}
+
+
+static inline int UsefulOutBuf_WillItFit(UsefulOutBuf *pMe, size_t uLen)
+{
+   return uLen <= UsefulOutBuf_RoomLeft(pMe);
+}
+
+
+static inline int UsefulOutBuf_IsBufferNULL(UsefulOutBuf *pMe)
+{
+   return pMe->UB.ptr == NULL;
+}
+
+
+static inline UsefulBuf UsefulOutBuf_GetOutPlace(UsefulOutBuf *pUOutBuf)
+{
+   UsefulBuf R;
+
+   R.len = UsefulOutBuf_RoomLeft(pUOutBuf);
+   if(R.len > 0 && pUOutBuf->UB.ptr != NULL) {
+      R.ptr = (uint8_t *)pUOutBuf->UB.ptr + pUOutBuf->data_len;
+   } else {
+      R.ptr = NULL;
+   }
+
+   return R;
+}
+
+
+
+
+static inline void UsefulInputBuf_Init(UsefulInputBuf *pMe, UsefulBufC UB)
+{
+   pMe->cursor = 0;
+   pMe->err    = 0;
+   pMe->magic  = UIB_MAGIC;
+   pMe->UB     = UB;
+}
+
+static inline size_t UsefulInputBuf_Tell(UsefulInputBuf *pMe)
+{
+   return pMe->cursor;
+}
+
+
+static inline size_t UsefulInputBuf_GetBufferLength(UsefulInputBuf *pMe)
+{
+    return pMe->UB.len;
+}
+
+
+static inline void UsefulInputBuf_Seek(UsefulInputBuf *pMe, size_t uPos)
+{
+   if(uPos > pMe->UB.len) {
+      pMe->err = 1;
+   } else {
+      pMe->cursor = uPos;
+   }
+}
+
+
+static inline size_t UsefulInputBuf_BytesUnconsumed(UsefulInputBuf *pMe)
+{
+   /* Code Reviewers: THIS FUNCTION DOES POINTER MATH */
+
+   /* Magic number is messed up. Either the structure got overwritten
+    * or was never initialized.
+    */
+   if(pMe->magic != UIB_MAGIC) {
+      return 0;
+   }
+
+   /* The cursor is off the end of the input buffer given.
+    * Presuming there are no bugs in this code, this should never happen.
+    * If it is so, the struct was corrupted. The check is retained as
+    * as a defense in case there is a bug in this code or the struct is
+    * corrupted by an attacker or accidentally.
+    */
+   if(pMe->cursor > pMe->UB.len) {
+      return 0;
+   }
+
+   /* subtraction can't go negative because of check above */
+   return pMe->UB.len - pMe->cursor;
+}
+
+
+static inline int UsefulInputBuf_BytesAvailable(UsefulInputBuf *pMe, size_t uLen)
+{
+   return UsefulInputBuf_BytesUnconsumed(pMe) >= uLen ? 1 : 0;
+}
+
+
+static inline size_t UsefulInputBuf_PointerToOffset(UsefulInputBuf *pUInBuf, const void *p)
+{
+   return UsefulBuf_PointerToOffset(pUInBuf->UB, p);
+}
+
+
+static inline const void *UsefulInputBuf_OffsetToPointer(UsefulInputBuf *pUInBuf, size_t uOffset)
+ {
+    return UsefulBuf_OffsetToPointer(pUInBuf->UB, uOffset);
+ }
+
+
+static inline UsefulBufC UsefulInputBuf_GetUsefulBuf(UsefulInputBuf *pMe, size_t uNum)
+{
+   const void *pResult = UsefulInputBuf_GetBytes(pMe, uNum);
+   if(!pResult) {
+      return NULLUsefulBufC;
+   } else {
+      UsefulBufC UBC;
+      UBC.ptr = pResult;
+      UBC.len = uNum;
+      return UBC;
+   }
+}
+
+
+static inline uint8_t UsefulInputBuf_GetByte(UsefulInputBuf *pMe)
+{
+   const void *pResult = UsefulInputBuf_GetBytes(pMe, sizeof(uint8_t));
+
+   /* The ternary operator is subject to integer promotion, because
+    * the operands are smaller than int, so cast back to uint8_t is
+    * needed to be completely explicit about types (for static
+    * analyzers).
+    */
+   return (uint8_t)(pResult ? *(const uint8_t *)pResult : 0);
+}
+
+static inline uint16_t UsefulInputBuf_GetUint16(UsefulInputBuf *pMe)
+{
+   const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint16_t));
+
+   if(!pResult) {
+      return 0;
+   }
+
+   /* See UsefulInputBuf_GetUint64() for comments on this code */
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
+   uint16_t uTmp;
+   memcpy(&uTmp, pResult, sizeof(uint16_t));
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   return uTmp;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   return ntohs(uTmp);
+
+#else
+   return __builtin_bswap16(uTmp);
+
+#endif
+
+#else
+
+   /* The operations here are subject to integer promotion because the
+    * operands are smaller than int. They will be promoted to unsigned
+    * int for the shift and addition. The cast back to uint16_t is is
+    * needed to be completely explicit about types (for static
+    * analyzers).
+    */
+   return (uint16_t)((pResult[0] << 8) + pResult[1]);
+
+#endif
+}
+
+
+static inline uint32_t UsefulInputBuf_GetUint32(UsefulInputBuf *pMe)
+{
+   const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint32_t));
+
+   if(!pResult) {
+      return 0;
+   }
+
+   /* See UsefulInputBuf_GetUint64() for comments on this code */
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
+   uint32_t uTmp;
+   memcpy(&uTmp, pResult, sizeof(uint32_t));
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   return uTmp;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   return ntohl(uTmp);
+
+#else
+   return __builtin_bswap32(uTmp);
+
+#endif
+
+#else
+   return ((uint32_t)pResult[0]<<24) +
+          ((uint32_t)pResult[1]<<16) +
+          ((uint32_t)pResult[2]<<8)  +
+           (uint32_t)pResult[3];
+#endif
+}
+
+
+static inline uint64_t UsefulInputBuf_GetUint64(UsefulInputBuf *pMe)
+{
+   const uint8_t *pResult = (const uint8_t *)UsefulInputBuf_GetBytes(pMe, sizeof(uint64_t));
+
+   if(!pResult) {
+      return 0;
+   }
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN) || defined(USEFULBUF_CONFIG_HTON) || defined(USEFULBUF_CONFIG_BSWAP)
+   /* pResult will probably not be aligned.  This memcpy() moves the
+    * bytes into a temp variable safely for CPUs that can or can't do
+    * unaligned memory access. Many compilers will optimize the
+    * memcpy() into a simple move instruction.
+    */
+   uint64_t uTmp;
+   memcpy(&uTmp, pResult, sizeof(uint64_t));
+
+#if defined(USEFULBUF_CONFIG_BIG_ENDIAN)
+   /* We have been told expliclity this is a big-endian CPU.  Since
+    * network byte order is big-endian, there is nothing to do.
+    */
+
+   return uTmp;
+
+#elif defined(USEFULBUF_CONFIG_HTON)
+   /* We have been told to use ntoh(), the system function to handle
+    * big- and little-endian. This works on both big- and
+    * little-endian machines, but ntoh() is not always available or in
+    * a standard place so it is not used by default. On some CPUs the
+    * code for this is very compact through use of a special swap
+    * instruction.
+    */
+
+   return ntohll(uTmp);
+
+#else
+   /* Little-endian (since it is not USEFULBUF_CONFIG_BIG_ENDIAN) and
+    * USEFULBUF_CONFIG_BSWAP (since it is not USEFULBUF_CONFIG_HTON).
+    * __builtin_bswap64() and friends are not conditional on CPU
+    * endianness so this must only be used on little-endian machines.
+    */
+
+   return __builtin_bswap64(uTmp);
+
+
+#endif
+
+#else
+   /* This is the default code that works on every CPU and every
+    * endianness with no dependency on ntoh().  This works on CPUs
+    * that either allow or do not allow unaligned access. It will
+    * always work, but usually is a little less efficient than ntoh().
+    */
+
+   return   ((uint64_t)pResult[0]<<56) +
+            ((uint64_t)pResult[1]<<48) +
+            ((uint64_t)pResult[2]<<40) +
+            ((uint64_t)pResult[3]<<32) +
+            ((uint64_t)pResult[4]<<24) +
+            ((uint64_t)pResult[5]<<16) +
+            ((uint64_t)pResult[6]<<8)  +
+            (uint64_t)pResult[7];
+#endif
+}
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+static inline float UsefulInputBuf_GetFloat(UsefulInputBuf *pMe)
+{
+   uint32_t uResult = UsefulInputBuf_GetUint32(pMe);
+
+   return uResult ? UsefulBufUtil_CopyUint32ToFloat(uResult) : 0;
+}
+
+
+static inline double UsefulInputBuf_GetDouble(UsefulInputBuf *pMe)
+{
+   uint64_t uResult = UsefulInputBuf_GetUint64(pMe);
+
+   return uResult ? UsefulBufUtil_CopyUint64ToDouble(uResult) : 0;
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+static inline int UsefulInputBuf_GetError(UsefulInputBuf *pMe)
+{
+   return pMe->err;
+}
+
+
+static inline void UsefulInputBuf_SetBufferLength(UsefulInputBuf *pMe, size_t uNewLen)
+{
+    pMe->UB.len = uNewLen;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _UsefulBuf_h */
+
+
diff --git a/core/lib/qcbor/inc/qcbor/qcbor.h b/core/lib/qcbor/inc/qcbor/qcbor.h
new file mode 100644
index 0000000000000000000000000000000000000000..968a85693425ef0a3cc9a184d824bce584be5286
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor.h
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*==============================================================================
+ Copyright (c) 2016-2018, The Linux Foundation.
+ Copyright (c) 2018-2020, Laurence Lundblade.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of The Linux Foundation nor the names of its
+ contributors, nor the name "Laurence Lundblade" may be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ =============================================================================*/
+
+/**
+ * @file qcbor.h
+ *
+ * Backwards compatibility for includers of qcbor.h (which has been split
+ * into four include files).
+ */
+
+#include "qcbor_encode.h"
+#include "qcbor_decode.h"
diff --git a/core/lib/qcbor/inc/qcbor/qcbor_common.h b/core/lib/qcbor/inc/qcbor/qcbor_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b06918d185aae5e7914d7844914f911696a42e5
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor_common.h
@@ -0,0 +1,586 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+
+#ifndef qcbor_common_h
+#define qcbor_common_h
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} // Keep editor indention formatting happy
+#endif
+#endif
+
+
+/**
+ * @file qcbor_common.h
+ *
+ * Constant values for types, error codes and such that are common to
+ * encoding and decoding.
+ */
+
+
+/**
+ * Semantic versioning for QCBOR x.y.z from 1.3.0 on
+ *
+ * Note:
+ *   - QCBOR 1.2 is indicated by the #define QCBOR_1_2
+ *   - QCBOR 1.1 is indicated by the #define QCBOR_1_1
+ *   - QCBOR 1.0 is indicated by the absence of all the above
+ */
+#define QCBOR_VERSION_MAJOR 1
+#define QCBOR_VERSION_MINOR 4
+#define QCBOR_VERSION_PATCH 1
+
+
+/**
+ * This define indicates a version of QCBOR that supports spiffy
+ * decode, the decode functions found in qcbor_spiffy_decode.h.
+ *
+ * Versions of QCBOR that support spiffy decode are backwards
+ * compatible with previous versions, but there are a few minor
+ * exceptions such as some aspects of tag handling that are
+ * different. This define can be used to handle these variances.
+ */
+#define QCBOR_SPIFFY_DECODE
+
+
+
+/* Standard CBOR Major type for positive integers of various lengths. */
+#define CBOR_MAJOR_TYPE_POSITIVE_INT 0
+
+/* Standard CBOR Major type for negative integer of various lengths. */
+#define CBOR_MAJOR_TYPE_NEGATIVE_INT 1
+
+/* Standard CBOR Major type for an array of arbitrary 8-bit bytes. */
+#define CBOR_MAJOR_TYPE_BYTE_STRING  2
+
+/* Standard CBOR Major type for a UTF-8 string. Note this is true 8-bit UTF8
+ * with no encoding and no NULL termination. */
+#define CBOR_MAJOR_TYPE_TEXT_STRING  3
+
+/* Standard CBOR Major type for an ordered array of other CBOR data items. */
+#define CBOR_MAJOR_TYPE_ARRAY        4
+
+/* Standard CBOR Major type for CBOR MAP. Maps an array of pairs. The
+ * first item in the pair is the "label" (key, name or identfier) and the second
+ * item is the value.  */
+#define CBOR_MAJOR_TYPE_MAP          5
+
+/* Standard CBOR major type for a tag number. This creates a CBOR "tag" that
+ * is the tag number and a data item that follows as the tag content.
+ *
+ * Note that this was called an optional tag in RFC 7049, but there's
+ * not really anything optional about it. It was misleading. It is
+ * renamed in RFC 8949.
+ */
+#define CBOR_MAJOR_TYPE_TAG          6
+#define CBOR_MAJOR_TYPE_OPTIONAL     6
+
+/* Standard CBOR simple types like float, the values true, false, null... */
+#define CBOR_MAJOR_TYPE_SIMPLE       7
+
+
+
+
+/*
+ * Tags that are used with CBOR_MAJOR_TYPE_OPTIONAL. These
+ * are types defined in RFC 8949 and some additional ones
+ * in the IANA CBOR tags registry.
+ */
+/** See QCBOREncode_AddDateString(). */
+#define CBOR_TAG_DATE_STRING    0
+/** See QCBOREncode_AddDateEpoch(). */
+#define CBOR_TAG_DATE_EPOCH     1
+/** See QCBOREncode_AddPositiveBignum(). */
+#define CBOR_TAG_POS_BIGNUM     2
+/** See QCBOREncode_AddNegativeBignum(). */
+#define CBOR_TAG_NEG_BIGNUM     3
+/** CBOR tag for a two-element array representing a fraction with a
+ *  mantissa and base-10 scaling factor. See
+ *  QCBOREncode_AddDecimalFraction() and @ref expAndMantissa. */
+#define CBOR_TAG_DECIMAL_FRACTION  4
+/** CBOR tag for a two-element array representing a fraction with a
+ *  mantissa and base-2 scaling factor. See QCBOREncode_AddBigFloat()
+ *  and @ref expAndMantissa. */
+#define CBOR_TAG_BIGFLOAT       5
+/** Not Decoded by QCBOR. Tag for COSE format encryption with no
+ *  recipient identification. See [RFC 8152, COSE]
+ *  (https://tools.ietf.org/html/rfc8152). No API is provided for this
+ *  tag. */
+#define CBOR_TAG_COSE_ENCRYPT0 16
+#define CBOR_TAG_COSE_ENCRYPTO 16
+/** Not Decoded by QCBOR. Tag for COSE format MAC'd data with no
+ *  recipient identification. See [RFC 8152, COSE]
+ *  (https://tools.ietf.org/html/rfc8152). No API is provided for this
+ *  tag. */
+#define CBOR_TAG_COSE_MAC0     17
+/** Tag for COSE format single signature signing. No API is provided
+ *  for this tag. See [RFC 8152, COSE]
+ *  (https://tools.ietf.org/html/rfc8152). */
+#define CBOR_TAG_COSE_SIGN1    18
+/** A hint that the following byte string should be encoded in
+ *  Base64URL when converting to JSON or similar text-based
+ *  representations. Call @c
+ *  QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B64URL) before the call to
+ *  QCBOREncode_AddBytes(). */
+#define CBOR_TAG_ENC_AS_B64URL 21
+/** A hint that the following byte string should be encoded in Base64
+ *  when converting to JSON or similar text-based
+ *  representations. Call @c
+ *  QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B64) before the call to
+ *  QCBOREncode_AddBytes(). */
+#define CBOR_TAG_ENC_AS_B64    22
+/** A hint that the following byte string should be encoded in base-16
+ *  format per [RFC 4648] (https://tools.ietf.org/html/rfc4648) when
+ *  converting to JSON or similar text-based
+ *  representations. Essentially, Base-16 encoding is the standard
+ *  case- insensitive hex encoding and may be referred to as
+ *  "hex". Call @c QCBOREncode_AddTag(pCtx,CBOR_TAG_ENC_AS_B16) before
+ *  the call to QCBOREncode_AddBytes(). */
+#define CBOR_TAG_ENC_AS_B16    23
+/** See QCBORDecode_EnterBstrWrapped()). */
+#define CBOR_TAG_CBOR          24
+/** See QCBOREncode_AddURI(). */
+#define CBOR_TAG_URI           32
+/** See QCBOREncode_AddB64URLText(). */
+#define CBOR_TAG_B64URL        33
+/** See QCBOREncode_AddB64Text(). */
+#define CBOR_TAG_B64           34
+/** See QCBOREncode_AddRegex(). */
+#define CBOR_TAG_REGEX         35
+/** See QCBOREncode_AddMIMEData(). */
+#define CBOR_TAG_MIME          36
+/** See QCBOREncode_AddBinaryUUID(). */
+#define CBOR_TAG_BIN_UUID      37
+/** The data is a CBOR Web Token per [RFC 8392]
+ *  (https://tools.ietf.org/html/rfc8932). No API is provided for this
+ *  tag. */
+#define CBOR_TAG_CWT           61
+/** Tag for COSE format encryption. See [RFC 8152, COSE]
+ *  (https://tools.ietf.org/html/rfc8152). No API is provided for this
+ *  tag. */
+#define CBOR_TAG_CBOR_SEQUENCE 63
+/** Not Decoded by QCBOR. Tag for COSE format encrypt. See [RFC 8152, COSE]
+ *  (https://tools.ietf.org/html/rfc8152). No API is provided for this
+ *  tag. */
+#define CBOR_TAG_COSE_ENCRYPT  96
+#define CBOR_TAG_ENCRYPT       96
+/** Not Decoded by QCBOR. Tag for COSE format MAC. See [RFC 8152, COSE]
+    (https://tools.ietf.org/html/rfc8152). No API is provided for this
+    tag. */
+#define CBOR_TAG_COSE_MAC      97
+#define CBOR_TAG_MAC           97
+/** Not Decoded by QCBOR. Tag for COSE format signed data. See [RFC 8152, COSE]
+    (https://tools.ietf.org/html/rfc8152). No API is provided for this
+    tag. */
+#define CBOR_TAG_COSE_SIGN     98
+#define CBOR_TAG_SIGN          98
+/** Tag for date counted by days from Jan 1 1970 per [RFC 8943]
+ *  (https://tools.ietf.org/html/rfc8943). See
+ *  QCBOREncode_AddTDaysEpoch(). */
+#define CBOR_TAG_DAYS_EPOCH    100
+/** Not Decoded by QCBOR. World geographic coordinates. See ISO 6709, [RFC 5870]
+ *  (https://tools.ietf.org/html/rfc5870) and WGS-84. No API is
+ *  provided for this tag. */
+#define CBOR_TAG_GEO_COORD     103
+/** Binary MIME.*/
+#define CBOR_TAG_BINARY_MIME   257
+/** Tag for date string without time or time zone per [RFC 8943]
+ *  (https://tools.ietf.org/html/rfc8943). See
+ *  QCBOREncode_AddTDaysString(). */
+#define CBOR_TAG_DAYS_STRING   1004
+/** The magic number, self-described CBOR. No API is provided for this
+ * tag. */
+#define CBOR_TAG_CBOR_MAGIC    55799
+
+/** The 16-bit invalid tag from the CBOR tags registry */
+#define CBOR_TAG_INVALID16 0xffff
+/** The 32-bit invalid tag from the CBOR tags registry */
+#define CBOR_TAG_INVALID32 0xffffffff
+/** The 64-bit invalid tag from the CBOR tags registry */
+#define CBOR_TAG_INVALID64 0xffffffffffffffff
+
+
+
+
+/**
+ * Error codes returned by QCBOR Encoder-Decoder.
+ *
+ * They are grouped to keep the code size of
+ * QCBORDecode_IsNotWellFormedError() and
+ * QCBORDecode_IsUnrecoverableError() minimal.
+ *
+ *    1..19: Encode errors
+ *    20..: Decode errors
+ *    20-39: QCBORDecode_IsNotWellFormedError()
+ *    30..59: QCBORDecode_IsUnrecoverableError()
+ *    60..: Other decode errors
+ *
+ * Error renumbering may occur in the future when new error codes are
+ * added for new QCBOR features.
+ */
+typedef enum {
+   /** The encode or decode completed correctly. */
+   QCBOR_SUCCESS = 0,
+
+   /** The buffer provided for the encoded output when doing encoding
+    *   was too small and the encoded output will not fit. */
+   QCBOR_ERR_BUFFER_TOO_SMALL = 1,
+
+   /** During encoding, an attempt to create simple value between 24
+    *  and 31. */
+   QCBOR_ERR_ENCODE_UNSUPPORTED = 2,
+
+   /** During encoding, the length of the encoded CBOR exceeded
+    *  @ref QCBOR_MAX_ARRAY_OFFSET, which is slightly less than
+    *  @c UINT32_MAX. */
+   QCBOR_ERR_BUFFER_TOO_LARGE = 3,
+
+   /** During encoding, the array or map nesting was deeper than this
+    *  implementation can handle. Note that in the interest of code
+    *  size and memory use, QCBOR has a hard limit on array
+    *  nesting. The limit is defined as the constant
+    *  @ref QCBOR_MAX_ARRAY_NESTING. */
+   QCBOR_ERR_ARRAY_NESTING_TOO_DEEP = 4,
+
+   /** During encoding, @c QCBOREncode_CloseXxx() called for a
+    *  different type than is currently open.  */
+   QCBOR_ERR_CLOSE_MISMATCH = 5,
+
+   /** During encoding, the array or map had too many items in it.
+    *  This limit @ref QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,535. */
+   QCBOR_ERR_ARRAY_TOO_LONG = 6,
+
+   /** During encoding, more arrays or maps were closed than
+    *  opened. This is a coding error on the part of the caller of the
+    *  encoder. */
+   QCBOR_ERR_TOO_MANY_CLOSES = 7,
+
+   /** During encoding, the number of array or map opens was not
+    *  matched by the number of closes. Also occurs with opened byte
+    *  strings that are not closed. */
+   QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN = 8,
+
+   /** During encoding, opening a byte string while a byte string is
+    *  open is not allowed. */
+   QCBOR_ERR_OPEN_BYTE_STRING = 9,
+
+   /** Trying to cancel a byte string wrapping after items have been
+    *  added to it. */
+   QCBOR_ERR_CANNOT_CANCEL = 10,
+
+#define QCBOR_START_OF_NOT_WELL_FORMED_ERRORS 20
+
+   /** During decoding, the CBOR is not well-formed because a simple
+    *  value between 0 and 31 is encoded in a two-byte integer rather
+    *  than one. */
+   QCBOR_ERR_BAD_TYPE_7 = 20,
+
+   /** During decoding, returned by QCBORDecode_Finish() if all the
+    *  inputs bytes have not been consumed. This is considered not
+    *  well-formed. */
+   QCBOR_ERR_EXTRA_BYTES = 21,
+
+   /** During decoding, some CBOR construct was encountered that this
+    *  decoder doesn't support, primarily this is the reserved
+    *  additional info values, 28 through 30. The CBOR is not
+    *  well-formed.
+    */
+   QCBOR_ERR_UNSUPPORTED = 22,
+
+   /** During decoding, the an array or map was not fully consumed.
+    *  Returned by QCBORDecode_Finish(). The CBOR is not
+    *  well-formed. */
+   QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED = 23,
+
+   /** During decoding, an integer type is encoded with a bad length
+    *  (that of an indefinite length string). The CBOR is not-well
+    *  formed. */
+   QCBOR_ERR_BAD_INT = 24,
+
+#define QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS 30
+
+   /** During decoding, one of the chunks in an indefinite-length
+    *  string is not of the type of the start of the string.  The CBOR
+    *  is not well-formed.  This error makes no further decoding
+    *  possible. */
+   QCBOR_ERR_INDEFINITE_STRING_CHUNK = 30,
+
+   /** During decoding, hit the end of the given data to decode. For
+    *  example, a byte string of 100 bytes was expected, but the end
+    *  of the input was hit before finding those 100 bytes.  Corrupted
+    *  CBOR input will often result in this error. See also
+    *  @ref QCBOR_ERR_NO_MORE_ITEMS. The CBOR is not well-formed.
+    *  This error makes no further decoding possible. */
+   QCBOR_ERR_HIT_END = 31,
+
+   /** During decoding, a break occurred outside an indefinite-length
+    *  item. The CBOR is not well-formed. This error makes no further
+    *  decoding possible. */
+   QCBOR_ERR_BAD_BREAK = 32,
+
+#define QCBOR_END_OF_NOT_WELL_FORMED_ERRORS 39
+
+   /** During decoding, the input is too large. It is greater than
+    *  QCBOR_MAX_DECODE_INPUT_SIZE. This is an implementation limit.
+    *  This error makes no further decoding possible. */
+   QCBOR_ERR_INPUT_TOO_LARGE = 40,
+
+   /** During decoding, the array or map nesting was deeper than this
+    *  implementation can handle. Note that in the interest of code
+    *  size and memory use, QCBOR has a hard limit on array
+    *  nesting. The limit is defined as the constant
+    *  @ref QCBOR_MAX_ARRAY_NESTING. This error makes no further
+    *  decoding possible. */
+   QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP = 41,
+
+   /** During decoding, the array or map had too many items in it.
+    *  This limit @ref QCBOR_MAX_ITEMS_IN_ARRAY, typically 65,534,
+    *  UINT16_MAX - 1. This error makes no further decoding
+    *  possible. */
+   QCBOR_ERR_ARRAY_DECODE_TOO_LONG = 42,
+
+   /** When decoding, a string's size is greater than what a size_t
+    *  can hold less 4. In all but some very strange situations this
+    *  is because of corrupt input CBOR and should be treated as
+    *  such. The strange situation is a CPU with a very small size_t
+    *  (e.g., a 16-bit CPU) and a large string (e.g., > 65KB). This
+    *  error makes no further decoding possible. */
+   QCBOR_ERR_STRING_TOO_LONG = 43,
+
+   /** Something is wrong with a decimal fraction or bigfloat such as
+    *  it not consisting of an array with two integers. This error
+    *  makes no further decoding possible. */
+   QCBOR_ERR_BAD_EXP_AND_MANTISSA = 44,
+
+   /** Unable to decode an indefinite-length string because no string
+    *  allocator was configured. See QCBORDecode_SetMemPool() or
+    *  QCBORDecode_SetUpAllocator().  This error makes no further
+    *  decoding possible.*/
+   QCBOR_ERR_NO_STRING_ALLOCATOR = 45,
+
+   /** Error allocating memory for a string, usually out of memory.
+    * This primarily occurs decoding indefinite-length strings. This
+    * error makes no further decoding possible. */
+   QCBOR_ERR_STRING_ALLOCATE = 46,
+
+   /** During decoding, the type of the label for a map entry is not
+    *  one that can be handled in the current decoding mode. Typically
+    *  this is because a label is not an integer or a string. This is
+    *  an implementation limit. */
+   QCBOR_ERR_MAP_LABEL_TYPE = 47,
+
+   /** When the built-in tag decoding encounters an unexpected type,
+    *  this error is returned. This error is unrecoverable because the
+    *  built-in tag decoding doesn't try to consume the unexpected
+    *  type. In previous versions of QCBOR this was considered a
+    *  recoverable error hence @ref QCBOR_ERR_BAD_TAG_CONTENT. Going
+    *  back further, RFC 7049 use the name "optional tags". That name
+    *  is no longer used because "optional" was causing confusion. See
+    *  also @ref QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT. */
+   QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT = 48,
+   QCBOR_ERR_BAD_TAG_CONTENT = 48,
+   QCBOR_ERR_BAD_OPT_TAG = 48,
+
+   /** Indefinite length string handling is disabled and there is an
+    *  indefinite length string in the input CBOR. */
+   QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED = 49,
+
+   /** Indefinite length arrays and maps handling are disabled and
+    *  there is an indefinite length map or array in the input
+    *  CBOR. */
+   QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED = 50,
+
+   /** All decoding of tags (major type 6) has been disabled and a tag
+    *  occurred in the decode input. */
+   QCBOR_ERR_TAGS_DISABLED = 51,
+
+#define QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS 59
+
+   /** More than @ref QCBOR_MAX_TAGS_PER_ITEM tags encountered for a
+    *  CBOR ITEM.  @ref QCBOR_MAX_TAGS_PER_ITEM is a limit of this
+    *  implementation.  During decoding, too many tags in the
+    *  caller-configured tag list, or not enough space in
+    *  @ref  QCBORTagListOut. This error makes no further decoding
+    *  possible.  */
+   QCBOR_ERR_TOO_MANY_TAGS = 60,
+
+   /** When decoding for a specific type, the type was not expected.  */
+   QCBOR_ERR_UNEXPECTED_TYPE = 61,
+
+   /** Duplicate label detected in a map. */
+   QCBOR_ERR_DUPLICATE_LABEL = 62,
+
+   /** During decoding, the buffer given to QCBORDecode_SetMemPool()
+    *  is either too small, smaller than
+    *  @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE or too large, larger than
+    *  UINT32_MAX. */
+   QCBOR_ERR_MEM_POOL_SIZE = 63,
+
+   /** During decoding, an integer smaller than INT64_MIN was received
+    *  (CBOR can represent integers smaller than INT64_MIN, but C
+    *  cannot). */
+   QCBOR_ERR_INT_OVERFLOW = 64,
+
+   /** During decoding, a date greater than +- 292 billion years from
+    *  Jan 1 1970 encountered during parsing. This is an
+    *  implementation limit. */
+   QCBOR_ERR_DATE_OVERFLOW = 65,
+
+   /** During decoding, @c QCBORDecode_ExitXxx() was called for a
+    *  different type than @c QCBORDecode_EnterXxx(). */
+   QCBOR_ERR_EXIT_MISMATCH = 66,
+
+   /** All well-formed data items have been consumed and there are no
+    *  more. If parsing a CBOR stream this indicates the non-error end
+    *  of the stream. If not parsing a CBOR stream/sequence, this
+    *  probably indicates that some data items expected are not
+    *  present.  See also @ref QCBOR_ERR_HIT_END. */
+   QCBOR_ERR_NO_MORE_ITEMS = 67,
+
+   /** When finding an item by label, an item with the requested label
+    *  was not found. */
+   QCBOR_ERR_LABEL_NOT_FOUND = 68,
+
+   /** Number conversion failed because of sign. For example a
+    *  negative int64_t can't be converted to a uint64_t */
+   QCBOR_ERR_NUMBER_SIGN_CONVERSION = 69,
+
+   /** When converting a decoded number, the value is too large or too
+    *  small for the conversion target. */
+   QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW = 70,
+
+   /** Trying to get an item by label when a map has not been
+    *  entered. */
+   QCBOR_ERR_MAP_NOT_ENTERED = 71,
+
+   /** A callback indicates processing should not continue for some
+    *  non-CBOR reason. */
+   QCBOR_ERR_CALLBACK_FAIL = 72,
+
+   /** This error code is deprecated. Instead,
+    *  @ref QCBOR_ERR_HALF_PRECISION_DISABLED,
+    *  @ref QCBOR_ERR_HW_FLOAT_DISABLED or @ref QCBOR_ERR_ALL_FLOAT_DISABLED
+    *  is returned depending on the specific floating-point functionality
+    *  that is disabled and the type of floating-point input. */
+   QCBOR_ERR_FLOAT_DATE_DISABLED = 73,
+
+   /** Support for half-precision float decoding is disabled. */
+   QCBOR_ERR_HALF_PRECISION_DISABLED = 74,
+
+   /** Use of floating-point HW is disabled. This affects all type
+    *  conversions to and from double and float types. */
+   QCBOR_ERR_HW_FLOAT_DISABLED = 75,
+
+   /** Unable to complete operation because a floating-point value
+    *  that is a NaN (not a number), that is too large, too small,
+    *  infinity or -infinity was encountered in encoded CBOR. Usually
+    *  this because conversion of the float-point value was being
+    *  attempted. */
+   QCBOR_ERR_FLOAT_EXCEPTION = 76,
+
+   /** Floating point support is completely turned off,
+    *  encoding/decoding floating point numbers is not possible. */
+   QCBOR_ERR_ALL_FLOAT_DISABLED = 77,
+
+   /** Like @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT, but recoverable.
+    * If an implementation decodes a tag and can and does consume the
+    * whole tag contents when it is not the correct tag content, this
+    * error can be returned. None of the built-in tag decoders do this
+    * (to save object code). */
+   QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT = 78,
+
+   /** QCBORDecode_EnterBstrWrapped() cannot be used on
+    * indefinite-length strings because they exist in memory pool for
+    * a @ref QCBORStringAllocate. */
+   QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING = 79,
+
+   /** A range of error codes that can be made use of by the
+    * caller. QCBOR internally does nothing with these except notice
+    * that they are not QCBOR_SUCCESS. See QCBORDecode_SetError(). */
+   QCBOR_ERR_FIRST_USER_DEFINED = 128,
+
+   /** See \ref QCBOR_ERR_FIRST_USER_DEFINED */
+   QCBOR_ERR_LAST_USER_DEFINED = 255
+
+   /* This is stored in uint8_t; never add values > 255 */
+} QCBORError;
+
+
+/**
+ * @brief Get string describing an error code.
+ *
+ * @param[in] uErr   The error code.
+ *
+ * @return  NULL-terminated string describing error or "Unidentified
+ *          error" if the error is not known.
+ *
+ * This is not thread-safe because it uses a static buffer
+ * for formatting, but this is only a diagnostic and the only
+ * consequence is the wrong description.
+ */
+const char *
+qcbor_err_to_str(QCBORError uErr);
+
+
+
+
+/**
+ * The maximum nesting of arrays and maps when encoding or
+ * decoding. The error @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP will be
+ * returned on encoding or @ref QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP on
+ * decoding if it is exceeded. Do not increase this over 255.
+ */
+#define QCBOR_MAX_ARRAY_NESTING  15
+
+
+/**
+ * The maximum number of items in a single array or map when encoding or
+ * decoding.
+ */
+#define QCBOR_MAX_ITEMS_IN_ARRAY (UINT16_MAX-1) /* -1 is because the
+                                                 * value UINT16_MAX is
+                                                 * used to indicate
+                                                 * indefinite-length.
+                                                 */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_common_h */
diff --git a/core/lib/qcbor/inc/qcbor/qcbor_decode.h b/core/lib/qcbor/inc/qcbor/qcbor_decode.h
new file mode 100644
index 0000000000000000000000000000000000000000..6efd404c9569c4bf9cb29ad8bc94d3c21fddb1f8
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor_decode.h
@@ -0,0 +1,1669 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ===========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+
+#ifndef qcbor_decode_h
+#define qcbor_decode_h
+
+
+#include "qcbor/qcbor_common.h"
+#include "qcbor/qcbor_private.h"
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} /* Keep editor indention formatting happy */
+#endif
+#endif
+
+
+/**
+ * @file qcbor_decode.h
+ *
+ * @anchor BasicDecode
+ * # QCBOR Basic Decode
+ *
+ * This section discusses decoding assuming familiarity with the
+ * general description of this encoder-decoder in section @ref
+ * Overview.
+ *
+ * Encoded CBOR has a tree structure where the leaf nodes are
+ * non-aggregate types like integers and strings and the intermediate
+ * nodes are either arrays or maps. Fundamentally, CBOR decoding is a
+ * pre-order traversal of this tree with CBOR sequences a minor
+ * exception. Calling QCBORDecode_GetNext() repeatedly will perform
+ * this. QCBOR maintains an internal traversal cursor. It is possible
+ * to decode any CBOR by only calling QCBORDecode_GetNext(), though
+ * this doesn't take advantage of many QCBOR features.
+ *
+ * QCBORDecode_GetNext() returns a 56 byte structure called
+ * @ref QCBORItem that describes the decoded item including:
+ * - The data itself, integer, string, floating-point number...
+ * - The label if present
+ * - Unprocessed tags
+ * - Nesting level
+ * - Allocation type (primarily of interest for indefinite length strings)
+ *
+ * For strings, this structure contains a pointer and length back into
+ * the original data.
+ *
+ * Most of the tags that QCBOR supports directly are decoded into a
+ * representation in @ref QCBORItem.
+ *
+ * A string allocator must be used when decoding indefinite length
+ * strings. See QCBORDecode_SetMemPool() or
+ * QCBORDecode_SetUpAllocator(). @ref QCBORItem indicates if a string
+ * was allocated with the string allocator.
+ *
+ * This pre-order traversal gives natural decoding of arrays where the
+ * array members are taken in order. Maps can be decoded this way too,
+ * but the @ref SpiffyDecode APIs that allow searching maps by label
+ * are often more convenient.
+ *
+ * @anchor Decode-Errors-Overview
+ * # Decode Errors Overview
+ *
+ * The simplest way to handle decoding errors is to make use of the
+ * internal error tracking. The only error code check necessary is
+ * at the end when QCBORDecode_Finish() is called. To do this:
+ *
+ * - Use QCBORDecode_VGetNext(), QCBORDecode_VPeekNext()
+ *  and any or all of the functions in qcbor_spiffy_decode.h. Don't use
+ *  QCBORDecode_GetNext() or QCBORDecode_PeekNext().
+ * - Call QCBORDecode_Finish() and check its return code.
+ * - Do not reference any decoded data until after
+ *    QCBORDecode_Finish() returns success.
+ *
+ * Once an encoding error has been encountered, the error state is
+ * entered and further decoding function calls will do nothing.  It is
+ * safe to continue calling decoding functions after an error. No
+ * error checking is necessary making the code to decode a protocol
+ * simpler.  The two exceptions are QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext() which will try to decode even if the decoder
+ * is in the error state. Use QCBORDecode_VGetNext() and
+ * QCBORDecode_VPeekNext() instead.
+ *
+ * While some protocols are simple enough to be decoded this way, many
+ * aren’t because the data items earlier in the protocol determine how
+ * later data items are to be decoded. In that case it is necessary to
+ * call QCBORDecode_GetError() to know the earlier items were
+ * successfully decoded before examining their value or type.
+ *
+ * The internal decode error state can be reset by reinitializing the
+ * decoder or calling QCBORDecode_GetErrorAndReset(). Code calling
+ * QCBOR may take advantage of the internal error state to halt
+ * futher decoding and propagate errors it detects using
+ * QCBORDecode_SetError().
+ *
+ * It is only useful to reset the error state by calling
+ * QCBORDecode_GetErrorAndReset() on recoverable errors. Examples of
+ * recoverable errors are a map entry not being found or integer
+ * overflow or underflow during conversion. Examples of unrecoverable
+ * errors are hitting the end of the input and array or map nesting
+ * beyond the limits of the implementation. See
+ * QCBORDecode_IsUnrecoverableError().Trying to reset and decode after
+ * an unrecoverable error will usually just lead to another error.
+ *
+ * It is possible to use QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext() to decode an entire protocol. However, that is
+ * usually more work, more code and less convenient than using spiffy
+ * decode functions.
+ *
+ * It is also possible to mix the use of QCBORDecode_GetNext() with
+ * QCBORDecode_VGetNext() and the spiffy decode functions, but
+ * QCBORDecode_GetError() must be called and return QCBOR_SUCCESS before
+ * QCBORDecode_GetNext() is called.
+ *
+ * The effect of a decoding error on the traversal cursor position
+ * varies by the decoding method called. It is unaffected by spiffy
+ * decode methods that get items by map label.
+ * QCBORDecode_GetInt64InMapN() is an example of this. The traversal
+ * cursor will be advanced by most other decode methods even when
+ * there is a decode error, often leaving it in an indeterminate
+ * position. If it is necessary to continue to decoding after an
+ * error, QCBORDecode_Rewind() can be used to reset it to a known-good
+ * position.
+ *
+ * When using spiffy decode methods to get an item by label from a map
+ * the whole map is internally traversed including nested arrays and
+ * maps. If there is any unrecoverable error during that traversal,
+ * the retrieval by label will fail. The unrecoverable error will be
+ * returned even if it is not because the item being sought is in
+ * error. Recoverable errors will be ignored unless they are on the
+ * item being sought, in which case the unrecoverable error will be
+ * returned. Unrecoverable errors are those indicated by
+ * QCBORDecode_IsUnrecoverableError().
+ *
+ * @anchor Disabilng-Tag-Decoding
+ * # Disabilng Tag Decoding
+ *
+ * If QCBOR_DISABLE_TAGS is defined, all code for decoding tags will
+ * be omitted reducing the core decoder, QCBORDecode_VGetNext(), by
+ * about 400 bytes. If a tag number is encountered in the decoder
+ * input the unrecoverable error @ref QCBOR_ERR_TAGS_DISABLED will be
+ * returned.  No input with tags can be decoded.
+ *
+ * Decode functions like QCBORDecode_GetEpochDate() and
+ * QCBORDecode_GetDecimalFraction() that can decode the tag content
+ * even if the tag number is absent are still available.  Typically
+ * they won't be linked in because of dead stripping. The
+ * @c uTagRequirement parameter has no effect, but if it is
+ * @ref QCBOR_TAG_REQUIREMENT_TAG, @ref QCBOR_ERR_TAGS_DISABLED
+ * will be set.
+ */
+
+/**
+ * The decode mode options.
+ */
+typedef enum {
+   /** See QCBORDecode_Init() */
+   QCBOR_DECODE_MODE_NORMAL = 0,
+   /** See QCBORDecode_Init() */
+   QCBOR_DECODE_MODE_MAP_STRINGS_ONLY = 1,
+   /** See QCBORDecode_Init() */
+   QCBOR_DECODE_MODE_MAP_AS_ARRAY = 2
+   /* This is stored in uint8_t in places; never add values > 255 */
+} QCBORDecodeMode;
+
+/**
+ * The maximum size of input to the decoder. Slightly less than
+ * @c UINT32_MAX to make room for some special indicator values.
+ */
+#define QCBOR_MAX_DECODE_INPUT_SIZE (UINT32_MAX - 2)
+
+/**
+ * The maximum number of tags that may occur on an individual nested
+ * item. Typically 4.
+ */
+#define QCBOR_MAX_TAGS_PER_ITEM QCBOR_MAX_TAGS_PER_ITEM1
+
+
+
+/* Do not renumber these. Code depends on some of these values. */
+/** The data type is unknown, unset or invalid. */
+#define QCBOR_TYPE_NONE           0
+
+/** Never used in QCBORItem. Used by functions that match QCBOR types. */
+#define QCBOR_TYPE_ANY            1
+
+/** Type for an integer that decoded either between @c INT64_MIN and
+ *  @c INT32_MIN or @c INT32_MAX and @c INT64_MAX. Data is in member
+ *  @c val.int64. */
+#define QCBOR_TYPE_INT64          2
+
+/** Type for an integer that decoded to a more than @c INT64_MAX and
+ *  @c UINT64_MAX.  Data is in member @c val.uint64. */
+#define QCBOR_TYPE_UINT64         3
+
+/** Type for an array. See comments on @c val.uCount. */
+#define QCBOR_TYPE_ARRAY          4
+
+/** Type for a map. See comments on @c val.uCount. */
+#define QCBOR_TYPE_MAP            5
+
+/** Type for a buffer full of bytes. Data is in @c val.string. */
+#define QCBOR_TYPE_BYTE_STRING    6
+
+/** Type for a UTF-8 string. It is not NULL-terminated. See
+ *  QCBOREncode_AddText() for a discussion of line endings in CBOR. Data
+ *  is in @c val.string.  */
+#define QCBOR_TYPE_TEXT_STRING    7
+
+/** Type for a positive big number. Data is in @c val.bignum, a
+ *  pointer and a length. */
+#define QCBOR_TYPE_POSBIGNUM      9
+
+/** Type for a negative big number. Data is in @c val.bignum, a
+ *  pointer and a length. */
+#define QCBOR_TYPE_NEGBIGNUM     10
+
+/** Type for [RFC 3339] (https://tools.ietf.org/html/rfc3339) date
+ *  string, possibly with time zone. Data is in @c val.string . Note this
+ *  was previously in @c val.dateString, however this is the same as
+ *  val.string being the same type in same union. val.dateString will
+ *  be deprecated.. */
+#define QCBOR_TYPE_DATE_STRING   11
+
+/** Type for integer seconds since Jan 1970 + floating-point
+ *  fraction. Data is in @c val.epochDate */
+#define QCBOR_TYPE_DATE_EPOCH    12
+
+/** The CBOR major type "simple" has a small integer value indicating
+ *  what it is. The standard CBOR simples are true, false, null, undef
+ *  (values 20-23) and float-point numbers (values 25-27).  The values
+ *  0-19 and 32-255 are unassigned and may be used if registered with
+ *  in the IANA Simple Values Registry.  If these unassigned simple
+ *  values occur in the input they will be decoded as this.  The value
+ *  is in @c val.uSimple. */
+#define QCBOR_TYPE_UKNOWN_SIMPLE 13
+
+/** A decimal fraction made of decimal exponent and integer mantissa.
+ *  See @ref expAndMantissa and QCBOREncode_AddDecimalFraction(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION            14
+
+/** A decimal fraction made of decimal exponent and positive big
+ *  number mantissa. See @ref expAndMantissa and
+ *  QCBOREncode_AddDecimalFractionBigNum(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM 15
+
+/** A decimal fraction made of decimal exponent and negative big
+ *  number mantissa. See @ref expAndMantissa and
+ *  QCBOREncode_AddDecimalFractionBigNum(). */
+#define QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM 16
+
+/** A floating-point number made of base-2 exponent and integer
+ *  mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddBigFloat(). */
+#define QCBOR_TYPE_BIGFLOAT                    17
+
+/** A floating-point number made of base-2 exponent and positive big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddBigFloatBigNum(). */
+#define QCBOR_TYPE_BIGFLOAT_POS_BIGNUM         18
+
+/** A floating-point number made of base-2 exponent and negative big
+ *  number mantissa.  See @ref expAndMantissa and
+ *  QCBOREncode_AddBigFloatBigNum(). */
+#define QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM         19
+
+/** Type for the simple value false. */
+#define QCBOR_TYPE_FALSE         20
+
+/** Type for the simple value true. */
+#define QCBOR_TYPE_TRUE          21
+
+/** Type for the simple value null. */
+#define QCBOR_TYPE_NULL          22
+
+/** Type for the simple value undef. */
+#define QCBOR_TYPE_UNDEF         23
+
+/** Type for a floating-point number. Data is in @c val.fnum. */
+#define QCBOR_TYPE_FLOAT         26
+
+/** Type for a double floating-point number. Data is in @c val.dfnum. */
+#define QCBOR_TYPE_DOUBLE        27
+
+#define QCBOR_TYPE_BREAK         31 /* Used internally; never returned */
+
+/** For @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY decode mode, a map that is
+ *  being traversed as an array. See QCBORDecode_Init() */
+#define QCBOR_TYPE_MAP_AS_ARRAY  32
+
+/** Encoded CBOR that is wrapped in a byte string. Often used when the
+ *  CBOR is to be hashed for signing or HMAC. See also @ref
+ *  QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE. Data is in @c val.string. */
+#define QBCOR_TYPE_WRAPPED_CBOR  36
+
+/** A URI as defined in RFC 3986.  Data is in @c val.string. */
+#define QCBOR_TYPE_URI           44
+
+/** Text is base64 URL encoded in RFC 4648.  The base64 encoding is
+ *  NOT removed. Data is in @c val.string. */
+#define QCBOR_TYPE_BASE64URL     45
+
+/** Text is base64 encoded in RFC 4648.  The base64 encoding is NOT
+ *  removed. Data is in @c val.string. */
+#define QCBOR_TYPE_BASE64        46
+
+/** PERL-compatible regular expression. Data is in @c val.string. */
+#define QCBOR_TYPE_REGEX         47
+
+/** Non-binary MIME per RFC 2045.  See also @ref
+ *  QCBOR_TYPE_BINARY_MIME. Data is in @c val.string. */
+#define QCBOR_TYPE_MIME          48
+
+/** Binary UUID per RFC 4122.  Data is in @c val.string. */
+#define QCBOR_TYPE_UUID          49
+
+/** A CBOR sequence per RFC 8742. See also @ ref
+ *  QBCOR_TYPE_WRAPPED_CBOR.  Data is in @c val.string. */
+#define QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE  75
+
+/** Binary MIME per RFC 2045. See also @ref QCBOR_TYPE_MIME. Data is
+ *  in @c val.string. */
+#define QCBOR_TYPE_BINARY_MIME   76
+
+/** Type for [RFC 8943](https://tools.ietf.org/html/rfc8943) date
+ *  string, a date with no time or time zone info. Data is in
+ *  @c val.string */
+#define QCBOR_TYPE_DAYS_STRING   77
+
+/** Type for integer days since Jan 1 1970 described in
+ *  [RFC 8943](https://tools.ietf.org/html/rfc8943). Data is in
+ *  @c val.epochDays */
+#define QCBOR_TYPE_DAYS_EPOCH    78
+
+#define QCBOR_TYPE_TAG          254 /* Used internally; never returned */
+
+#define QCBOR_TYPE_OPTTAG   QCBOR_TYPE_TAG /* Depricated. See QCBOR_TYPE_TAG */
+
+
+
+/**
+ * The largest value in @c utags that is unmapped and can be used without
+ * mapping it through QCBORDecode_GetNthTag().
+ */
+#define QCBOR_LAST_UNMAPPED_TAG (CBOR_TAG_INVALID16 - QCBOR_NUM_MAPPED_TAGS - 1)
+
+
+/**
+ * This holds a decoded data item. It is returned by the
+ * QCBORDecode_GetNext(), the principle decoding function.
+ * It holds the type, value, label, tags and other details
+ * of the decoded data item.
+ *
+ * This is typically 56 bytes on 64-bit CPUs and 52 bytes on 32-bit
+ * CPUs (the CPU and the system's ABI determine this size).
+ */
+typedef struct _QCBORItem {
+   /** Tells what element of the @c val union to use. One of @ref
+    *  QCBOR_TYPE_INT64, @ref QCBOR_TYPE_ARRAY, ...*/
+   uint8_t  uDataType;
+
+   /** Tells what element of the @c label union to use. One of
+    *  @ref QCBOR_TYPE_INT64, @ref QCBOR_TYPE_BYTE_STRING, ...*/
+   uint8_t  uLabelType;
+
+   /** Holds the nesting depth for arrays and map. 0 is the top level
+    *  with no arrays or maps entered. */
+   uint8_t  uNestingLevel;
+
+   /** Holds the nesting level of the next item after this one.  If
+    *  less than @c uNestingLevel, this item was the last one in an
+    *  arry or map and it closed out at least one nesting level. */
+   uint8_t  uNextNestLevel;
+
+   /** 1 if a @c val that is a string is allocated with string
+    * allocator, 0 if not. Always 0 unless an allocator has been set
+    * up by calling QCBORDecode_SetMemPool() or
+    * QCBORDecode_SetUpAllocator(). */
+   uint8_t  uDataAlloc;
+
+   /** 1 if a @c label that is a string is allocated with string
+    * allocator, 0 if not. Always 0 unless an allocator has been set
+    * up by calling QCBORDecode_SetMemPool() or
+    * QCBORDecode_SetUpAllocator(). */
+   uint8_t  uLabelAlloc;
+
+   /** The union holding the item's value. Select union member based
+    *  on @c uDataType. */
+   union {
+      /** The value for @c uDataType @ref QCBOR_TYPE_INT64. */
+      int64_t     int64;
+      /** The value for @c uDataType @ref QCBOR_TYPE_UINT64. */
+      uint64_t    uint64;
+      /** The value for @c uDataType @ref QCBOR_TYPE_BYTE_STRING and
+       *  @ref QCBOR_TYPE_TEXT_STRING. Also
+       *  for many tags whose content is a string such @ref QCBOR_TYPE_DAYS_STRING
+       *  and @ref QCBOR_TYPE_URI. */
+      UsefulBufC  string;
+      /** The "value" for @c uDataType @ref QCBOR_TYPE_ARRAY or @ref
+       *  QCBOR_TYPE_MAP, the number of items in the array or map.  It
+       *  is @c UINT16_MAX when decoding indefinite-lengths maps and
+       *  arrays. Detection of the end of a map or array is best done
+       *  with @c uNestLevel and @c uNextNestLevel so as to work for
+       *  both definite and indefinite length maps and arrays. */
+      uint16_t    uCount;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+      /** The value for @c uDataType @ref QCBOR_TYPE_DOUBLE. */
+      double      dfnum;
+      /** The value for @c uDataType @ref QCBOR_TYPE_FLOAT. */
+      float       fnum;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+      /** The value for @c uDataType @ref QCBOR_TYPE_DATE_EPOCH, the
+       *  number of seconds after or before Jan 1, 1970. This has a
+       *  range of 500 billion years. Floating-point dates are
+       *  converted to this integer + fractional value. If the input
+       *  value is beyond the 500 billion-year range (e.g., +/i
+       *  infinity, large floating point values, NaN)
+       *  @ref QCBOR_ERR_DATE_OVERFLOW will be returned. If the input
+       *  is floating-point and QCBOR has been compiled with
+       *  floating-point disabled, one of the various floating-point
+       *  disabled errors will be returned. */
+      struct {
+         int64_t  nSeconds;
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+         double   fSecondsFraction;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+      } epochDate;
+
+      /** The value for @c uDataType @ref QCBOR_TYPE_DAYS_EPOCH -- the
+       *  number of days before or after Jan 1, 1970. */
+      int64_t     epochDays;
+      /** No longer used. Was the value for @ref QCBOR_TYPE_DATE_STRING,
+       * but now that value is in @c string. This will be removed in QCBOR 2.0. */
+      UsefulBufC  dateString;
+      /** The value for @c uDataType @ref QCBOR_TYPE_POSBIGNUM and
+       * @ref QCBOR_TYPE_NEGBIGNUM.  */
+      UsefulBufC  bigNum;
+      /** See @ref QCBOR_TYPE_UKNOWN_SIMPLE */
+      uint8_t     uSimple;
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      /**
+       * @anchor expAndMantissa
+       *
+       * This holds the value for big floats and decimal fractions.
+       * The use of the fields in this structure depends on @c
+       * uDataType.
+       *
+       * When @c uDataType indicates a decimal fraction, the
+       * @c nExponent is base 10. When it indicates a big float, it
+       * is base 2.
+       *
+       * When @c uDataType indicates a big number, then the @c bigNum
+       * member of @c Mantissa is valid. Otherwise the @c nInt member
+       * of @c Mantissa is valid.
+       *
+       * See @ref QCBOR_TYPE_DECIMAL_FRACTION,
+       * @ref QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+       * @ref QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM,
+       * @ref QCBOR_TYPE_BIGFLOAT, @ref QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+       * and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
+       *
+       * Also see QCBOREncode_AddTDecimalFraction(),
+       * QCBOREncode_AddTBigFloat(),
+       * QCBOREncode_AddTDecimalFractionBigNum() and
+       * QCBOREncode_AddTBigFloatBigNum().
+       */
+      struct {
+         int64_t nExponent;
+         union {
+            int64_t    nInt;
+            UsefulBufC bigNum;
+         } Mantissa;
+      } expAndMantissa;
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+      uint64_t    uTagV;  /* Used internally during decoding */
+
+   } val;
+
+   /** Union holding the different label types selected based on @c uLabelType */
+   union {
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_INT64 */
+      int64_t     int64;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      /** The label for @c uLabelType for @ref QCBOR_TYPE_UINT64 */
+      uint64_t    uint64;
+      /** The label for @c uLabelType @ref QCBOR_TYPE_BYTE_STRING and
+       *  @ref QCBOR_TYPE_TEXT_STRING */
+      UsefulBufC  string;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+   } label;
+
+#ifndef QCBOR_DISABLE_TAGS
+   /**
+    * The tags numbers for which the item is the tag content.  Tags
+    * nest, so index 0 in the array is the tag on the data item
+    * itself, index 1 is the tag that applies to the tag in index
+    * 0. The end of the list is indicated by @ref CBOR_TAG_INVALID16
+    *
+    * Tag nesting is uncommon and rarely deep. This implementation
+    * only allows nesting to a depth of @ref QCBOR_MAX_TAGS_PER_ITEM,
+    * usually 4.
+    *
+    * Tag numbers in the array below and equal to @ref
+    * QCBOR_LAST_UNMAPPED_TAG are unmapped and can be used
+    * directly. Tag numbers above this must be translated through
+    * QCBORDecode_GetNthTag().
+    *
+    * See also the large number of functions like
+    * QCBORDecode_GetEpochDate() and QCBORDecode_GetBignum() in
+    * qcbor_spiffy_decode.h for a way to decode tagged types without
+    * having to reference this array. Also see @ref Tags-Overview.
+    */
+   uint16_t uTags[QCBOR_MAX_TAGS_PER_ITEM];
+#endif
+
+} QCBORItem;
+
+/**
+ * An array or map's length is indefinite when it has this value.
+ */
+#define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX
+
+
+
+
+/**
+ * @brief Prototype for the implementation of a string allocator.
+ *
+ * @param[in] pAllocateCxt Pointer to context for the particular
+ *                         allocator implementation. Its contents
+ *                         depend on how a particular string allocator
+ *                         works. Typically, it will contain a pointer
+ *                         to the memory pool and some booking keeping
+ *                         data.
+ *
+ * @param[in] pOldMem      Points to some memory previously allocated
+ *                         that is either to be freed or to be
+ *                         reallocated to be larger. It is @c NULL for
+ *                         new allocations and when called as the
+ *                         destructor.
+ *
+ * @param[in] uNewSize     Size of memory to be allocated or new size
+ *                         for a chunk being reallocated. Zero when
+ *                         called to free memory or when called as the
+ *                         destructor.
+ *
+ * @return Either the allocated buffer is returned, or
+ *         @ref NULLUsefulBufC. @ref NULLUsefulBufC is returned on a
+ *         failed allocation and in the two cases where there is
+ *         nothing to return.
+ *
+ * This function must be implemented for a custom string
+ * allocator. See QCBORDecode_SetUpAllocator().
+ *
+ * This is not needed if the built-in string allocator available
+ * through QCBORDecode_SetMemPool() is used.
+ *
+ * After being set up by a call to QCBORDecode_SetUpAllocator(),
+ * this is called back in four modes:
+ *
+ * - allocate: @c uNewSize is the amount to allocate. @c pOldMem is
+ *  @c NULL.
+ *
+ * - free: @c uNewSize is 0. @c pOldMem points to the memory to be
+ * freed.  When the decoder calls this, it will always be for the most
+ * recent block that was either allocated or reallocated.
+ *
+ * - reallocate: @c pOldMem is the block to reallocate. @c uNewSize is
+ * its new size.  When the decoder calls this, it will always be for the
+ * most recent block that was either allocated or reallocated.
+ *
+ * - destruct: @c pOldMem is @c NULL and @c uNewSize is 0. This is
+ * called when the decoding is complete by
+ * QCBORDecode_Finish(). Usually, the strings allocated by a string
+ * allocator are in use after the decoding is completed so this
+ * usually will not free those strings. Many string allocators will
+ * not need to do anything in this mode.
+ *
+ * The strings allocated by this will have @c uDataAlloc set to true
+ * in the @ref QCBORItem when they are returned. The user of the
+ * strings will have to free them. How they free them, depends on the
+ * design of the string allocator.
+ */
+typedef UsefulBuf (* QCBORStringAllocate)(void   *pAllocateCxt,
+                                          void   *pOldMem,
+                                          size_t  uNewSize);
+
+
+/**
+ * For the built-in string allocator available via
+ * QCBORDecode_SetMemPool(), this is the size overhead needed
+ * internally.  The amount of memory available for decoded strings is
+ * the size of the buffer given to QCBORDecode_SetMemPool() less this
+ * amount.
+ *
+ * This doesn't apply to custom string allocators, only to the one
+ * available via QCBORDecode_SetMemPool().
+ */
+#define QCBOR_DECODE_MIN_MEM_POOL_SIZE 8
+
+
+
+
+/**
+ * QCBORDecodeContext holds the context for decoding CBOR.  It is
+ * about 300 bytes, so it can go on the stack.  The contents are
+ * opaque, and the caller should not access any internal items.  A
+ * context may be re-used serially as long as it is re initialized.
+ */
+typedef struct _QCBORDecodeContext QCBORDecodeContext;
+
+
+/**
+ * Initialize the CBOR decoder context.
+ *
+ * @param[in] pCtx         The context to initialize.
+ * @param[in] EncodedCBOR  The buffer with CBOR encoded bytes to be decoded.
+ * @param[in] nMode        See below and @ref QCBORDecodeMode.
+ *
+ * Initialize context for a pre-order traversal of the encoded CBOR
+ * tree.
+ *
+ * Most CBOR decoding can be completed by calling this function to
+ * start and QCBORDecode_GetNext() in a loop.
+ *
+ * If indefinite-length strings are to be decoded, then
+ * QCBORDecode_SetMemPool() or QCBORDecode_SetUpAllocator() must be
+ * called to set up a string allocator.
+ *
+ * Three decoding modes are supported.  In normal mode, @ref
+ * QCBOR_DECODE_MODE_NORMAL, maps are decoded and strings and integers
+ * are accepted as map labels. If a label is other than these, the
+ * error @ref QCBOR_ERR_MAP_LABEL_TYPE is returned by
+ * QCBORDecode_GetNext().
+ *
+ * In strings-only mode, @ref QCBOR_DECODE_MODE_MAP_STRINGS_ONLY, only
+ * text strings are accepted for map labels.  This lines up with CBOR
+ * that converts to JSON. The error @ref QCBOR_ERR_MAP_LABEL_TYPE is
+ * returned by QCBORDecode_GetNext() if anything but a text string
+ * label is encountered.
+ *
+ * In @ref QCBOR_DECODE_MODE_MAP_AS_ARRAY maps are treated as special
+ * arrays.  They will be returned with special @c uDataType @ref
+ * QCBOR_TYPE_MAP_AS_ARRAY and @c uCount, the number of items, will be
+ * double what it would be for a normal map because the labels are
+ * also counted. This mode is useful for decoding CBOR that has labels
+ * that are not integers or text strings, but the caller must manage
+ * much of the map decoding.
+ */
+void
+QCBORDecode_Init(QCBORDecodeContext *pCtx, UsefulBufC EncodedCBOR, QCBORDecodeMode nMode);
+
+
+/**
+ * @brief Set up the MemPool string allocator for indefinite-length strings.
+ *
+ * @param[in] pCtx         The decode context.
+ * @param[in] MemPool      The pointer and length of the memory pool.
+ * @param[in] bAllStrings  If true, all strings, even of definite
+ *                         length, will be allocated with the string
+ *                         allocator.
+ *
+ * @return Error if the MemPool was greater than @c UINT32_MAX
+ *         or less than @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE.
+ *
+ * Indefinite-length strings (text and byte) cannot be decoded unless
+ * there is a string allocator configured. MemPool is a simple
+ * built-in string allocator that allocates bytes from a memory pool
+ * handed to it by calling this function.  The memory pool is just a
+ * pointer and length for some block of memory that is to be used for
+ * string allocation. It can come from the stack, heap or other.
+ *
+ * The memory pool must be @ref QCBOR_DECODE_MIN_MEM_POOL_SIZE plus
+ * space for all the strings allocated.  There is no overhead per
+ * string allocated. A conservative way to size this buffer is to make
+ * it the same size as the CBOR being decoded plus @ref
+ * QCBOR_DECODE_MIN_MEM_POOL_SIZE.
+ *
+ * This memory pool is used for all indefinite-length strings that are
+ * text strings or byte strings, including strings used as labels.
+ *
+ * The pointers to strings in @ref QCBORItem will point into the
+ * memory pool set here. They do not need to be individually
+ * freed. Just discard the buffer when they are no longer needed.
+ *
+ * If @c bAllStrings is set, then the size will be the overhead plus
+ * the space to hold **all** strings, definite and indefinite-length,
+ * value or label. The advantage of this is that after the decode is
+ * complete, the original memory holding the encoded CBOR does not
+ * need to remain valid.
+ *
+ * This simple allocator is not hard linked to the QCBOR decoder.
+ * Assuming dead-stripping of unused symbols is being performed, this
+ * simple allocator will not be linked in unless
+ * QCBORDecode_SetMemPool() is called.
+ *
+ * See also QCBORDecode_SetUpAllocator() to set up a custom allocator
+ * if this one isn't sufficient.
+ */
+QCBORError
+QCBORDecode_SetMemPool(QCBORDecodeContext *pCtx,
+                       UsefulBuf           MemPool,
+                       bool                bAllStrings);
+
+
+/**
+ * @brief Sets up a custom string allocator for indefinite-length strings
+ *
+ * @param[in] pCtx                 The decoder context to set up an
+ *                                 allocator for.
+ * @param[in] pfAllocateFunction   Pointer to function that will be
+ *                                 called by QCBOR for allocations and
+ *                                 frees.
+ * @param[in] pAllocateContext     Context passed to @c
+ *                                 pfAllocateFunction.
+ * @param[in] bAllStrings          If true, all strings, even of definite
+ *                                 length, will be allocated with the
+ *                                 string allocator.
+ *
+ * Indefinite-length strings (text and byte) cannot be decoded unless
+ * a string allocator is configured. QCBORDecode_SetUpAllocator()
+ * allows the caller to configure an external string allocator
+ * implementation if the internal string allocator is
+ * unsuitable. See QCBORDecode_SetMemPool() to configure the internal
+ * allocator.
+ *
+ * The string allocator configured here is a custom one designed
+ * and implemented by the caller.  See @ref QCBORStringAllocate for
+ * the requirements for a string allocator implementation.
+ *
+ * A malloc-based string external allocator can be obtained by calling
+ * @c QCBORDecode_MakeMallocStringAllocator(). It will return a
+ * function and pointer that can be given here as @c pAllocatorFunction
+ * and @c pAllocatorContext. It uses standard @c malloc() so @c free()
+ * must be called on all strings marked by @c uDataAlloc @c == @c 1 or
+ * @c uLabelAlloc @c == @c 1 in @ref QCBORItem. Note this is in a
+ * separate GitHub repository.
+ */
+void
+QCBORDecode_SetUpAllocator(QCBORDecodeContext *pCtx,
+                           QCBORStringAllocate pfAllocateFunction,
+                           void               *pAllocateContext,
+                           bool                bAllStrings);
+
+
+/**
+ * @brief Get the next item (integer, byte string, array...) in the
+ * preorder traversal of the CBOR tree.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @c pDecodedItem is filled from the decoded item. Generally, the
+ * following data is returned in the structure:
+ *
+ * - @c uDataType which indicates which member of the @c val union the
+ *   data is in. This decoder figures out the type based on the CBOR
+ *   major type, the CBOR "additionalInfo", the CBOR optional tags and
+ *   the value of the integer.
+ *
+ * - The value of the item, which might be an integer, a pointer and a
+ *   length, the count of items in an array, a floating-point number or
+ *   other.
+ *
+ * - The nesting level for maps and arrays.
+ *
+ * - The label for an item in a map, which may be a text or byte string
+ *   or an integer.
+ *
+ * - The unprocessed tag numbers for which the item is the tag content.
+ *
+ * See @ref QCBORItem for all the details about what is returned.
+ *
+ * This function handles arrays and maps. When an array or map is
+ * first encountered a @ref QCBORItem will be returned with major type
+ * @ref QCBOR_TYPE_ARRAY or @ref QCBOR_TYPE_MAP.  @c
+ * QCBORItem.val.uNestLevel gives the nesting level of the opening of
+ * the array or map. When the next item is fetched, it will be the
+ * first one in the array or map and its @c QCBORItem.val.uNestLevel
+ * will be one more than that of the opening of the array or map.
+ *
+ * Nesting level 0 is the top-most nesting level. The first item
+ * decoded always has nesting level 0. A map or array at the top level
+ * has nesting level 0 and the members of the array or map have
+ * nesting level 1.
+ *
+ * Here is an example of how the nesting level is reported for a CBOR
+ * sequence with no arrays or maps at all.
+ *
+ * @code
+ * Data Item           Nesting Level
+ * integer                     0
+ * byte string                 0
+ * @endcode
+ *
+ * Here is an example of how the nesting level is reported for a CBOR
+ * sequence with a simple array and some top-level items.
+ *
+ * @code
+ * Data Item           Nesting Level
+ * integer                     0
+ * array with 2 items          0
+ *    byte string              1
+ *    byte string              1
+ * integer                     0
+ * @endcode
+ *
+ * Here's a more complex example that is not a CBOR sequence
+ *
+ * @code
+ * Data Item           Nesting Level
+ * map with 4 items            0
+ *    text string              1
+ *    array with 3 integers    1
+ *       integer               2
+ *       integer               2
+ *       integer               2
+ *    text string              1
+ *    byte string              1
+ * @endcode
+ *
+ * In @ref QCBORItem, @c uNextNestLevel is the nesting level for the
+ * next call to QCBORDecode_VGetNext(). It indicates if any maps or
+ * arrays were closed out during the processing of the just-fetched
+ * @ref QCBORItem. This processing includes a look-ahead for any
+ * breaks that close out indefinite-length arrays or maps. This value
+ * is needed to be able to understand the hierarchical structure. If
+ * @c uNextNestLevel is not equal to @c uNestLevel the end of the
+ * current map or array has been encountered. This works for both
+ * definite and indefinite-length arrays so it is the best way to find the
+ * end of a map or array. Alternatively, for definite-length arrays,
+ * @c QCBORItem.val.uCount contains the number of items in the
+ * array. For indefinite-length arrays, @c QCBORItem.val.uCount
+ * is @c UINT16_MAX.
+ *
+ * All tags defined in RFC 8949 are automatically fully decoded. There
+ * are QCBOR_TYPES and members in @ref QCBORItem for them. For
+ * example, the tag 9 will show up in the @ref QCBORItem as type
+ * @ref QCBOR_TYPE_POSBIGNUM with the value in
+ * @c QCBORItem.val.bignum. There is also support for
+ * some of the tags in the IANA tag registry.
+ *
+ * Most tags with a CBOR_TAG_XXX define in qcbor_common.h like @ref
+ * CBOR_TAG_DATE_STRING are automaticlly decoded by QCBOR. Those that
+ * are defined but not decoded are so noted.
+ *
+ * Tags that are not decoded by QCBOR will be identified and recorded
+ * in @ref QCBORItem. Use QCBORDecode_GetNthTag() to get them. Only
+ * @ref QCBOR_MAX_TAGS_PER_ITEM tags are recorded per item and an
+ * error is returned if there are more than that.
+ *
+ * Previous versions of QCBOR handled tags in a more complex way using
+ * QCBORDecode_SetCallerConfiguredTagList() and
+ * QCBORDecode_GetNextWithTags().  This version is largely compatible, but
+ * imposes the limit of @ref QCBOR_MAX_TAGS_PER_ITEM tags per item.
+ *
+ * See @ref Tags-Overview for a description of how to go about
+ * creating custom tags.
+ *
+ * This tag decoding design is to be open-ended and flexible to be
+ * able to handle newly defined tags, while using very little memory,
+ * in particular keeping @ref QCBORItem as small as possible.
+ *
+ * See [Decode Error Overview](#Decode-Errors-Overview).
+ *
+ * If a decoding error occurs or previously occured, \c uDataType and
+ * \c uLabelType will be set to @ref QCBOR_TYPE_NONE. If there is no
+ * need to know the specific error, it is sufficient to check for @ref
+ * QCBOR_TYPE_NONE.
+ *
+ * Errors fall in several categories:
+ *
+ * - Not well-formed errors are those where there is something
+ *   syntactically and fundamentally wrong with the CBOR being
+ *   decoded. Decoding should stop completely.
+ *
+ * - Invalid CBOR is well-formed, but still not correct. It is
+ *   probably best to stop decoding, but not necessary.
+ *
+ * - This implementation has some size limits. They should rarely be
+ *   encountered. If they are it may because something is wrong with
+ *   the CBOR, for example an array size is incorrect.
+ *
+ * - There are a few CBOR constructs that are not handled without some
+ *   extra configuration. These are indefinite length strings and maps
+ *   with labels that are not strings or integers. See
+ *   QCBORDecode_Init().  Also, the QCBOR library may have been
+ *   compiled with some features disabled to reduce code size and this
+ *   can result in some errors.
+ *
+ * - Resource exhaustion. This only occurs when a string allocator is
+ *   configured to handle indefinite-length strings as other than
+ *   that, this implementation does no dynamic memory allocation.
+ *
+ * | Error | Description |
+ * | ---- | ---- |
+ * | __Not well-formed errors__  ||
+ * | @ref QCBOR_ERR_HIT_END                 | Partial data item; need more input bytes to complete decoding |
+ * | @ref QCBOR_ERR_UNSUPPORTED             | Input contains CBOR with reserved additional info values |
+ * | @ref QCBOR_ERR_BAD_TYPE_7              | Simple value encoded as two-byte integer rather than one |
+ * | @ref QCBOR_ERR_BAD_BREAK               | Break occured outside an indefinite-length map or such |
+ * | @ref QCBOR_ERR_BAD_INT                 | Length of integer is bad |
+ * | @ref QCBOR_ERR_INDEFINITE_STRING_CHUNK | One of the chunks in indefinite-length string is the wrong type |
+ * | __Invalid CBOR__  ||
+ * | @ref QCBOR_ERR_NO_MORE_ITEMS        | Need more input data items to decode |
+ * | @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA | The structure of a big float or big number is invalid |
+ * | @ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT | The content of a tag is of the wrong type |
+ * | __Implementation Limits__  ||
+ * | @ref QCBOR_ERR_INT_OVERFLOW                  | Input integer smaller than INT64_MIN |
+ * | @ref QCBOR_ERR_ARRAY_DECODE_TOO_LONG         | Array or map has more elements than can be handled |
+ * | @ref QCBOR_ERR_DATE_OVERFLOW                 | Date larger than can be handled |
+ * | @ref QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP | Nesting deeper than can be handled |
+ * | @ref QCBOR_ERR_STRING_TOO_LONG               | Encountered a string longer than size_t can hold less 4 bytes |
+ * | @ref QCBOR_ERR_TOO_MANY_TAGS                 | Tag nesting deeper than limit, typically 4 |
+ * | __Configuration errors__  ||
+ * | @ref QCBOR_ERR_NO_STRING_ALLOCATOR        | Encountered indefinite-length string with no allocator configured |
+ * | @ref QCBOR_ERR_MAP_LABEL_TYPE             | A map label that is not a string on an integer |
+ * | @ref QCBOR_ERR_HALF_PRECISION_DISABLED    | Half-precision input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  | Indefinite-length input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED | Indefinite-length input, but disabled in QCBOR library |
+ * | @ref QCBOR_ERR_ALL_FLOAT_DISABLED             | Library compiled with floating-point support turned off. |
+ * | __Resource exhaustion errors__  ||
+ * | @ref QCBOR_ERR_STRING_ALLOCATE | The string allocator is unable to allocate more memory |
+ */
+void
+QCBORDecode_VGetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Preorder traversal like QCBORDecode_VGetNext() without use
+ * of internal error state.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @return See error table of decoding errors set by QCBORDecode_VGetNext().
+ *
+ * This is the same as QCBORDecode_VGetNext() except it
+ * doesn't set the internal decoding error and will attempt to decode
+ * even if the decoder is in the error state.
+ */
+QCBORError
+QCBORDecode_GetNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next item, fully consuming it if it is a map or array.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * @c pItem returned is the same as QCBORDecode_VGetNext(). If the
+ * item is an array or map, the entire contents of the array or map
+ * will be consumed leaving the cursor after the array or map.
+ *
+ * If an array or map is being consumed by this, an error will occur
+ * if any of the items in the array or map are in error.
+ *
+ * If the item is a tag the contents of which is an array or map, like
+ * a big float, @c pItem will identify it as such and the contents
+ * will be consumed, but the validity of the tag won't be checked
+ * other than for being well-formed.
+ *
+ * In order to go back to decode the contents of an array or map
+ * consumed by this, the decoder must be rewound using
+ * QCBORDecode_Rewind().
+ */
+void
+QCBORDecode_VGetNextConsume(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next data item without consuming it.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * This is the same as QCBORDecode_VGetNext() but does not consume the
+ * data item. This only looks ahead one item. Calling it repeatedly
+ * will just return the same item over and over.
+ *
+ * This uses about 200 bytes of stack, far more than anything else
+ * here in qcbor_decode.h because it saves a copy of most of the
+ * decode context temporarily.
+ *
+ * This is useful for looking ahead to determine the type of a data
+ * item to know which type-specific spiffy decode function to call or
+ * decoding protocols where the types of later data items
+ * depending on type of earlier ones.
+ *
+ * The error must be retrieved with QCBORDecode_GetError() and checked
+ * to know the peek was successful before referencing the contents of
+ * @c pDecodedItem.
+ */
+void
+QCBORDecode_VPeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the next data item without consuming it without use
+ * of internal error state.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  The decoded CBOR item.
+ *
+ * This is the same as QCBORDecode_VPeekNext() except it doesn't set
+ * the internal decoding error and will attempt to decode even if the
+ * decoder is in the error state.
+ */
+QCBORError
+QCBORDecode_PeekNext(QCBORDecodeContext *pCtx, QCBORItem *pDecodedItem);
+
+
+/**
+ * @brief Get the current traversal cursort offset in the input CBOR.
+ *
+ * @param[in]  pCtx   The decoder context.
+ *
+ * @returns The traversal cursor offset or @c UINT32_MAX.
+
+ * The position returned is always the start of the next item that
+ * would be next decoded with QCBORDecode_VGetNext(). The cursor
+ * returned may be at the end of the input in which case the next call
+ * to QCBORDecode_VGetNext() will result in the @ref
+ * QCBOR_ERR_NO_MORE_ITEMS. See also QCBORDecode_AtEnd().
+ *
+ * If the decoder is in error state from previous decoding,
+ * @c UINT32_MAX is returned.
+ *
+ * When decoding map items, the position returned is always of the
+ * label, never the value.
+ *
+ * For indefinite-length arrays and maps, the break byte is consumed
+ * when the last item in the array or map is consumed so the cursor is
+ * at the next item to be decoded as expected.
+ *
+ * There are some special rules for the traversal cursor when fetching
+ * map items by label. See the description of @SpiffyDecode.
+ *
+ * When traversal is bounded because an array or map has been entered
+ * (e.g., QCBORDecode_EnterMap()) and all items in the array or map
+ * have been consumed, the position returned will be of the item
+ * outside of the array or map. The array or map must be exited before
+ * QCBORDecode_VGetNext() will decode it.
+ *
+ * In many cases the position returned will be in the middle of
+ * an array or map. It will not be possible to start decoding at
+ * that location with another instance of the decoder and go to
+ * the end. It is not valid CBOR. If the input is a CBOR sequence
+ * and the position is not in the moddle of an array or map
+ * then it is possible to decode to the end.
+ *
+ * There is no corresponding seek method because it is too complicated
+ * to restore the internal decoder state that tracks nesting.
+ */
+static uint32_t
+QCBORDecode_Tell(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Tell whether cursor is at end of the input.
+ *
+ * @param[in] pCtx   The decoder context.
+ *
+ * @returns Error code possibly indicating end of input.
+ *
+ * This returns the same as QCBORDecode_GetError() except that @ref
+ * QCBOR_ERR_NO_MORE_ITEMS is returned if the travseral cursor is at
+ * the end of the CBOR input bytes (not the end of an entered array or
+ * map).
+ */
+QCBORError
+QCBORDecode_EndCheck(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Returns the tag numbers for an item.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @param[in] pItem The CBOR item to get the tag for.
+ * @param[in] uIndex The index of the tag to get.
+ *
+ * @returns The nth tag number or CBOR_TAG_INVALID64.
+ *
+ * When QCBOR decodes an item that is a tag, it will fully decode tags
+ * it is able to. Tags that it is unable to process are put in a list
+ * in the QCBORItem.
+ *
+ * Tags nest. Here the tag with index 0 has the data item as its content. The
+ * tag with index 1 has the tag at index 0 has its content and so forth.
+ *
+ * Deep tag nesting is rare so this implementation imposes a limit of
+ * @ref QCBOR_MAX_TAGS_PER_ITEM on nesting and returns @ref
+ * QCBOR_ERR_TOO_MANY_TAGS if there are more. This is a limit of this
+ * implementation, not of CBOR. (To be able to handle deeper
+ * nesting, the constant can be increased and the library
+ * recompiled. It will use more memory).
+ *
+ * See also @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
+ *
+ * To reduce memory used by a QCBORItem, tag numbers larger than
+ * @c UINT16_MAX are mapped so the tag numbers in @c uTags should be
+ * accessed with this function rather than directly.
+ *
+ * This returns @ref CBOR_TAG_INVALID64 if any error occurred when
+ * getting the item. This is also returned if there are no tags on the
+ * item or no tag at @c uIndex.
+ */
+uint64_t
+QCBORDecode_GetNthTag(QCBORDecodeContext *pCtx, const QCBORItem *pItem, uint32_t uIndex);
+
+
+/**
+ * @brief Returns the tag numbers for last-decoded item.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @param[in] uIndex The index of the tag to get.
+ *
+ * @returns The nth tag number or CBOR_TAG_INVALID64.
+ *
+ * This returns tags of the most recently decoded item.  See
+ * QCBORDecode_GetNthTag(). This is particularly of use for spiffy
+ * decode functions that don't return a @ref QCBORItem.
+ *
+ * This does not work for QCBORDecode_GetNext(),
+ * QCBORDecode_PeekNext(), QCBORDecode_VPeekNext() or
+ * QCBORDecode_VGetNextConsume() but these all return a
+ * @ref QCBORItem, so it is not necessary.
+ *
+ * If a decoding error is set, then this returns CBOR_TAG_INVALID64.
+ */
+uint64_t
+QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pCtx, uint32_t uIndex);
+
+
+/**
+ * @brief Check that a decode completed successfully.
+ *
+ * @param[in]  pCtx  The context to check.
+ *
+ * @returns The internal tracked decode error or @ref QCBOR_SUCCESS.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * This should always be called at the end of a decode to determine if
+ * it completed successfully.  For some protocols, checking the return
+ * value here may be the only error check necessary.
+ *
+ * This returns the internal tracked error if the decoder is in the
+ * error state, the same one returned by QCBORDecode_GetError().  This
+ * performs final checks at the end of the decode, and may also return
+ * @ref QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN
+ * or @ref QCBOR_ERR_EXTRA_BYTES.
+ *
+ * This calls the destructor for the string allocator, if one is in
+ * use. Because of this, It can't be called multiple times like
+ * QCBORDecode_PartialFinish().
+ *
+ * Some CBOR protocols use a CBOR sequence defined in [RFC 8742]
+ * (https://tools.ietf.org/html/rfc8742). A CBOR sequence typically
+ * doesn't start out with a map or an array. The end of the CBOR is
+ * determined in some other way, perhaps by external framing, or by
+ * the occurrence of some particular CBOR data item or such. The
+ * buffer given to decode must start out with valid CBOR, but it can
+ * have extra bytes at the end that are not CBOR or CBOR that is to be
+ * ignored.
+ *
+ * QCBORDecode_Finish() should still be called when decoding CBOR
+ * sequences to check that the input decoded was well-formed. If the
+ * input was well-formed and there are extra bytes at the end @ref
+ * QCBOR_ERR_EXTRA_BYTES will be returned.  This can be considered a
+ * successful decode.  See also QCBORDecode_PartialFinish().
+ */
+QCBORError
+QCBORDecode_Finish(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Return number of bytes consumed so far.
+ *
+ * @param[in]  pCtx        The context to check.
+ * @param[out] puConsumed  The number of bytes consumed so far.
+ *                          May be @c NULL.
+ *
+ * @returns The same as QCBORDecode_Finish();
+ *
+ * This is primarily for partially decoding CBOR sequences. It is the
+ * same as QCBORDecode_Finish() except it returns the number of bytes
+ * consumed and doesn't call the destructor for the string allocator
+ * (See @ref QCBORDecode_SetMemPool()).
+ *
+ * When this is called before all input bytes are consumed, @ref
+ * QCBOR_ERR_EXTRA_BYTES will be returned as QCBORDecode_Finish()
+ * does. For typical use of this, that particular error is disregarded.
+ *
+ * Decoding with the same @ref QCBORDecodeContext can continue after
+ * calling this and this may be called many times.
+ *
+ * Another way to resume decoding is to call QCBORDecode_Init() with the
+ * bytes not decoded, but this only works on CBOR sequences when the
+ * decoding stopped with no open arrays, maps or byte strings.
+ */
+QCBORError
+QCBORDecode_PartialFinish(QCBORDecodeContext *pCtx, size_t *puConsumed);
+
+
+/**
+ * @brief Get the decoding error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @return            The decoding error.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * The returns the tracked internal error code. All decoding functions
+ * set the internal error except QCBORDecode_GetNext() and
+ * QCBORDecode_PeekNext().
+ *
+ * For many protocols it is only necessary to check the return code
+ * from QCBORDecode_Finish() at the end of all the decoding.  It is
+ * unnecessary to call this.
+ *
+ * For some protocols, the decoding sequence depends on the types,
+ * values or labels of data items. If so, this must be called before
+ * using decoded values to know the decode was a success and the
+ * type, value and label is valid.
+ *
+ * Some errors, like integer conversion overflow, date string format
+ * may not affect the flow of a protocol. The protocol decoder may
+ * wish to proceed even if they occur. In that case
+ * QCBORDecode_GetAndResetError() may be called after these data items
+ * are fetched.
+ */
+static QCBORError
+QCBORDecode_GetError(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Get and reset the decoding error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @returns The decoding error.
+ *
+ * This returns the same as QCBORDecode_GetError() and also resets the
+ * error state to @ref QCBOR_SUCCESS.
+ */
+static QCBORError
+QCBORDecode_GetAndResetError(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Whether an error indicates non-well-formed CBOR.
+ *
+ * @param[in] uErr    The QCBOR error code.
+ * @return @c true if the error code indicates non-well-formed CBOR.
+ */
+static bool
+QCBORDecode_IsNotWellFormedError(QCBORError uErr);
+
+
+/**
+ * @brief Whether a decoding error is recoverable.
+ *
+ * @param[in] uErr    The QCBOR error code.
+ * @return @c true if the error code indicates and uncrecoverable error.
+ *
+ * When an error is unrecoverable, no further decoding of the input is
+ * possible.  CBOR is a compact format with almost no redundancy so
+ * errors like incorrect lengths or array counts are
+ * unrecoverable. Unrecoverable errors also occur when implementation
+ * limits such as the limit on array and map nesting are encountered.
+ * When the built-in decoding of a tag like an epoch date encounters
+ * an error such as a data item of an unexpected type, this is also an
+ * unrecoverable error because the internal decoding doesn't try to
+ * decode everything in the tag.
+ *
+ * The unrecoverable errors are a range of the errors in
+ * @ref QCBORError.
+ */
+static bool
+QCBORDecode_IsUnrecoverableError(QCBORError uErr);
+
+
+/**
+ * @brief Manually set error condition, or set user-defined error.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @param[in] uError  The error code to set.
+ *
+ * Once set, none of the QCBORDecode methods will do anything and the
+ * error code set will stay until cleared with
+ * QCBORDecode_GetAndResetError().  A user-defined error can be set
+ * deep in some decoding layers to short-circuit further decoding
+ * and propagate up.
+ *
+ * When the error condition is set, QCBORDecode_VGetNext() will always
+ * return an item with data and label type as \ref QCBOR_TYPE_NONE.
+ *
+ * The main intent of this is to set a user-defined error code in the
+ * range of \ref QCBOR_ERR_FIRST_USER_DEFINED to
+ * \ref QCBOR_ERR_LAST_USER_DEFINED, but it is OK to set QCBOR-defined
+ * error codes too.
+ */
+static void
+QCBORDecode_SetError(QCBORDecodeContext *pCtx, QCBORError uError);
+
+
+
+
+/**
+ * @brief Convert int64_t to smaller integers safely.
+ *
+ * @param [in]  src   An @c int64_t.
+ * @param [out] dest  A smaller sized integer to convert to.
+ *
+ * @return 0 on success -1 if not
+ *
+ * When decoding an integer, the CBOR decoder will return the value as
+ * an int64_t unless the integer is in the range of @c INT64_MAX and
+ * @c UINT64_MAX. That is, unless the value is so large that it can only be
+ * represented as a @c uint64_t, it will be an @c int64_t.
+ *
+ * CBOR itself doesn't size the individual integers it carries at
+ * all. The only limits it puts on the major integer types is that they
+ * are 8 bytes or less in length. Then encoders like this one use the
+ * smallest number of 1, 2, 4 or 8 bytes to represent the integer based
+ * on its value. There is thus no notion that one data item in CBOR is
+ * a 1-byte integer and another is a 4-byte integer.
+ *
+ * The interface to this CBOR encoder only uses 64-bit integers. Some
+ * CBOR protocols or implementations of CBOR protocols may not want to
+ * work with something smaller than a 64-bit integer.  Perhaps an array
+ * of 1,000 integers needs to be sent and none has a value larger than
+ * 50,000 and are represented as @c uint16_t.
+ *
+ * The sending / encoding side is easy. Integers are temporarily widened
+ * to 64-bits as a parameter passing through QCBOREncode_AddInt64() and
+ * encoded in the smallest way possible for their value, possibly in
+ * less than an @c uint16_t.
+ *
+ * On the decoding side the integers will be returned at @c int64_t even if
+ * they are small and were represented by only 1 or 2 bytes in the
+ * encoded CBOR. The functions here will convert integers to a small
+ * representation with an overflow check.
+ *
+ * (The decoder could have support 8 different integer types and
+ * represented the integer with the smallest type automatically, but
+ * this would have made the decoder more complex and code calling the
+ * decoder more complex in most use cases.  In most use cases on 64-bit
+ * machines it is no burden to carry around even small integers as
+ * 64-bit values).
+ */
+static inline int
+QCBOR_Int64ToInt32(int64_t src, int32_t *dest)
+{
+   if(src > INT32_MAX || src < INT32_MIN) {
+      return -1;
+   } else {
+      *dest = (int32_t) src;
+   }
+   return 0;
+}
+
+static inline int
+QCBOR_Int64ToInt16(int64_t src, int16_t *dest)
+{
+   if(src > INT16_MAX || src < INT16_MIN) {
+      return -1;
+   } else {
+      *dest = (int16_t) src;
+   }
+   return 0;
+}
+
+static inline int
+QCBOR_Int64ToInt8(int64_t src, int8_t *dest)
+{
+   if(src > INT8_MAX || src < INT8_MIN) {
+      return -1;
+   } else {
+      *dest = (int8_t) src;
+   }
+   return 0;
+}
+
+static inline int
+QCBOR_Int64ToUInt32(int64_t src, uint32_t *dest)
+{
+   if(src > UINT32_MAX || src < 0) {
+      return -1;
+   } else {
+      *dest = (uint32_t) src;
+   }
+   return 0;
+}
+
+/**
+ * https://github.com/laurencelundblade/QCBOR/pull/243
+ * For backwards compatibility
+ */
+#define QCBOR_Int64UToInt16 QCBOR_Int64ToUInt16
+
+static inline int
+QCBOR_Int64ToUInt16(int64_t src, uint16_t *dest)
+{
+   if(src > UINT16_MAX || src < 0) {
+      return -1;
+   } else {
+      *dest = (uint16_t) src;
+   }
+   return 0;
+}
+
+static inline int
+QCBOR_Int64ToUInt8(int64_t src, uint8_t *dest)
+{
+   if(src > UINT8_MAX || src < 0) {
+      return -1;
+   } else {
+      *dest = (uint8_t) src;
+   }
+   return 0;
+}
+
+static inline int
+QCBOR_Int64ToUInt64(int64_t src, uint64_t *dest)
+{
+   if(src < 0) {
+      return -1;
+   } else {
+      *dest = (uint64_t) src;
+   }
+   return 0;
+}
+
+
+
+
+/* ------------------------------------------------------------------------
+ * Deprecated functions retained for backwards compatibility. Their use is
+ * not recommended.
+ * ---- */
+
+
+/**
+ * Deprecated -- Tag handling has been revised and this is no longer
+ * used. See QCBORDecode_GetNthTag() for new tag handling.
+ */
+typedef struct {
+   uint8_t         uNumTags;
+   const uint64_t *puTags;
+} QCBORTagListIn;
+
+
+/**
+ * Deprecated -- this is retained only for backwards compatibility.
+ * Use QCBORDecode_GetNthTag() instead.
+ *
+ * This is for QCBORDecode_GetNextWithTags() to be able to return the
+ * full list of tags on an item.
+ *
+ * On input, @c puTags points to a buffer to be filled in and
+ * uNumAllocated is the number of @c uint64_t values in the buffer.
+ *
+ * On output the buffer contains the tags for the item.  @c uNumUsed
+ * tells how many there are.
+ */
+typedef struct {
+   uint8_t   uNumUsed;
+   uint8_t   uNumAllocated;
+   uint64_t *puTags;
+} QCBORTagListOut;
+
+
+/**
+ * @brief Deprecated -- Configure list of caller-selected tags to be recognized.
+ *
+ * @param[in] pCtx       The decode context.
+ * @param[out] pTagList  Structure holding the list of tags to configure.
+ *
+ * Tag handling has been revised and it is no longer ncessary to use
+ * this.  See QCBORDecode_GetNthTag().
+ */
+void
+QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext   *pCtx,
+                                       const QCBORTagListIn *pTagList);
+
+
+/**
+ * @brief Deprecated -- Determine if a CBOR item is a particular tag.
+ *
+ * @param[in] pCtx    The decoder context.
+ * @param[in] pItem   The CBOR item to check.
+ * @param[in] uTag    The tag to check, one of @c CBOR_TAG_XXX,
+ *                   for example, @ref CBOR_TAG_DATE_STRING.
+ *
+ * @return true if it was tagged, false if not.
+ *
+ * See QCBORDecode_GetNext() for the main description of tag
+ * handling. For tags that are not fully decoded a bit corresponding
+ * to the tag is set in in @c uTagBits in the @ref QCBORItem. The
+ * particular bit depends on an internal mapping table. This function
+ * checks for set bits against the mapping table.
+ *
+ * Typically, a protocol implementation just wants to know if a
+ * particular tag is present. That is what this provides. To get the
+ * full list of tags on a data item, see
+ * QCBORDecode_GetNextWithTags().
+ *
+ * Also see QCBORDecode_SetCallerConfiguredTagList() for the means to
+ * add new tags to the internal list so they can be checked for with
+ * this function.
+ */
+bool
+QCBORDecode_IsTagged(QCBORDecodeContext *pCtx,
+                     const QCBORItem    *pItem,
+                     uint64_t            uTag);
+
+
+/**
+ * @brief Deprecated -- Gets the next item including full list of tags for item.
+ *
+ * @param[in]  pCtx          The decoder context.
+ * @param[out] pDecodedItem  Holds the CBOR item just decoded.
+ * @param[in,out] pTagList   On input array to put tags in; on output
+ * the tags on this item. See
+ * @ref QCBORTagListOut.
+ *
+ * @return See return values for QCBORDecode_GetNext().
+ *
+ * @retval QCBOR_ERR_TOO_MANY_TAGS  The size of @c pTagList is too small.
+ *
+ * This is retained for backwards compatibility. It is replaced by
+ * QCBORDecode_GetNthTag() which also returns all the tags that have
+ * been decoded.
+ *
+ * This is not backwards compatibile in two ways. First, it is limited
+ * to @ref QCBOR_MAX_TAGS_PER_ITEM items whereas previously it was
+ * unlimited. Second, it will not inlucde the tags that QCBOR decodes
+ * internally.
+ *
+ * This works the same as QCBORDecode_GetNext() except that it also
+ * returns the list of tags for the data item in \c pTagList.
+ *
+ * The 0th tag returned here is the one furthest from the data
+ * item. This is opposite the order for QCBORDecode_GetNthTag().
+ *
+ * CBOR has no upper bound or limit on the number of tags that can be
+ * associated with a data item but in practice the number of tags on
+ * an item will usually be small. This will return @ref
+ * QCBOR_ERR_TOO_MANY_TAGS if the array in @c pTagList is too small to
+ * hold all the tags for the item.
+ */
+QCBORError
+QCBORDecode_GetNextWithTags(QCBORDecodeContext *pCtx,
+                            QCBORItem          *pDecodedItem,
+                            QCBORTagListOut    *pTagList);
+
+
+
+
+/* ------------------------------------------------------------------------
+ * Inline implementations of public functions defined above.
+ * ---- */
+
+static inline uint32_t
+QCBORDecode_Tell(QCBORDecodeContext *pMe)
+{
+   if(pMe->uLastError) {
+      return UINT32_MAX;
+   }
+
+   /* Cast is safe because decoder input size is restricted. */
+   return (uint32_t)UsefulInputBuf_Tell(&(pMe->InBuf));
+}
+
+static inline QCBORError
+QCBORDecode_GetError(QCBORDecodeContext *pMe)
+{
+    return (QCBORError)pMe->uLastError;
+}
+
+static inline QCBORError
+QCBORDecode_GetAndResetError(QCBORDecodeContext *pMe)
+{
+    const QCBORError uReturn = (QCBORError)pMe->uLastError;
+    pMe->uLastError = QCBOR_SUCCESS;
+    return uReturn;
+}
+
+static inline bool
+QCBORDecode_IsNotWellFormedError(const QCBORError uErr)
+{
+   if(uErr >= QCBOR_START_OF_NOT_WELL_FORMED_ERRORS &&
+      uErr <= QCBOR_END_OF_NOT_WELL_FORMED_ERRORS) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+static inline bool
+QCBORDecode_IsUnrecoverableError(const QCBORError uErr)
+{
+   if(uErr >= QCBOR_START_OF_UNRECOVERABLE_DECODE_ERRORS &&
+      uErr <= QCBOR_END_OF_UNRECOVERABLE_DECODE_ERRORS) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static inline void
+QCBORDecode_SetError(QCBORDecodeContext *pMe, QCBORError uError)
+{
+   pMe->uLastError = (uint8_t)uError;
+}
+
+
+/* A few cross checks on size constants and special value lengths */
+#if  QCBOR_MAP_OFFSET_CACHE_INVALID < QCBOR_MAX_DECODE_INPUT_SIZE
+#error QCBOR_MAP_OFFSET_CACHE_INVALID is too large
+#endif
+
+#if QCBOR_NON_BOUNDED_OFFSET < QCBOR_MAX_DECODE_INPUT_SIZE
+#error QCBOR_NON_BOUNDED_OFFSET is too large
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_decode_h */
diff --git a/core/lib/qcbor/inc/qcbor/qcbor_encode.h b/core/lib/qcbor/inc/qcbor/qcbor_encode.h
new file mode 100644
index 0000000000000000000000000000000000000000..4fa7fab5fafec86ca46038587a25dfaf1b7db1e4
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor_encode.h
@@ -0,0 +1,4052 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ===========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+
+#ifndef qcbor_encode_h
+#define qcbor_encode_h
+
+
+#include "qcbor/qcbor_common.h"
+#include "qcbor/qcbor_private.h"
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} // Keep editor indention formatting happy
+#endif
+#endif
+
+
+/**
+ * @file qcbor_encode.h
+ *
+ * @anchor Overview
+ *
+ * # QCBOR Overview
+ *
+ * This implements CBOR -- Concise Binary Object Representation as
+ * defined in [RFC 8949] (https://tools.ietf.org/html/rfc8949). More
+ * information is at http://cbor.io.  This is a near-complete implementation of
+ * the specification. [RFC 8742] (https://tools.ietf.org/html/rfc8742) CBOR
+ * Sequences is also supported. Limitations are listed further down.
+ *
+ * See @ref Encoding for general discussion on encoding,
+ * @ref BasicDecode for general discussion on the basic decode features
+ * and @ref SpiffyDecode for general discussion on the easier-to-use
+ * decoder functions.
+ *
+ * CBOR is intentionally designed to be translatable to JSON, but not
+ * all CBOR can convert to JSON. See RFC 8949 for more info on how to
+ * construct CBOR that is the most JSON friendly.
+ *
+ * The memory model for encoding and decoding is that encoded CBOR must
+ * be in a contiguous buffer in memory.  During encoding the caller must
+ * supply an output buffer and if the encoding would go off the end of
+ * the buffer an error is returned.  During decoding the caller supplies
+ * the encoded CBOR in a contiguous buffer and the decoder returns
+ * pointers and lengths into that buffer for strings.
+ *
+ * This implementation does not require malloc. All data structures
+ * passed in/out of the APIs can fit on the stack.
+ *
+ * Decoding of indefinite-length strings is a special case that requires
+ * a "string allocator" to allocate memory into which the segments of
+ * the string are coalesced. Without this, decoding will error out if an
+ * indefinite-length string is encountered (indefinite-length maps and
+ * arrays do not require the string allocator). A simple string
+ * allocator called MemPool is built-in and will work if supplied with a
+ * block of memory to allocate. The string allocator can optionally use
+ * malloc() or some other custom scheme.
+ *
+ * Here are some terms and definitions:
+ *
+ * - "Item", "Data Item": An integer or string or such. The basic "thing" that
+ * CBOR is about. An array is an item itself that contains some items.
+ *
+ * - "Array": An ordered sequence of items, the same as JSON.
+ *
+ * - "Map": A collection of label/value pairs. Each pair is a data
+ * item. A JSON "object" is the same as a CBOR "map".
+ *
+ * - "Label": The data item in a pair in a map that names or identifies
+ * the pair, not the value. This implementation refers to it as a
+ * "label".  JSON refers to it as the "name". The CBOR RFC refers to it
+ * this as a "key".  This implementation chooses label instead because
+ * key is too easily confused with a cryptographic key. The COSE
+ * standard, which uses CBOR, has also chosen to use the term "label"
+ * rather than "key" for this same reason.
+ *
+ * - "Key": See "Label" above.
+ *
+ * - "Tag": A data item that is an explicitly labeled new data
+ * type made up of the tagging integer and the tag content.
+ * See @ref Tags-Overview and @ref Tag-Usage.
+ *
+ * - "Initial Byte": The first byte of an encoded item. Encoding and
+ * decoding of this byte is taken care of by the implementation.
+ *
+ * - "Additional Info": In addition to the major type, all data items
+ * have some other info. This is usually the length of the data but can
+ * be several other things. Encoding and decoding of this is taken care
+ * of by the implementation.
+ *
+ * CBOR has two mechanisms for tagging and labeling the data values like
+ * integers and strings. For example, an integer that represents
+ * someone's birthday in epoch seconds since Jan 1, 1970 could be
+ * encoded like this:
+ *
+ * - First it is CBOR_MAJOR_TYPE_POSITIVE_INT (@ref QCBOR_TYPE_INT64),
+ * the primitive positive integer.
+ *
+ * - Next it has a "tag" @ref CBOR_TAG_DATE_EPOCH indicating the integer
+ * represents a date in the form of the number of seconds since Jan 1,
+ * 1970.
+ *
+ * - Last it has a string "label" like "BirthDate" indicating the
+ * meaning of the data.
+ *
+ * The encoded binary looks like this:
+ *
+ *      a1                      # Map of 1 item
+ *         69                   # Indicates text string of 9 bytes
+ *           426972746844617465 # The text "BirthDate"
+ *        c1                    # Tags next integer as epoch date
+ *           1a                 # Indicates a 4-byte integer
+ *               580d4172       # unsigned integer date 1477263730
+ *
+ * Implementors using this API will primarily work with
+ * labels. Generally, tags are only needed for making up new data
+ * types. This implementation covers most of the data types defined in
+ * the RFC using tags. It also, allows for the use of custom tags if
+ * necessary.
+ *
+ * This implementation explicitly supports labels that are text strings
+ * and integers. Text strings translate nicely into JSON objects and are
+ * very readable.  Integer labels are much less readable but can be very
+ * compact. If they are in the range of 0 to 23, they take up only one
+ * byte.
+ *
+ * CBOR allows a label to be any type of data including an array or a
+ * map. It is possible to use this API to construct and parse such
+ * labels, but it is not explicitly supported.
+ *
+ * @anchor Encoding
+ *
+ * ## Encoding
+ *
+ * A common encoding usage mode is to invoke the encoding twice. First
+ * with the output buffer as @ref SizeCalculateUsefulBuf to compute the
+ * length of the needed output buffer. The correct sized output buffer
+ * is allocated. The encoder is invoked a second time with the allocated
+ * output buffer.
+ *
+ * The double invocation is not required if the maximum output buffer
+ * size can be predicted. This is usually possible for simple CBOR
+ * structures.
+ *
+ * If a buffer too small to hold the encoded output is given, the error
+ * @ref QCBOR_ERR_BUFFER_TOO_SMALL will be returned. Data will never be
+ * written off the end of the output buffer no matter which functions
+ * here are called or what parameters are passed to them.
+ *
+ * The encoding error handling is simple. The only possible errors are
+ * trying to encode structures that are too large or too complex. There
+ * are no internal malloc calls so there will be no failures for out of
+ * memory.  The error state is tracked internally, so there is no need
+ * to check for errors when encoding. Only the return code from
+ * QCBOREncode_Finish() need be checked as once an error happens, the
+ * encoder goes into an error state and calls to it to add more data
+ * will do nothing. An error check is not needed after every data item
+ * is added.
+ *
+ * Encoding generally proceeds by calling QCBOREncode_Init(), calling
+ * lots of @c QCBOREncode_AddXxx() functions and calling
+ * QCBOREncode_Finish(). There are many @c QCBOREncode_AddXxx()
+ * functions for various data types. The input buffers need only to be
+ * valid during the @c QCBOREncode_AddXxx() calls as the data is copied
+ * into the output buffer.
+ *
+ * There are three `Add` functions for each data type. The first / main
+ * one for the type is for adding the data item to an array.  The second
+ * one's name ends in `ToMap`, is used for adding data items to maps and
+ * takes a string argument that is its label in the map. The third one
+ * ends in `ToMapN`, is also used for adding data items to maps, and
+ * takes an integer argument that is its label in the map.
+ *
+ * The simplest aggregate type is an array, which is a simple ordered
+ * set of items without labels the same as JSON arrays. Call
+ * QCBOREncode_OpenArray() to open a new array, then various @c
+ * QCBOREncode_AddXxx() functions to put items in the array and then
+ * QCBOREncode_CloseArray(). Nesting to the limit @ref
+ * QCBOR_MAX_ARRAY_NESTING is allowed.  All opens must be matched by
+ * closes or an encoding error will be returned.
+ *
+ * The other aggregate type is a map which does use labels. The `Add`
+ * functions that end in `ToMap` and `ToMapN` are convenient ways to add
+ * labeled data items to a map. You can also call any type of `Add`
+ * function once to add a label of any type and then call any type of
+ * `Add` again to add its value.
+ *
+ * Note that when you nest arrays or maps in a map, the nested array or
+ * map has a label.
+ *
+ * Many CBOR-based protocols start with an array or map. This makes them
+ * self-delimiting. No external length or end marker is needed to know
+ * the end. It is also possible not start this way, in which case this
+ * it is usually called a CBOR sequence which is described in
+ * [RFC 8742] (https://tools.ietf.org/html/rfc8742). This encoder supports
+ * either just by whether the first item added is an array, map or other.
+ *
+ * If QCBOR is compiled with QCBOR_DISABLE_ENCODE_USAGE_GUARDS defined,
+ * the errors QCBOR_ERR_CLOSE_MISMATCH, QCBOR_ERR_ARRAY_TOO_LONG,
+ * QCBOR_ERR_TOO_MANY_CLOSES, QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN, and
+ * QCBOR_ERR_ENCODE_UNSUPPORTED will never be returned. It is up to the
+ * caller to make sure that opened maps, arrays and byte-string wrapping
+ * is closed correctly and that QCBOREncode_AddType7() is called
+ * correctly.  With this defined, it is easier to make a mistake when
+ * authoring the encoding of a protocol that will output not well formed
+ * CBOR, but as long as the calling code is correct, it is safe to
+ * disable these checks. Bounds checking that prevents security issues
+ * in the code is still enforced. This define reduces the size of
+ * encoding object code by about 150 bytes.
+ *
+ * @anchor Tags-Overview
+ *
+ * ## Tags Overview
+ *
+ * Any CBOR data item can be made into a tag to add semantics, define a
+ * new data type or such. Some tags are fully standardized and some are
+ * just registered. Others are not registered and used in a proprietary
+ * way.
+ *
+ * Encoding and decoding of many of the registered tags is fully
+ * implemented by QCBOR. It is also possible to encode and decode tags
+ * that are not directly supported.  For many use cases the built-in tag
+ * support should be adequate.
+ *
+ * For example, the registered epoch date tag is supported in encoding
+ * by QCBOREncode_AddDateEpoch() and in decoding by @ref
+ * QCBOR_TYPE_DATE_EPOCH and the @c epochDate member of @ref
+ * QCBORItem. This is typical of the built-in tag support. There is an
+ * API to encode data for it and a @c QCBOR_TYPE_XXX when it is decoded.
+ *
+ * Tags are registered in the [IANA CBOR Tags Registry]
+ * (https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml). There
+ * are roughly three options to create a new tag. First, a public
+ * specification can be created and the new tag registered with IANA.
+ * This is the most formal. Second, the new tag can be registered with
+ * IANA with just a short description rather than a full specification.
+ * These tags must be greater than 256. Third, a tag can be used without
+ * any IANA registration, though the registry should be checked to see
+ * that the new value doesn't collide with one that is registered. The
+ * value of these tags must be 256 or larger.
+ *
+ * See also @ref CBORTags and @ref Tag-Usage
+ *
+ * The encoding side of tags not built-in is handled by
+ * QCBOREncode_AddTag() and is relatively simple. Tag decoding is more
+ * complex and mainly handled by QCBORDecode_GetNext(). Decoding of the
+ * structure of tagged data not built-in (if there is any) has to be
+ * implemented by the caller.
+ *
+ * @anchor Floating-Point
+ *
+ * ## Floating-Point
+ *
+ * By default QCBOR fully supports IEEE 754 floating-point:
+ *  - Encode/decode of double, single and half-precision
+ *  - CBOR preferred serialization of floating-point
+ *  - Floating-point epoch dates
+ *
+ * For the most part, the type double is used in the interface for
+ * floating-point values. In the default configuration, all decoded
+ * floating-point values are returned as a double.
+ *
+ * With CBOR preferred serialization, the encoder outputs the smallest
+ * representation of the double or float that preserves precision. Zero,
+ * NaN and infinity are always output as a half-precision, each taking
+ * just 2 bytes. This reduces the number of bytes needed to encode
+ * double and single-precision, especially if zero, NaN and infinity are
+ * frequently used.
+ *
+ * To avoid use of preferred serialization in the standard configuration
+ * when encoding, use QCBOREncode_AddDoubleNoPreferred() or
+ * QCBOREncode_AddFloatNoPreferred().
+ *
+ * This implementation of preferred floating-point serialization and
+ * half-precision does not depend on the CPU having floating-point HW or
+ * the compiler bringing in a (sometimes large) library to compensate
+ * for lack of CPU support. This implementation uses shifts and masks
+ * rather than floating-point functions.
+ *
+ * To reduce overall object code by about 900 bytes, define
+ * QCBOR_DISABLE_PREFERRED_FLOAT. This will eliminate all support for
+ * preferred serialization and half-precision. An error will be returned
+ * when attempting to decode half-precision. A float will always be
+ * encoded and decoded as 32-bits and a double will always be encoded
+ * and decoded as 64 bits.
+ *
+ * Note that even if QCBOR_DISABLE_PREFERRED_FLOAT is not defined all
+ * the float-point encoding object code can be avoided by never calling
+ * any functions that encode double or float. Just not calling
+ * floating-point functions will reduce object code by about 500 bytes.
+ *
+ * On CPUs that have no floating-point hardware,
+ * QCBOR_DISABLE_FLOAT_HW_USE should be defined in most cases. If it is
+ * not, then the compiler will bring in possibly large software
+ * libraries to compensate. Defining QCBOR_DISABLE_FLOAT_HW_USE reduces
+ * object code size on CPUs with floating-point hardware by a tiny
+ * amount and eliminates the need for <math.h>
+ *
+ * When QCBOR_DISABLE_FLOAT_HW_USE is defined, trying to decoding
+ * floating-point dates will give error
+ * @ref QCBOR_ERR_FLOAT_DATE_DISABLED and decoded single-precision
+ * numbers will be returned as @ref QCBOR_TYPE_FLOAT instead of
+ * converting them to double as usual.
+ *
+ * If both QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
+ * are defined, then the only thing QCBOR can do is encode/decode a C
+ * float type as 32-bits and a C double type as 64-bits. Floating-point
+ * epoch dates will be unsupported.
+ *
+ * If USEFULBUF_DISABLE_ALL_FLOAT is defined, then floating point
+ * support is completely disabled. Decoding functions return
+ * @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is
+ * encountered during decoding. Functions that are encoding floating
+ * point values are not available.
+ *
+ * ## Limitations
+ *
+ * Summary limitations:
+ * - The entire encoded CBOR must fit into contiguous memory.
+ * - Max size of encoded CBOR data is a few bytes less than
+ *   @c UINT32_MAX (4GB).
+ * - Max array / map nesting level when encoding or decoding is
+ *   @ref QCBOR_MAX_ARRAY_NESTING (this is typically 15).
+ * - Max items in an array or map when encoding or decoding is
+ *   @ref QCBOR_MAX_ITEMS_IN_ARRAY (typically 65,536).
+ * - Does not directly support labels in maps other than text strings & integers.
+ * - Does not directly support integer labels beyond whats fits in @c int64_t
+ *   or @c uint64_t.
+ * - Epoch dates limited to @c INT64_MAX (+/- 292 billion years).
+ * - Exponents for bigfloats and decimal integers are limited to whats fits in
+ *   @c int64_t.
+ * - Tags on labels are ignored during decoding.
+ * - The maximum tag nesting is @c QCBOR_MAX_TAGS_PER_ITEM (typically 4).
+ * - Works only on 32- and 64-bit CPUs.
+ * - QCBORDecode_EnterBstrWrapped() doesn't work on indefinite-length strings.
+ *
+ * The public interface uses @c size_t for all lengths. Internally the
+ * implementation uses 32-bit lengths by design to use less memory and
+ * fit structures on the stack. This limits the encoded CBOR it can
+ * work with to size @c UINT32_MAX (4GB).
+ *
+ * This implementation requires two's compliment integers. While
+ * C doesn't require two's compliment,  <stdint.h> does. Other
+ * parts of this implementation may also require two's compliment.
+ */
+
+
+/**
+ * The size of the buffer to be passed to QCBOREncode_EncodeHead(). It
+ * is one byte larger than sizeof(uint64_t) + 1, the actual maximum
+ * size of the head of a CBOR data item because
+ * QCBOREncode_EncodeHead() needs one extra byte to work.
+ */
+#define QCBOR_HEAD_BUFFER_SIZE  (sizeof(uint64_t) + 2)
+
+
+/**
+ * Output the full CBOR tag. See @ref CBORTags, @ref Tag-Usage and
+ * @ref Tags-Overview.
+ */
+#define QCBOR_ENCODE_AS_TAG      0
+
+/**
+ * Output only the 'borrowed' content format for the relevant tag.
+ * See @ref CBORTags, @ref Tag-Usage and @ref Tags-Overview.
+ */
+#define QCBOR_ENCODE_AS_BORROWED 1
+
+
+/**
+ * QCBOREncodeContext is the data type that holds context for all the
+ * encoding functions. It is less than 200 bytes, so it can go on the
+ * stack. The contents are opaque, and the caller should not access
+ * internal members.  A context may be re used serially as long as it is
+ * re initialized.
+ */
+typedef struct _QCBOREncodeContext QCBOREncodeContext;
+
+
+/**
+ * Initialize the encoder to prepare to encode some CBOR.
+ *
+ * @param[in,out]  pCtx     The encoder context to initialize.
+ * @param[in]      Storage  The buffer into which the encoded result
+ *                          will be written.
+ *
+ * Call this once at the start of an encoding of some CBOR. Then call
+ * the many functions like QCBOREncode_AddInt64() and
+ * QCBOREncode_AddText() to add the different data items. Finally,
+ * call QCBOREncode_Finish() to get the pointer and length of the
+ * encoded result.
+ *
+ * The primary purpose of this function is to give the pointer and
+ * length of the output buffer into which the encoded CBOR will be
+ * written. This is done with a @ref UsefulBuf structure, which is
+ * just a pointer and length (it is equivalent to two parameters, one
+ * a pointer and one a length, but a little prettier).
+ *
+ * The output buffer can be allocated any way (malloc, stack,
+ * static). It is just some memory that QCBOR writes to. The length
+ * must be the length of the allocated buffer. QCBOR will never write
+ * past that length, but might write up to that length. If the buffer
+ * is too small, encoding will go into an error state and not write
+ * anything further.
+ *
+ * If allocating on the stack the convenience macro
+ * UsefulBuf_MAKE_STACK_UB() can be used, but its use is not required.
+ *
+ * Since there is no reallocation or such, the output buffer must be
+ * correctly sized when passed in here. It is OK, but wasteful if it
+ * is too large. One way to pick the size is to figure out the maximum
+ * size that will ever be needed and hard code a buffer of that size.
+ *
+ * Another way to do it is to have QCBOR calculate it for you. To do
+ * this, pass @ref SizeCalculateUsefulBuf for @c Storage.  Then call
+ * all the functions to add the CBOR exactly as if encoding for
+ * real. Finally, call QCBOREncode_FinishGetSize().  Once the length
+ * is obtained, allocate a buffer of that size, call
+ * QCBOREncode_Init() again with the real buffer. Call all the add
+ * functions again and finally, QCBOREncode_Finish() to obtain the
+ * final result. This uses twice the CPU time, but that is usually not
+ * an issue.
+ *
+ * See QCBOREncode_Finish() for how the pointer and length for the
+ * encoded CBOR is returned.
+ *
+ * For practical purposes QCBOR can't output encoded CBOR larger than
+ * @c UINT32_MAX (4GB) even on 64-bit CPUs because the internal
+ * offsets used to track the start of an array/map are 32 bits to
+ * reduce the size of the encoding context.
+ *
+ * A @ref QCBOREncodeContext can be reused over and over as long as
+ * QCBOREncode_Init() is called before each use.
+ */
+void
+QCBOREncode_Init(QCBOREncodeContext *pCtx, UsefulBuf Storage);
+
+
+/**
+ * @brief  Add a signed 64-bit integer to the encoded output.
+ *
+ * @param[in] pCtx   The encoding context to add the integer to.
+ * @param[in] nNum   The integer to add.
+ *
+ * The integer will be encoded and added to the CBOR output.
+ *
+ * This function figures out the size and the sign and encodes in the
+ * correct minimal CBOR. Specifically, it will select CBOR major type
+ * 0 or 1 based on sign and will encode to 1, 2, 4 or 8 bytes
+ * depending on the value of the integer. Values less than 24
+ * effectively encode to one byte because they are encoded in with the
+ * CBOR major type.  This is a neat and efficient characteristic of
+ * CBOR that can be taken advantage of when designing CBOR-based
+ * protocols. If integers like tags can be kept between -23 and 23
+ * they will be encoded in one byte including the major type.
+ *
+ * If you pass a smaller int, say an @c int16_t or a small value, say
+ * 100, the encoding will still be CBOR's most compact that can
+ * represent the value.  For example, CBOR always encodes the value 0
+ * as one byte, 0x00. The representation as 0x00 includes
+ * identification of the type as an integer too as the major type for
+ * an integer is 0. See [RFC 8949]
+ * (https://tools.ietf.org/html/rfc8949) Appendix A for more examples
+ * of CBOR encoding. This compact encoding is also preferred
+ * serialization CBOR as per section 34.1 in RFC 8949.
+ *
+ * There are no functions to add @c int16_t or @c int32_t because they
+ * are not necessary because this always encodes to the smallest
+ * number of bytes based on the value (If this code is running on a
+ * 32-bit machine having a way to add 32-bit integers would reduce
+ * code size some).
+ *
+ * If the encoding context is in an error state, this will do
+ * nothing. If an error occurs when adding this integer, the internal
+ * error flag will be set, and the error will be returned when
+ * QCBOREncode_Finish() is called.
+ *
+ * See also QCBOREncode_AddUInt64().
+ */
+void
+QCBOREncode_AddInt64(QCBOREncodeContext *pCtx, int64_t nNum);
+
+static void
+QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, int64_t uNum);
+
+static void
+QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, int64_t uNum);
+
+
+/**
+ * @brief  Add an unsigned 64-bit integer to the encoded output.
+ *
+ * @param[in] pCtx  The encoding context to add the integer to.
+ * @param[in] uNum  The integer to add.
+ *
+ * The integer will be encoded and added to the CBOR output.
+ *
+ * The only reason so use this function is for integers larger than
+ * @c INT64_MAX and smaller than @c UINT64_MAX. Otherwise
+ * QCBOREncode_AddInt64() will work fine.
+ *
+ * Error handling is the same as for QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddUInt64(QCBOREncodeContext *pCtx, uint64_t uNum);
+
+static void
+QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pCtx, const char *szLabel, uint64_t uNum);
+
+static void
+QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, uint64_t uNum);
+
+
+/**
+ * @brief  Add a UTF-8 text string to the encoded output.
+ *
+ * @param[in] pCtx   The encoding context to add the text to.
+ * @param[in] Text   Pointer and length of text to add.
+ *
+ * The text passed in must be unencoded UTF-8 according to [RFC 3629]
+ * (https://tools.ietf.org/html/rfc3629). There is no NULL
+ * termination. The text is added as CBOR major type 3.
+ *
+ * If called with @c nBytesLen equal to 0, an empty string will be
+ * added. When @c nBytesLen is 0, @c pBytes may be @c NULL.
+ *
+ * Note that the restriction of the buffer length to a @c uint32_t is
+ * entirely intentional as this encoder is not capable of encoding
+ * lengths greater. This limit to 4GB for a text string should not be
+ * a problem.
+ *
+ * Text lines in Internet protocols (on the wire) are delimited by
+ * either a CRLF or just an LF. Officially many protocols specify
+ * CRLF, but implementations often work with either. CBOR type 3 text
+ * can be either line ending, even a mixture of both.
+ *
+ * Operating systems usually have a line end convention. Windows uses
+ * CRLF. Linux and MacOS use LF. Some applications on a given OS may
+ * work with either and some may not.
+ *
+ * The majority of use cases and CBOR protocols using type 3 text will
+ * work with either line ending. However, some use cases or protocols
+ * may not work with either in which case translation to and/or from
+ * the local line end convention, typically that of the OS, is
+ * necessary.
+ *
+ * QCBOR does no line ending translation for type 3 text when encoding
+ * and decoding.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddText(QCBOREncodeContext *pCtx, UsefulBufC Text);
+
+static void
+QCBOREncode_AddTextToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Text);
+
+static void
+QCBOREncode_AddTextToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Text);
+
+
+/**
+ * @brief  Add a UTF-8 text string to the encoded output.
+ *
+ * @param[in] pCtx      The encoding context to add the text to.
+ * @param[in] szString  Null-terminated text to add.
+ *
+ * This works the same as QCBOREncode_AddText().
+ */
+static void
+QCBOREncode_AddSZString(QCBOREncodeContext *pCtx, const char *szString);
+
+static void
+QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pCtx, const char *szLabel, const char *szString);
+
+static void
+QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, const char *szString);
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Add a double-precision floating-point number to the encoded output.
+ *
+ * @param[in] pCtx  The encoding context to add the double to.
+ * @param[in] dNum  The double-precision number to add.
+ *
+ * This encodes and outputs a floating-point number. CBOR major type 7
+ * is used.
+ *
+ * This implements preferred serialization, selectively encoding the
+ * double-precision floating-point number as either double-precision,
+ * single-precision or half-precision. Infinity, NaN and 0 are always
+ * encoded as half-precision. If no precision will be lost in the
+ * conversion to half-precision, then it will be converted and
+ * encoded. If not and no precision will be lost in conversion to
+ * single-precision, then it will be converted and encoded. If not,
+ * then no conversion is performed, and it encoded as a
+ * double-precision.
+ *
+ * Half-precision floating-point numbers take up 2 bytes, half that of
+ * single-precision, one quarter of double-precision
+ *
+ * This automatically reduces the size of encoded CBOR, maybe even by
+ * four if most of values are 0, infinity or NaN.
+ *
+ * When decoded, QCBOR will usually return these values as
+ * double-precision.
+ *
+ * It is possible to disable this preferred serialization when compiling
+ * QCBOR. In that case, this functions the same as
+ * QCBOREncode_AddDoubleNoPreferred().
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddDoubleNoPreferred(), QCBOREncode_AddFloat()
+ * and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+ */
+static void
+QCBOREncode_AddDouble(QCBOREncodeContext *pCtx, double dNum);
+
+static void
+QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
+
+static void
+QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
+
+
+/**
+ * @brief Add a single-precision floating-point number to the encoded output.
+ *
+ * @param[in] pCtx  The encoding context to add the double to.
+ * @param[in] fNum  The single-precision number to add.
+ *
+ * This is identical to QCBOREncode_AddDouble() except the input is
+ * single-precision.
+ *
+ * See also QCBOREncode_AddDouble(), QCBOREncode_AddDoubleNoPreferred(),
+ * and QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+ */
+static void
+QCBOREncode_AddFloat(QCBOREncodeContext *pCtx, float fNum);
+
+static void
+QCBOREncode_AddFloatToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
+
+static void
+QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float dNum);
+
+
+/**
+ * @brief Add a double-precision floating-point number without preferred encoding.
+ *
+ * @param[in] pCtx  The encoding context to add the double to.
+ * @param[in] dNum  The double-precision number to add.
+ *
+ * This always outputs the number as a 64-bit double-precision.
+ * Preferred serialization is not used.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
+ * QCBOREncode_AddFloatNoPreferred() and @ref Floating-Point.
+ */
+static void
+QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pCtx, double dNum);
+
+static void
+QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, double dNum);
+
+static void
+QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, double dNum);
+
+
+/**
+ * @brief Add a single-precision floating-point number without preferred encoding.
+ *
+ * @param[in] pCtx  The encoding context to add the double to.
+ * @param[in] fNum  The single-precision number to add.
+ *
+ * This always outputs the number as a 32-bit single-precision.
+ * Preferred serialization is not used.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddDouble(), QCBOREncode_AddFloat(), and
+ * QCBOREncode_AddDoubleNoPreferred() and @ref Floating-Point.
+ */
+static void
+QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pCtx, float fNum);
+
+static void
+QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pCtx, const char *szLabel, float fNum);
+
+static void
+QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, float fNum);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+/**
+ * @brief Add an optional tag.
+ *
+ * @param[in] pCtx  The encoding context to add the tag to.
+ * @param[in] uTag  The tag to add
+ *
+ * This outputs a CBOR major type 6 item that tags the next data item
+ * that is output usually to indicate it is some new data type.
+ *
+ * For many of the common standard tags, a function to encode data
+ * using it is provided and this is not needed. For example,
+ * QCBOREncode_AddDateEpoch() already exists to output integers
+ * representing dates with the right tag.
+ *
+ * The tag is applied to the next data item added to the encoded
+ * output. That data item that is to be tagged can be of any major
+ * CBOR type. Any number of tags can be added to a data item by
+ * calling this multiple times before the data item is added.
+ *
+ * See @ref Tags-Overview for discussion of creating new non-standard
+ * tags. See QCBORDecode_GetNext() for discussion of decoding custom
+ * tags.
+ */
+static void
+QCBOREncode_AddTag(QCBOREncodeContext *pCtx, uint64_t uTag);
+
+
+/**
+ * @brief  Add an epoch-based date.
+ *
+ * @param[in] pCtx             The encoding context to add the date to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] nDate            Number of seconds since 1970-01-01T00:00Z
+ *                             in UTC time.
+ *
+ * As per RFC 8949 this is similar to UNIX/Linux/POSIX dates. This is
+ * the most compact way to specify a date and time in CBOR. Note that
+ * this is always UTC and does not include the time zone.  Use
+ * QCBOREncode_AddDateString() if you want to include the time zone.
+ *
+ * The preferred integer serialization rules apply here so the date will be
+ * encoded in a minimal number of bytes. Until about the year 2106
+ * these dates will encode in 6 bytes -- one byte for the tag, one
+ * byte for the type and 4 bytes for the integer. After that it will
+ * encode to 10 bytes.
+ *
+ * Negative values are supported for dates before 1970.
+ *
+ * If you care about leap-seconds and that level of accuracy, make sure
+ * the system you are running this code on does it correctly. This code
+ * just takes the value passed in.
+ *
+ * This implementation cannot encode fractional seconds using float or
+ * double even though that is allowed by CBOR, but you can encode them
+ * if you want to by calling QCBOREncode_AddTag() and QCBOREncode_AddDouble().
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddTDaysEpoch().
+ */
+static void
+QCBOREncode_AddTDateEpoch(QCBOREncodeContext *pCtx,
+                          uint8_t             uTagRequirement,
+                          int64_t             nDate);
+
+static void
+QCBOREncode_AddTDateEpochToMapSZ(QCBOREncodeContext *pCtx,
+                                 const char         *szLabel,
+                                 uint8_t             uTagRequirement,
+                                 int64_t             nDate);
+
+static void
+QCBOREncode_AddTDateEpochToMapN(QCBOREncodeContext *pCtx,
+                                int64_t             nLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t             nDate);
+
+
+static void
+QCBOREncode_AddDateEpoch(QCBOREncodeContext *pCtx,
+                         int64_t             nDate);
+
+static void
+QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pCtx,
+                              const char         *szLabel,
+                              int64_t             nDate);
+
+static void
+QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pCtx,
+                               int64_t             nLabel,
+                               int64_t             nDate);
+
+
+
+/**
+ *  @brief  Add an epoch-based day-count date.
+ *
+ *  @param[in] pCtx             The encoding context to add the date to.
+ *  @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                              @ref QCBOR_ENCODE_AS_BORROWED.
+ *  @param[in] nDays            Number of days before or after 1970-01-0.
+ *
+ * This date format is described in
+ * [RFC 8943] (https://tools.ietf.org/html/rfc8943).
+ *
+ * The preferred integer serialization rules apply here so the date
+ * will be encoded in a minimal number of bytes. Until about the year
+ * 2149 these dates will encode in 4 bytes -- one byte for the tag,
+ * one byte for the type and 2 bytes for the integer.
+ *
+ * See also QCBOREncode_AddTDateEpoch().
+ */
+static void
+QCBOREncode_AddTDaysEpoch(QCBOREncodeContext *pCtx,
+                          uint8_t             uTagRequirement,
+                          int64_t             nDays);
+
+static void
+QCBOREncode_AddTDaysEpochToMapSZ(QCBOREncodeContext *pCtx,
+                                 const char         *szLabel,
+                                 uint8_t             uTagRequirement,
+                                 int64_t             nDays);
+
+static void
+QCBOREncode_AddTDaysEpochToMapN(QCBOREncodeContext *pCtx,
+                                int64_t             nLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t             nDays);
+
+
+
+
+/**
+ * @brief Add a byte string to the encoded output.
+ *
+ * @param[in] pCtx   The encoding context to add the bytes to.
+ * @param[in] Bytes  Pointer and length of the input data.
+ *
+ * Simply adds the bytes to the encoded output as CBOR major type 2.
+ *
+ * If called with @c Bytes.len equal to 0, an empty string will be
+ * added. When @c Bytes.len is 0, @c Bytes.ptr may be @c NULL.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddBytes(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static void
+QCBOREncode_AddBytesToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static void
+QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+/**
+ * @brief Set up to write a byte string value directly to encoded output.
+ *
+ * @param[in] pCtx     The encoding context to add the bytes to.
+ * @param[out] pPlace  Pointer and length of place to write byte string value.
+ *
+ * QCBOREncode_AddBytes() is the normal way to encode a byte string.
+ * This is for special cases and by passes some of the pointer safety.
+ *
+ * The purpose of this is to output the bytes that make up a byte
+ * string value directly to the QCBOR output buffer so you don't need
+ * to have a copy of it in memory. This is particularly useful if the
+ * byte string is large, for example, the encrypted payload of a
+ * COSE_Encrypt message. The payload encryption algorithm can output
+ * directly to the encoded CBOR buffer, perhaps by making it the
+ * output buffer for some function (e.g. symmetric encryption) or by
+ * multiple writes.
+ *
+ * The pointer in @c pPlace is where to start writing. Writing is just
+ * copying bytes to the location by the pointer in \c pPlace.  Writing
+ * past the length in @c pPlace will be writing off the end of the
+ * output buffer.
+ *
+ * If there is no room in the output buffer @ref NULLUsefulBuf will be
+ * returned and there is no need to call QCBOREncode_CloseBytes().
+ *
+ * The byte string must be closed by calling QCBOREncode_CloseBytes().
+ *
+ * Warning: this bypasses some of the usual checks provided by QCBOR
+ * against writing off the end of the encoded output buffer.
+ */
+void
+QCBOREncode_OpenBytes(QCBOREncodeContext *pCtx, UsefulBuf *pPlace);
+
+static void
+QCBOREncode_OpenBytesInMapSZ(QCBOREncodeContext *pCtx,
+                             const char         *szLabel,
+                             UsefulBuf          *pPlace);
+
+static void
+QCBOREncode_OpenBytesInMapN(QCBOREncodeContext *pCtx,
+                            int64_t             nLabel,
+                            UsefulBuf          *pPlace);
+
+
+/**
+ *  @brief Close out a byte string written directly to encoded output.
+ *
+ *  @param[in] pCtx      The encoding context to add the bytes to.
+ *  @param[out] uAmount  The number of bytes written, the length of the
+ *                       byte string.
+ *
+ * This closes out a call to QCBOREncode_OpenBytes().  This inserts a
+ * CBOR header at the front of the byte string value to make it a
+ * well-formed byte string.
+ *
+ * If there was no call to QCBOREncode_OpenBytes() then @ref
+ * QCBOR_ERR_TOO_MANY_CLOSES is set.
+ */
+void
+QCBOREncode_CloseBytes(QCBOREncodeContext *pCtx, size_t uAmount);
+
+
+/**
+ * @brief Add a binary UUID to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the UUID to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Bytes            Pointer and length of the binary UUID.
+ *
+ * A binary UUID as defined in [RFC 4122]
+ * (https://tools.ietf.org/html/rfc4122) is added to the output.
+ *
+ * It is output as CBOR major type 2, a binary string, with tag @ref
+ * CBOR_TAG_BIN_UUID indicating the binary string is a UUID.
+ */
+static void
+QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTBinaryUUIDToMapSZ(QCBOREncodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTBinaryUUIDToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t             nLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBufC          Bytes);
+
+
+static void
+QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pCtx, UsefulBufC Bytes);
+
+static void
+QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Bytes);
+
+static void
+QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Bytes);
+
+
+/**
+ * @brief Add a positive big number to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the big number to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Bytes            Pointer and length of the big number.
+ *
+ * Big numbers are integers larger than 64-bits. Their format is
+ * described in [RFC 8949] (https://tools.ietf.org/html/rfc8949).
+ *
+ * It is output as CBOR major type 2, a binary string, with tag
+ * @ref CBOR_TAG_POS_BIGNUM indicating the binary string is a positive
+ * big number.
+ *
+ * Often big numbers are used to represent cryptographic keys,
+ * however, COSE which defines representations for keys chose not to
+ * use this particular type.
+ */
+static void
+QCBOREncode_AddTPositiveBignum(QCBOREncodeContext *pCtx,
+                               uint8_t             uTagRequirement,
+                               UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTPositiveBignumToMapSZ(QCBOREncodeContext *pCtx,
+                                      const char         *szLabel,
+                                      uint8_t             uTagRequirement,
+                                      UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTPositiveBignumToMapN(QCBOREncodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint8_t             uTagRequirement,
+                                     UsefulBufC          Bytes);
+
+
+static void
+QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pCtx,
+                             UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pCtx,
+                                   const char         *szLabel,
+                                   UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pCtx,
+                                    int64_t             nLabel,
+                                    UsefulBufC          Bytes);
+
+
+/**
+ * @brief Add a negative big number to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the big number to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Bytes            Pointer and length of the big number.
+ *
+ * Big numbers are integers larger than 64-bits. Their format is
+ * described in [RFC 8949] (https://tools.ietf.org/html/rfc8949).
+ *
+ * It is output as CBOR major type 2, a binary string, with tag
+ * @ref CBOR_TAG_NEG_BIGNUM indicating the binary string is a negative
+ * big number.
+ *
+ * Often big numbers are used to represent cryptographic keys,
+ * however, COSE which defines representations for keys chose not to
+ * use this particular type.
+ */
+static void
+QCBOREncode_AddTNegativeBignum(QCBOREncodeContext *pCtx,
+                               uint8_t             uTagRequirement,
+                               UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTNegativeBignumToMapSZ(QCBOREncodeContext *pCtx,
+                                      const char         *szLabel,
+                                      uint8_t             uTagRequirement,
+                                      UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddTNegativeBignumToMapN(QCBOREncodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint8_t             uTagRequirement,
+                                     UsefulBufC          Bytes);
+
+
+static void
+QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pCtx,
+                              UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pCtx,
+                                   const char         *szLabel,
+                                   UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pCtx,
+                                    int64_t             nLabel,
+                                    UsefulBufC          Bytes);
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+/**
+ * @brief Add a decimal fraction to the encoded output.
+ *
+ * @param[in] pCtx             Encoding context to add the decimal fraction to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] nMantissa        The mantissa.
+ * @param[in] nBase10Exponent  The exponent.
+ *
+ * The value is nMantissa * 10 ^ nBase10Exponent.
+ *
+ * A decimal fraction is good for exact representation of some values
+ * that can't be represented exactly with standard C (IEEE 754)
+ * floating-point numbers.  Much larger and much smaller numbers can
+ * also be represented than floating-point because of the larger
+ * number of bits in the exponent.
+ *
+ * The decimal fraction is conveyed as two integers, a mantissa and a
+ * base-10 scaling factor.
+ *
+ * For example, 273.15 is represented by the two integers 27315 and -2.
+ *
+ * The exponent and mantissa have the range from @c INT64_MIN to
+ * @c INT64_MAX for both encoding and decoding (CBOR allows
+ * @c -UINT64_MAX to @c UINT64_MAX, but this implementation doesn't
+ * support this range to reduce code size and interface complexity a
+ * little).
+ *
+ * CBOR Preferred serialization of the integers is used, thus they
+ * will be encoded in the smallest number of bytes possible.
+ *
+ * See also QCBOREncode_AddDecimalFractionBigNum() for a decimal
+ * fraction with arbitrarily large precision and
+ * QCBOREncode_AddBigFloat().
+ *
+ * There is no representation of positive or negative infinity or NaN
+ * (Not a Number). Use QCBOREncode_AddDouble() to encode them.
+ *
+ * See @ref expAndMantissa for decoded representation.
+ */
+static void
+QCBOREncode_AddTDecimalFraction(QCBOREncodeContext *pCtx,
+                                uint8_t             uTagRequirement,
+                                int64_t             nMantissa,
+                                int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddTDecimalFractionToMapSZ(QCBOREncodeContext *pCtx,
+                                       const char         *szLabel,
+                                       uint8_t             uTagRequirement,
+                                       int64_t             nMantissa,
+                                       int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddTDecimalFractionToMapN(QCBOREncodeContext *pCtx,
+                                      int64_t             nLabel,
+                                      uint8_t             uTagRequirement,
+                                      int64_t             nMantissa,
+                                      int64_t             nBase10Exponent);
+
+
+static void
+QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pCtx,
+                               int64_t             nMantissa,
+                               int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pCtx,
+                                    const char         *szLabel,
+                                    int64_t             nMantissa,
+                                    int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     int64_t             nMantissa,
+                                     int64_t             nBase10Exponent);
+
+
+/**
+ * @brief Add a decimal fraction with a big number mantissa to the encoded output.
+ *
+ * @param[in] pCtx             Encoding context to add the decimal fraction to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Mantissa         The mantissa.
+ * @param[in] bIsNegative      false if mantissa is positive, true if negative.
+ * @param[in] nBase10Exponent  The exponent.
+ *
+ * This is the same as QCBOREncode_AddDecimalFraction() except the
+ * mantissa is a big number (See QCBOREncode_AddPositiveBignum())
+ * allowing for arbitrarily large precision.
+ *
+ * See @ref expAndMantissa for decoded representation.
+ */
+static void
+QCBOREncode_AddTDecimalFractionBigNum(QCBOREncodeContext *pCtx,
+                                      uint8_t             uTagRequirement,
+                                      UsefulBufC          Mantissa,
+                                      bool                bIsNegative,
+                                      int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddTDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pCtx,
+                                             const char         *szLabel,
+                                             uint8_t             uTagRequirement,
+                                             UsefulBufC          Mantissa,
+                                             bool                bIsNegative,
+                                             int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddTDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
+                                            int64_t             nLabel,
+                                            uint8_t             uTagRequirement,
+                                            UsefulBufC          Mantissa,
+                                            bool                bIsNegative,
+                                            int64_t             nBase10Exponent);
+
+
+static void
+QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pCtx,
+                                     UsefulBufC          Mantissa,
+                                     bool                bIsNegative,
+                                     int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pCtx,
+                                            const char         *szLabel,
+                                            UsefulBufC          Mantissa,
+                                            bool                bIsNegative,
+                                            int64_t             nBase10Exponent);
+
+static void
+QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pCtx,
+                                           int64_t             nLabel,
+                                           UsefulBufC          Mantissa,
+                                           bool                bIsNegative,
+                                           int64_t             nBase10Exponent);
+
+/**
+ * @brief Add a big floating-point number to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the bigfloat to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] nMantissa        The mantissa.
+ * @param[in] nBase2Exponent   The exponent.
+ *
+ * The value is nMantissa * 2 ^ nBase2Exponent.
+ *
+ * "Bigfloats", as CBOR terms them, are similar to IEEE floating-point
+ * numbers in having a mantissa and base-2 exponent, but they are not
+ * supported by hardware or encoded the same. They explicitly use two
+ * CBOR-encoded integers to convey the mantissa and exponent, each of
+ * which can be 8, 16, 32 or 64 bits. With both the mantissa and
+ * exponent 64 bits they can express more precision and a larger range
+ * than an IEEE double floating-point number. See
+ * QCBOREncode_AddBigFloatBigNum() for even more precision.
+ *
+ * For example, 1.5 would be represented by a mantissa of 3 and an
+ * exponent of -1.
+ *
+ * The exponent and mantissa have the range from @c INT64_MIN to
+ * @c INT64_MAX for both encoding and decoding (CBOR allows @c
+ * -UINT64_MAX to @c UINT64_MAX, but this implementation doesn't
+ * support this range to reduce code size and interface complexity a
+ * little).
+ *
+ * CBOR preferred serialization of the integers is used, thus they will
+ * be encoded in the smallest number of bytes possible.
+ *
+ * This can also be used to represent floating-point numbers in
+ * environments that don't support IEEE 754.
+ *
+ * See @ref expAndMantissa for decoded representation.
+ */
+static void
+QCBOREncode_AddTBigFloat(QCBOREncodeContext *pCtx,
+                         uint8_t             uTagRequirement,
+                         int64_t             nMantissa,
+                         int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddTBigFloatToMapSZ(QCBOREncodeContext *pCtx,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t             nMantissa,
+                                int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddTBigFloatToMapN(QCBOREncodeContext *pCtx,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t             nMantissa,
+                               int64_t             nBase2Exponent);
+
+
+static void
+QCBOREncode_AddBigFloat(QCBOREncodeContext *pCtx,
+                        int64_t             nMantissa,
+                        int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pCtx,
+                             const char         *szLabel,
+                             int64_t             nMantissa,
+                             int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pCtx,
+                              int64_t             nLabel,
+                              int64_t             nMantissa,
+                              int64_t             nBase2Exponent);
+
+/**
+ * @brief Add a big floating-point number with a big number mantissa to
+ *        the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the bigfloat to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Mantissa         The mantissa.
+ * @param[in] bIsNegative      false if mantissa is positive, true if negative.
+ * @param[in] nBase2Exponent   The exponent.
+ *
+ * This is the same as QCBOREncode_AddBigFloat() except the mantissa
+ * is a big number (See QCBOREncode_AddPositiveBignum()) allowing for
+ * arbitrary precision.
+ *
+ * See @ref expAndMantissa for decoded representation.
+ */
+static void
+QCBOREncode_AddTBigFloatBigNum(QCBOREncodeContext *pCtx,
+                               uint8_t             uTagRequirement,
+                               UsefulBufC          Mantissa,
+                               bool                bIsNegative,
+                               int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddTBigFloatBigNumToMapSZ(QCBOREncodeContext *pCtx,
+                                      const char         *szLabel,
+                                      uint8_t             uTagRequirement,
+                                      UsefulBufC          Mantissa,
+                                      bool                bIsNegative,
+                                      int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddTBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint8_t             uTagRequirement,
+                                     UsefulBufC          Mantissa,
+                                     bool                bIsNegative,
+                                     int64_t             nBase2Exponent);
+
+
+static void
+QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pCtx,
+                              UsefulBufC          Mantissa,
+                              bool                bIsNegative,
+                              int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pCtx,
+                                   const char         *szLabel,
+                                   UsefulBufC          Mantissa,
+                                   bool                bIsNegative,
+                                   int64_t             nBase2Exponent);
+
+static void
+QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pCtx,
+                                    int64_t             nLabel,
+                                    UsefulBufC          Mantissa,
+                                    bool                bIsNegative,
+                                    int64_t             nBase2Exponent);
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+/**
+ * @brief Add a text URI to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the URI to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] URI              Pointer and length of the URI.
+ *
+ * The format of URI must be per [RFC 3986]
+ * (https://tools.ietf.org/html/rfc3986).
+ *
+ * It is output as CBOR major type 3, a text string, with tag @ref
+ * CBOR_TAG_URI indicating the text string is a URI.
+ *
+ * A URI in a NULL-terminated string, @c szURI, can be easily added with
+ * this code:
+ *
+ *      QCBOREncode_AddURI(pCtx, UsefulBuf_FromSZ(szURI));
+ */
+static void
+QCBOREncode_AddTURI(QCBOREncodeContext *pCtx,
+                    uint8_t             uTagRequirement,
+                    UsefulBufC          URI);
+
+static void
+QCBOREncode_AddTURIToMapSZ(QCBOREncodeContext *pCtx,
+                           const char         *szLabel,
+                           uint8_t             uTagRequirement,
+                           UsefulBufC          URI);
+
+static void
+QCBOREncode_AddTURIToMapN(QCBOREncodeContext *pCtx,
+                          int64_t             nLabel,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC          URI);
+
+
+static void
+QCBOREncode_AddURI(QCBOREncodeContext *pCtx,
+                   UsefulBufC          URI);
+
+static void
+QCBOREncode_AddURIToMap(QCBOREncodeContext *pCtx,
+                        const char         *szLabel,
+                        UsefulBufC          URI);
+
+static void
+QCBOREncode_AddURIToMapN(QCBOREncodeContext *pCtx,
+                         int64_t             nLabel,
+                         UsefulBufC          URI);
+
+
+/**
+ * @brief Add Base64-encoded text to encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the base-64 text to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] B64Text          Pointer and length of the base-64 encoded text.
+ *
+ * The text content is Base64 encoded data per [RFC 4648]
+ * (https://tools.ietf.org/html/rfc4648).
+ *
+ * It is output as CBOR major type 3, a text string, with tag @ref
+ * CBOR_TAG_B64 indicating the text string is Base64 encoded.
+ */
+static void
+QCBOREncode_AddTB64Text(QCBOREncodeContext *pCtx,
+                        uint8_t             uTagRequirement,
+                                    UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddTB64TextToMapSZ(QCBOREncodeContext *pCtx,
+                               const char         *szLabel,
+                               uint8_t             uTagRequirement,
+                               UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddTB64TextToMapN(QCBOREncodeContext *pCtx,
+                              int64_t nLabel,
+                              uint8_t uTagRequirement,
+                              UsefulBufC B64Text);
+
+
+static void
+QCBOREncode_AddB64Text(QCBOREncodeContext *pCtx,
+                       UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pCtx,
+                            const char         *szLabel,
+                            UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pCtx,
+                             int64_t             nLabel,
+                             UsefulBufC          B64Text);
+
+
+
+/**
+ * @brief Add base64url encoded data to encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the base64url to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] B64Text          Pointer and length of the base64url encoded text.
+ *
+ * The text content is base64URL encoded text as per [RFC 4648]
+ * (https://tools.ietf.org/html/rfc4648).
+ *
+ * It is output as CBOR major type 3, a text string, with tag
+ * @ref CBOR_TAG_B64URL indicating the text string is a Base64url
+ * encoded.
+ */
+static void
+QCBOREncode_AddTB64URLText(QCBOREncodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddTB64URLTextToMapSZ(QCBOREncodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddTB64URLTextToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t             nLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBufC          B64Text);
+
+
+static void
+QCBOREncode_AddB64URLText(QCBOREncodeContext *pCtx,
+                          UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pCtx,
+                               const char         *szLabel,
+                               UsefulBufC          B64Text);
+
+static void
+QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pCtx,
+                                int64_t             nLabel,
+                                UsefulBufC          B64Text);
+
+
+/**
+ * @brief Add Perl Compatible Regular Expression.
+ *
+ * @param[in] pCtx             Encoding context to add the regular expression to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] Regex            Pointer and length of the regular expression.
+ *
+ * The text content is Perl Compatible Regular
+ * Expressions (PCRE) / JavaScript syntax [ECMA262].
+ *
+ * It is output as CBOR major type 3, a text string, with tag @ref
+ * CBOR_TAG_REGEX indicating the text string is a regular expression.
+ */
+static void
+QCBOREncode_AddTRegex(QCBOREncodeContext *pCtx,
+                      uint8_t            uTagRequirement,
+                      UsefulBufC         Regex);
+
+static void
+QCBOREncode_AddTRegexToMapSZ(QCBOREncodeContext *pCtx,
+                             const char         *szLabel,
+                             uint8_t             uTagRequirement,
+                             UsefulBufC          Regex);
+
+static void
+QCBOREncode_AddTRegexToMapN(QCBOREncodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint8_t             uTagRequirement,
+                            UsefulBufC          Regex);
+
+
+static void
+QCBOREncode_AddRegex(QCBOREncodeContext *pCtx,
+                     UsefulBufC          Regex);
+
+static void
+QCBOREncode_AddRegexToMap(QCBOREncodeContext *pCtx,
+                          const char         *szLabel,
+                          UsefulBufC          Regex);
+
+static void
+QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pCtx,
+                           int64_t             nLabel,
+                           UsefulBufC          Regex);
+
+
+/**
+ * @brief MIME encoded data to the encoded output.
+ *
+ * @param[in] pCtx             The encoding context to add the MIME data to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] MIMEData         Pointer and length of the MIME data.
+ *
+ * The text content is in MIME format per [RFC 2045]
+ * (https://tools.ietf.org/html/rfc2045) including the headers.
+ *
+ * It is output as CBOR major type 2, a binary string, with tag
+ * @ref CBOR_TAG_BINARY_MIME indicating the string is MIME data.  This
+ * outputs tag 257, not tag 36, as it can carry any type of MIME
+ * binary, 7-bit, 8-bit, quoted-printable and base64 where tag 36
+ * cannot.
+ *
+ * Previous versions of QCBOR, those before spiffy decode, output tag
+ * 36. Decoding supports both tag 36 and 257.  (if the old behavior
+ * with tag 36 is needed, copy the inline functions below and change
+ * the tag number).
+ *
+ * See also QCBORDecode_GetMIMEMessage() and
+ * @ref QCBOR_TYPE_BINARY_MIME.
+ *
+ * This does no translation of line endings. See QCBOREncode_AddText()
+ * for a discussion of line endings in CBOR.
+ */
+static void
+QCBOREncode_AddTMIMEData(QCBOREncodeContext *pCtx,
+                         uint8_t             uTagRequirement,
+                         UsefulBufC          MIMEData);
+
+static void
+QCBOREncode_AddTMIMEDataToMapSZ(QCBOREncodeContext *pCtx,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                UsefulBufC          MIMEData);
+
+static void
+QCBOREncode_AddTMIMEDataToMapN(QCBOREncodeContext *pCtx,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               UsefulBufC          MIMEData);
+
+
+static void
+QCBOREncode_AddMIMEData(QCBOREncodeContext *pCtx,
+                        UsefulBufC          MIMEData);
+
+static void
+QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pCtx,
+                             const char         *szLabel,
+                             UsefulBufC          MIMEData);
+
+static void
+QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pCtx,
+                              int64_t             nLabel,
+                              UsefulBufC          MIMEData);
+
+
+/**
+ * @brief  Add an RFC 3339 date string
+ *
+ * @param[in] pCtx             The encoding context to add the date to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] szDate           Null-terminated string with date to add.
+ *
+ * The string szDate should be in the form of [RFC 3339]
+ * (https://tools.ietf.org/html/rfc3339) as defined by section 3.3 in
+ * [RFC 4287] (https://tools.ietf.org/html/rfc4287). This is as
+ * described in section 3.4.1 in [RFC 8949]
+ * (https://tools.ietf.org/html/rfc8949).
+ *
+ * Note that this function doesn't validate the format of the date
+ * string at all. If you add an incorrect format date string, the
+ * generated CBOR will be incorrect and the receiver may not be able
+ * to handle it.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddTDayString().
+ */
+static void
+QCBOREncode_AddTDateString(QCBOREncodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           const char         *szDate);
+
+static void
+QCBOREncode_AddTDateStringToMapSZ(QCBOREncodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  const char         *szDate);
+
+static void
+QCBOREncode_AddTDateStringToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t             nLabel,
+                                 uint8_t             uTagRequirement,
+                                 const char         *szDate);
+
+
+static void
+QCBOREncode_AddDateString(QCBOREncodeContext *pCtx,
+                          const char         *szDate);
+
+static void
+QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pCtx,
+                               const char         *szLabel,
+                               const char         *szDate);
+
+static void
+QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pCtx,
+                                int64_t             nLabel,
+                                const char         *szDate);
+
+
+/**
+ * @brief  Add a date-only string.
+ *
+ * @param[in] pCtx             The encoding context to add the date to.
+ * @param[in] uTagRequirement  Either @ref QCBOR_ENCODE_AS_TAG or
+ *                             @ref QCBOR_ENCODE_AS_BORROWED.
+ * @param[in] szDate           Null-terminated string with date to add.
+ *
+ * This date format is described in
+ * [RFC 8943] (https://tools.ietf.org/html/rfc8943), but that mainly
+ * references RFC 3339.  The string szDate must be in the forrm
+ * specified the ABNF for a full-date in
+ * [RFC 3339] (https://tools.ietf.org/html/rfc3339). Examples of this
+ * are "1985-04-12" and "1937-01-01".  The time and the time zone are
+ * never included.
+ *
+ * Note that this function doesn't validate the format of the date
+ * string at all. If you add an incorrect format date string, the
+ * generated CBOR will be incorrect and the receiver may not be able
+ * to handle it.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ *
+ * See also QCBOREncode_AddTDateString().
+ */
+static void
+QCBOREncode_AddTDaysString(QCBOREncodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           const char         *szDate);
+
+static void
+QCBOREncode_AddTDaysStringToMapSZ(QCBOREncodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  const char         *szDate);
+
+static void
+QCBOREncode_AddTDaysStringToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t             nLabel,
+                                 uint8_t             uTagRequirement,
+                                 const char         *szDate);
+
+
+/**
+ * @brief  Add a standard Boolean.
+ *
+ * @param[in] pCtx  The encoding context to add the Boolean to.
+ * @param[in] b     true or false from @c <stdbool.h>.
+ *
+ * Adds a Boolean value as CBOR major type 7.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddBool(QCBOREncodeContext *pCtx, bool b);
+
+static void
+QCBOREncode_AddBoolToMap(QCBOREncodeContext *pCtx, const char *szLabel, bool b);
+
+static void
+QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, bool b);
+
+
+/**
+ * @brief  Add a NULL to the encoded output.
+ *
+ * @param[in] pCtx  The encoding context to add the NULL to.
+ *
+ * Adds the NULL value as CBOR major type 7.
+ *
+ * This NULL doesn't have any special meaning in CBOR such as a
+ * terminating value for a string or an empty value.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddNULL(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_AddNULLToMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void
+QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ * @brief  Add an "undef" to the encoded output.
+ *
+ * @param[in] pCtx  The encoding context to add the "undef" to.
+ *
+ * Adds the undef value as CBOR major type 7.
+ *
+ * Note that this value will not translate to JSON.
+ *
+ * This Undef doesn't have any special meaning in CBOR such as a
+ * terminating value for a string or an empty value.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static void
+QCBOREncode_AddUndef(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_AddUndefToMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void
+QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ * @brief Add a simple value.
+ *
+ * @param[in] pMe    The encode context.
+ * @param[in] uNum   The simple value.
+ *
+ * QCBOREncode_AddBool(), QCBOREncode_AddUndef() and
+ * QCBOREncode_AddNull() are preferred to this for the simple values
+ * defined in RFC 8949, but this can be used for them too.
+ *
+ * The main purpose of this is to add simple values beyond those in
+ * defined RFC 8949. Note that simple values must be registered with
+ * IANA. Those in the range of 0 to 19 must be standardized.  Those in
+ * the range of 32 to 255 do not require a standard, but must be
+ * publically specified. There is no range of values for proprietary
+ * use. See
+ * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml
+ */
+static void
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum);
+
+static void
+QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const uint8_t       uSimple);
+
+static void
+QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uSimple);
+
+
+/**
+ * @brief  Indicates that the next items added are in an array.
+ *
+ * @param[in] pCtx The encoding context to open the array in.
+ *
+ * Arrays are the basic CBOR aggregate or structure type. Call this
+ * function to start or open an array. Then call the various
+ * @c QCBOREncode_AddXxx() functions to add the items that go into the
+ * array. Then call QCBOREncode_CloseArray() when all items have been
+ * added. The data items in the array can be of any type and can be of
+ * mixed types.
+ *
+ * Nesting of arrays and maps is allowed and supported just by calling
+ * QCBOREncode_OpenArray() again before calling
+ * QCBOREncode_CloseArray().  While CBOR has no limit on nesting, this
+ * implementation does in order to keep it smaller and simpler.  The
+ * limit is @ref QCBOR_MAX_ARRAY_NESTING. This is the max number of
+ * times this can be called without calling
+ * QCBOREncode_CloseArray(). QCBOREncode_Finish() will return
+ * @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP when it is called as this
+ * function just sets an error state and returns no value when this
+ * occurs.
+ *
+ * If you try to add more than @ref QCBOR_MAX_ITEMS_IN_ARRAY items to
+ * a single array or map, @ref QCBOR_ERR_ARRAY_TOO_LONG will be
+ * returned when QCBOREncode_Finish() is called.
+ *
+ * An array itself must have a label if it is being added to a map.
+ * Note that array elements do not have labels (but map elements do).
+ *
+ * An array itself may be tagged by calling QCBOREncode_AddTag()
+ * before this call.
+ */
+static void
+QCBOREncode_OpenArray(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void
+QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pCtx,  int64_t nLabel);
+
+
+/**
+ * @brief Close an open array.
+ *
+ * @param[in] pCtx The encoding context to close the array in.
+ *
+ * The closes an array opened by QCBOREncode_OpenArray(). It reduces
+ * nesting level by one. All arrays (and maps) must be closed before
+ * calling QCBOREncode_Finish().
+ *
+ * When an error occurs as a result of this call, the encoder records
+ * the error and enters the error state. The error will be returned
+ * when QCBOREncode_Finish() is called.
+ *
+ * If this has been called more times than QCBOREncode_OpenArray(), then
+ * @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when QCBOREncode_Finish()
+ * is called.
+ *
+ * If this is called and it is not an array that is currently open,
+ * @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
+ * QCBOREncode_Finish() is called.
+ */
+static void
+QCBOREncode_CloseArray(QCBOREncodeContext *pCtx);
+
+
+
+
+/**
+ * @brief  Indicates that the next items added are in a map.
+ *
+ * @param[in] pCtx The encoding context to open the map in.
+ *
+ * See QCBOREncode_OpenArray() for more information, particularly
+ * error handling.
+ *
+ * CBOR maps are an aggregate type where each item in the map consists
+ * of a label and a value. They are similar to JSON objects.
+ *
+ * The value can be any CBOR type including another map.
+ *
+ * The label can also be any CBOR type, but in practice they are
+ * typically, integers as this gives the most compact output. They
+ * might also be text strings which gives readability and translation
+ * to JSON.
+ *
+ * Every @c QCBOREncode_AddXxx() call has one version that ends with
+ * @c InMap for adding items to maps with string labels and one that
+ * ends with @c InMapN that is for adding with integer labels.
+ *
+ * RFC 8949 uses the term "key" instead of "label".
+ *
+ * If you wish to use map labels that are neither integer labels nor
+ * text strings, then just call the QCBOREncode_AddXxx() function
+ * explicitly to add the label. Then call it again to add the value.
+ *
+ * See the [RFC 8949] (https://tools.ietf.org/html/rfc8949) for a lot
+ * more information on creating maps.
+ */
+static void
+QCBOREncode_OpenMap(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_OpenMapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void
+QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ * @brief Close an open map.
+ *
+ * @param[in] pCtx The encoding context to close the map in.
+ *
+ * This closes a map opened by QCBOREncode_OpenMap(). It reduces
+ * nesting level by one.
+ *
+ * When an error occurs as a result of this call, the encoder records
+ * the error and enters the error state. The error will be returned
+ * when QCBOREncode_Finish() is called.
+ *
+ * If this has been called more times than QCBOREncode_OpenMap(), then
+ * @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
+ * QCBOREncode_Finish() is called.
+ *
+ * If this is called and it is not a map that is currently open,
+ * @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
+ * QCBOREncode_Finish() is called.
+ */
+static void
+QCBOREncode_CloseMap(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Indicates that the next items added are in an indefinite length array.
+ *
+ * @param[in] pCtx The encoding context to open the array in.
+ *
+ * This is the same as QCBOREncode_OpenArray() except the array is
+ * indefinite length.
+ *
+ * This must be closed with QCBOREncode_CloseArrayIndefiniteLength().
+ */
+static void
+QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pCtx,
+                                           const char         *szLabel);
+
+static void
+QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pCtx,
+                                            int64_t            nLabel);
+
+
+/**
+ * @brief Close an open indefinite length array.
+ *
+ * @param[in] pCtx The encoding context to close the array in.
+ *
+ * This is the same as QCBOREncode_CloseArray(), but the open array
+ * that is being close must be of indefinite length.
+ */
+static void
+QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Indicates that the next items added are in an indefinite length map.
+ *
+ * @param[in] pCtx The encoding context to open the map in.
+ *
+ * This is the same as QCBOREncode_OpenMap() except the array is
+ * indefinite length.
+ *
+ * This must be closed with QCBOREncode_CloseMapIndefiniteLength().
+ */
+static void
+QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pCtx,
+                                         const char         *szLabel);
+
+static void
+QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pCtx,
+                                          int64_t            nLabel);
+
+
+/**
+ * @brief Close an open indefinite length map.
+ *
+ * @param[in] pCtx The encoding context to close the map in.
+ *
+ * This is the same as QCBOREncode_CloseMap(), but the open map that
+ * is being close must be of indefinite length.
+ */
+static  void
+QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pCtx);
+
+
+
+
+/**
+ * @brief Indicate start of encoded CBOR to be wrapped in a bstr.
+ *
+ * @param[in] pCtx The encoding context to open the bstr-wrapped CBOR in.
+ *
+ * All added encoded items between this call and a call to
+ * QCBOREncode_CloseBstrWrap2() will be wrapped in a bstr. They will
+ * appear in the final output as a byte string.  That byte string will
+ * contain encoded CBOR. This increases nesting level by one.
+ *
+ * The typical use case is for encoded CBOR that is to be
+ * cryptographically hashed, as part of a [RFC 8152, COSE]
+ * (https://tools.ietf.org/html/rfc8152) implementation. The wrapping
+ * byte string is taken as input by the hash function (which is why it
+ * is returned by QCBOREncode_CloseBstrWrap2()).  It is also easy to
+ * recover on decoding with standard CBOR decoders.
+ *
+ * Using QCBOREncode_BstrWrap() and QCBOREncode_CloseBstrWrap2()
+ * avoids having to encode the items first in one buffer (e.g., the
+ * COSE payload) and then add that buffer as a bstr to another
+ * encoding (e.g. the COSE to-be-signed bytes, the @c Sig_structure)
+ * potentially halving the memory needed.
+ *
+ * CBOR by nature must be decoded item by item in order from the
+ * start.  By wrapping some CBOR in a byte string, the decoding of
+ * that wrapped CBOR can be skipped. This is another use of wrapping,
+ * perhaps because the CBOR is large and deeply nested. Perhaps APIs
+ * for handling one defined CBOR message that is being embedded in
+ * another only take input as a byte string. Perhaps the desire is to
+ * be able to decode the out layer even in the wrapped has errors.
+ */
+static void
+QCBOREncode_BstrWrap(QCBOREncodeContext *pCtx);
+
+static void
+QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pCtx, const char *szLabel);
+
+static void
+QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pCtx, int64_t nLabel);
+
+
+/**
+ * @brief Close a wrapping bstr.
+ *
+ * @param[in] pCtx              The encoding context to close of bstr wrapping in.
+ * @param[in] bIncludeCBORHead  Include the encoded CBOR head of the bstr
+ *                              as well as the bytes in @c pWrappedCBOR.
+ * @param[out] pWrappedCBOR     A @ref UsefulBufC containing wrapped bytes.
+ *
+ * The closes a wrapping bstr opened by QCBOREncode_BstrWrap(). It reduces
+ * nesting level by one.
+ *
+ * A pointer and length of the enclosed encoded CBOR is returned in @c
+ * *pWrappedCBOR if it is not @c NULL. The main purpose of this is so
+ * this data can be hashed (e.g., with SHA-256) as part of a [RFC
+ * 8152, COSE] (https://tools.ietf.org/html/rfc8152)
+ * implementation. **WARNING**, this pointer and length should be used
+ * right away before any other calls to @c QCBOREncode_CloseXxx() as
+ * they will move data around and the pointer and length will no
+ * longer be to the correct encoded CBOR.
+ *
+ * When an error occurs as a result of this call, the encoder records
+ * the error and enters the error state. The error will be returned
+ * when QCBOREncode_Finish() is called.
+ *
+ * If this has been called more times than QCBOREncode_BstrWrap(),
+ * then @ref QCBOR_ERR_TOO_MANY_CLOSES will be returned when
+ * QCBOREncode_Finish() is called.
+ *
+ * If this is called and it is not a wrapping bstr that is currently
+ * open, @ref QCBOR_ERR_CLOSE_MISMATCH will be returned when
+ * QCBOREncode_Finish() is called.
+ *
+ * QCBOREncode_CloseBstrWrap() is a deprecated version of this function
+ * that is equivalent to the call with @c bIncludeCBORHead @c true.
+ */
+void
+QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pCtx, bool bIncludeCBORHead, UsefulBufC *pWrappedCBOR);
+
+static void
+QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pCtx, UsefulBufC *pWrappedCBOR);
+
+
+/**
+ * @brief Cancel byte string wrapping.
+ *
+ * @param[in] pCtx       The encoding context.
+ *
+ * This cancels QCBOREncode_BstrWrap() making tghe encoding as if it
+ * were never called.
+ *
+ * WARNING: This does not work on QCBOREncode_BstrWrapInMap()
+ * or QCBOREncode_BstrWrapInMapN() and there is no error detection
+ * of an attempt at their use.
+ *
+ * This only works if nothing has been added into the wrapped byte
+ * string.  If something has been added, this sets the error
+ * @ref QCBOR_ERR_CANNOT_CANCEL.
+ */
+void
+QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Add some already-encoded CBOR bytes.
+ *
+ * @param[in] pCtx     The encoding context to add the already-encode CBOR to.
+ * @param[in] Encoded  The already-encoded CBOR to add to the context.
+ *
+ * The encoded CBOR being added must be fully conforming CBOR. It must
+ * be complete with no arrays or maps that are incomplete. While this
+ * encoder doesn't ever produce indefinite lengths, it is OK for the
+ * raw CBOR added here to have indefinite lengths.
+ *
+ * The raw CBOR added here is not checked in anyway. If it is not
+ * conforming or has open arrays or such, the final encoded CBOR
+ * will probably be wrong or not what was intended.
+ *
+ * If the encoded CBOR being added here contains multiple items, they
+ * must be enclosed in a map or array. At the top level the raw
+ * CBOR must be a single data item.
+ */
+void
+QCBOREncode_AddEncoded(QCBOREncodeContext *pCtx, UsefulBufC Encoded);
+
+static void
+QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pCtx, const char *szLabel, UsefulBufC Encoded);
+
+static void
+QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pCtx, int64_t nLabel, UsefulBufC Encoded);
+
+
+/**
+ * @brief Get the encoded result.
+ *
+ * @param[in] pCtx           The context to finish encoding with.
+ * @param[out] pEncodedCBOR  Structure in which the pointer and length of
+ *                           the encoded CBOR is returned.
+ *
+ * @retval QCBOR_SUCCESS                     Encoded CBOR is returned.
+ *
+ * @retval QCBOR_ERR_TOO_MANY_CLOSES         Nesting error
+ *
+ * @retval QCBOR_ERR_CLOSE_MISMATCH          Nesting error
+ *
+ * @retval QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN Nesting error
+ *
+ * @retval QCBOR_ERR_BUFFER_TOO_LARGE        Encoded output buffer size
+ *
+ * @retval QCBOR_ERR_BUFFER_TOO_SMALL        Encoded output buffer size
+ *
+ * @retval QCBOR_ERR_ARRAY_NESTING_TOO_DEEP  Implementation limit
+ *
+ * @retval QCBOR_ERR_ARRAY_TOO_LONG          Implementation limit
+ *
+ * On success, the pointer and length of the encoded CBOR are returned
+ * in @c *pEncodedCBOR. The pointer is the same pointer that was passed
+ * in to QCBOREncode_Init(). Note that it is not const when passed to
+ * QCBOREncode_Init(), but it is const when returned here.  The length
+ * will be smaller than or equal to the length passed in when
+ * QCBOREncode_Init() as this is the length of the actual result, not
+ * the size of the buffer it was written to.
+ *
+ * If a @c NULL was passed for @c Storage.ptr when QCBOREncode_Init()
+ * was called, @c NULL will be returned here, but the length will be
+ * that of the CBOR that would have been encoded.
+ *
+ * Encoding errors primarily manifest here as most other encoding function
+ * do no return an error. They just set the error state in the encode
+ * context after which no encoding function does anything.
+ *
+ * Three types of errors manifest here. The first type are nesting
+ * errors where the number of @c QCBOREncode_OpenXxx() calls do not
+ * match the number @c QCBOREncode_CloseXxx() calls. The solution is to
+ * fix the calling code.
+ *
+ * The second type of error is because the buffer given is either too
+ * small or too large. The remedy is to give a correctly sized buffer.
+ *
+ * The third type are due to limits in this implementation.
+ * @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP can be worked around by
+ * encoding the CBOR in two (or more) phases and adding the CBOR from
+ * the first phase to the second with @c QCBOREncode_AddEncoded().
+ *
+ * If an error is returned, the buffer may have partially encoded
+ * incorrect CBOR in it and it should not be used. Likewise, the length
+ * may be incorrect and should not be used.
+ *
+ * Note that the error could have occurred in one of the many
+ * @c QCBOREncode_AddXxx() calls long before QCBOREncode_Finish() was
+ * called. This error handling reduces the CBOR implementation size
+ * but makes debugging harder.
+ *
+ * This may be called multiple times. It will always return the
+ * same. It can also be interleaved with calls to
+ * QCBOREncode_FinishGetSize().
+ *
+ * QCBOREncode_GetErrorState() can be called to get the current
+ * error state in order to abort encoding early as an optimization, but
+ * calling it is is never required.
+ */
+QCBORError
+QCBOREncode_Finish(QCBOREncodeContext *pCtx, UsefulBufC *pEncodedCBOR);
+
+
+/**
+ * @brief Get the encoded CBOR and error status.
+ *
+ * @param[in] pCtx          The context to finish encoding with.
+ * @param[out] uEncodedLen  The length of the encoded or potentially
+ *                          encoded CBOR in bytes.
+ *
+ * @return The same errors as QCBOREncode_Finish().
+ *
+ * This functions the same as QCBOREncode_Finish(), but only returns the
+ * size of the encoded output.
+ */
+QCBORError
+QCBOREncode_FinishGetSize(QCBOREncodeContext *pCtx, size_t *uEncodedLen);
+
+
+/**
+ * @brief Indicate whether output buffer is NULL or not.
+ *
+ * @param[in] pCtx  The encoding context.
+ *
+ * @return 1 if the output buffer is @c NULL.
+ *
+ * Sometimes a @c NULL input buffer is given to QCBOREncode_Init() so
+ * that the size of the generated CBOR can be calculated without
+ * allocating a buffer for it. This returns 1 when the output buffer
+ * is @c NULL and 0 when it is not.
+ */
+static int
+QCBOREncode_IsBufferNULL(QCBOREncodeContext *pCtx);
+
+
+/**
+ * @brief Get the encoding error state.
+ *
+ * @param[in] pCtx  The encoding context.
+ *
+ * @return One of @ref QCBORError. See return values from
+ *         QCBOREncode_Finish()
+ *
+ * Normally encoding errors need only be handled at the end of
+ * encoding when QCBOREncode_Finish() is called. This can be called to
+ * get the error result before finish should there be a need to halt
+ * encoding before QCBOREncode_Finish() is called.
+ */
+static QCBORError
+QCBOREncode_GetErrorState(QCBOREncodeContext *pCtx);
+
+
+/**
+ * Encode the "head" of a CBOR data item.
+ *
+ * @param Buffer       Buffer to output the encoded head to; must be
+ *                     @ref QCBOR_HEAD_BUFFER_SIZE bytes in size.
+ * @param uMajorType   One of CBOR_MAJOR_TYPE_XX.
+ * @param uMinLen      The minimum number of bytes to encode uNumber. Almost
+ *                     always this is 0 to use preferred
+ *                     serialization. If this is 4, then even the
+ *                     values 0xffff and smaller will be encoded in 4
+ *                     bytes. This is used primarily when encoding a
+ *                     float or double put into uNumber as the leading
+ *                     zero bytes for them must be encoded.
+ * @param uNumber      The numeric argument part of the CBOR head.
+ * @return             Pointer and length of the encoded head or
+ *                     @ref NULLUsefulBufC if the output buffer is too small.
+ *
+ * Callers do not to need to call this for normal CBOR encoding. Note
+ * that it doesn't even take a @ref QCBOREncodeContext argument.
+ *
+ * This encodes the major type and argument part of a data item. The
+ * argument is an integer that is usually either the value or the length
+ * of the data item.
+ *
+ * This is exposed in the public interface to allow hashing of some CBOR
+ * data types, bstr in particular, a chunk at a time so the full CBOR
+ * doesn't have to be encoded in a contiguous buffer.
+ *
+ * For example, if you have a 100,000 byte binary blob in a buffer that
+ * needs to be a bstr encoded and then hashed. You could allocate a
+ * 100,010 byte buffer and encode it normally. Alternatively, you can
+ * encode the head in a 10 byte buffer with this function, hash that and
+ * then hash the 100,000 bytes using the same hash context.
+ */
+UsefulBufC
+QCBOREncode_EncodeHead(UsefulBuf Buffer,
+                       uint8_t   uMajorType,
+                       uint8_t   uMinLen,
+                       uint64_t  uNumber);
+
+
+
+
+/* =========================================================================
+     BEGINNING OF PRIVATE IMPLEMENTATION
+   ========================================================================= */
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
+                                        const uint8_t       uMajorType,
+                                        const uint64_t      uArgument,
+                                        const uint8_t       uMinLen);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pCtx,
+                              uint8_t             uMajorType,
+                              UsefulBufC          Bytes);
+
+
+/* Semi-private function for adding a double with preferred encoding. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, const double dNum);
+
+
+/* Semi-private function for adding a float with preferred encoding. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, const float fNum);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pCtx,
+                                   uint8_t             uMajorType);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
+                                                   uint8_t             uMajorType);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pCtx,
+                                    uint8_t             uMajorType);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pCtx,
+                                                    uint8_t             uMajorType);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_encode.c */
+void
+QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pCtx,
+                                   uint64_t            uTag,
+                                   UsefulBufC          BigNumMantissa,
+                                   bool                bBigNumIsNegative,
+                                   int64_t             nMantissa,
+                                   int64_t             nExponent);
+
+
+/**
+ * @brief  Semi-private method to add simple items and floating-point.
+ *
+ * @param[in] pMe        The encoding context.
+ * @param[in] uMinLen    Minimum encoding size for uNum. Usually 0.
+ * @param[in] uArgument  The value to add.
+ *
+ * This is used to add simple types like true and false and float-point
+ * values, both of which are type 7.
+ *
+ * Call QCBOREncode_AddBool(), QCBOREncode_AddNULL(),
+ * QCBOREncode_AddUndef() QCBOREncode_AddDouble() instead of this.
+ *
+ * Error handling is the same as QCBOREncode_AddInt64().
+ */
+static inline void
+QCBOREncode_Private_AddType7(QCBOREncodeContext *pMe,
+                             const uint8_t       uMinLen,
+                             const uint64_t      uArgument)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_SIMPLE, uArgument, uMinLen);
+}
+
+
+/**
+ * @brief Semi-private method to add only the type and length of a byte string.
+ *
+ * @param[in] pCtx    The context to initialize.
+ * @param[in] Bytes   Pointer and length of the input data.
+ *
+ * This will be removed in QCBOR 2.0. It was never a public function.
+ *
+ * This is the same as QCBOREncode_AddBytes() except it only adds the
+ * CBOR encoding for the type and the length. It doesn't actually add
+ * the bytes. You can't actually produce correct CBOR with this and
+ * the rest of this API. It is only used for a special case where the
+ * valid CBOR is created manually by putting this type and length in
+ * and then adding the actual bytes. In particular, when only a hash
+ * of the encoded CBOR is needed, where the type and header are hashed
+ * separately and then the bytes is hashed. This makes it possible to
+ * implement COSE Sign1 with only one copy of the payload in the
+ * output buffer, rather than two, roughly cutting memory use in half.
+ *
+ * This is only used for this odd case, but this is a supported
+ * tested function for QCBOR 1.0.
+ *
+ * See also QCBOREncode_EncodeHead().
+ */
+static void
+QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pCtx,
+                            UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pCtx,
+                                 const char         *szLabel,
+                                 UsefulBufC          Bytes);
+
+static void
+QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pCtx,
+                                 int64_t              nLabel,
+                                 UsefulBufC           Bytes);
+
+
+/* Forward declaration */
+static void
+QCBOREncode_AddSZString(QCBOREncodeContext *pMe, const char *szString);
+
+
+
+
+static inline void
+QCBOREncode_AddInt64ToMap(QCBOREncodeContext *pMe,
+                          const char        *szLabel,
+                          const int64_t      uNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddInt64(pMe, uNum);
+}
+
+static inline void
+QCBOREncode_AddInt64ToMapN(QCBOREncodeContext *pMe,
+                           const int64_t       nLabel,
+                           const int64_t       uNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddInt64(pMe, uNum);
+}
+
+
+static inline void
+QCBOREncode_AddUInt64(QCBOREncodeContext *pMe, const uint64_t uValue)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_POSITIVE_INT, uValue, 0);
+}
+
+
+static inline void
+QCBOREncode_AddUInt64ToMap(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const uint64_t      uNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddUInt64(pMe, uNum);
+}
+
+static inline void
+QCBOREncode_AddUInt64ToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint64_t      uNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddUInt64(pMe, uNum);
+}
+
+
+static inline void
+QCBOREncode_AddText(QCBOREncodeContext *pMe, const UsefulBufC Text)
+{
+   QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_TYPE_TEXT_STRING, Text);
+}
+
+static inline void
+QCBOREncode_AddTextToMap(QCBOREncodeContext *pMe,
+                         const char         *szLabel,
+                         const UsefulBufC    Text)
+{
+   QCBOREncode_AddText(pMe, UsefulBuf_FromSZ(szLabel));
+   QCBOREncode_AddText(pMe, Text);
+}
+
+static inline void
+QCBOREncode_AddTextToMapN(QCBOREncodeContext *pMe,
+                          const int64_t       nLabel,
+                          const UsefulBufC    Text)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddText(pMe, Text);
+}
+
+
+inline static void
+QCBOREncode_AddSZString(QCBOREncodeContext *pMe, const char *szString)
+{
+   QCBOREncode_AddText(pMe, UsefulBuf_FromSZ(szString));
+}
+
+static inline void
+QCBOREncode_AddSZStringToMap(QCBOREncodeContext *pMe,
+                             const char         *szLabel,
+                             const char         *szString)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddSZString(pMe, szString);
+}
+
+static inline void
+QCBOREncode_AddSZStringToMapN(QCBOREncodeContext *pMe,
+                              const int64_t       nLabel,
+                              const char         *szString)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddSZString(pMe, szString);
+}
+
+
+
+/*
+ * Public functions for adding a tag. See qcbor/qcbor_encode.h
+ */
+static inline void
+QCBOREncode_AddTag(QCBOREncodeContext *pMe, const uint64_t uTag)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_TAG, uTag, 0);
+}
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+
+static inline void
+QCBOREncode_AddDoubleNoPreferred(QCBOREncodeContext *pMe, const double dNum)
+{
+   QCBOREncode_Private_AddType7(pMe,
+                                sizeof(uint64_t),
+                                UsefulBufUtil_CopyDoubleToUint64(dNum));
+}
+
+static inline void
+QCBOREncode_AddFloatNoPreferred(QCBOREncodeContext *pMe, const float fNum)
+{
+   QCBOREncode_Private_AddType7(pMe,
+                                sizeof(uint32_t),
+                                UsefulBufUtil_CopyFloatToUint32(fNum));
+}
+
+
+static inline void
+QCBOREncode_AddDouble(QCBOREncodeContext *pMe, const double dNum)
+{
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   QCBOREncode_Private_AddPreferredDouble(pMe, dNum);
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+}
+
+static inline void
+QCBOREncode_AddDoubleToMap(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const double        dNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddDouble(pMe, dNum);
+}
+
+static inline void
+QCBOREncode_AddDoubleToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const double        dNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddDouble(pMe, dNum);
+}
+
+
+static inline void
+QCBOREncode_AddFloat(QCBOREncodeContext *pMe, const float fNum)
+{
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+   QCBOREncode_Private_AddPreferredFloat(pMe, fNum);
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   QCBOREncode_AddFloatNoPreferred(pMe, fNum);
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+}
+
+static inline void
+QCBOREncode_AddFloatToMap(QCBOREncodeContext *pMe,
+                          const char         *szLabel,
+                          const float         dNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddFloat(pMe, dNum);
+}
+
+static inline void
+QCBOREncode_AddFloatToMapN(QCBOREncodeContext *pMe,
+                           const int64_t       nLabel,
+                           const float         fNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddFloat(pMe, fNum);
+}
+
+static inline void
+QCBOREncode_AddDoubleNoPreferredToMap(QCBOREncodeContext *pMe,
+                                      const char         *szLabel,
+                                      const double        dNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
+}
+
+static inline void
+QCBOREncode_AddDoubleNoPreferredToMapN(QCBOREncodeContext *pMe,
+                                       const int64_t       nLabel,
+                                       const double        dNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddDoubleNoPreferred(pMe, dNum);
+}
+
+static inline void
+QCBOREncode_AddFloatNoPreferredToMap(QCBOREncodeContext *pMe,
+                                     const char         *szLabel,
+                                     const float         dNum)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddFloatNoPreferred(pMe, dNum);
+}
+
+static inline void
+QCBOREncode_AddFloatNoPreferredToMapN(QCBOREncodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const float         dNum)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddFloatNoPreferred(pMe, dNum);
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+
+static inline void
+QCBOREncode_AddTDateEpoch(QCBOREncodeContext *pMe,
+                          const uint8_t       uTag,
+                          const int64_t       nDate)
+{
+   if(uTag == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_DATE_EPOCH);
+   }
+   QCBOREncode_AddInt64(pMe, nDate);
+}
+
+static inline void
+QCBOREncode_AddTDateEpochToMapSZ(QCBOREncodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTag,
+                                 const int64_t       nDate)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDateEpoch(pMe, uTag, nDate);
+}
+
+static inline void
+QCBOREncode_AddTDateEpochToMapN(QCBOREncodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTag,
+                                const int64_t       nDate)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDateEpoch(pMe, uTag, nDate);
+}
+
+static inline void
+QCBOREncode_AddDateEpoch(QCBOREncodeContext *pMe,
+                         const int64_t       nDate)
+{
+   QCBOREncode_AddTDateEpoch(pMe, QCBOR_ENCODE_AS_TAG, nDate);
+}
+
+static inline void
+QCBOREncode_AddDateEpochToMap(QCBOREncodeContext *pMe,
+                              const char         *szLabel,
+                              const int64_t       nDate)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddDateEpoch(pMe, nDate);
+}
+
+static inline void
+QCBOREncode_AddDateEpochToMapN(QCBOREncodeContext *pMe,
+                               const int64_t       nLabel,
+                               const int64_t       nDate)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddDateEpoch(pMe, nDate);
+}
+
+
+static inline void
+QCBOREncode_AddTDaysEpoch(QCBOREncodeContext *pMe,
+                          const uint8_t       uTag,
+                          const int64_t       nDays)
+{
+   if(uTag == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_DAYS_EPOCH);
+   }
+   QCBOREncode_AddInt64(pMe, nDays);
+}
+
+static inline void
+QCBOREncode_AddTDaysEpochToMapSZ(QCBOREncodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTag,
+                                 const int64_t       nDays)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDaysEpoch(pMe, uTag, nDays);
+}
+
+static inline void
+QCBOREncode_AddTDaysEpochToMapN(QCBOREncodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTag,
+                                const int64_t       nDays)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDaysEpoch(pMe, uTag, nDays);
+}
+
+
+static inline void
+QCBOREncode_AddBytes(QCBOREncodeContext *pMe,
+                     const UsefulBufC    Bytes)
+{
+   QCBOREncode_Private_AddBuffer(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBytesToMap(QCBOREncodeContext *pMe,
+                          const char         *szLabel,
+                          const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddBytes(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBytesToMapN(QCBOREncodeContext *pMe,
+                           const int64_t       nLabel,
+                           const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddBytes(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_OpenBytesInMapSZ(QCBOREncodeContext *pMe,
+                             const char         *szLabel,
+                             UsefulBuf          *pPlace)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_OpenBytes(pMe, pPlace);
+}
+
+static inline void
+QCBOREncode_OpenBytesInMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            UsefulBuf          *pPlace)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_OpenBytes(pMe, pPlace);
+}
+
+
+/*
+ * Public functions for adding only a byte string length. See qcbor/qcbor_encode.h
+ */
+static inline void
+QCBOREncode_AddBytesLenOnly(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, Bytes.len, 0);
+}
+
+
+static inline void
+QCBOREncode_AddBytesLenOnlyToMap(QCBOREncodeContext *pMe,
+                                 const char         *szLabel,
+                                 const UsefulBufC    Bytes)
+{
+    QCBOREncode_AddSZString(pMe, szLabel);
+    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBytesLenOnlyToMapN(QCBOREncodeContext *pMe,
+                                  const int64_t       nLabel,
+                                  const UsefulBufC    Bytes)
+{
+    QCBOREncode_AddInt64(pMe, nLabel);
+    QCBOREncode_AddBytesLenOnly(pMe, Bytes);
+}
+
+
+static inline void
+QCBOREncode_AddTBinaryUUID(QCBOREncodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           const UsefulBufC    Bytes)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_BIN_UUID);
+   }
+   QCBOREncode_AddBytes(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTBinaryUUIDToMapSZ(QCBOREncodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTBinaryUUID(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTBinaryUUIDToMapN(QCBOREncodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTBinaryUUID(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBinaryUUID(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_AddTBinaryUUID(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBinaryUUIDToMap(QCBOREncodeContext *pMe,
+                               const char         *szLabel,
+                               const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTBinaryUUIDToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddBinaryUUIDToMapN(QCBOREncodeContext *pMe,
+                                const int64_t       nLabel,
+                                const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTBinaryUUIDToMapN(pMe,
+                                    nLabel,
+                                    QCBOR_ENCODE_AS_TAG,
+                                    Bytes);
+}
+
+
+static inline void
+QCBOREncode_AddTPositiveBignum(QCBOREncodeContext *pMe,
+                               const uint8_t       uTagRequirement,
+                               const UsefulBufC    Bytes)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_POS_BIGNUM);
+   }
+   QCBOREncode_AddBytes(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTPositiveBignumToMapSZ(QCBOREncodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint8_t       uTagRequirement,
+                                      const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTPositiveBignum(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTPositiveBignumToMapN(QCBOREncodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint8_t       uTagRequirement,
+                                     const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTPositiveBignum(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddPositiveBignum(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_AddTPositiveBignum(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddPositiveBignumToMap(QCBOREncodeContext *pMe,
+                                   const char         *szLabel,
+                                   const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTPositiveBignumToMapSZ(pMe,
+                                         szLabel,
+                                         QCBOR_ENCODE_AS_TAG,
+                                         Bytes);
+}
+
+static inline void
+QCBOREncode_AddPositiveBignumToMapN(QCBOREncodeContext *pMe,
+                                    const int64_t       nLabel,
+                                    const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTPositiveBignumToMapN(pMe,
+                                        nLabel,
+                                        QCBOR_ENCODE_AS_TAG,
+                                        Bytes);
+}
+
+
+static inline void
+QCBOREncode_AddTNegativeBignum(QCBOREncodeContext *pMe,
+                               const uint8_t       uTagRequirement,
+                               const UsefulBufC    Bytes)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_NEG_BIGNUM);
+   }
+   QCBOREncode_AddBytes(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTNegativeBignumToMapSZ(QCBOREncodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint8_t       uTagRequirement,
+                                      const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTNegativeBignum(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTNegativeBignumToMapN(QCBOREncodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint8_t       uTagRequirement,
+                                     const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTNegativeBignum(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddNegativeBignum(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_AddTNegativeBignum(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddNegativeBignumToMap(QCBOREncodeContext *pMe,
+                                   const char         *szLabel,
+                                   const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTNegativeBignumToMapSZ(pMe,
+                                         szLabel,
+                                         QCBOR_ENCODE_AS_TAG,
+                                         Bytes);
+}
+
+static inline void
+QCBOREncode_AddNegativeBignumToMapN(QCBOREncodeContext *pMe,
+                                    const int64_t       nLabel,
+                                    const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTNegativeBignumToMapN(pMe,
+                                        nLabel,
+                                        QCBOR_ENCODE_AS_TAG,
+                                        Bytes);
+}
+
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+static inline void
+QCBOREncode_AddTDecimalFraction(QCBOREncodeContext *pMe,
+                                const uint8_t       uTagRequirement,
+                                const int64_t       nMantissa,
+                                const int64_t       nBase10Exponent)
+{
+   uint64_t uTag;
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      uTag = CBOR_TAG_DECIMAL_FRACTION;
+   } else {
+      uTag = CBOR_TAG_INVALID64;
+   }
+   QCBOREncode_Private_AddExpMantissa(pMe,
+                                      uTag,
+                                      NULLUsefulBufC,
+                                      false,
+                                      nMantissa,
+                                      nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddTDecimalFractionToMapSZ(QCBOREncodeContext *pMe,
+                                       const char         *szLabel,
+                                       const uint8_t       uTagRequirement,
+                                       const int64_t       nMantissa,
+                                       const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDecimalFraction(pMe,
+                                   uTagRequirement,
+                                   nMantissa,
+                                   nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddTDecimalFractionToMapN(QCBOREncodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const uint8_t       uTagRequirement,
+                                      const int64_t       nMantissa,
+                                      const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDecimalFraction(pMe,
+                                   uTagRequirement,
+                                   nMantissa,
+                                   nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFraction(QCBOREncodeContext *pMe,
+                               const int64_t       nMantissa,
+                               const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddTDecimalFraction(pMe,
+                                   QCBOR_ENCODE_AS_TAG,
+                                   nMantissa,
+                                   nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFractionToMap(QCBOREncodeContext *pMe,
+                                    const char         *szLabel,
+                                    const int64_t       nMantissa,
+                                    const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddTDecimalFractionToMapSZ(pMe,
+                                          szLabel,
+                                          QCBOR_ENCODE_AS_TAG,
+                                          nMantissa,
+                                          nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFractionToMapN(QCBOREncodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const int64_t       nMantissa,
+                                     const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddTDecimalFractionToMapN(pMe,
+                                         nLabel,
+                                         QCBOR_ENCODE_AS_TAG,
+                                         nMantissa,
+                                         nBase10Exponent);
+}
+
+
+
+static inline void
+QCBOREncode_AddTDecimalFractionBigNum(QCBOREncodeContext *pMe,
+                                      const uint8_t       uTagRequirement,
+                                      const UsefulBufC    Mantissa,
+                                      const bool          bIsNegative,
+                                      const int64_t       nBase10Exponent)
+{
+   uint64_t uTag;
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      uTag = CBOR_TAG_DECIMAL_FRACTION;
+   } else {
+      uTag = CBOR_TAG_INVALID64;
+   }
+   QCBOREncode_Private_AddExpMantissa(pMe,
+                                      uTag,
+                                      Mantissa,
+                                      bIsNegative,
+                                      0,
+                                      nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddTDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pMe,
+                                             const char         *szLabel,
+                                             const uint8_t       uTagRequirement,
+                                             const UsefulBufC    Mantissa,
+                                             const bool          bIsNegative,
+                                             const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDecimalFractionBigNum(pMe,
+                                         uTagRequirement,
+                                         Mantissa,
+                                         bIsNegative,
+                                         nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddTDecimalFractionBigNumToMapN(QCBOREncodeContext *pMe,
+                                            const int64_t       nLabel,
+                                            const uint8_t       uTagRequirement,
+                                            const UsefulBufC    Mantissa,
+                                            const bool          bIsNegative,
+                                            const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDecimalFractionBigNum(pMe,
+                                         uTagRequirement,
+                                         Mantissa,
+                                         bIsNegative,
+                                         nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFractionBigNum(QCBOREncodeContext *pMe,
+                                     const UsefulBufC    Mantissa,
+                                     const bool          bIsNegative,
+                                     const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddTDecimalFractionBigNum(pMe,
+                                         QCBOR_ENCODE_AS_TAG,
+                                         Mantissa,
+                                         bIsNegative,
+                                         nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFractionBigNumToMapSZ(QCBOREncodeContext *pMe,
+                                            const char         *szLabel,
+                                            const UsefulBufC    Mantissa,
+                                            const bool          bIsNegative,
+                                            const int64_t       nBase10Exponent)
+{
+   QCBOREncode_AddTDecimalFractionBigNumToMapSZ(pMe,
+                                                szLabel,
+                                                QCBOR_ENCODE_AS_TAG,
+                                                Mantissa,
+                                                bIsNegative,
+                                                nBase10Exponent);
+}
+
+static inline void
+QCBOREncode_AddDecimalFractionBigNumToMapN(QCBOREncodeContext *pMe,
+                                           const int64_t       nLabel,
+                                           const UsefulBufC    Mantissa,
+                                           const bool          bIsNegative,
+                                           const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTDecimalFractionBigNumToMapN(pMe,
+                                               nLabel,
+                                               QCBOR_ENCODE_AS_TAG,
+                                               Mantissa,
+                                               bIsNegative,
+                                               nBase2Exponent);
+}
+
+
+
+
+
+static inline void
+QCBOREncode_AddTBigFloat(QCBOREncodeContext *pMe,
+                         const uint8_t       uTagRequirement,
+                         const int64_t       nMantissa,
+                         const int64_t       nBase2Exponent)
+{
+   uint64_t uTag;
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      uTag = CBOR_TAG_BIGFLOAT;
+   } else {
+      uTag = CBOR_TAG_INVALID64;
+   }
+   QCBOREncode_Private_AddExpMantissa(pMe,
+                                      uTag,
+                                      NULLUsefulBufC,
+                                      false,
+                                      nMantissa,
+                                      nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddTBigFloatToMapSZ(QCBOREncodeContext *pMe,
+                                const char         *szLabel,
+                                const uint8_t       uTagRequirement,
+                                const int64_t       nMantissa,
+                                const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTBigFloat(pMe, uTagRequirement, nMantissa, nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddTBigFloatToMapN(QCBOREncodeContext *pMe,
+                               const int64_t       nLabel,
+                               const uint8_t       uTagRequirement,
+                               const int64_t       nMantissa,
+                               const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTBigFloat(pMe, uTagRequirement, nMantissa, nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddBigFloat(QCBOREncodeContext *pMe,
+                        const int64_t       nMantissa,
+                        const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloat(pMe,
+                            QCBOR_ENCODE_AS_TAG,
+                            nMantissa,
+                            nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddBigFloatToMap(QCBOREncodeContext *pMe,
+                             const char         *szLabel,
+                             const int64_t       nMantissa,
+                             const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloatToMapSZ(pMe,
+                                   szLabel,
+                                   QCBOR_ENCODE_AS_TAG,
+                                   nMantissa,
+                                   nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddBigFloatToMapN(QCBOREncodeContext *pMe,
+                              const int64_t       nLabel,
+                              const int64_t       nMantissa,
+                              const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloatToMapN(pMe,
+                                  nLabel,
+                                  QCBOR_ENCODE_AS_TAG,
+                                  nMantissa,
+                                  nBase2Exponent);
+}
+
+
+
+static inline void
+QCBOREncode_AddTBigFloatBigNum(QCBOREncodeContext *pMe,
+                               const uint8_t       uTagRequirement,
+                               const UsefulBufC    Mantissa,
+                               const bool          bIsNegative,
+                               const int64_t       nBase2Exponent)
+{
+   uint64_t uTag;
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      uTag = CBOR_TAG_BIGFLOAT;
+   } else {
+      uTag = CBOR_TAG_INVALID64;
+   }
+   QCBOREncode_Private_AddExpMantissa(pMe,
+                                      uTag,
+                                      Mantissa,
+                                      bIsNegative,
+                                      0,
+                                      nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddTBigFloatBigNumToMapSZ(QCBOREncodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint8_t       uTagRequirement,
+                                      const UsefulBufC    Mantissa,
+                                      const bool          bIsNegative,
+                                      const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTBigFloatBigNum(pMe,
+                                  uTagRequirement,
+                                  Mantissa,
+                                  bIsNegative,
+                                  nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddTBigFloatBigNumToMapN(QCBOREncodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint8_t       uTagRequirement,
+                                     const UsefulBufC    Mantissa,
+                                     const bool          bIsNegative,
+                                     const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTBigFloatBigNum(pMe,
+                                  uTagRequirement,
+                                  Mantissa,
+                                  bIsNegative,
+                                  nBase2Exponent);
+}
+
+
+static inline void
+QCBOREncode_AddBigFloatBigNum(QCBOREncodeContext *pMe,
+                              const UsefulBufC    Mantissa,
+                              const bool          bIsNegative,
+                              const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloatBigNum(pMe,
+                                  QCBOR_ENCODE_AS_TAG,
+                                  Mantissa, bIsNegative,
+                                  nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddBigFloatBigNumToMap(QCBOREncodeContext *pMe,
+                                   const char         *szLabel,
+                                   const UsefulBufC    Mantissa,
+                                   const bool          bIsNegative,
+                                   const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloatBigNumToMapSZ(pMe,
+                                         szLabel,
+                                         QCBOR_ENCODE_AS_TAG,
+                                         Mantissa,
+                                         bIsNegative,
+                                         nBase2Exponent);
+}
+
+static inline void
+QCBOREncode_AddBigFloatBigNumToMapN(QCBOREncodeContext *pMe,
+                                    const int64_t       nLabel,
+                                    const UsefulBufC    Mantissa,
+                                    const bool          bIsNegative,
+                                    const int64_t       nBase2Exponent)
+{
+   QCBOREncode_AddTBigFloatBigNumToMapN(pMe,
+                                        nLabel,
+                                        QCBOR_ENCODE_AS_TAG,
+                                        Mantissa,
+                                        bIsNegative,
+                                        nBase2Exponent);
+}
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+static inline void
+QCBOREncode_AddTURI(QCBOREncodeContext *pMe,
+                    const uint8_t       uTagRequirement,
+                    const UsefulBufC    URI)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_URI);
+   }
+   QCBOREncode_AddText(pMe, URI);
+}
+
+static inline void
+QCBOREncode_AddTURIToMapSZ(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const uint8_t       uTagRequirement,
+                           const UsefulBufC    URI)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTURI(pMe, uTagRequirement, URI);
+}
+
+static inline void
+QCBOREncode_AddTURIToMapN(QCBOREncodeContext *pMe,
+                          const int64_t       nLabel,
+                          const uint8_t       uTagRequirement,
+                          const UsefulBufC    URI)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTURI(pMe, uTagRequirement, URI);
+}
+
+static inline void
+QCBOREncode_AddURI(QCBOREncodeContext *pMe, const UsefulBufC URI)
+{
+   QCBOREncode_AddTURI(pMe, QCBOR_ENCODE_AS_TAG, URI);
+}
+
+static inline void
+QCBOREncode_AddURIToMap(QCBOREncodeContext *pMe,
+                        const char         *szLabel,
+                        const UsefulBufC    URI)
+{
+   QCBOREncode_AddTURIToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, URI);
+}
+
+static inline void
+QCBOREncode_AddURIToMapN(QCBOREncodeContext *pMe,
+                         const int64_t       nLabel,
+                         const UsefulBufC    URI)
+{
+   QCBOREncode_AddTURIToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, URI);
+}
+
+
+
+static inline void
+QCBOREncode_AddTB64Text(QCBOREncodeContext *pMe,
+                        const uint8_t       uTagRequirement,
+                        const UsefulBufC    B64Text)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_B64);
+   }
+   QCBOREncode_AddText(pMe, B64Text);
+}
+
+static inline void
+QCBOREncode_AddTB64TextToMapSZ(QCBOREncodeContext *pMe,
+                               const char         *szLabel,
+                               const uint8_t       uTagRequirement,
+                               const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTB64Text(pMe, uTagRequirement, B64Text);
+}
+
+static inline void
+QCBOREncode_AddTB64TextToMapN(QCBOREncodeContext *pMe,
+                              const int64_t       nLabel,
+                              const uint8_t       uTagRequirement,
+                              const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTB64Text(pMe, uTagRequirement, B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64Text(QCBOREncodeContext *pMe, const UsefulBufC B64Text)
+{
+   QCBOREncode_AddTB64Text(pMe, QCBOR_ENCODE_AS_TAG, B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64TextToMap(QCBOREncodeContext *pMe,
+                            const char         *szLabel,
+                            const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddTB64TextToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64TextToMapN(QCBOREncodeContext *pMe,
+                             const int64_t       nLabel,
+                             const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddTB64TextToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, B64Text);
+}
+
+
+
+static inline void
+QCBOREncode_AddTB64URLText(QCBOREncodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           const UsefulBufC    B64Text)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_B64URL);
+   }
+   QCBOREncode_AddText(pMe, B64Text);
+}
+
+static inline void
+QCBOREncode_AddTB64URLTextToMapSZ(QCBOREncodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTB64URLText(pMe, uTagRequirement, B64Text);
+}
+
+static inline void
+QCBOREncode_AddTB64URLTextToMapN(QCBOREncodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTB64URLText(pMe, uTagRequirement, B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64URLText(QCBOREncodeContext *pMe, const UsefulBufC B64Text)
+{
+   QCBOREncode_AddTB64URLText(pMe, QCBOR_ENCODE_AS_TAG, B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64URLTextToMap(QCBOREncodeContext *pMe,
+                               const char         *szLabel,
+                               const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddTB64URLTextToMapSZ(pMe,
+                                     szLabel,
+                                     QCBOR_ENCODE_AS_TAG,
+                                     B64Text);
+}
+
+static inline void
+QCBOREncode_AddB64URLTextToMapN(QCBOREncodeContext *pMe,
+                                const int64_t       nLabel,
+                                const UsefulBufC    B64Text)
+{
+   QCBOREncode_AddTB64URLTextToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, B64Text);
+}
+
+
+
+static inline void
+QCBOREncode_AddTRegex(QCBOREncodeContext *pMe,
+                      const uint8_t       uTagRequirement,
+                      const UsefulBufC    Bytes)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_REGEX);
+   }
+   QCBOREncode_AddText(pMe, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTRegexToMapSZ(QCBOREncodeContext *pMe,
+                             const char         *szLabel,
+                             const uint8_t       uTagRequirement,
+                             const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTRegex(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddTRegexToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uTagRequirement,
+                            const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTRegex(pMe, uTagRequirement, Bytes);
+}
+
+static inline void
+QCBOREncode_AddRegex(QCBOREncodeContext *pMe, const UsefulBufC Bytes)
+{
+   QCBOREncode_AddTRegex(pMe, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddRegexToMap(QCBOREncodeContext *pMe,
+                          const char         *szLabel,
+                          const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTRegexToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, Bytes);
+}
+
+static inline void
+QCBOREncode_AddRegexToMapN(QCBOREncodeContext *pMe,
+                           const int64_t       nLabel,
+                           const UsefulBufC    Bytes)
+{
+   QCBOREncode_AddTRegexToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, Bytes);
+
+}
+
+
+static inline void
+QCBOREncode_AddTMIMEData(QCBOREncodeContext *pMe,
+                         const uint8_t       uTagRequirement,
+                         const UsefulBufC    MIMEData)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_BINARY_MIME);
+   }
+   QCBOREncode_AddBytes(pMe, MIMEData);
+}
+
+static inline void
+QCBOREncode_AddTMIMEDataToMapSZ(QCBOREncodeContext *pMe,
+                                const char         *szLabel,
+                                const uint8_t       uTagRequirement,
+                                const UsefulBufC    MIMEData)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTMIMEData(pMe, uTagRequirement, MIMEData);
+}
+
+static inline void
+QCBOREncode_AddTMIMEDataToMapN(QCBOREncodeContext *pMe,
+                               const int64_t       nLabel,
+                               const uint8_t       uTagRequirement,
+                               const UsefulBufC    MIMEData)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTMIMEData(pMe, uTagRequirement, MIMEData);
+}
+
+static inline void
+QCBOREncode_AddMIMEData(QCBOREncodeContext *pMe, UsefulBufC MIMEData)
+{
+   QCBOREncode_AddTMIMEData(pMe, QCBOR_ENCODE_AS_TAG, MIMEData);
+}
+
+static inline void
+QCBOREncode_AddMIMEDataToMap(QCBOREncodeContext *pMe,
+                             const char         *szLabel,
+                             const UsefulBufC    MIMEData)
+{
+   QCBOREncode_AddTMIMEDataToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, MIMEData);
+}
+
+static inline void
+QCBOREncode_AddMIMEDataToMapN(QCBOREncodeContext *pMe,
+                              const int64_t       nLabel,
+                              const UsefulBufC    MIMEData)
+{
+   QCBOREncode_AddTMIMEDataToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, MIMEData);
+}
+
+
+static inline void
+QCBOREncode_AddTDateString(QCBOREncodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           const char         *szDate)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_DATE_STRING);
+   }
+   QCBOREncode_AddSZString(pMe, szDate);
+}
+
+static inline void
+QCBOREncode_AddTDateStringToMapSZ(QCBOREncodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  const char         *szDate)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDateString(pMe, uTagRequirement, szDate);
+}
+
+static inline void
+QCBOREncode_AddTDateStringToMapN(QCBOREncodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 const char         *szDate)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDateString(pMe, uTagRequirement, szDate);
+}
+
+static inline void
+QCBOREncode_AddDateString(QCBOREncodeContext *pMe, const char *szDate)
+{
+   QCBOREncode_AddTDateString(pMe, QCBOR_ENCODE_AS_TAG, szDate);
+}
+
+static inline void
+QCBOREncode_AddDateStringToMap(QCBOREncodeContext *pMe,
+                               const char         *szLabel,
+                               const char         *szDate)
+{
+   QCBOREncode_AddTDateStringToMapSZ(pMe, szLabel, QCBOR_ENCODE_AS_TAG, szDate);
+}
+
+static inline void
+QCBOREncode_AddDateStringToMapN(QCBOREncodeContext *pMe,
+                                const int64_t       nLabel,
+                                const char         *szDate)
+{
+   QCBOREncode_AddTDateStringToMapN(pMe, nLabel, QCBOR_ENCODE_AS_TAG, szDate);
+}
+
+
+static inline void
+QCBOREncode_AddTDaysString(QCBOREncodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           const char         *szDate)
+{
+   if(uTagRequirement == QCBOR_ENCODE_AS_TAG) {
+      QCBOREncode_AddTag(pMe, CBOR_TAG_DAYS_STRING);
+   }
+   QCBOREncode_AddSZString(pMe, szDate);
+}
+
+static inline void
+QCBOREncode_AddTDaysStringToMapSZ(QCBOREncodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  const char         *szDate)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddTDaysString(pMe, uTagRequirement, szDate);
+}
+
+static inline void
+QCBOREncode_AddTDaysStringToMapN(QCBOREncodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 const char         *szDate)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddTDaysString(pMe, uTagRequirement, szDate);
+}
+
+
+static inline void
+QCBOREncode_AddSimple(QCBOREncodeContext *pMe, const uint8_t uNum)
+{
+   /* This check often is optimized out because uNum is known at compile time. */
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(uNum >= CBOR_SIMPLEV_RESERVED_START && uNum <= CBOR_SIMPLEV_RESERVED_END) {
+      pMe->uError = QCBOR_ERR_ENCODE_UNSUPPORTED;
+      return;
+   }
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   QCBOREncode_Private_AddType7(pMe, 0, uNum);
+}
+
+static inline void
+QCBOREncode_AddSimpleToMap(QCBOREncodeContext *pMe,
+                           const char         *szLabel,
+                           const uint8_t       uSimple)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddSimple(pMe, uSimple);
+}
+
+static inline void
+QCBOREncode_AddSimpleToMapN(QCBOREncodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uSimple)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddSimple(pMe, uSimple);
+}
+
+
+static inline void
+QCBOREncode_AddBool(QCBOREncodeContext *pMe, const bool b)
+{
+   uint8_t uSimple = CBOR_SIMPLEV_FALSE;
+   if(b) {
+      uSimple = CBOR_SIMPLEV_TRUE;
+   }
+   QCBOREncode_AddSimple(pMe, uSimple);
+}
+
+static inline void
+QCBOREncode_AddBoolToMap(QCBOREncodeContext *pMe, const char *szLabel, const bool b)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddBool(pMe, b);
+}
+
+static inline void
+QCBOREncode_AddBoolToMapN(QCBOREncodeContext *pMe, const int64_t nLabel, const bool b)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddBool(pMe, b);
+}
+
+
+static inline void
+QCBOREncode_AddNULL(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_AddSimple(pMe, CBOR_SIMPLEV_NULL);
+}
+
+static inline void
+QCBOREncode_AddNULLToMap(QCBOREncodeContext *pMe, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddNULL(pMe);
+}
+
+static inline void
+QCBOREncode_AddNULLToMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddNULL(pMe);
+}
+
+
+static inline void
+QCBOREncode_AddUndef(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_AddSimple(pMe, CBOR_SIMPLEV_UNDEF);
+}
+
+static inline void
+QCBOREncode_AddUndefToMap(QCBOREncodeContext *pMe, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddUndef(pMe);
+}
+
+static inline void
+QCBOREncode_AddUndefToMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddUndef(pMe);
+}
+
+
+static inline void
+QCBOREncode_OpenArray(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_ARRAY);
+}
+
+static inline void
+QCBOREncode_OpenArrayInMap(QCBOREncodeContext *pMe, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_OpenArray(pMe);
+}
+
+static inline void
+QCBOREncode_OpenArrayInMapN(QCBOREncodeContext *pMe,  const int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_OpenArray(pMe);
+}
+
+static inline void
+QCBOREncode_CloseArray(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_ARRAY);
+}
+
+
+static inline void
+QCBOREncode_OpenMap(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
+}
+
+static inline void
+QCBOREncode_OpenMapInMap(QCBOREncodeContext *pMe, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_OpenMap(pMe);
+}
+
+static inline void
+QCBOREncode_OpenMapInMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_OpenMap(pMe);
+}
+
+static inline void
+QCBOREncode_CloseMap(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_CloseMapOrArray(pMe, CBOR_MAJOR_TYPE_MAP);
+}
+
+static inline void
+QCBOREncode_OpenArrayIndefiniteLength(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
+}
+
+static inline void
+QCBOREncode_OpenArrayIndefiniteLengthInMap(QCBOREncodeContext *pMe,
+                                           const char         *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_OpenArrayIndefiniteLength(pMe);
+}
+
+static inline void
+QCBOREncode_OpenArrayIndefiniteLengthInMapN(QCBOREncodeContext *pMe,
+                                            const int64_t       nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_OpenArrayIndefiniteLength(pMe);
+}
+
+static inline void
+QCBOREncode_CloseArrayIndefiniteLength(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN);
+}
+
+
+static inline void
+QCBOREncode_OpenMapIndefiniteLength(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
+}
+
+static inline void
+QCBOREncode_OpenMapIndefiniteLengthInMap(QCBOREncodeContext *pMe,
+                                         const char         *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_OpenMapIndefiniteLength(pMe);
+}
+
+static inline void
+QCBOREncode_OpenMapIndefiniteLengthInMapN(QCBOREncodeContext *pMe,
+                                          const int64_t       nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_OpenMapIndefiniteLength(pMe);
+}
+
+static inline void
+QCBOREncode_CloseMapIndefiniteLength(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(pMe, CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN);
+}
+
+
+static inline void
+QCBOREncode_BstrWrap(QCBOREncodeContext *pMe)
+{
+   QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_TYPE_BYTE_STRING);
+}
+
+static inline void
+QCBOREncode_BstrWrapInMap(QCBOREncodeContext *pMe, const char *szLabel)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_BstrWrap(pMe);
+}
+
+static inline void
+QCBOREncode_BstrWrapInMapN(QCBOREncodeContext *pMe, const int64_t nLabel)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_BstrWrap(pMe);
+}
+
+static inline void
+QCBOREncode_CloseBstrWrap(QCBOREncodeContext *pMe, UsefulBufC *pWrappedCBOR)
+{
+   QCBOREncode_CloseBstrWrap2(pMe, true, pWrappedCBOR);
+}
+
+
+
+static inline void
+QCBOREncode_AddEncodedToMap(QCBOREncodeContext *pMe,
+                            const char         *szLabel,
+                            const UsefulBufC    Encoded)
+{
+   QCBOREncode_AddSZString(pMe, szLabel);
+   QCBOREncode_AddEncoded(pMe, Encoded);
+}
+
+static inline void
+QCBOREncode_AddEncodedToMapN(QCBOREncodeContext *pMe,
+                             const int64_t       nLabel,
+                             const UsefulBufC    Encoded)
+{
+   QCBOREncode_AddInt64(pMe, nLabel);
+   QCBOREncode_AddEncoded(pMe, Encoded);
+}
+
+
+static inline int
+QCBOREncode_IsBufferNULL(QCBOREncodeContext *pMe)
+{
+   return UsefulOutBuf_IsBufferNULL(&(pMe->OutBuf));
+}
+
+static inline QCBORError
+QCBOREncode_GetErrorState(QCBOREncodeContext *pMe)
+{
+   if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
+      /* Items didn't fit in the buffer. This check catches this
+       * condition for all the appends and inserts so checks aren't
+       * needed when the appends and inserts are performed.  And of
+       * course UsefulBuf will never overrun the input buffer given to
+       * it. No complex analysis of the error handling in this file is
+       * needed to know that is true. Just read the UsefulBuf code.
+       */
+      pMe->uError = QCBOR_ERR_BUFFER_TOO_SMALL;
+      /* QCBOR_ERR_BUFFER_TOO_SMALL masks other errors, but that is
+       * OK. Once the caller fixes this, they'll be unmasked.
+       */
+   }
+
+   return (QCBORError)pMe->uError;
+}
+
+
+/* ========================================================================
+     END OF PRIVATE INLINE IMPLEMENTATION
+   ======================================================================== */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_encode_h */
diff --git a/core/lib/qcbor/inc/qcbor/qcbor_private.h b/core/lib/qcbor/inc/qcbor/qcbor_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..ae28e650f025f343b6f76658858350aada2db5b3
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor_private.h
@@ -0,0 +1,410 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+
+#ifndef qcbor_private_h
+#define qcbor_private_h
+
+
+#include <stdint.h>
+#include "UsefulBuf.h"
+#include "qcbor/qcbor_common.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} // Keep editor indention formatting happy
+#endif
+#endif
+
+
+/* This was originally defined as QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA,
+ * but this is inconsistent with all the other QCBOR_DISABLE_
+ * #defines, so the name was changed and this was added for backwards
+ * compatibility
+ */
+#ifdef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+#define QCBOR_DISABLE_EXP_AND_MANTISSA
+#endif
+
+/* If USEFULBUF_DISABLE_ALL_FLOATis defined then define
+ * QCBOR_DISABLE_FLOAT_HW_USE and QCBOR_DISABLE_PREFERRED_FLOAT
+ */
+#ifdef USEFULBUF_DISABLE_ALL_FLOAT
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+#define QCBOR_DISABLE_FLOAT_HW_USE
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+#define QCBOR_DISABLE_PREFERRED_FLOAT
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+/*
+ * Convenience macro for selecting the proper return value in case floating
+ * point feature(s) are disabled.
+ *
+ * The macros:
+ *
+ *  FLOAT_ERR_CODE_NO_FLOAT(x) Can be used when disabled floating point should
+ *                              result error, and all other cases should return
+ *                             'x'.
+ *
+ *  The below macros always return QCBOR_ERR_ALL_FLOAT_DISABLED when all
+ *  floating point is disabled.
+ *
+ *  FLOAT_ERR_CODE_NO_HALF_PREC(x) Can be used when disabled preferred float
+ *                                 results in error, and all other cases should
+ *                                 return 'x'.
+ *  FLOAT_ERR_CODE_NO_FLOAT_HW(x) Can be used when disabled hardware floating
+ *                                point results in error, and all other cases
+ *                                should return 'x'.
+ *  FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) Can be used when either disabled
+ *                                             preferred float or disabling
+ *                                             hardware floating point results in
+ *                                             error, and all other cases should
+ *                                             return 'x'.
+ */
+#ifdef USEFULBUF_DISABLE_ALL_FLOAT
+   #define FLOAT_ERR_CODE_NO_FLOAT(x)                 QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_HALF_PREC(x)             QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)              QCBOR_ERR_ALL_FLOAT_DISABLED
+   #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_ALL_FLOAT_DISABLED
+#else /* USEFULBUF_DISABLE_ALL_FLOAT*/
+   #define FLOAT_ERR_CODE_NO_FLOAT(x)     x
+   #ifdef QCBOR_DISABLE_PREFERRED_FLOAT
+      #define FLOAT_ERR_CODE_NO_HALF_PREC(x) QCBOR_ERR_HALF_PRECISION_DISABLED
+      #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HALF_PRECISION_DISABLED
+   #else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+      #define FLOAT_ERR_CODE_NO_HALF_PREC(x) x
+      #ifdef QCBOR_DISABLE_FLOAT_HW_USE
+         #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) QCBOR_ERR_HW_FLOAT_DISABLED
+      #else
+         #define FLOAT_ERR_CODE_NO_HALF_PREC_NO_FLOAT_HW(x) x
+      #endif
+   #endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+   #ifdef QCBOR_DISABLE_FLOAT_HW_USE
+      #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)  QCBOR_ERR_HW_FLOAT_DISABLED
+   #else /* QCBOR_DISABLE_FLOAT_HW_USE */
+      #define FLOAT_ERR_CODE_NO_FLOAT_HW(x)  x
+   #endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+#endif /*USEFULBUF_DISABLE_ALL_FLOAT*/
+
+
+/*
+ * These are special values for the AdditionalInfo bits that are part of
+ * the first byte.  Mostly they encode the length of the data item.
+ */
+#define LEN_IS_ONE_BYTE    24
+#define LEN_IS_TWO_BYTES   25
+#define LEN_IS_FOUR_BYTES  26
+#define LEN_IS_EIGHT_BYTES 27
+#define ADDINFO_RESERVED1  28
+#define ADDINFO_RESERVED2  29
+#define ADDINFO_RESERVED3  30
+#define LEN_IS_INDEFINITE  31
+
+
+/*
+ * 24 is a special number for CBOR. Integers and lengths
+ * less than it are encoded in the same byte as the major type.
+ */
+#define CBOR_TWENTY_FOUR   24
+
+
+/*
+ * Values for the 5 bits for items of major type 7
+ */
+#define CBOR_SIMPLEV_FALSE   20
+#define CBOR_SIMPLEV_TRUE    21
+#define CBOR_SIMPLEV_NULL    22
+#define CBOR_SIMPLEV_UNDEF   23
+#define CBOR_SIMPLEV_ONEBYTE 24
+#define HALF_PREC_FLOAT      25
+#define SINGLE_PREC_FLOAT    26
+#define DOUBLE_PREC_FLOAT    27
+#define CBOR_SIMPLE_BREAK    31
+#define CBOR_SIMPLEV_RESERVED_START  CBOR_SIMPLEV_ONEBYTE
+#define CBOR_SIMPLEV_RESERVED_END    CBOR_SIMPLE_BREAK
+
+
+/* The largest offset to the start of an array or map. It is slightly
+ * less than UINT32_MAX so the error condition can be tested on 32-bit
+ * machines.  UINT32_MAX comes from uStart in QCBORTrackNesting being
+ * a uin32_t.
+ *
+ * This will cause trouble on a machine where size_t is less than 32-bits.
+ */
+#define QCBOR_MAX_ARRAY_OFFSET  (UINT32_MAX - 100)
+
+
+/* The number of tags that are 16-bit or larger that can be handled
+ * in a decode.
+ */
+#define QCBOR_NUM_MAPPED_TAGS 4
+
+/* The number of tags (of any size) recorded for an individual item. */
+#define QCBOR_MAX_TAGS_PER_ITEM1 4
+
+
+
+
+/*
+ * PRIVATE DATA STRUCTURE
+ *
+ * Holds the data for tracking array and map nesting during
+ * encoding. Pairs up with the Nesting_xxx functions to make an
+ * "object" to handle nesting encoding.
+ *
+ * uStart is a uint32_t instead of a size_t to keep the size of this
+ * struct down so it can be on the stack without any concern.  It
+ * would be about double if size_t was used instead.
+ *
+ * Size approximation (varies with CPU/compiler):
+ *    64-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 8 = 136 bytes
+ *   32-bit machine: (15 + 1) * (4 + 2 + 1 + 1 pad) + 4 = 132 bytes
+ */
+typedef struct __QCBORTrackNesting {
+  /* PRIVATE DATA STRUCTURE */
+   struct {
+      /* See QCBOREncode_OpenMapOrArray() for details on how this works */
+      uint32_t  uStart;   /* uStart is the position where the array starts */
+      uint16_t  uCount;   /* Number of items in the arrary or map; counts items
+                           * in a map, not pairs of items */
+      uint8_t   uMajorType; /* Indicates if item is a map or an array */
+   } pArrays[QCBOR_MAX_ARRAY_NESTING+1], /* stored state for nesting levels */
+   *pCurrentNesting; /* the current nesting level */
+} QCBORTrackNesting;
+
+
+/*
+ * PRIVATE DATA STRUCTURE
+ *
+ * Context / data object for encoding some CBOR. Used by all encode
+ * functions to form a public "object" that does the job of encdoing.
+ *
+ * Size approximation (varies with CPU/compiler):
+ *   64-bit machine: 27 + 1 (+ 4 padding) + 136 = 32 + 136 = 168 bytes
+ *  32-bit machine: 15 + 1 + 132 = 148 bytes
+ */
+struct _QCBOREncodeContext {
+   /* PRIVATE DATA STRUCTURE */
+   UsefulOutBuf      OutBuf;  /* Pointer to output buffer, its length and
+                               * position in it. */
+   uint8_t           uError;  /* Error state, always from QCBORError enum */
+   QCBORTrackNesting nesting; /* Keep track of array and map nesting */
+};
+
+
+/*
+ * PRIVATE DATA STRUCTURE
+ *
+ * Holds the data for array and map nesting for decoding work. This
+ * structure and the DecodeNesting_Xxx() functions in qcbor_decode.c
+ * form an "object" that does the work for arrays and maps. All access
+ * to this structure is through DecodeNesting_Xxx() functions.
+ *
+ * 64-bit machine size
+ *   128 = 16 * 8 for the two unions
+ *   64  = 16 * 4 for the uLevelType, 1 byte padded to 4 bytes for alignment
+ *   16  = 16 bytes for two pointers
+ *   208 TOTAL
+ *
+ * 32-bit machine size is 200 bytes
+ */
+typedef struct __QCBORDecodeNesting  {
+  /* PRIVATE DATA STRUCTURE */
+   struct nesting_decode_level {
+      /*
+       * This keeps tracking info for each nesting level. There are two
+       * main types of levels:
+       *   1) Byte count tracking. This is for the top level input CBOR
+       *   which might be a single item or a CBOR sequence and byte
+       *   string wrapped encoded CBOR.
+       *   2) Item count tracking. This is for maps and arrays.
+       *
+       * uLevelType has value QCBOR_TYPE_BYTE_STRING for 1) and
+       * QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP_AS_ARRAY
+       * for 2).
+       *
+       * Item count tracking is either for definite or indefinite-length
+       * maps/arrays. For definite lengths, the total count and items
+       * unconsumed are tracked. For indefinite-length, uTotalCount is
+       * QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH (UINT16_MAX) and
+       * there is no per-item count of members. For indefinite-length
+       * maps and arrays, uCountCursor is UINT16_MAX if not consumed
+       * and zero if it is consumed in the pre-order
+       * traversal. Additionally, if entered in bounded mode,
+       * uCountCursor is QCBOR_COUNT_INDICATES_ZERO_LENGTH to indicate
+       * it is empty.
+       *
+       * This also records whether a level is bounded or not. All
+       * byte-count tracked levels (the top-level sequence and
+       * bstr-wrapped CBOR) are bounded implicitly. Maps and arrays
+       * may or may not be bounded. They are bounded if they were
+       * Entered() and not if they were traversed with GetNext(). They
+       * are marked as bounded by uStartOffset not being @c UINT32_MAX.
+       */
+      /*
+       * If uLevelType can put in a separately indexed array, the
+       * union/struct will be 8 bytes rather than 9 and a lot of
+       * wasted padding for alignment will be saved.
+       */
+      uint8_t  uLevelType;
+      union {
+         struct {
+#define QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH UINT16_MAX
+#define QCBOR_COUNT_INDICATES_ZERO_LENGTH UINT16_MAX-1
+            uint16_t uCountTotal;
+            uint16_t uCountCursor;
+#define QCBOR_NON_BOUNDED_OFFSET UINT32_MAX
+            /* The start of the array or map in bounded mode so
+             * the input can be rewound for GetInMapXx() by label. */
+            uint32_t uStartOffset;
+         } ma; /* for maps and arrays */
+         struct {
+            /* The end of the input before the bstr was entered so that
+             * it can be restored when the bstr is exited. */
+            uint32_t uSavedEndOffset;
+            /* The beginning of the bstr so that it can be rewound. */
+            uint32_t uBstrStartOffset;
+         } bs; /* for top-level sequence and bstr-wrapped CBOR */
+      } u;
+   } pLevels[QCBOR_MAX_ARRAY_NESTING+1],
+    *pCurrent,
+    *pCurrentBounded;
+   /*
+    * pCurrent is for item-by-item pre-order traversal.
+    *
+    * pCurrentBounded points to the current bounding level or is NULL
+    * if there isn't one.
+    *
+    * pCurrent must always be below pCurrentBounded as the pre-order
+    * traversal is always bounded by the bounding level.
+    *
+    * When a bounded level is entered, the pre-order traversal is set
+    * to the first item in the bounded level. When a bounded level is
+    * exited, the pre-order traversl is set to the next item after the
+    * map, array or bstr. This may be more than one level up, or even
+    * the end of the input CBOR.
+    */
+} QCBORDecodeNesting;
+
+
+typedef struct  {
+   /* PRIVATE DATA STRUCTURE */
+   void *pAllocateCxt;
+   UsefulBuf (* pfAllocator)(void *pAllocateCxt, void *pOldMem, size_t uNewSize);
+} QCBORInternalAllocator;
+
+
+/*
+ * PRIVATE DATA STRUCTURE
+ *
+ * The decode context. This data structure plus the public
+ * QCBORDecode_xxx functions form an "object" that does CBOR decoding.
+ *
+ * Size approximation (varies with CPU/compiler):
+ *  64-bit machine: 32 + 1 + 1 + 6 bytes padding + 72 + 16 + 8 + 8 = 144 bytes
+ *  32-bit machine: 16 + 1 + 1 + 2 bytes padding + 68 +  8 + 8 + 4 = 108 bytes
+ */
+struct _QCBORDecodeContext {
+  /* PRIVATE DATA STRUCTURE */
+   UsefulInputBuf InBuf;
+
+   QCBORDecodeNesting nesting;
+
+   /* If a string allocator is configured for indefinite-length
+    * strings, it is configured here.
+    */
+   QCBORInternalAllocator StringAllocator;
+
+   /* These are special for the internal MemPool allocator.  They are
+    * not used otherwise. We tried packing these in the MemPool
+    * itself, but there are issues with memory alignment.
+    */
+   uint32_t uMemPoolSize;
+   uint32_t uMemPoolFreeOffset;
+
+   /* A cached offset to the end of the current map 0 if no value is
+    * cached.
+    */
+#define QCBOR_MAP_OFFSET_CACHE_INVALID UINT32_MAX
+   uint32_t uMapEndOffsetCache;
+
+   uint8_t  uDecodeMode;
+   uint8_t  bStringAllocateAll;
+   uint8_t  uLastError;  /* QCBORError stuffed into a uint8_t */
+
+   /* See MapTagNumber() for description of how tags are mapped. */
+   uint64_t auMappedTags[QCBOR_NUM_MAPPED_TAGS];
+
+   uint16_t uLastTags[QCBOR_MAX_TAGS_PER_ITEM1];
+};
+
+
+/* Used internally in the impementation here Must not conflict with
+ * any of the official CBOR types
+ */
+#define CBOR_MAJOR_NONE_TAG_LABEL_REORDER  10
+#define CBOR_MAJOR_NONE_TYPE_OPEN_BSTR     12
+
+
+/* Add this to types to indicate they are to be encoded as indefinite lengths */
+#define QCBOR_INDEFINITE_LEN_TYPE_MODIFIER 0x80
+#define CBOR_MAJOR_NONE_TYPE_ARRAY_INDEFINITE_LEN \
+            CBOR_MAJOR_TYPE_ARRAY + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
+#define CBOR_MAJOR_NONE_TYPE_MAP_INDEFINITE_LEN \
+            CBOR_MAJOR_TYPE_MAP + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
+#define CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK \
+            CBOR_MAJOR_TYPE_SIMPLE + QCBOR_INDEFINITE_LEN_TYPE_MODIFIER
+
+
+/* Value of QCBORItem.val.string.len when the string length is
+ * indefinite. Used temporarily in the implementation and never
+ * returned in the public interface.
+ */
+#define QCBOR_STRING_LENGTH_INDEFINITE SIZE_MAX
+
+
+/* The number of elements in a C array of a particular type */
+#define C_ARRAY_COUNT(array, type) (sizeof(array)/sizeof(type))
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_private_h */
diff --git a/core/lib/qcbor/inc/qcbor/qcbor_spiffy_decode.h b/core/lib/qcbor/inc/qcbor/qcbor_spiffy_decode.h
new file mode 100644
index 0000000000000000000000000000000000000000..f89d2b0d32a9038c8d80c8d576169b929a069634
--- /dev/null
+++ b/core/lib/qcbor/inc/qcbor/qcbor_spiffy_decode.h
@@ -0,0 +1,3046 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * qcbor_spiffy_decode.h -- higher-level easier-to-use CBOR decoding.
+ *
+ * Copyright (c) 2020-2024, Laurence Lundblade. All rights reserved.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Forked from qcbor_decode.h on 7/23/2020
+ * ========================================================================== */
+#ifndef qcbor_spiffy_decode_h
+#define qcbor_spiffy_decode_h
+
+
+#include "qcbor/qcbor_decode.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#if 0
+} // Keep editor indention formatting happy
+#endif
+#endif
+
+
+/**
+ * @file qcbor_spiffy_decode.h
+ *
+ * @anchor SpiffyDecode
+ * # Spiffy Decode
+ *
+ * This section discusses spiffy decoding assuming familiarity with
+ * the general description of decoding in the
+ * @ref BasicDecode section.
+ *
+ * Spiffy decode is extra decode features over and above the @ref
+ * BasicDecode features that generally are easier to use, mirror the
+ * encoding functions better and can result in smaller code size for
+ * larger and more complex CBOR protocols.  In particular, spiffy
+ * decode facilitates getting the next data item of a specific type,
+ * setting an error if it is not of that type. It facilitates
+ * explicitly entering and exiting arrays and maps. It facilates
+ * fetching items by label from a map including duplicate label
+ * detection.
+ *
+ * Encoded CBOR can be viewed to have a tree structure where the leaf
+ * nodes are non-aggregate types like integers and strings and the
+ * intermediate nodes are either arrays or maps. Fundamentally, all
+ * decoding is a pre-order traversal of the tree. Calling
+ * QCBORDecode_GetNext() repeatedly will perform this.
+ *
+ * This pre-order traversal gives natural decoding of arrays where the
+ * array members are taken in order, but does not give natural decoding
+ * of maps where access by label is usually preferred.  Using the
+ * QCBORDecode_EnterMap() and QCBORDecode_GetXxxxInMapX() methods like
+ * QCBORDecode_GetInt64InMapN(), map items can be accessed by
+ * label. QCBORDecode_EnterMap() bounds decoding to a particular
+ * map. QCBORDecode_GetXxxxInMapX() methods allows decoding the item of
+ * a particular label in the particular map. This can be used with
+ * nested maps by using QCBORDecode_EnterMapFromMapX().
+ *
+ * When QCBORDecode_EnterMap() is called, pre-order traversal
+ * continues to work. There is a cursor that is run over the tree with
+ * calls to QCBORDecode_GetNext(). Attempts to use
+ * QCBORDecode_GetNext() beyond the end of the map will give the
+ * @ref QCBOR_ERR_NO_MORE_ITEMS error.
+ *
+ * Use of the traversal cursor can be mixed with the fetching of items
+ * by label with some caveats. When a non-aggregate item like an
+ * integer or string is fetched by label, the traversal cursor is
+ * unaffected so the mixing can be done freely.  When an aggregate
+ * item is entered by label (by QCBORDecode_EnterMapFromMapN() and
+ * similar), the traversal cursor is set to the item after the
+ * subordinate aggregate item when it is exited. This will not matter
+ * to many use cases. Use cases that mix can be sure to separate
+ * traversal by the cursor from fetching by label.
+ * QCBORDecode_Rewind() may be useful to reset the traversal cursor
+ * after fetching aggregate items by label.
+ *
+ * (This behavior was incorrectly documented in QCBOR 1.2 and prior
+ * which described aggregate and non-aggregate as behaving the same.
+ * Rather than changing to make aggregate and non-aggregate
+ * consistent, the behavior is retained and documented because 1) it
+ * is usable as is, 2) a change would bring backward compatibility
+ * issues, 3) the change would increase the decode context size and
+ * code size.  In QCBOR 1.3 test cases were added to validate the
+ * behavior. No problems were uncovered.)
+ *
+ * QCBORDecode_EnterArray() can be used to narrow the traversal to the
+ * extent of the array.
+ *
+ * All the QCBORDecode_GetXxxxInMapX() methods support duplicate label
+ * detection and will result in an error if the map has duplicate
+ * labels.
+ *
+ * All the QCBORDecode_GetXxxxInMapX() methods are implemented by
+ * performing the pre-order traversal of the map to find the labeled
+ * item everytime it is called. It doesn't build up a hash table, a
+ * binary search tree or some other efficiently searchable structure
+ * internally. For small maps this is fine and for high-speed CPUs
+ * this is fine, but for large, perhaps deeply nested, maps on slow
+ * CPUs, it may have performance issues (these have not be
+ * quantified). One way ease this is to use
+ * QCBORDecode_GetItemsInMap() which allows decoding of a list of
+ * items expected in an map in one traveral.
+ *
+ * @anchor Tag-Usage
+ * ## Tag Usage
+ *
+ * Data types beyond the basic CBOR types of numbers, strings, maps and
+ * arrays are called tags. The main registry of these new types is in
+ * the IANA CBOR tags registry. These new types may be simple such a
+ * number that is to be interpreted as a date, or of moderate complexity
+ * such as defining a decimal fraction that is an array containing a
+ * mantissa and exponent, or complex such as format for signing and
+ * encryption.
+ *
+ * When a tag occurs in a protocol it is encoded as an integer tag
+ * number plus the content of the tag.
+ *
+ * The content format of a tag may also be "borrowed". For example, a
+ * protocol definition may say that a particular data item is an epoch
+ * date just like tag 1, but not actually tag 1. In practice the
+ * difference is the presence or absence of the integer tag number in
+ * the encoded CBOR.
+ *
+ * The decoding functions for these new types takes a tag requirement
+ * parameter to say whether the item is a tag, is just borrowing the
+ * content format and is not a tag, or whether either is OK.
+ *
+ * If the parameter indicates the item must be a tag (@ref
+ * QCBOR_TAG_REQUIREMENT_TAG), then @ref QCBOR_ERR_UNEXPECTED_TYPE is
+ * set if it is not one of the expected tag types. To decode correctly
+ * the contents of the tag must also be of the correct type. For
+ * example, to decode an epoch date tag the content must be an integer
+ * or floating-point value.
+ *
+ * If the parameter indicates it should not be a tag
+ * (@ref  QCBOR_TAG_REQUIREMENT_NOT_A_TAG), then
+ *  @ref QCBOR_ERR_UNEXPECTED_TYPE set if it is a tag or the type of the
+ * encoded CBOR is not what is expected.  In the example of an epoch
+ * date, the data type must be an integer or floating-point value. This
+ * is the case where the content format of a tag is borrowed.
+ *
+ * The parameter can also indicate that either a tag or no tag is
+ * allowed ( @ref QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG ).  A good protocol
+ * design should however be clear and choose one or the other and not
+ * need this option. This is a way to implement "be liberal in what you
+ * accept", however these days that is less in favor. See
+ * https://tools.ietf.org/id/draft-thomson-postel-was-wrong-03.html.
+ *
+ * Map searching works with indefinite length strings. A string
+ * allocator must be set up the same as for any handling of indefinite
+ * length strings.  However, It currently over-allocates memory from the
+ * string pool and thus requires a much larger string pool than it
+ * should. The over-allocation happens every time a map is searched by
+ * label.  (This may be corrected in the future).
+ */
+
+
+
+
+/** The data item must be a tag of the expected type. It is an error
+ *  if it is not. For example when calling QCBORDecode_GetEpochDate(),
+ *  the data item must be an @ref CBOR_TAG_DATE_EPOCH tag.  See
+ *  @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_TAG 0
+
+/** The data item must be of the type expected for content data type
+ *  being fetched. It is an error if it is not. For example, when
+ *  calling QCBORDecode_GetEpochDate() and it must not be an @ref
+ *  CBOR_TAG_DATE_EPOCH tag. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_NOT_A_TAG  1
+
+/** Either of the above two are allowed. This allows implementation of
+ *  being liberal in what you receive, but it is better if CBOR-based
+ *  protocols pick one and stick to and not required the reciever to
+ *  take either. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG 2
+
+/** Add this into the above value if other tags not processed by QCBOR
+ *  are to be allowed to surround the data item. See @ref Tag-Usage. */
+#define QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS 0x80
+
+
+
+
+/** Conversion will proceed if the CBOR item to be decoded is an
+ *  integer or either type 0 (unsigned) or type 1 (negative). */
+#define QCBOR_CONVERT_TYPE_XINT64           0x01
+/** Conversion will proceed if the CBOR item to be decoded is either
+ *  double, single or half-precision floating-point (major type 7). */
+#define QCBOR_CONVERT_TYPE_FLOAT            0x02
+/** Conversion will proceed if the CBOR item to be decoded is a big
+ *  number, positive or negative (tag 2 or tag 3). */
+#define QCBOR_CONVERT_TYPE_BIG_NUM          0x04
+/** Conversion will proceed if the CBOR item to be decoded is a
+ *  decimal fraction (tag 4). */
+#define QCBOR_CONVERT_TYPE_DECIMAL_FRACTION 0x08
+/** Conversion will proceed if the CBOR item to be decoded is a big
+ *  float (tag 5). */
+#define QCBOR_CONVERT_TYPE_BIGFLOAT         0x10
+
+
+
+
+/**
+ * @brief Decode next item into a signed 64-bit integer.
+ *
+ * @param[in] pCtx      The decode context.
+ * @param[out] pnValue  The returned 64-bit signed integer.
+ *
+ * The CBOR data item to decode must be a positive or negative integer
+ * (CBOR major type 0 or 1). If not @ref QCBOR_ERR_UNEXPECTED_TYPE is set.
+ *
+ * If the CBOR integer is either too large or too small to fit in an
+ * int64_t, the error @ref QCBOR_ERR_INT_OVERFLOW or
+ * @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW is set.  Note that type 0
+ * unsigned integers can be larger than will fit in an int64_t and
+ * type 1 negative integers can be smaller than will fit in an
+ * int64_t.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_GetUInt64(), QCBORDecode_GetInt64Convert(),
+ * QCBORDecode_GetInt64ConvertAll() and QCBORDecode_GetDoubleConvert()
+ */
+static void
+QCBORDecode_GetInt64(QCBORDecodeContext *pCtx,
+                     int64_t            *pnValue);
+
+static void
+QCBORDecode_GetInt64InMapN(QCBORDecodeContext *pCtx,
+                           int64_t             nLabel,
+                           int64_t            *pnValue);
+
+static void
+QCBORDecode_GetInt64InMapSZ(QCBORDecodeContext *pCtx,
+                            const char         *szLabel,
+                            int64_t            *pnValue);
+
+
+/**
+ * @brief Decode next item into a signed 64-bit integer with basic conversions.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] pnValue       The returned 64-bit signed integer.
+ *
+ * @c uConvertTypes controls what conversions this will perform and
+ * thus what CBOR types will be decoded.  @c uConvertType is a bit map
+ * listing the conversions to be allowed. This function supports
+ * @ref QCBOR_CONVERT_TYPE_XINT64 and @ref QCBOR_CONVERT_TYPE_FLOAT
+ * conversions.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * If the CBOR data type can never be convered by this function or the
+ * conversion was not selected in @c uConversionTypes
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE is set.
+ *
+ * When converting floating-point values, the integer is rounded to
+ * the nearest integer using llround(). By default, floating-point
+ * suport is enabled for QCBOR.
+ *
+ * If floating-point HW use is disabled this will set
+ * @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is
+ * encountered. If half-precision support is disabled, this will set
+ * @ref QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number
+ * is encountered.
+ *
+ * If floating-point usage is disabled this will set
+ * @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is
+ * encountered.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll() which will perform the
+ * same conversions as this and a lot more at the cost of adding more
+ * object code to your executable.
+ */
+static void
+QCBORDecode_GetInt64Convert(QCBORDecodeContext *pCtx,
+                            uint32_t            uConvertTypes,
+                            int64_t            *pnValue);
+
+static void
+QCBORDecode_GetInt64ConvertInMapN(QCBORDecodeContext *pCtx,
+                                  int64_t             nLabel,
+                                  uint32_t            uConvertTypes,
+                                  int64_t            *pnValue);
+
+static void
+QCBORDecode_GetInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                   const char         *szLabel,
+                                   uint32_t            uConvertTypes,
+                                   int64_t            *pnValue);
+
+
+/**
+ * @brief Decode next item into a signed 64-bit integer with conversions.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] pnValue       The returned 64-bit signed integer.
+ *
+ * This is the same as QCBORDecode_GetInt64Convert() but additionally
+ * supports conversion from positive and negative bignums, decimal
+ * fractions and big floats, including decimal fractions and big floats
+ * that use bignums. The conversion types supported are
+ * @ref QCBOR_CONVERT_TYPE_XINT64, @ref QCBOR_CONVERT_TYPE_FLOAT,
+ * @ref QCBOR_CONVERT_TYPE_BIG_NUM,
+ * @ref QCBOR_CONVERT_TYPE_DECIMAL_FRACTION and
+ * @ref QCBOR_CONVERT_TYPE_BIGFLOAT.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * Note that most these types can support numbers much larger that can
+ * be represented by in a 64-bit integer, so
+ * @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW may often be encountered.
+ *
+ * When converting bignums and decimal fractions,
+ * @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will be set if the result
+ * is below 1, unless the mantissa is zero, in which case the
+ * coversion is successful and the value of 0 is returned.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll() which does some of these
+ * conversions, but links in much less object code. See also
+ * QCBORDecode_GetUInt64ConvertAll().
+ *
+ * This relies on CBOR tags to identify big numbers, decimal fractions
+ * and big floats. It will not attempt to decode non-tag CBOR that might
+ * be one of these.  (If QCBOR_DISABLE_TAGS is set, this is effectively
+ * the same as QCBORDecode_GetInt64Convert() because all the additional
+ * number types this decodes are tags).
+ */
+void
+QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pCtx,
+                               uint32_t            uConvertTypes,
+                               int64_t            *pnValue);
+
+void
+QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint32_t            uConvertTypes,
+                                     int64_t            *pnValue);
+
+void
+QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pCtx,
+                                      const char         *szLabel,
+                                      uint32_t            uConvertTypes,
+                                      int64_t            *pnValue);
+
+
+/**
+ * @brief Decode next item into an unsigned 64-bit integer.
+ *
+ * @param[in] pCtx      The decode context.
+ * @param[out] puValue  The returned 64-bit unsigned integer.
+ *
+ * This is the same as QCBORDecode_GetInt64(), but returns an unsigned integer
+ * and thus can only decode CBOR positive integers.
+ * @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION is set if the input is a negative
+ * integer.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_GetUInt64Convert() and QCBORDecode_GetUInt64ConvertAll().
+ */
+static void
+QCBORDecode_GetUInt64(QCBORDecodeContext *pCtx,
+                      uint64_t           *puValue);
+
+static void
+QCBORDecode_GetUInt64InMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint64_t           *puValue);
+
+static void
+QCBORDecode_GetUInt64InMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             uint64_t           *puValue);
+
+
+/**
+ * @brief Decode next item as an unsigned 64-bit integer with basic conversions.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] puValue       The returned 64-bit unsigned integer.
+ *
+ * This is the same as QCBORDecode_GetInt64Convert(), but returns an
+ * unsigned integer and thus sets @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION
+ * if the value to be decoded is negatve.
+ *
+ * If floating-point HW use is disabled this will set
+ * @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is
+ * encountered. If half-precision support is disabled, this will set
+ * @ref QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number
+ * is encountered.
+ *
+ * If floating-point usage is disabled this will set
+ * @ref QCBOR_ERR_ALL_FLOAT_DISABLED if a floating point value is
+ * encountered.
+ *
+ * See also QCBORDecode_GetUInt64Convert() and
+ * QCBORDecode_GetUInt64ConvertAll().
+ */
+static void
+QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pCtx,
+                             uint32_t            uConvertTypes,
+                             uint64_t           *puValue);
+
+static void
+QCBORDecode_GetUInt64ConvertInMapN(QCBORDecodeContext *pCtx,
+                                   int64_t             nLabel,
+                                   uint32_t            uConvertTypes,
+                                   uint64_t           *puValue);
+
+static void
+QCBORDecode_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                    const char         *szLabel,
+                                    uint32_t            uConvertTypes,
+                                    uint64_t           *puValue);
+
+
+/**
+ * @brief Decode next item into an unsigned 64-bit integer with conversions
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] puValue       The returned 64-bit unsigned integer.
+ *
+ * This is the same as QCBORDecode_GetInt64ConvertAll(), but returns
+ * an unsigned integer and thus sets @ref QCBOR_ERR_NUMBER_SIGN_CONVERSION
+ * if the value to be decoded is negatve.
+ *
+ * See also QCBORDecode_GetUInt64() and QCBORDecode_GetUInt64Convert().
+ */
+void
+QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pCtx,
+                                uint32_t            uConvertTypes,
+                                uint64_t           *puValue);
+
+void
+QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pCtx,
+                                      int64_t             nLabel,
+                                      uint32_t            uConvertTypes,
+                                      uint64_t           *puValue);
+
+void
+QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pCtx,
+                                       const char         *szLabel,
+                                       uint32_t            uConvertTypes,
+                                       uint64_t           *puValue);
+
+
+
+
+/**
+ * @brief Decode the next item as a byte string
+ *
+ * @param[in] pCtx     The decode context.
+ * @param[out] pBytes  The decoded byte string.
+ *
+ * The CBOR item to decode must be a byte string, CBOR type 2.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * If the CBOR item to decode is not a byte string, the
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE error is set.
+ */
+static void
+QCBORDecode_GetByteString(QCBORDecodeContext *pCtx,
+                          UsefulBufC         *pBytes);
+
+static void
+QCBORDecode_GetByteStringInMapN(QCBORDecodeContext *pCtx,
+                                int64_t             nLabel,
+                                UsefulBufC         *pBytes);
+
+static void
+QCBORDecode_GetByteStringInMapSZ(QCBORDecodeContext *pCtx,
+                                 const char         *szLabel,
+                                 UsefulBufC         *pBytes);
+
+
+/**
+ * @brief Decode the next item as a text string.
+ *
+ * @param[in] pCtx    The decode context.
+ * @param[out] pText  The decoded byte string.
+ *
+ * The CBOR item to decode must be a text string, CBOR type 3.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ * It the CBOR item to decode is not a text string, the
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE error is set.
+ *
+ * This does no translation of line endings. See QCBOREncode_AddText()
+ * for a discussion of line endings in CBOR.
+ */
+static void
+QCBORDecode_GetTextString(QCBORDecodeContext *pCtx,
+                          UsefulBufC         *pText);
+
+static void
+QCBORDecode_GetTextStringInMapN(QCBORDecodeContext *pCtx,
+                                int64_t             nLabel,
+                                UsefulBufC         *pText);
+
+static void
+QCBORDecode_GetTextStringInMapSZ(QCBORDecodeContext *pCtx,
+                                 const char         *szLabel,
+                                 UsefulBufC         *pText);
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Decode next item into a double floating-point value.
+ *
+ * @param[in] pCtx     The decode context.
+ * @param[out] pValue  The returned floating-point value.
+ *
+ * The CBOR data item to decode must be a half-precision,
+ * single-precision or double-precision floating-point value. If not
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE is set.
+ *
+ * If floating-point HW use is disabled this will set
+ * @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is
+ * encountered. If half-precision support is disabled, this will set
+ * @ref QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number
+ * is encountered.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_GetDoubleConvert() and
+ * QCBORDecode_GetDoubleConvertAll().
+ */
+static void
+QCBORDecode_GetDouble(QCBORDecodeContext *pCtx,
+                      double             *pValue);
+
+static void
+QCBORDecode_GetDoubleInMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            double             *pdValue);
+
+static void
+QCBORDecode_GetDoubleInMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             double             *pdValue);
+
+
+/**
+ * @brief Decode next item into a double floating-point with basic conversion.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] pdValue       The returned floating-point value.
+ *
+ * This will decode CBOR integer and floating-point numbers, returning
+ * them as a double floating-point number. This function supports
+
+ * @ref QCBOR_CONVERT_TYPE_XINT64 and @ref QCBOR_CONVERT_TYPE_FLOAT
+ * conversions. If the encoded CBOR is not one of the requested types
+ * or a type not supported by this function, @ref QCBOR_ERR_UNEXPECTED_TYPE
+ * is set.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * If floating-point HW use is disabled this will set
+ * @ref QCBOR_ERR_HW_FLOAT_DISABLED if a single-precision number is
+ * encountered. If half-precision support is disabled, this will set
+ * @ref QCBOR_ERR_HALF_PRECISION_DISABLED if a half-precision number is
+ * encountered.
+ *
+ * Positive and negative integers can always be converted to
+ * floating-point, so this will never error on CBOR major type 0 or 1.
+ *
+ * Note that a large 64-bit integer can have more precision (64 bits)
+ * than even a double floating-point (52 bits) value, so there is loss
+ * of precision in some conversions.
+ *
+ * See also QCBORDecode_GetDouble() and QCBORDecode_GetDoubleConvertAll().
+ */
+static void
+QCBORDecode_GetDoubleConvert(QCBORDecodeContext *pCtx,
+                             uint32_t            uConvertTypes,
+                             double             *pdValue);
+
+static void
+QCBORDecode_GetDoubleConvertInMapN(QCBORDecodeContext *pCtx,
+                                   int64_t             nLabel,
+                                   uint32_t            uConvertTypes,
+                                   double             *pdValue);
+
+static void
+QCBORDecode_GetDoubleConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                    const char         *szLabel,
+                                    uint32_t            uConvertTypes,
+                                    double             *pdValue);
+
+
+/**
+ * @brief Decode next item as a double floating-point value with conversion.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in] uConvertTypes  The integer conversion options.
+ * @param[out] pdValue       The returned floating-point value.
+ *
+ * This is the same as QCBORDecode_GetDoubleConvert() but supports
+ * many more conversions at the cost of linking in more object
+ * code. The conversion types supported are @ref QCBOR_CONVERT_TYPE_XINT64,
+ * @ref QCBOR_CONVERT_TYPE_FLOAT, @ref QCBOR_CONVERT_TYPE_BIG_NUM,
+ * @ref QCBOR_CONVERT_TYPE_DECIMAL_FRACTION and
+ * @ref QCBOR_CONVERT_TYPE_BIGFLOAT.
+ *
+ * Big numbers, decimal fractions and big floats that are too small or
+ * too large to be reprented as a double floating-point number will be
+ * returned as plus or minus zero or infinity rather than setting an
+ * under or overflow error.
+ *
+ * There is often loss of precision in the conversion.
+ *
+ * See also QCBORDecode_GetDoubleConvert() and QCBORDecode_GetDoubleConvert().
+ */
+void
+QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pCtx,
+                                uint32_t            uConvertTypes,
+                                double             *pdValue);
+
+void
+QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pCtx,
+                                      int64_t             nLabel,
+                                      uint32_t            uConvertTypes,
+                                      double             *pdValue);
+
+void
+QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pCtx,
+                                       const char         *szLabel,
+                                       uint32_t            uConvertTypes,
+                                       double             *pdValue);
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+/**
+ * @brief Enter an array for decoding in bounded mode.
+ *
+ * @param[in] pCtx    The decode context.
+ * @param[out] pItem  The optionally returned QCBORItem that has the
+ *                    label and tags for the array. May be @c NULL (and
+ *                    usually is).
+ *
+ * This enters an array for decoding in bounded mode. The items in
+ * the array are decoded in order the same as when not in bounded mode,
+ * but the decoding will not proceed past the end or the array.
+ *
+ * The typical way to iterate over items in an array is to call
+ * QCBORDecode_VGetNext() until QCBORDecode_GetError() returns
+ * @ref QCBOR_ERR_NO_MORE_ITEMS. Other methods like QCBORDecode_GetInt64(),
+ * QCBORDecode_GetBignum() and such may also called until
+ * QCBORDecode_GetError() doesn't return QCBOR_SUCCESS.
+ *
+ * Another option is to get the array item count from
+ * @c pItem->val.uCount, but note that that will not work with
+ * indefinte-length arrays, where as QCBORDecode_GetError() will.
+ *
+ * Nested decoding of arrays may be handled by calling
+ * QCBORDecode_EnterArray() or by using QCBORDecode_VGetNext() to
+ * descend into and back out of the nested array.
+ *
+ * QCBORDecode_Rewind() can be called to restart decoding from the
+ * first item in the array.
+ *
+ * When all decoding in an array is complete, QCBORDecode_ExitArray() must
+ * be called. It is a decoding error to not have a corresponding call
+ * to QCBORDecode_ExitArray() for every call to QCBORDecode_EnterArray().
+ * If not, @ref QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN will be returned when
+ * QCBORDecode_Finish() is called.
+ *
+ * After QCBORDecode_ExitArray() is called the traversal cusor is at
+ * the item right after the array. This is true whether or not all
+ * items in the array were consumed. QCBORDecode_ExitArray() can even
+ * be called right after QCBORDecode_EnterArray() as a way to skip
+ * over an array and all its contents.
+ *
+ * This works the same for definite and indefinite length arrays.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * If attempting to enter a data item that is not an array
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE wil be set.
+ *
+ * Nested arrays and maps may be entered to a depth of
+ * @ref QCBOR_MAX_ARRAY_NESTING.
+ *
+ * See also QCBORDecode_ExitArray(), QCBORDecode_EnterMap(),
+ * QCBORDecode_EnterBstrWrapped() and QCBORDecode_GetArray().
+ */
+static void
+QCBORDecode_EnterArray(QCBORDecodeContext *pCtx, QCBORItem *pItem);
+
+void
+QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t uLabel);
+
+void
+QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char *szLabel);
+
+
+/**
+ * @brief Exit an array that has been enetered.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * An array must have been entered for this to succeed.
+ *
+ * The items in the array that was entered do not have to have been
+ * consumed for this to succeed.
+ *
+ * This sets the traversal cursor to the item after the
+ * array that was exited.
+ *
+ * This will result in an error if any item in the array is not well
+ * formed (since all items in the array must be decoded to find its
+ * end), or there are not enough items in the array.
+ */
+static void
+QCBORDecode_ExitArray(QCBORDecodeContext *pCtx);
+
+
+
+/**
+ * @brief Get the encoded bytes that make up an array.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[out] pItem         Place to return the item.
+ * @param[out] pEncodedCBOR  Place to return pointer and length of the array.
+ *
+ * The next item to decode must be an array.
+ *
+ * The encoded bytes of the array will be returned. They can be
+ * decoded by another decoder instance.
+ *
+ * @c pItem will have the label and tags for the array. It is filled
+ * in the same as if QCBORDecode_GetNext() were called on the array item. In
+ * particular, the array count will be filled in for definite-length
+ * arrays and set to @c UINT16_MAX for indefinite-length arrays.
+ *
+ * This works on both definite and indefinite length arrays (unless
+ * indefinite length array decoding has been disabled).
+ *
+ * The pointer returned is to the data item that opens the array. The
+ * length in bytes includes it and all the member data items. If the array
+ * occurs in another map and thus has a label, the label is not included
+ * in what is returned.
+ *
+ * If the array is preceeded by tags, those encoded tags are included
+ * in the encoded CBOR that is returned.
+ *
+ * QCBORDecode_GetArray() consumes the entire array and leaves the
+ * traversal cursor at the item after the array.
+ * QCBORDecode_GetArrayFromMapN() and QCBORDecode_GetArrayFromMapSZ()
+ * don't affect the traversal cursor.
+ *
+ * This traverses the whole array and every subordinate array or map in
+ * it. This is necessary to determine the length of the array.
+ *
+ * This will fail if any item in the array is not well-formed.
+ *
+ * This uses a few hundred bytes of stack, more than most methods.
+ *
+ * See also QCBORDecode_EnterArray().
+ */
+static void
+QCBORDecode_GetArray(QCBORDecodeContext *pCtx,
+                     QCBORItem          *pItem,
+                     UsefulBufC         *pEncodedCBOR);
+
+static void
+QCBORDecode_GetArrayFromMapN(QCBORDecodeContext *pCtx,
+                             int64_t             nLabel,
+                             QCBORItem          *pItem,
+                             UsefulBufC         *pEncodedCBOR);
+
+static void
+QCBORDecode_GetArrayFromMapSZ(QCBORDecodeContext *pCtx,
+                              const char         *szLabel,
+                              QCBORItem          *pItem,
+                              UsefulBufC         *pEncodedCBOR);
+
+
+/**
+ * @brief Enter a map for decoding and searching.
+ *
+ * @param[in] pCtx    The decode context.
+ * @param[out] pItem  The optionally returned QCBORItem that has the
+ *                    label and tags for the map. May be @c NULL (and
+ *                    usually is).
+ *
+ * The next item in the CBOR input must be map or this sets an error.
+ *
+ * This puts the decoder in bounded mode which narrows decoding to the
+ * map entered and enables getting items by label.
+ *
+ * All items in the map must be well-formed to be able to search it by
+ * label because a full traversal is done for each search. If not, the
+ * search will retun an error for the item that is not well-formed.
+ * This will be the first non-well-formed item which may not be the
+ * item with the label that is the target of the search.
+ *
+ * Nested maps can be decoded like this by entering each map in turn.
+ *
+ * Call QCBORDecode_ExitMap() to exit the current map decoding
+ * level. When all map decoding layers are exited then bounded mode is
+ * fully exited.
+ *
+ * While in bounded mode, QCBORDecode_GetNext() works as usual on the
+ * map and the traversal cursor is maintained. It starts out
+ * at the first item in the map just entered. Attempts to get items
+ * off the end of the map will give error @ref QCBOR_ERR_NO_MORE_ITEMS
+ * rather going to the next item after the map as it would when not in
+ * bounded mode.
+ *
+ * It is possible to mix use of the traversal cursor with the fetching
+ * of items in a map by label with the caveat that fetching
+ * non-aggregate items by label behaves differently from entering subordinate
+ * aggregate items by label.  See dicussion in @ref SpiffyDecode.
+ *
+ * Exiting leaves the traversal cursor at the data item following the
+ * last entry in the map or at the end of the input CBOR if there
+ * nothing after the map.
+ *
+ * Entering and Exiting a map is a way to skip over an entire map and
+ * its contents. After QCBORDecode_ExitMap(), the traversal
+ * cursor will be at the first item after the map.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_EnterArray() and
+ * QCBORDecode_EnterBstrWrapped().  Entering and exiting any nested
+ * combination of maps, arrays and bstr-wrapped CBOR is supported up
+ * to the maximum of @ref QCBOR_MAX_ARRAY_NESTING.
+ *
+ * See also QCBORDecode_GetMap().
+ */
+static void
+QCBORDecode_EnterMap(QCBORDecodeContext *pCtx, QCBORItem *pItem);
+
+void
+QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pCtx, int64_t nLabel);
+
+void
+QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pCtx, const char *szLabel);
+
+
+/**
+ * @brief Exit a map that has been enetered.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * A map must have been entered for this to succeed.
+ *
+ * The items in the map that was entered do not have to have been
+ * consumed for this to succeed.
+ *
+ * This sets the traversal cursor to the item after the map
+ * that was exited.
+ *
+ * This will result in an error if any item in the map is not well
+ * formed (since all items in the map must be decoded to find its
+ * end), or there are not enough items in the map.
+ */
+static void
+QCBORDecode_ExitMap(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Get the bytes that make up a map.
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[out] pItem         Place to return the item.
+ * @param[out] pEncodedCBOR  Place to return pointer and length of the map.
+ *
+ * The next item to decode must be a map.
+ *
+ * The encoded bytes of the map will be returned. They can be
+ * decoded by another decoder instance.
+ *
+ *  @c pItem will have the label and tags for the array. It is filled
+ * in the same as if QCBORDecode_GetNext() were called on the map item. In
+ * particular, the map count will be filled in for definite-length
+ * maps and set to @c UINT16_MAX for indefinite-length maps.
+ *
+ * This works on both definite and indefinite length maps (unless
+ * indefinite length map decoding has been disabled).
+ *
+ * The pointer returned is to the data item that opens the map. The
+ * length in bytes includes it and all the member data items. If the map
+ * occurs in another map and thus has a label, the label is not included
+ * in what is returned.
+ *
+ * If the map is preceeded by tags, those encoded tags are included in
+ * the encoded CBOR that is returned.
+ *
+ * QCBORDecode_GetMap() consumes the entire array and leaves the
+ * traversal cursor at the item after the map.
+ * QCBORDecode_GetMapFromMapN() and QCBORDecode_GetMapFromMapSZ()
+ * don't affect the traversal cursor.
+ *
+ * This traverses the whole map and every subordinate array or map in
+ * it. This is necessary to determine the length of the map. The
+ * traversal cursor is left at the first item after the map.
+ *
+ * This will fail if any item in the map is not well-formed.
+ *
+ * This uses a few hundred bytes of stack, more than most methods.
+ *
+ * See also QCBORDecode_EnterMap().
+ */
+static void
+QCBORDecode_GetMap(QCBORDecodeContext *pCtx,
+                   QCBORItem          *pItem,
+                   UsefulBufC         *pEncodedCBOR);
+
+static void
+QCBORDecode_GetMapFromMapN(QCBORDecodeContext *pCtx,
+                           int64_t             nLabel,
+                           QCBORItem          *pItem,
+                           UsefulBufC         *pEncodedCBOR);
+
+static void
+QCBORDecode_GetMapFromMapSZ(QCBORDecodeContext *pCtx,
+                            const char         *szLabel,
+                            QCBORItem          *pItem,
+                            UsefulBufC         *pEncodedCBOR);
+
+
+/**
+ * @brief Reset traversal cursor to start of map, array, byte-string
+ *        wrapped CBOR or start of input.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * If an array, map or wrapping byte string has been entered this sets
+ * the traversal cursor to its beginning. If several arrays, maps or
+ * byte strings have been entered, this sets the traversal cursor to
+ * the beginning of the one most recently entered.
+ *
+ * If no map or array has been entered, this resets the traversal
+ * cursor to the beginning of the input CBOR.
+ *
+ * This also resets the error state.
+ */
+void
+QCBORDecode_Rewind(QCBORDecodeContext *pCtx);
+
+
+/**
+ * @brief Get an item in map by label and type.
+ *
+ * @param[in] pCtx    The decode context.
+ * @param[in] nLabel  The integer label.
+ * @param[in] uQcborType  The QCBOR type. One of @c QCBOR_TYPE_XXX.
+ * @param[out] pItem  The returned item.
+ *
+ * A map must have been entered to use this. If not
+ * @ref QCBOR_ERR_MAP_NOT_ENTERED is set.
+ *
+ * The map is searched for an item of the requested label and type.
+ * @ref QCBOR_TYPE_ANY can be given to search for the label without
+ * matching the type.
+ *
+ * This will always search the entire map. This will always perform
+ * duplicate label detection, setting @ref QCBOR_ERR_DUPLICATE_LABEL
+ * if there is more than one occurance of the label being searched
+ * for.
+ *
+ * Duplicate label detection is performed for the item being sought
+ * and only for the item being sought.
+ *
+ * This performs a full decode of every item in the map being
+ * searched which involves a full traversal of every item. For maps
+ * with little nesting, this is of little consequence, but may be of
+ * consequence for large deeply nested CBOR structures on slow CPUs.
+ *
+ * The position of the traversal cursor is not changed.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_GetItemsInMap() for error discussion.
+ */
+void
+QCBORDecode_GetItemInMapN(QCBORDecodeContext *pCtx,
+                          int64_t             nLabel,
+                          uint8_t             uQcborType,
+                          QCBORItem          *pItem);
+
+void
+QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pCtx,
+                           const char         *szLabel,
+                           uint8_t             uQcborType,
+                           QCBORItem          *pItem);
+
+
+/**
+ * @brief Get a group of labeled items all at once from a map
+ *
+ * @param[in] pCtx           The decode context.
+ * @param[in,out] pItemList  On input, the items to search for. On output,
+ *                           the returne *d items.
+ *
+ * This gets several labeled items out of a map.
+ *
+ * @c pItemList is an array of items terminated by an item with @c
+ * uLabelType @ref QCBOR_TYPE_NONE.
+ *
+ * On input the labels to search for are in the @c uLabelType and
+ * label fields in the items in @c pItemList.
+ *
+ * Also on input are the requested QCBOR types in the field
+ * @c uDataType.  To match any type, searching just by label,
+ * @c uDataType can be @ref QCBOR_TYPE_ANY.
+ *
+ * This is a CPU-efficient way to decode a bunch of items in a map. It
+ * is more efficient than scanning each individually because the map
+ * only needs to be traversed once.
+ *
+ * This will return maps and arrays that are in the map, but provides
+ * no way to descend into and decode them. Use
+ * QCBORDecode_EnterMapinMapN(), QCBORDecode_EnterArrayInMapN() and
+ * such to descend into and process maps and arrays.
+ *
+ * The position of the traversal cursor is not changed.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * The following errors are set:
+ *
+ * @ref QCBOR_ERR_MAP_NOT_ENTERED when calling this without previousl
+ * calling QCBORDecode_EnterMap() or other methods to enter a map.
+ *
+ * @ref QCBOR_ERR_DUPLICATE_LABEL when one of the labels being searched
+ * for is duplicate.
+ *
+ * @ref QCBOR_ERR_HIT_END or other errors classifed as not-well-formed
+ * by QCBORDecode_IsNotWellFormed() as it is not possible to traverse
+ * maps that have any non-well formed items.
+ *
+ * @ref QCBOR_ERR_UNEXPECTED_TYPE when the type of an item found by
+ * matching a label is not the type requested.
+ *
+ * @ref QCBOR_ERR_ARRAY_NESTING_TOO_DEEP and other implementation
+ * limit errors as it is not possible to travere a map beyond the
+ * limits of the implementation.
+ *
+ * The error may occur on items that are not being searched for.  For
+ * example, it is impossible to traverse over a map that has an array in
+ * it that is not closed or over array and map nesting deeper than this
+ * implementation can track.
+ *
+ * See also QCBORDecode_GetItemInMapN().
+ */
+void
+QCBORDecode_GetItemsInMap(QCBORDecodeContext *pCtx, QCBORItem *pItemList);
+
+
+/**
+ * @brief Per-item callback for map searching.
+ *
+ * @param[in] pCallbackCtx  Pointer to the caller-defined context for the callback.
+ * @param[in] pItem         The item from the map.
+ *
+ * The error set is intended for QCBOR errors, not general protocol
+ * decoding errors. If this sets other than @ref QCBOR_SUCCESS, the
+ * search will stop and the value it returns will be set in
+ * QCBORDecode_GetItemsInMapWithCallback(). The special error,
+ * @ref QCBOR_ERR_CALLBACK_FAIL, can be returned to indicate some
+ * protocol processing error that is not a CBOR error. The specific
+ * details of the protocol processing error can be returned the call
+ * back context.
+ */
+typedef QCBORError (*QCBORItemCallback)(void            *pCallbackCtx,
+                                        const QCBORItem *pItem);
+
+
+/**
+ * @brief Get a group of labeled items all at once from a map with a callback.
+ *
+ * @param[in] pCtx              The decode context.
+ * @param[in,out] pItemList     On input, the items to search for. On output,
+ *                              the returne *d items.
+ * @param[in,out] pCallbackCtx  Pointer to a context structure for
+ *                              @ref QCBORItemCallback
+ * @param[in] pfCB              Pointer to function of type
+ *                              @ref QCBORItemCallback that is called on
+ *                              unmatched items.
+ *
+ * This searchs a map like QCBORDecode_GetItemsInMap(), but calls a
+ * callback on items not matched rather than ignoring them. If @c
+ * pItemList is empty, the call back will be called on every item in the
+ * map.
+ *
+ * Like QCBORDecode_GetItemsInMap(), this only matches and calls back on
+ * the items at the top level of the map entered. Items in nested
+ * maps and arrays are skipped over and not candidate for matching or the
+ * callback.
+ *
+ * See QCBORItemCallback() for error handling.
+ */
+void
+QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pCtx,
+                                      QCBORItem          *pItemList,
+                                      void               *pCallbackCtx,
+                                      QCBORItemCallback   pfCB);
+
+
+
+
+/**
+ * @brief Decode the next item as a Boolean.
+ *
+ * @param[in] pCtx     The decode context.
+ * @param[out] pbBool  The decoded byte string.
+ *
+ * The CBOR item to decode must be either the CBOR simple value (CBOR
+ * type 7) @c true or @c false.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview". If
+ * the CBOR item to decode is not true or false the @ref
+ * QCBOR_ERR_UNEXPECTED_TYPE error is set.
+*/
+void
+QCBORDecode_GetBool(QCBORDecodeContext *pCtx, bool *pbBool);
+
+void
+QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pCtx,
+                          int64_t             nLabel,
+                          bool               *pbBool);
+
+void
+QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pCtx,
+                           const char         *szLabel,
+                           bool               *pbBool);
+
+
+/**
+ * @brief Decode the next item as a null.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * The CBOR item to decode must be the CBOR simple value (CBOR type 7)
+ * @c null. The reason to call this is to see if an error is returned
+ * or not indicating whether the item is a CBOR null. If it is not
+ * then the @ref QCBOR_ERR_UNEXPECTED_TYPE error is set.
+ */
+static void
+QCBORDecode_GetNull(QCBORDecodeContext *pCtx);
+
+static void
+QCBORDecode_GetNullInMapN(QCBORDecodeContext *pCtx,
+                          int64_t             nLabel);
+
+static void
+QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pCtx,
+                           const char         *szLabel);
+
+
+/**
+ * @brief Decode the next item as a CBOR "undefined" item.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * The CBOR item to decode must be the CBOR simple value (CBOR type 7)
+ * @c undefined. The reason to call this is to see if an error is
+ * returned or not indicating whether the item is a CBOR undefed
+ * item. If it is not then the @ref QCBOR_ERR_UNEXPECTED_TYPE error is
+ * set.
+ */
+static void
+QCBORDecode_GetUndefined(QCBORDecodeContext *pCtx);
+
+static void
+QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pCtx,
+                               int64_t             nLabel);
+
+static void
+QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pCtx,
+                                const char         *szLabel);
+
+
+/**
+ * @brief Decode the next item as a CBOR simple value.
+ *
+ * @param[in] pCtx            The decode context.
+ * @param[out] puSimpleValue  The simplle value returned.
+ *
+ * The purpose of this is to get a CBOR simple value other than a
+ * Boolean, NULL or "undefined", but this works on all simple
+ * values. See QCBOREncode_AddSimple() for more details on simple
+ * values in general.
+ *
+ * See QCBORDecode_GetBool(), QCBORDecode_GetNull(),
+ * QCBORDecode_GetUndefined() for the preferred way of getting those
+ * simple values.
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pCtx, uint8_t *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint8_t            *puSimpleValue);
+
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             uint8_t            *puSimpleValue);
+
+
+
+
+/**
+ * @brief Decode the next item as a date string.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pDateString     The decoded date.
+ *
+ * This decodes the standard CBOR date/time string tag, integer tag
+ * number of 0, or encoded CBOR that is not a tag, but borrows the
+ * date string content format.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_DATE_STRING, QCBOREncode_AddDateString() and
+ * @ref QCBOR_TYPE_DATE_STRING.
+ */
+static void
+QCBORDecode_GetDateString(QCBORDecodeContext *pCtx,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC         *pDateString);
+
+static void
+QCBORDecode_GetDateStringInMapN(QCBORDecodeContext *pCtx,
+                                int64_t             nLabel,
+                                uint8_t             uTagRequirement,
+                                UsefulBufC         *pDateString);
+
+static void
+QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pCtx,
+                                 const char         *szLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBufC         *pDateString);
+
+
+/**
+ * @brief Decode the next item as a date-only string.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pDateString     The decoded date.
+ *
+ * This decodes the CBOR date-only string tag, integer tag number of
+ * 1004, or encoded CBOR that is not a tag, but borrows the date-only
+ * string content format. An example of the format is "1985-04-12".
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_DAYS_STRING, QCBOREncode_AddDaysString() and
+ * @ref QCBOR_TYPE_DAYS_STRING.
+ */
+static void
+QCBORDecode_GetDaysString(QCBORDecodeContext *pCtx,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC         *pDateString);
+
+static void
+QCBORDecode_GetDaysStringInMapN(QCBORDecodeContext *pCtx,
+                                int64_t             nLabel,
+                                uint8_t             uTagRequirement,
+                                UsefulBufC         *pDateString);
+
+static void
+QCBORDecode_GetDaysStringInMapSZ(QCBORDecodeContext *pCtx,
+                                 const char         *szLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBufC         *pDateString);
+
+
+/**
+ * @brief Decode the next item as an epoch date.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnTime          The decoded epoch date.
+ *
+ * This decodes the standard CBOR epoch date/time tag, integer tag
+ * number of 1. This will also decode any integer or floating-point
+ * number as an epoch date (a tag 1 epoch date is just an integer or
+ * floating-point number).
+ *
+ * This will set @ref QCBOR_ERR_DATE_OVERFLOW if the input integer
+ * will not fit in an @c int64_t. Note that an @c int64_t can
+ * represent a range of over 500 billion years with one second
+ * resolution.
+ *
+ * Floating-point dates are always returned as an @c int64_t. The
+ * fractional part is discarded.
+ *
+ * If the input is a floating-point date and the QCBOR library is
+ * compiled with some or all floating-point features disabled, the
+ * following errors will be set.  If the input is half-precision and
+ * half-precision is disabled @ref QCBOR_ERR_HALF_PRECISION_DISABLED
+ * is set. This function needs hardware floating-point to convert the
+ * floating-point value to an integer so if HW floating point is
+ * disabled @ref QCBOR_ERR_HW_FLOAT_DISABLED is set. If all
+ * floating-point is disabled then @ref QCBOR_ERR_ALL_FLOAT_DISABLED
+ * is set.  A previous version of this function would return
+ * @ref QCBOR_ERR_FLOAT_DATE_DISABLED in some, but not all, cases when
+ * floating-point decoding was disabled.
+ *
+ * Floating-point dates that are plus infinity, minus infinity or NaN
+ * (not-a-number) will result in the @ref QCBOR_ERR_DATE_OVERFLOW
+ * error.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_DATE_EPOCH, QCBOREncode_AddDateEpoch() and
+ * @ref QCBOR_TYPE_DATE_EPOCH.
+*/
+void
+QCBORDecode_GetEpochDate(QCBORDecodeContext *pCtx,
+                         uint8_t             uTagRequirement,
+                         int64_t            *pnTime);
+
+void
+QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pCtx,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnTime);
+
+void
+QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pCtx,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t            *pnTime);
+
+
+/**
+ * @brief Decode the next item as an days-count epoch date.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnDays          The decoded epoch date.
+ *
+ * This decodes the CBOR epoch date tag, integer tag number of 100, or
+ * encoded CBOR that is not a tag, but borrows the content format. The
+ * date is the number of days (not number of seconds) before or after
+ * Jan 1, 1970.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_DAYS_EPOCH, QCBOREncode_AddTDaysEpoch() and
+ * @ref QCBOR_TYPE_DAYS_EPOCH.
+*/
+void
+QCBORDecode_GetEpochDays(QCBORDecodeContext *pCtx,
+                         uint8_t             uTagRequirement,
+                         int64_t            *pnDays);
+
+void
+QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pCtx,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnDays);
+
+void
+QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pCtx,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t            *pnDays);
+
+
+
+
+/**
+ * @brief Decode the next item as a big number.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pValue          The returned big number.
+ * @param[out] pbIsNegative    Is @c true if the big number is negative. This
+ *                             is only valid when @c uTagRequirement is
+ *                             @ref QCBOR_TAG_REQUIREMENT_TAG.
+ *
+ * This decodes a standard CBOR big number, integer tag number of 2 or
+ * 3, or encoded CBOR that is not a tag, but borrows the content
+ * format.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * The big number is in network byte order. The first byte in @c
+ * pValue is the most significant byte. There may be leading zeros.
+ *
+ * The negative value is computed as -1 - n, where n is the postive
+ * big number in @c pValue. There is no standard representation for
+ * big numbers, positive or negative in C, so this implementation
+ * leaves it up to the caller to apply this computation for negative
+ * big numbers.
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * Determination of the sign of the big number depends on the tag
+ * requirement of the protocol using the big number. If the protocol
+ * requires tagging, @ref QCBOR_TAG_REQUIREMENT_TAG, then the sign
+ * indication is in the protocol and @c pbIsNegative indicates the
+ * sign. If the protocol doesn't use a tag, @ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+ * then the protocol design must have some way of indicating the sign.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll(),
+ * QCBORDecode_GetUInt64ConvertAll() and
+ * QCBORDecode_GetDoubleConvertAll() which can convert big numbers.
+ *
+ * See also @ref CBOR_TAG_POS_BIGNUM, @ref CBOR_TAG_NEG_BIGNUM,
+ * QCBOREncode_AddPositiveBignum(), QCBOREncode_AddNegativeBignum(),
+ * @ref QCBOR_TYPE_POSBIGNUM and @ref QCBOR_TYPE_NEGBIGNUM.
+ */
+// Improvement: Add function that converts integers and other to big nums
+void
+QCBORDecode_GetBignum(QCBORDecodeContext *pCtx,
+                      uint8_t             uTagRequirement,
+                      UsefulBufC         *pValue,
+                      bool               *pbIsNegative);
+
+void
+QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint8_t             uTagRequirement,
+                            UsefulBufC         *pValue,
+                            bool               *pbIsNegative);
+
+void
+QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             uint8_t             uTagRequirement,
+                             UsefulBufC         *pValue,
+                             bool               *pbIsNegative);
+
+
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+/**
+ * @brief Decode the next item as a decimal fraction.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnMantissa      The mantissa.
+ * @param[out] pnExponent      The base 10 exponent.
+ *
+ * This decodes a standard CBOR decimal fraction, integer tag number
+ * of 4, or encoded CBOR that is not a tag, but borrows the content
+ * format.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * The  value of this is computed by:
+ *
+ *     mantissa * ( 10 ** exponent )
+ *
+ * In the encoded CBOR, the mantissa and exponent may be of CBOR type
+ * 0 (positive integer), type 1 (negative integer), type 2 tag 2
+ * (positive big number) or type 2 tag 3 (negative big number). This
+ * implementation will attempt to convert all of these to an @c
+ * int64_t. If the value won't fit, @ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW
+ * or @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA will be set.
+ *
+ * This implementation limits the exponent to between @c INT64_MIN and
+ * @c INT64_MAX while CBOR allows the range of @c -UINT64_MAX to
+ * @c UINT64_MAX.
+ *
+ * Various format and type issues will result in
+ * @ref QCBOR_ERR_BAD_EXP_AND_MANTISSA being set.
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll(),
+ * QCBORDecode_GetUInt64ConvertAll() and
+ * QCBORDecode_GetDoubleConvertAll() which can convert big numbers.
+ *
+ * See also @ref CBOR_TAG_DECIMAL_FRACTION,
+ * QCBOREncode_AddDecimalFraction(), @ref QCBOR_TYPE_DECIMAL_FRACTION
+ * and QCBORDecode_GetDecimalFractionBig().
+ *
+ * If QCBOR_DISABLE_TAGS is set, the only input this will decode is an
+ * array of two integers. It will set an error if the the array is
+ * preceded by by a tag number or if the mantissa is a big number.
+ */
+void
+QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pCtx,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnMantissa,
+                               int64_t            *pnExponent);
+
+void
+QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint8_t             uTagRequirement,
+                                     int64_t            *pnMantissa,
+                                     int64_t            *pnExponent);
+
+void
+QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
+                                      const char         *szLabel,
+                                      uint8_t             uTagRequirement,
+                                      int64_t            *pnMantissa,
+                                      int64_t            *pnExponent);
+
+
+/**
+ * @brief Decode the next item as a decimal fraction with a big number mantissa.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[in] MantissaBuffer   The buffer in which to put the mantissa.
+ * @param[out] pMantissa       The big num mantissa.
+ * @param[out] pbMantissaIsNegative  Is @c true if @c pMantissa is negative.
+ * @param[out] pnExponent      The base 10 exponent.
+ *
+ * This is the same as QCBORDecode_GetDecimalFraction() except the
+ * mantissa is returned as a big number.
+ *
+ * In the encoded CBOR, the mantissa may be a type 0 (positive
+ * integer), type 1 (negative integer), type 2 tag 2 (positive big
+ * number) or type 2 tag 3 (negative big number). This implementation
+ * will convert all these to a big number. The limit to this
+ * conversion is the size of @c MantissaBuffer.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll(),
+ * QCBORDecode_GetUInt64ConvertAll() and
+ * QCBORDecode_GetDoubleConvertAll() which can convert decimal
+ * fractions.
+ *
+ * See also @ref CBOR_TAG_DECIMAL_FRACTION,
+ * QCBOREncode_AddDecimalFraction(), @ref QCBOR_TYPE_DECIMAL_FRACTION
+ * and QCBORDecode_GetDecimalFraction().
+ */
+void
+QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pCtx,
+                                  uint8_t             uTagRequirement,
+                                  UsefulBuf           MantissaBuffer,
+                                  UsefulBufC         *pMantissa,
+                                  bool               *pbMantissaIsNegative,
+                                  int64_t            *pnExponent);
+
+void
+QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pCtx,
+                                        int64_t             nLabel,
+                                        uint8_t             uTagRequirement,
+                                        UsefulBuf           MantissaBuffer,
+                                        UsefulBufC         *pbMantissaIsNegative,
+                                        bool               *pbIsNegative,
+                                        int64_t            *pnExponent);
+
+void
+QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pCtx,
+                                         const char         *szLabel,
+                                         uint8_t             uTagRequirement,
+                                         UsefulBuf           MantissaBuffer,
+                                         UsefulBufC         *pMantissa,
+                                         bool               *pbMantissaIsNegative,
+                                         int64_t            *pnExponent);
+
+
+/**
+ * @brief Decode the next item as a big float.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnMantissa      The mantissa.
+ * @param[out] pnExponent      The base 2 exponent.
+ *
+ * This decodes a standard CBOR big float, integer tag number of 5, or
+ * encoded CBOR that is not a tag, but borrows the content format.
+ *
+ * This is the same as QCBORDecode_GetDecimalFraction() with the
+ * important distinction that the value is computed by:
+ *
+ *     mantissa * ( 2 ** exponent )
+ *
+ * If the mantissa is a tag that is a positive or negative big number,
+ * this will attempt to fit it into the int64_t that @c pnMantissa is
+ * and set an overflow error if it doesn't fit.
+ *
+ * See also QCBORDecode_GetInt64ConvertAll(),
+ * QCBORDecode_GetUInt64ConvertAll() and
+ * QCBORDecode_GetDoubleConvertAll() which can convert big floats.
+ *
+ * See also @ref CBOR_TAG_BIGFLOAT, QCBOREncode_AddBigFloat(), @ref
+ * QCBOR_TYPE_BIGFLOAT and QCBORDecode_GetBigFloatBig().
+ */
+void
+QCBORDecode_GetBigFloat(QCBORDecodeContext *pCtx,
+                        uint8_t             uTagRequirement,
+                        int64_t            *pnMantissa,
+                        int64_t            *pnExponent);
+
+void
+QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pCtx,
+                              int64_t             nLabel,
+                              uint8_t             uTagRequirement,
+                              int64_t            *pnMantissa,
+                              int64_t            *pnExponent);
+
+void
+QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pCtx,
+                               const char         *szLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnMantissa,
+                               int64_t            *pnExponent);
+
+
+/**
+ * @brief Decode the next item as a big float with a big number mantissa.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[in] MantissaBuffer   The buffer in which to put the mantissa.
+ * @param[out] pMantissa       The big num mantissa.
+ * @param[out] pbMantissaIsNegative  Is @c true if @c pMantissa is negative.
+ * @param[out] pnExponent      The base 2 exponent.
+ *
+ * This is the same as QCBORDecode_GetDecimalFractionBig() with the
+ * important distinction that the value is computed by:
+ *
+ *     mantissa * ( 2 ** exponent )
+ *
+ * See also QCBORDecode_GetInt64ConvertAll(),
+ * QCBORDecode_GetUInt64ConvertAll() and
+ * QCBORDecode_GetDoubleConvertAll() which can convert big floats.
+ *
+ * See also @ref CBOR_TAG_BIGFLOAT, QCBOREncode_AddBigFloat(),
+ * @ref QCBOR_TYPE_BIGFLOAT and QCBORDecode_GetBigFloat().
+ */
+void
+QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           UsefulBuf           MantissaBuffer,
+                           UsefulBufC         *pMantissa,
+                           bool               *pbMantissaIsNegative,
+                           int64_t            *pnExponent);
+
+void
+QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pCtx,
+                                 int64_t             nLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBuf           MantissaBuffer,
+                                 UsefulBufC         *pMantissa,
+                                 bool               *pbMantissaIsNegative,
+                                 int64_t            *pnExponent);
+
+void
+QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  UsefulBuf           MantissaBuffer,
+                                  UsefulBufC         *pMantissa,
+                                  bool               *pbMantissaIsNegative,
+                                  int64_t            *pnExponent);
+#endif /* #ifndef QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+
+
+/**
+ * @brief Decode the next item as a URI.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pURI            The decoded URI.
+ *
+ * This decodes a standard CBOR URI tag, integer tag number of 32, or
+ * encoded CBOR that is not a tag, that is a URI encoded in a text
+ * string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_URI, QCBOREncode_AddURI() and
+ *  @ref QCBOR_TYPE_URI.
+ */
+static void
+QCBORDecode_GetURI(QCBORDecodeContext *pCtx,
+                   uint8_t             uTagRequirement,
+                   UsefulBufC         *pURI);
+
+static void
+QCBORDecode_GetURIInMapN(QCBORDecodeContext *pCtx,
+                         int64_t             nLabel,
+                         uint8_t             uTagRequirement,
+                         UsefulBufC         *pURI);
+
+static void
+QCBORDecode_GetURIInMapSZ(QCBORDecodeContext *pCtx,
+                          const char *        szLabel,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC         *pURI);
+
+
+/**
+ * @brief Decode the next item as base64 encoded text.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pB64Text        The decoded base64 text.
+ *
+ * This decodes a standard CBOR base64 tag, integer tag number of 34,
+ * or encoded CBOR that is not a tag, that is base64 encoded bytes
+ * encoded in a text string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * Note that this does not actually remove the base64 encoding.
+ *
+ * See also @ref CBOR_TAG_B64, QCBOREncode_AddB64Text() and
+ * @ref QCBOR_TYPE_BASE64.
+ */
+static void
+QCBORDecode_GetB64(QCBORDecodeContext *pCtx,
+                   uint8_t             uTagRequirement,
+                   UsefulBufC         *pB64Text);
+
+static void
+QCBORDecode_GetB64InMapN(QCBORDecodeContext *pCtx,
+                         int64_t             nLabel,
+                         uint8_t             uTagRequirement,
+                         UsefulBufC         *pB64Text);
+
+static void
+QCBORDecode_GetB64InMapSZ(QCBORDecodeContext *pCtx,
+                          const char         *szLabel,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC         *pB64Text);
+
+/**
+ * @brief Decode the next item as base64URL encoded text.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pB64Text        The decoded base64 text.
+ *
+ * This decodes a standard CBOR base64url tag, integer tag number of
+ * 33, or encoded CBOR that is not a tag, that is base64url encoded
+ * bytes encoded in a text string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * Note that this does not actually remove the base64url encoding.
+ *
+ * See also @ref CBOR_TAG_B64URL, QCBOREncode_AddB64URLText() and
+ * @ref QCBOR_TYPE_BASE64URL.
+ */
+static void
+QCBORDecode_GetB64URL(QCBORDecodeContext *pCtx,
+                      uint8_t             uTagRequirement,
+                      UsefulBufC         *pB64Text);
+
+static void
+QCBORDecode_GetB64URLInMapN(QCBORDecodeContext *pCtx,
+                            int64_t             nLabel,
+                            uint8_t             uTagRequirement,
+                            UsefulBufC         *pB64Text);
+
+static void
+QCBORDecode_GetB64URLInMapSZ(QCBORDecodeContext *pCtx,
+                             const char         *szLabel,
+                             uint8_t             uTagRequirement,
+                             UsefulBufC         *pB64Text);
+
+/**
+ * @brief Decode the next item as a regular expression.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pRegex          The decoded regular expression.
+ *
+ * This decodes a standard CBOR regex tag, integer tag number of 35,
+ * or encoded CBOR that is not a tag, that is a PERL-compatible
+ * regular expression encoded in a text string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_REGEX, QCBOREncode_AddRegex() and
+ * @ref QCBOR_TYPE_REGEX.
+ */
+static void
+QCBORDecode_GetRegex(QCBORDecodeContext *pCtx,
+                     uint8_t             uTagRequirement,
+                     UsefulBufC         *pRegex);
+
+static void
+QCBORDecode_GetRegexInMapN(QCBORDecodeContext *pCtx,
+                           int64_t             nLabel,
+                           uint8_t             uTagRequirement,
+                           UsefulBufC         *pRegex);
+
+static void
+QCBORDecode_GetRegexInMapSZ(QCBORDecodeContext *pCtx,
+                            const char *        szLabel,
+                            uint8_t             uTagRequirement,
+                             UsefulBufC         *pRegex);
+
+
+/**
+ * @brief Decode the next item as a MIME message.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pMessage        The decoded regular expression.
+ * @param[out] pbIsTag257      @c true if tag was 257. May be @c NULL.
+ *
+ * This decodes the standard CBOR MIME and binary MIME tags, integer
+ * tag numbers of 36 or 257, or encoded CBOR that is not a tag, that
+ * is a MIME message encoded in a text or binary string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * The MIME message itself is not parsed.
+ *
+ * This decodes both tag 36 and 257. If it is tag 257, pbIsTag257 is
+ * @c true. The difference between the two is that tag 36 is utf8 and
+ * tag 257 is a byte string that can carry binary MIME. QCBOR
+ * processes them exactly the same. Possibly the difference can be
+ * ignored.  NULL can be passed to have no value returned.
+ *
+ * See also @ref CBOR_TAG_MIME, @ref CBOR_TAG_BINARY_MIME,
+ * QCBOREncode_AddTMIMEData(), @ref QCBOR_TYPE_MIME and
+ * @ref QCBOR_TYPE_BINARY_MIME.
+ *
+ * This does no translation of line endings. See QCBOREncode_AddText()
+ * for a discussion of line endings in CBOR.
+ */
+static void
+QCBORDecode_GetMIMEMessage(QCBORDecodeContext *pCtx,
+                           uint8_t             uTagRequirement,
+                           UsefulBufC         *pMessage,
+                           bool               *pbIsTag257);
+
+static void
+QCBORDecode_GetMIMEMessageInMapN(QCBORDecodeContext *pCtx,
+                                 int64_t              nLabel,
+                                 uint8_t              uTagRequirement,
+                                 UsefulBufC          *pMessage,
+                                 bool                *pbIsTag257);
+
+
+static void
+QCBORDecode_GetMIMEMessageInMapSZ(QCBORDecodeContext *pCtx,
+                                  const char         *szLabel,
+                                  uint8_t             uTagRequirement,
+                                  UsefulBufC         *pMessage,
+                                  bool               *pbIsTag257);
+
+/**
+ * @brief Decode the next item as a UUID.
+ *
+ * @param[in] pCtx             The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pUUID           The decoded UUID
+ *
+ * This decodes a standard CBOR UUID tag, integer tag number of 37, or
+ * encoded CBOR that is not a tag, that is a UUID encoded in a byte
+ * string.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See @ref Tag-Usage for discussion on tag requirements.
+ *
+ * See also @ref CBOR_TAG_BIN_UUID, QCBOREncode_AddBinaryUUID() and
+ * @ref QCBOR_TYPE_UUID.
+ */
+static void
+QCBORDecode_GetBinaryUUID(QCBORDecodeContext *pCtx,
+                          uint8_t             uTagRequirement,
+                          UsefulBufC         *pUUID);
+
+static void
+QCBORDecode_GetBinaryUUIDInMapN(QCBORDecodeContext *pCtx,
+                                int64_t             nLabel,
+                                uint8_t             uTagRequirement,
+                                UsefulBufC         *pUUID);
+
+static void
+QCBORDecode_GetBinaryUUIDInMapSZ(QCBORDecodeContext *pCtx,
+                                 const char         *szLabel,
+                                 uint8_t             uTagRequirement,
+                                 UsefulBufC         *pUUID);
+
+
+
+/**
+ * @brief Decode some byte-string wrapped CBOR.
+ *
+ * @param[in] pCtx    The decode context.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pBstr  Pointer and length of byte-string wrapped CBOR (optional).
+ *
+ * This is for use on some CBOR that has been wrapped in a byte
+ * string. There are several ways that this can occur.
+ *
+ * First is tag 24 and tag 63. Tag 24 wraps a single CBOR data item
+ * and 63 a CBOR sequence.  This implementation doesn't distinguish
+ * between the two (it would be more code and doesn't seem important).
+ *
+ * The @ref Tag-Usage discussion on the tag requirement applies here
+ * just the same as any other tag.
+ *
+ * In other cases, CBOR is wrapped in a byte string, but it is
+ * identified as CBOR by other means. The contents of a COSE payload
+ * are one example of that. They can be identified by the COSE content
+ * type, or they can be identified as CBOR indirectly by the protocol
+ * that uses COSE. for example, if a blob of CBOR is identified as a
+ * CWT, then the COSE payload is CBOR.  To enter into CBOR of this
+ * type use the @ref QCBOR_TAG_REQUIREMENT_NOT_A_TAG as the \c
+ * uTagRequirement argument.
+ *
+ * Note that byte string wrapped CBOR can also be decoded by getting
+ * the byte string with QCBORDecode_GetItem() or
+ * QCBORDecode_GetByteString() and feeding it into another instance of
+ * QCBORDecode. Doing it with this function has the advantage of using
+ * less memory as another instance of QCBORDecode is not necessary.
+ *
+ * When the wrapped CBOR is entered with this function, the pre-order
+ * traversal and such are bounded to the wrapped
+ * CBOR. QCBORDecode_ExitBstrWrapped() must be called to resume
+ * processing CBOR outside the wrapped CBOR.
+ *
+ * This does not work on indefinite-length strings. The
+ * error @ref QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING will be set.
+ *
+ * If @c pBstr is not @c NULL the pointer and length of the wrapped
+ * CBOR will be returned. This is usually not needed, but sometimes
+ * useful, particularly in the case of verifying signed data like the
+ * COSE payload. This is usually the pointer and length of the data is
+ * that is hashed or MACed.
+ *
+ * Please see @ref Decode-Errors-Overview "Decode Errors Overview".
+ *
+ * See also QCBORDecode_ExitBstrWrapped(), QCBORDecode_EnterMap() and
+ * QCBORDecode_EnterArray().
+ */
+void
+QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pCtx,
+                             uint8_t             uTagRequirement,
+                             UsefulBufC         *pBstr);
+
+void
+QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pCtx,
+                                     int64_t             nLabel,
+                                     uint8_t             uTagRequirement,
+                                     UsefulBufC         *pBstr);
+
+void
+QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pCtx,
+                                      const char         *szLabel,
+                                      uint8_t             uTagRequirement,
+                                      UsefulBufC         *pBstr);
+
+
+/**
+ * @brief Exit some bstr-wrapped CBOR  has been enetered.
+ *
+ * @param[in] pCtx  The decode context.
+ *
+ * Bstr-wrapped CBOR must have been entered for this to succeed.
+ *
+ * The items in the wrapped CBOR that was entered do not have to have
+ * been consumed for this to succeed.
+ *
+ * The this sets the traversal cursor to the item after the
+ * byte string that was exited.
+ */
+void
+QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pCtx);
+
+
+
+
+/* ===========================================================================
+   BEGINNING OF PRIVATE INLINE IMPLEMENTATION
+   ========================================================================== */
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pCtx,
+                                     uint32_t            uConvertTypes,
+                                     uint64_t           *puValue,
+                                     QCBORItem          *pItem);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pCtx,
+                                           int64_t             nLabel,
+                                           uint32_t            uConvertTypes,
+                                           uint64_t           *puValue,
+                                           QCBORItem          *pItem);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                            const char         *szLabel,
+                                            uint32_t            uConvertTypes,
+                                            uint64_t           *puValue,
+                                            QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pCtx,
+                                           uint8_t             uType,
+                                           QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pCtx,
+                                          uint8_t             uType);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pCtx,
+                                    uint32_t            uConvertTypes,
+                                    int64_t            *pnValue,
+                                    QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pCtx,
+                                          int64_t             nLabel,
+                                          uint32_t            uConvertTypes,
+                                          int64_t            *pnValue,
+                                          QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                           const char         *szLabel,
+                                           uint32_t            uConvertTypes,
+                                           int64_t            *pnValue,
+                                           QCBORItem          *pItem);
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pCtx,
+                                     uint32_t            uConvertTypes,
+                                     double             *pValue,
+                                     QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pCtx,
+                                           int64_t             nLabel,
+                                           uint32_t            uConvertTypes,
+                                           double             *pdValue,
+                                           QCBORItem          *pItem);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pCtx,
+                                            const char         *szLabel,
+                                            uint32_t            uConvertTypes,
+                                            double             *pdValue,
+                                            QCBORItem          *pItem);
+#endif /* !USEFULBUF_DISABLE_ALL_FLOAT */
+
+#define QCBOR_TAGSPEC_NUM_TYPES 4
+/* Semi-private data structure (which might change).
+ *
+ * See QCBOR_Private_CheckTagRequirement() which uses this to check the
+ * type of an item to be decoded as a tag or tag content.
+ *
+ * Improvement: Carefully understand what compilers do with this,
+ * particularly initialization and see if it can be optimized so there
+ * is less code and maybe so it can be smaller.
+ */
+typedef struct {
+   /* One of QCBOR_TAGSPEC_MATCH_xxx */
+   uint8_t uTagRequirement;
+   /* The tagged type translated into QCBOR_TYPE_XXX. Used to match
+    * explicit tagging */
+   uint8_t uTaggedTypes[QCBOR_TAGSPEC_NUM_TYPES];
+   /* The types of the content, which are used to match implicit
+    * tagging */
+   uint8_t uAllowedContentTypes[QCBOR_TAGSPEC_NUM_TYPES];
+} QCBOR_Private_TagSpec;
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetTaggedString(QCBORDecodeContext   *pCtx,
+                                    QCBOR_Private_TagSpec TagSpec,
+                                    UsefulBufC           *pBstr);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext   *pCtx,
+                                          int64_t               nLabel,
+                                          QCBOR_Private_TagSpec TagSpec,
+                                          UsefulBufC           *pString);
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext   *pCtx,
+                                           const char           *szLabel,
+                                           QCBOR_Private_TagSpec TagSpec,
+                                           UsefulBufC           *pString);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+QCBORError
+QCBORDecode_Private_GetMIME(uint8_t           uTagRequirement,
+                            const QCBORItem  *pItem,
+                            UsefulBufC       *pMessage,
+                            bool             *pbIsTag257);
+
+
+
+
+
+static inline void
+QCBORDecode_GetUInt64Convert(QCBORDecodeContext *pMe,
+                             const uint32_t     uConvertTypes,
+                             uint64_t           *puValue)
+{
+    QCBORItem Item;
+    QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
+}
+
+static inline void
+QCBORDecode_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                   const int64_t       nLabel,
+                                   const uint32_t      uConvertTypes,
+                                   uint64_t           *puValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              puValue,
+                                              &Item);
+}
+
+static inline void
+QCBORDecode_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                    const char         *szLabel,
+                                    const uint32_t     uConvertTypes,
+                                    uint64_t           *puValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               puValue,
+                                               &Item);
+}
+
+static inline void
+QCBORDecode_GetUInt64(QCBORDecodeContext *pMe, uint64_t *puValue)
+{
+    QCBORDecode_GetUInt64Convert(pMe, QCBOR_CONVERT_TYPE_XINT64, puValue);
+}
+
+static inline void
+QCBORDecode_GetUInt64InMapN(QCBORDecodeContext *pMe,
+                            const int64_t       nLabel,
+                            uint64_t           *puValue)
+{
+   QCBORDecode_GetUInt64ConvertInMapN(pMe,
+                                      nLabel,
+                                      QCBOR_CONVERT_TYPE_XINT64,
+                                      puValue);
+}
+
+static inline void
+QCBORDecode_GetUInt64InMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             uint64_t           *puValue)
+{
+   QCBORDecode_GetUInt64ConvertInMapSZ(pMe,
+                                       szLabel,
+                                       QCBOR_CONVERT_TYPE_XINT64,
+                                       puValue);
+}
+
+
+static inline void
+QCBORDecode_EnterMap(QCBORDecodeContext *pMe, QCBORItem *pItem) {
+   QCBORDecode_Private_EnterBoundedMapOrArray(pMe, QCBOR_TYPE_MAP, pItem);
+}
+
+static inline void
+QCBORDecode_EnterArray(QCBORDecodeContext *pMe, QCBORItem *pItem) {
+   QCBORDecode_Private_EnterBoundedMapOrArray(pMe, QCBOR_TYPE_ARRAY, pItem);
+}
+
+
+static inline void
+QCBORDecode_ExitArray(QCBORDecodeContext *pMe)
+{
+   QCBORDecode_Private_ExitBoundedMapOrArray(pMe, QCBOR_TYPE_ARRAY);
+}
+
+static inline void
+QCBORDecode_ExitMap(QCBORDecodeContext *pMe)
+{
+   QCBORDecode_Private_ExitBoundedMapOrArray(pMe, QCBOR_TYPE_MAP);
+}
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pCtx,
+                                  uint8_t             uType,
+                                  QCBORItem          *pItem,
+                                  UsefulBufC         *pEncodedCBOR);
+
+
+/* Semi-private funcion used by public inline functions. See qcbor_decode.c */
+void
+QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pCtx,
+                                           QCBORItem          *pTarget,
+                                           QCBORItem          *pItem,
+                                           UsefulBufC         *pEncodedCBOR);
+
+
+static inline void
+QCBORDecode_GetArray(QCBORDecodeContext *pMe,
+                     QCBORItem          *pItem,
+                     UsefulBufC         *pEncodedCBOR)
+{
+   QCBORDecode_Private_GetArrayOrMap(pMe, QCBOR_TYPE_ARRAY, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetArrayFromMapN(QCBORDecodeContext *pMe,
+                             int64_t             nLabel,
+                             QCBORItem          *pItem,
+                             UsefulBufC         *pEncodedCBOR)
+{
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
+   OneItemSeach[0].label.int64 = nLabel;
+   OneItemSeach[0].uDataType   = QCBOR_TYPE_ARRAY;
+   OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetArrayFromMapSZ(QCBORDecodeContext *pMe,
+                              const char         *szLabel,
+                              QCBORItem          *pItem,
+                              UsefulBufC         *pEncodedCBOR)
+{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
+   OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+   OneItemSeach[0].uDataType    = QCBOR_TYPE_ARRAY;
+   OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+   (void)szLabel;
+   (void)pItem;
+   (void)pEncodedCBOR;
+   pMe->uLastError =  QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+}
+
+static inline void
+QCBORDecode_GetMap(QCBORDecodeContext *pMe,
+                   QCBORItem          *pItem,
+                   UsefulBufC         *pEncodedCBOR)
+{
+   QCBORDecode_Private_GetArrayOrMap(pMe, QCBOR_TYPE_MAP, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetMapFromMapN(QCBORDecodeContext *pMe,
+                           int64_t             nLabel,
+                           QCBORItem          *pItem,
+                           UsefulBufC         *pEncodedCBOR)
+{
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
+   OneItemSeach[0].label.int64 = nLabel;
+   OneItemSeach[0].uDataType   = QCBOR_TYPE_MAP;
+   OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+}
+
+
+static inline void
+QCBORDecode_GetMapFromMapSZ(QCBORDecodeContext *pMe,
+                            const char         *szLabel,
+                            QCBORItem          *pItem,
+                            UsefulBufC         *pEncodedCBOR)
+{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
+   OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+   OneItemSeach[0].uDataType    = QCBOR_TYPE_MAP;
+   OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndGetArrayOrMap(pMe, OneItemSeach, pItem, pEncodedCBOR);
+#else
+   (void)szLabel;
+   (void)pItem;
+   (void)pEncodedCBOR;
+   pMe->uLastError =  QCBOR_ERR_MAP_LABEL_TYPE;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+}
+
+
+
+static inline void
+QCBORDecode_GetInt64Convert(QCBORDecodeContext *pMe,
+                            const uint32_t      uConvertTypes,
+                            int64_t            *pnValue)
+{
+    QCBORItem Item;
+    QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
+}
+
+static inline void
+QCBORDecode_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                  const int64_t       nLabel,
+                                  const uint32_t      uConvertTypes,
+                                  int64_t            *pnValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
+                                             nLabel,
+                                             uConvertTypes,
+                                             pnValue,
+                                             &Item);
+}
+
+static inline void
+QCBORDecode_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                   const char         *szLabel,
+                                   const uint32_t     uConvertTypes,
+                                   int64_t            *pnValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
+                                              szLabel,
+                                              uConvertTypes,
+                                              pnValue,
+                                              &Item);
+}
+
+static inline void
+QCBORDecode_GetInt64(QCBORDecodeContext *pMe, int64_t *pnValue)
+{
+    QCBORDecode_GetInt64Convert(pMe, QCBOR_CONVERT_TYPE_XINT64, pnValue);
+}
+
+static inline void
+QCBORDecode_GetInt64InMapN(QCBORDecodeContext *pMe,
+                           const int64_t       nLabel,
+                           int64_t            *pnValue)
+{
+   QCBORDecode_GetInt64ConvertInMapN(pMe,
+                                     nLabel,
+                                     QCBOR_CONVERT_TYPE_XINT64,
+                                     pnValue);
+}
+
+static inline void
+QCBORDecode_GetInt64InMapSZ(QCBORDecodeContext *pMe,
+                            const char         *szLabel,
+                            int64_t            *pnValue)
+{
+   QCBORDecode_GetInt64ConvertInMapSZ(pMe,
+                                      szLabel,
+                                      QCBOR_CONVERT_TYPE_XINT64,
+                                      pnValue);
+}
+
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+static inline void
+QCBORDecode_GetDoubleConvert(QCBORDecodeContext *pMe,
+                             const uint32_t      uConvertTypes,
+                             double             *pdValue)
+{
+   QCBORItem Item;
+    QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
+}
+
+static inline void
+QCBORDecode_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
+                                   const int64_t       nLabel,
+                                   uint32_t            uConvertTypes,
+                                   double             *pdValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              pdValue,
+                                              &Item);
+}
+
+static inline void
+QCBORDecode_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
+                                    const char         *szLabel,
+                                    const uint32_t      uConvertTypes,
+                                    double             *pdValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               pdValue,
+                                               &Item);
+}
+
+static inline void
+QCBORDecode_GetDouble(QCBORDecodeContext *pMe, double *pValue)
+{
+    QCBORDecode_GetDoubleConvert(pMe, QCBOR_CONVERT_TYPE_FLOAT, pValue);
+}
+
+static inline void
+QCBORDecode_GetDoubleInMapN(QCBORDecodeContext *pMe,
+                            const int64_t       nLabel,
+                            double             *pdValue)
+{
+   QCBORDecode_GetDoubleConvertInMapN(pMe,
+                                      nLabel,
+                                      QCBOR_CONVERT_TYPE_FLOAT,
+                                      pdValue);
+}
+
+static inline void
+QCBORDecode_GetDoubleInMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             double             *pdValue)
+{
+   QCBORDecode_GetDoubleConvertInMapSZ(pMe,
+                                       szLabel,
+                                       QCBOR_CONVERT_TYPE_FLOAT,
+                                       pdValue);
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+
+static inline void
+QCBORDecode_GetByteString(QCBORDecodeContext *pMe,  UsefulBufC *pValue)
+{
+   // Complier should make this just a 64-bit integer parameter
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pValue);
+}
+
+static inline void
+QCBORDecode_GetByteStringInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                UsefulBufC         *pBstr)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pBstr);
+}
+
+static inline void
+QCBORDecode_GetByteStringInMapSZ(QCBORDecodeContext *pMe,
+                                 const char         *szLabel,
+                                 UsefulBufC         *pBstr)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pBstr);
+}
+
+
+static inline void
+QCBORDecode_GetTextString(QCBORDecodeContext *pMe,  UsefulBufC *pValue)
+{
+   // Complier should make this just 64-bit integer parameter
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pValue);
+}
+
+static inline void
+QCBORDecode_GetTextStringInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                UsefulBufC         *pText)
+{
+   // This TagSpec only matches text strings; it also should optimize down
+   // to passing a 64-bit integer
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText);
+}
+
+static inline void
+QCBORDecode_GetTextStringInMapSZ(QCBORDecodeContext *pMe,
+                                 const               char *szLabel,
+                                 UsefulBufC         *pText)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         QCBOR_TAG_REQUIREMENT_NOT_A_TAG,
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText);
+}
+
+static inline void
+QCBORDecode_GetNull(QCBORDecodeContext *pMe)
+{
+   QCBORItem item;
+
+   QCBORDecode_VGetNext(pMe, &item);
+   if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_NULL) {
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+static inline void
+QCBORDecode_GetNullInMapN(QCBORDecodeContext *pMe,
+                          const int64_t       nLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_NULL, &Item);
+}
+
+static inline void
+QCBORDecode_GetNullInMapSZ(QCBORDecodeContext *pMe,
+                           const char         *szLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_NULL, &Item);
+}
+
+static inline void
+QCBORDecode_GetUndefined(QCBORDecodeContext *pMe)
+{
+   QCBORItem item;
+
+   QCBORDecode_VGetNext(pMe, &item);
+   if(pMe->uLastError == QCBOR_SUCCESS && item.uDataType != QCBOR_TYPE_UNDEF) {
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+static inline void
+QCBORDecode_GetUndefinedInMapN(QCBORDecodeContext *pMe,
+                               const int64_t       nLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_UNDEF, &Item);
+}
+
+static inline void
+QCBORDecode_GetUndefinedInMapSZ(QCBORDecodeContext *pMe,
+                                const char         *szLabel)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_UNDEF, &Item);
+}
+
+
+
+static inline void
+QCBORDecode_GetDateString(QCBORDecodeContext *pMe,
+                          const uint8_t       uTagRequirement,
+                          UsefulBufC         *pValue)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pValue);
+}
+
+static inline void
+QCBORDecode_GetDateStringInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTagRequirement,
+                                UsefulBufC         *pText)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText);
+}
+
+static inline void
+QCBORDecode_GetDateStringInMapSZ(QCBORDecodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTagRequirement,
+                                 UsefulBufC         *pText)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DATE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText);
+}
+
+static inline void
+QCBORDecode_GetDaysString(QCBORDecodeContext *pMe,
+                          const uint8_t       uTagRequirement,
+                          UsefulBufC         *pValue)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pValue);
+}
+
+static inline void
+QCBORDecode_GetDaysStringInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTagRequirement,
+                                UsefulBufC         *pText)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pText);
+}
+
+static inline void
+QCBORDecode_GetDaysStringInMapSZ(QCBORDecodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTagRequirement,
+                                 UsefulBufC         *pText)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_DAYS_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pText);
+}
+
+
+
+static inline void
+QCBORDecode_GetURI(QCBORDecodeContext *pMe,
+                   const uint8_t       uTagRequirement,
+                   UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pUUID);
+}
+
+static inline void
+QCBORDecode_GetURIInMapN(QCBORDecodeContext *pMe,
+                         const int64_t       nLabel,
+                         const uint8_t       uTagRequirement,
+                         UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pUUID);
+}
+
+static inline void
+QCBORDecode_GetURIInMapSZ(QCBORDecodeContext *pMe,
+                          const char         *szLabel,
+                          const uint8_t       uTagRequirement,
+                          UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_URI, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pUUID);
+}
+
+
+static inline void
+QCBORDecode_GetB64(QCBORDecodeContext *pMe,
+                   const uint8_t       uTagRequirement,
+                   UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pB64Text);
+}
+
+static inline void
+QCBORDecode_GetB64InMapN(QCBORDecodeContext *pMe,
+                         const int64_t       nLabel,
+                         const uint8_t       uTagRequirement,
+                         UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pB64Text);
+}
+
+static inline void
+QCBORDecode_GetB64InMapSZ(QCBORDecodeContext *pMe,
+                          const char         *szLabel,
+                          const uint8_t       uTagRequirement,
+                          UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pB64Text);
+}
+
+
+static inline void
+QCBORDecode_GetB64URL(QCBORDecodeContext *pMe,
+                      const uint8_t       uTagRequirement,
+                      UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pB64Text);
+}
+
+static inline void
+QCBORDecode_GetB64URLInMapN(QCBORDecodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uTagRequirement,
+                            UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pB64Text);
+}
+
+static inline void
+QCBORDecode_GetB64URLInMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             const uint8_t       uTagRequirement,
+                             UsefulBufC         *pB64Text)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BASE64URL, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pB64Text);
+}
+
+
+static inline void
+QCBORDecode_GetRegex(QCBORDecodeContext *pMe,
+                     const uint8_t      uTagRequirement,
+                     UsefulBufC         *pRegex)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pRegex);
+}
+
+static inline void
+QCBORDecode_GetRegexInMapN(QCBORDecodeContext *pMe,
+                           const int64_t       nLabel,
+                           const uint8_t       uTagRequirement,
+                           UsefulBufC         *pRegex)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pRegex);
+}
+
+static inline void
+QCBORDecode_GetRegexInMapSZ(QCBORDecodeContext *pMe,
+                            const char *        szLabel,
+                            const uint8_t       uTagRequirement,
+                            UsefulBufC         *pRegex)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_REGEX, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pRegex);
+}
+
+
+static inline void
+QCBORDecode_GetMIMEMessage(QCBORDecodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           UsefulBufC         *pMessage,
+                           bool               *pbIsTag257)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state, do nothing */
+      return;
+   }
+
+   QCBORItem  Item;
+   QCBORError uError = QCBORDecode_GetNext(pMe, &Item);
+   if(uError != QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)uError;
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_GetMIME(uTagRequirement,
+                                                          &Item,
+                                                          pMessage,
+                                                          pbIsTag257);
+}
+
+static inline void
+QCBORDecode_GetMIMEMessageInMapN(QCBORDecodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 UsefulBufC         *pMessage,
+                                 bool               *pbIsTag257)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)QCBORDecode_Private_GetMIME(uTagRequirement,
+                                                             &Item,
+                                                             pMessage,
+                                                             pbIsTag257);
+   }
+}
+
+static inline void
+QCBORDecode_GetMIMEMessageInMapSZ(QCBORDecodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  UsefulBufC         *pMessage,
+                                  bool               *pbIsTag257)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)QCBORDecode_Private_GetMIME(uTagRequirement,
+                                                             &Item,
+                                                             pMessage,
+                                                             pbIsTag257);
+   }
+}
+
+
+static inline void
+QCBORDecode_GetBinaryUUID(QCBORDecodeContext *pMe,
+                          const uint8_t       uTagRequirement,
+                          UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedString(pMe, TagSpec, pUUID);
+}
+
+static inline void
+QCBORDecode_GetBinaryUUIDInMapN(QCBORDecodeContext *pMe,
+                                const int64_t       nLabel,
+                                const uint8_t       uTagRequirement,
+                                UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapN(pMe, nLabel, TagSpec, pUUID);
+}
+
+static inline void
+QCBORDecode_GetBinaryUUIDInMapSZ(QCBORDecodeContext *pMe,
+                                 const char         *szLabel,
+                                 const uint8_t       uTagRequirement,
+                                 UsefulBufC         *pUUID)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_UUID, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORDecode_Private_GetTaggedStringInMapSZ(pMe, szLabel, TagSpec, pUUID);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* qcbor_spiffy_decode_h */
diff --git a/core/lib/qcbor/src/UsefulBuf.c b/core/lib/qcbor/src/UsefulBuf.c
new file mode 100644
index 0000000000000000000000000000000000000000..1b5fd508ae38d8f0472a497592be2a5fc9519a2d
--- /dev/null
+++ b/core/lib/qcbor/src/UsefulBuf.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * Copyright (c) 2016-2018, The Linux Foundation.
+ * Copyright (c) 2018-2024, Laurence Lundblade.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors, nor the name "Laurence Lundblade" may be used to
+ *       endorse or promote products derived from this software without
+ *       specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ========================================================================= */
+
+
+
+/*=============================================================================
+ FILE:  UsefulBuf.c
+
+ DESCRIPTION:  General purpose input and output buffers
+
+ EDIT HISTORY FOR FILE:
+
+ This section contains comments describing changes made to the module.
+ Notice that changes are listed in reverse chronological order.
+
+ when        who          what, where, why
+ --------    ----         ---------------------------------------------------
+ 21/05/2024  llundblade   Comment formatting and some code tidiness.
+ 19/12/2022  llundblade   Don't pass NULL to memmove when adding empty data.
+ 4/11/2022   llundblade   Add GetOutPlace and Advance to UsefulOutBuf
+ 3/6/2021    mcr/llundblade  Fix warnings related to --Wcast-qual
+ 01/28/2020  llundblade   Refine integer signedness to quiet static analysis.
+ 01/08/2020  llundblade   Documentation corrections & improved code formatting.
+ 11/08/2019  llundblade   Re check pointer math and update comments
+ 3/6/2019    llundblade   Add UsefulBuf_IsValue()
+ 09/07/17    llundbla     Fix critical bug in UsefulBuf_Find() -- a read off
+                          the end of memory when the bytes to find is longer
+                          than the bytes to search.
+ 06/27/17    llundbla     Fix UsefulBuf_Compare() bug. Only affected comparison
+                          for < or > for unequal length buffers.  Added
+                          UsefulBuf_Set() function.
+ 05/30/17    llundbla     Functions for NULL UsefulBufs and const / unconst
+ 11/13/16    llundbla     Initial Version.
+
+ ============================================================================*/
+
+#include "UsefulBuf.h"
+
+/* used to catch use of uninitialized or corrupted UsefulOutBuf */
+#define USEFUL_OUT_BUF_MAGIC  (0x0B0F)
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+UsefulBufC UsefulBuf_CopyOffset(UsefulBuf Dest, size_t uOffset, const UsefulBufC Src)
+{
+   /* Do this with subtraction so it doesn't give an erroneous
+    * result if uOffset + Src.len overflows. Right side is equivalent to
+    * uOffset + Src.len > Dest.len
+    */
+   if(uOffset > Dest.len || Src.len > Dest.len - uOffset) {
+      return NULLUsefulBufC;
+   }
+
+   memcpy((uint8_t *)Dest.ptr + uOffset, Src.ptr, Src.len);
+
+   return (UsefulBufC){Dest.ptr, Src.len + uOffset};
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+int UsefulBuf_Compare(const UsefulBufC UB1, const UsefulBufC UB2)
+{
+   /* Use comparisons rather than subtracting lengths to
+    * return an int instead of a size_t
+    */
+   if(UB1.len < UB2.len) {
+      return -1;
+   } else if (UB1.len > UB2.len) {
+      return 1;
+   } /* else UB1.len == UB2.len */
+
+   return memcmp(UB1.ptr, UB2.ptr, UB1.len);
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+size_t UsefulBuf_IsValue(const UsefulBufC UB, uint8_t uValue)
+{
+   if(UsefulBuf_IsNULLOrEmptyC(UB)) {
+      /* Not a match */
+      return 0;
+   }
+
+   const uint8_t * const pEnd = (const uint8_t *)UB.ptr + UB.len;
+   for(const uint8_t *p = UB.ptr; p < pEnd; p++) {
+      if(*p != uValue) {
+         /* Byte didn't match */
+         /* Cast from signed to unsigned. Safe because the loop increments.*/
+         return (size_t)(p - (const uint8_t *)UB.ptr);
+      }
+   }
+
+   /* Success. All bytes matched */
+   return SIZE_MAX;
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+size_t UsefulBuf_FindBytes(UsefulBufC BytesToSearch, UsefulBufC BytesToFind)
+{
+   if(BytesToSearch.len < BytesToFind.len) {
+      return SIZE_MAX;
+   }
+
+   for(size_t uPos = 0; uPos <= BytesToSearch.len - BytesToFind.len; uPos++) {
+      UsefulBufC SearchNext;
+
+      SearchNext.ptr = ((const uint8_t *)BytesToSearch.ptr) + uPos;
+      SearchNext.len = BytesToFind.len;
+      if(!UsefulBuf_Compare(SearchNext, BytesToFind)) {
+         return uPos;
+      }
+   }
+
+   return SIZE_MAX;
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+void UsefulOutBuf_Init(UsefulOutBuf *pMe, UsefulBuf Storage)
+{
+    pMe->magic  = USEFUL_OUT_BUF_MAGIC;
+    UsefulOutBuf_Reset(pMe);
+    pMe->UB     = Storage;
+
+#if 0
+   /* This check is off by default.
+    *
+    * The following check fails on ThreadX
+    *
+    * Sanity check on the pointer and size to be sure we are not
+    * passed a buffer that goes off the end of the address space.
+    * Given this test, we know that all unsigned lengths less than
+    * me->size are valid and won't wrap in any pointer additions
+    * based off of pStorage in the rest of this code.
+    */
+    const uintptr_t ptrM = UINTPTR_MAX - Storage.len;
+    if(Storage.ptr && (uintptr_t)Storage.ptr > ptrM) /* Check #0 */
+        me->err = 1;
+#endif
+}
+
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * The core of UsefulOutBuf -- put some bytes in the buffer without writing off
+ *                             the end of it.
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ *
+ * This function inserts the source buffer, NewData, into the destination
+ * buffer, me->UB.ptr.
+ *
+ * Destination is represented as:
+ *   me->UB.ptr -- start of the buffer
+ *   me->UB.len -- size of the buffer UB.ptr
+ *   me->data_len -- length of value data in UB
+ *
+ * Source is data:
+ *   NewData.ptr -- start of source buffer
+ *   NewData.len -- length of source buffer
+ *
+ * Insertion point:
+ *   uInsertionPos.
+ *
+ * Steps:
+ *
+ * 0. Corruption checks on UsefulOutBuf
+ *
+ * 1. Figure out if the new data will fit or not
+ *
+ * 2. Is insertion position in the range of valid data?
+ *
+ * 3. If insertion point is not at the end, slide data to the right of the
+ *    insertion point to the right
+ *
+ * 4. Put the new data in at the insertion position.
+ *
+ */
+void UsefulOutBuf_InsertUsefulBuf(UsefulOutBuf *pMe, UsefulBufC NewData, size_t uInsertionPos)
+{
+   if(pMe->err) {
+      /* Already in error state. */
+      return;
+   }
+
+   /* 0. Sanity check the UsefulOutBuf structure
+    * A "counter measure". If magic number is not the right number it
+    * probably means pMe was not initialized or it was corrupted. Attackers
+    * can defeat this, but it is a hurdle and does good with very
+    * little code.
+    */
+   if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
+      pMe->err = 1;
+      return;  /* Magic number is wrong due to uninitalization or corrption */
+   }
+
+   /* Make sure valid data is less than buffer size. This would only occur
+    * if there was corruption of me, but it is also part of the checks to
+    * be sure there is no pointer arithmatic under/overflow.
+    */
+   if(pMe->data_len > pMe->UB.len) {  /* Check #1 */
+      pMe->err = 1;
+      /* Offset of valid data is off the end of the UsefulOutBuf due to
+       * uninitialization or corruption
+       */
+      return;
+   }
+
+   /* 1. Will it fit?
+    * WillItFit() is the same as: NewData.len <= (me->UB.len - me->data_len)
+    * Check #1 makes sure subtraction in RoomLeft will not wrap around
+    */
+   if(! UsefulOutBuf_WillItFit(pMe, NewData.len)) { /* Check #2 */
+      /* The new data will not fit into the the buffer. */
+      pMe->err = 1;
+      return;
+   }
+
+   /* 2. Check the Insertion Position
+    * This, with Check #1, also confirms that uInsertionPos <= me->data_len and
+    * that uInsertionPos + pMe->UB.ptr will not wrap around the end of the
+    * address space.
+    */
+   if(uInsertionPos > pMe->data_len) { /* Check #3 */
+      /* Off the end of the valid data in the buffer. */
+      pMe->err = 1;
+      return;
+   }
+
+   /* 3. Slide existing data to the right */
+   if (!UsefulOutBuf_IsBufferNULL(pMe)) {
+      uint8_t *pSourceOfMove      = ((uint8_t *)pMe->UB.ptr) + uInsertionPos; /* PtrMath #1 */
+      size_t   uNumBytesToMove    = pMe->data_len - uInsertionPos; /* PtrMath #2 */
+      uint8_t *pDestinationOfMove = pSourceOfMove + NewData.len; /* PtrMath #3*/
+
+      /* To know memmove won't go off end of destination, see PtrMath #4.
+       * Use memove because it handles overlapping buffers
+       */
+      memmove(pDestinationOfMove, pSourceOfMove, uNumBytesToMove);
+
+      /* 4. Put the new data in */
+      uint8_t *pInsertionPoint = pSourceOfMove;
+      /* To know memmove won't go off end of destination, see PtrMath #5 */
+      if(NewData.ptr != NULL) {
+         memmove(pInsertionPoint, NewData.ptr, NewData.len);
+      }
+   }
+
+   pMe->data_len += NewData.len;
+}
+
+
+/*
+ * Rationale that describes why the above pointer math is safe
+ *
+ * PtrMath #1 will never wrap around over because
+ *   Check #0 in UsefulOutBuf_Init that me->UB.ptr + me->UB.len doesn't wrap
+ *   Check #1 makes sure me->data_len is less than me->UB.len
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *
+ * PtrMath #2 will never wrap around under because
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *
+ * PtrMath #3 will never wrap around over because
+ *   PtrMath #1 is checked resulting in pSourceOfMove being between me->UB.ptr and me->UB.ptr + me->data_len
+ *   Check #2 that NewData.len will fit in the unused space left in me->UB
+ *
+ * PtrMath #4 will never wrap under because
+ *   Calculation for extent or memmove is uRoomInDestination  = me->UB.len - (uInsertionPos + NewData.len)
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ *   Check #3 allows Check #2 to be refactored as NewData.Len > (me->size - uInsertionPos)
+ *   This algebraically rearranges to me->size > uInsertionPos + NewData.len
+ *
+ * PtrMath #5 will never wrap under because
+ *   Calculation for extent of memove is uRoomInDestination = me->UB.len - uInsertionPos;
+ *   Check #1 makes sure me->data_len is less than me->size
+ *   Check #3 makes sure uInsertionPos is less than me->data_len
+ */
+
+
+/*
+ * Public function for advancing data length. See qcbor/UsefulBuf.h
+ */
+void UsefulOutBuf_Advance(UsefulOutBuf *pMe, size_t uAmount)
+{
+   /* This function is a trimmed down version of
+    * UsefulOutBuf_InsertUsefulBuf(). This could be combined with the
+    * code in UsefulOutBuf_InsertUsefulBuf(), but that would make
+    * UsefulOutBuf_InsertUsefulBuf() bigger and this will be very
+    * rarely used.
+    */
+
+   if(pMe->err) {
+      /* Already in error state. */
+      return;
+   }
+
+   /* 0. Sanity check the UsefulOutBuf structure
+    *
+    * A "counter measure". If magic number is not the right number it
+    * probably means me was not initialized or it was
+    * corrupted. Attackers can defeat this, but it is a hurdle and
+    * does good with very little code.
+    */
+   if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
+      pMe->err = 1;
+      return;  /* Magic number is wrong due to uninitalization or corrption */
+   }
+
+   /* Make sure valid data is less than buffer size. This would only
+    * occur if there was corruption of me, but it is also part of the
+    * checks to be sure there is no pointer arithmatic
+    * under/overflow.
+    */
+   if(pMe->data_len > pMe->UB.len) {  /* Check #1 */
+      pMe->err = 1;
+      /* Offset of valid data is off the end of the UsefulOutBuf due
+       * to uninitialization or corruption.
+       */
+      return;
+   }
+
+   /* 1. Will it fit?
+    *
+    * WillItFit() is the same as: NewData.len <= (me->UB.len -
+    * me->data_len) Check #1 makes sure subtraction in RoomLeft will
+    * not wrap around
+    */
+   if(! UsefulOutBuf_WillItFit(pMe, uAmount)) { /* Check #2 */
+      /* The new data will not fit into the the buffer. */
+      pMe->err = 1;
+      return;
+   }
+
+   pMe->data_len += uAmount;
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ */
+UsefulBufC UsefulOutBuf_OutUBuf(UsefulOutBuf *pMe)
+{
+   if(pMe->err) {
+      return NULLUsefulBufC;
+   }
+
+   if(pMe->magic != USEFUL_OUT_BUF_MAGIC) {
+      pMe->err = 1;
+      return NULLUsefulBufC;
+   }
+
+   return (UsefulBufC){pMe->UB.ptr, pMe->data_len};
+}
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * Copy out the data accumulated in to the output buffer.
+ */
+UsefulBufC UsefulOutBuf_CopyOut(UsefulOutBuf *pMe, UsefulBuf pDest)
+{
+   const UsefulBufC Tmp = UsefulOutBuf_OutUBuf(pMe);
+   if(UsefulBuf_IsNULLC(Tmp)) {
+      return NULLUsefulBufC;
+   }
+   return UsefulBuf_Copy(pDest, Tmp);
+}
+
+
+
+
+/*
+ * Public function -- see UsefulBuf.h
+ *
+ * The core of UsefulInputBuf -- consume bytes without going off end of buffer.
+ *
+ * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+const void * UsefulInputBuf_GetBytes(UsefulInputBuf *pMe, size_t uAmount)
+{
+   /* Already in error state. Do nothing. */
+   if(pMe->err) {
+      return NULL;
+   }
+
+   if(!UsefulInputBuf_BytesAvailable(pMe, uAmount)) {
+      /* Number of bytes asked for is more than available */
+      pMe->err = 1;
+      return NULL;
+   }
+
+   /* This is going to succeed */
+   const void * const result = ((const uint8_t *)pMe->UB.ptr) + pMe->cursor;
+   /* Won't overflow because of check using UsefulInputBuf_BytesAvailable() */
+   pMe->cursor += uAmount;
+   return result;
+}
diff --git a/core/lib/qcbor/src/ieee754.c b/core/lib/qcbor/src/ieee754.c
new file mode 100644
index 0000000000000000000000000000000000000000..9d08c5eb15fadc22b76f6c304ac34f9d59cc276c
--- /dev/null
+++ b/core/lib/qcbor/src/ieee754.c
@@ -0,0 +1,644 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * ieee754.c -- floating-point conversion between half, double & single-precision
+ *
+ * Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Created on 7/23/18
+ * ========================================================================== */
+
+/*
+ * Include before QCBOR_DISABLE_PREFERRED_FLOAT is checked as
+ * QCBOR_DISABLE_PREFERRED_FLOAT might be defined in qcbor/qcbor_common.h
+ */
+#include "qcbor/qcbor_common.h"
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+
+#include "ieee754.h"
+#include <string.h> /* For memcpy() */
+
+
+/*
+ * This code has long lines and is easier to read because of
+ * them. Some coding guidelines prefer 80 column lines (can they not
+ * afford big displays?).
+ *
+ * This code works solely using shifts and masks and thus has no
+ * dependency on any math libraries. It can even work if the CPU
+ * doesn't have any floating-point support, though that isn't the most
+ * useful thing to do.
+ *
+ * The memcpy() dependency is only for CopyFloatToUint32() and friends
+ * which only is needed to avoid type punning when converting the
+ * actual float bits to an unsigned value so the bit shifts and masks
+ * can work.
+ *
+ * The references used to write this code:
+ *
+ *  IEEE 754-2008, particularly section 3.6 and 6.2.1
+ *
+ *  https://en.wikipedia.org/wiki/IEEE_754 and subordinate pages
+ *
+ *  https://stackoverflow.com/questions/19800415/why-does-ieee-754-reserve-so-many-nan-values
+ *
+ *  https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
+ *
+ *  https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
+ *
+ * IEEE754_FloatToDouble(uint32_t uFloat) was created but is not
+ * needed. It can be retrieved from github history if needed.
+ */
+
+
+
+
+/* ----- Half Precsion ----------- */
+#define HALF_NUM_SIGNIFICAND_BITS (10)
+#define HALF_NUM_EXPONENT_BITS    (5)
+#define HALF_NUM_SIGN_BITS        (1)
+
+#define HALF_SIGNIFICAND_SHIFT    (0)
+#define HALF_EXPONENT_SHIFT       (HALF_NUM_SIGNIFICAND_BITS)
+#define HALF_SIGN_SHIFT           (HALF_NUM_SIGNIFICAND_BITS + HALF_NUM_EXPONENT_BITS)
+
+#define HALF_SIGNIFICAND_MASK     (0x3ffU) // The lower 10 bits
+#define HALF_EXPONENT_MASK        (0x1fU << HALF_EXPONENT_SHIFT) // 0x7c00 5 bits of exponent
+#define HALF_SIGN_MASK            (0x01U << HALF_SIGN_SHIFT) // 0x8000 1 bit of sign
+#define HALF_QUIET_NAN_BIT        (0x01U << (HALF_NUM_SIGNIFICAND_BITS-1)) // 0x0200
+
+/* Biased    Biased    Unbiased   Use
+ *  0x00       0        -15       0 and subnormal
+ *  0x01       1        -14       Smallest normal exponent
+ *  0x1e      30         15       Largest normal exponent
+ *  0x1F      31         16       NaN and Infinity  */
+#define HALF_EXPONENT_BIAS        (15)
+#define HALF_EXPONENT_MAX         (HALF_EXPONENT_BIAS)    //  15 Unbiased
+#define HALF_EXPONENT_MIN         (-HALF_EXPONENT_BIAS+1) // -14 Unbiased
+#define HALF_EXPONENT_ZERO        (-HALF_EXPONENT_BIAS)   // -15 Unbiased
+#define HALF_EXPONENT_INF_OR_NAN  (HALF_EXPONENT_BIAS+1)  //  16 Unbiased
+
+
+/* ------ Single-Precision -------- */
+#define SINGLE_NUM_SIGNIFICAND_BITS (23)
+#define SINGLE_NUM_EXPONENT_BITS    (8)
+#define SINGLE_NUM_SIGN_BITS        (1)
+
+#define SINGLE_SIGNIFICAND_SHIFT    (0)
+#define SINGLE_EXPONENT_SHIFT       (SINGLE_NUM_SIGNIFICAND_BITS)
+#define SINGLE_SIGN_SHIFT           (SINGLE_NUM_SIGNIFICAND_BITS + SINGLE_NUM_EXPONENT_BITS)
+
+#define SINGLE_SIGNIFICAND_MASK     (0x7fffffU) // The lower 23 bits
+#define SINGLE_EXPONENT_MASK        (0xffU << SINGLE_EXPONENT_SHIFT) // 8 bits of exponent
+#define SINGLE_SIGN_MASK            (0x01U << SINGLE_SIGN_SHIFT) // 1 bit of sign
+#define SINGLE_QUIET_NAN_BIT        (0x01U << (SINGLE_NUM_SIGNIFICAND_BITS-1))
+
+/* Biased  Biased   Unbiased  Use
+ *  0x0000     0     -127      0 and subnormal
+ *  0x0001     1     -126      Smallest normal exponent
+ *  0x7f     127        0      1
+ *  0xfe     254      127      Largest normal exponent
+ *  0xff     255      128      NaN and Infinity  */
+#define SINGLE_EXPONENT_BIAS        (127)
+#define SINGLE_EXPONENT_MAX         (SINGLE_EXPONENT_BIAS)
+#define SINGLE_EXPONENT_MIN         (-SINGLE_EXPONENT_BIAS+1)
+#define SINGLE_EXPONENT_ZERO        (-SINGLE_EXPONENT_BIAS)
+#define SINGLE_EXPONENT_INF_OR_NAN  (SINGLE_EXPONENT_BIAS+1)
+
+
+/* --------- Double-Precision ---------- */
+#define DOUBLE_NUM_SIGNIFICAND_BITS (52)
+#define DOUBLE_NUM_EXPONENT_BITS    (11)
+#define DOUBLE_NUM_SIGN_BITS        (1)
+
+#define DOUBLE_SIGNIFICAND_SHIFT    (0)
+#define DOUBLE_EXPONENT_SHIFT       (DOUBLE_NUM_SIGNIFICAND_BITS)
+#define DOUBLE_SIGN_SHIFT           (DOUBLE_NUM_SIGNIFICAND_BITS + DOUBLE_NUM_EXPONENT_BITS)
+
+#define DOUBLE_SIGNIFICAND_MASK     (0xfffffffffffffULL) // The lower 52 bits
+#define DOUBLE_EXPONENT_MASK        (0x7ffULL << DOUBLE_EXPONENT_SHIFT) // 11 bits of exponent
+#define DOUBLE_SIGN_MASK            (0x01ULL << DOUBLE_SIGN_SHIFT) // 1 bit of sign
+#define DOUBLE_QUIET_NAN_BIT        (0x01ULL << (DOUBLE_NUM_SIGNIFICAND_BITS-1))
+
+
+/* Biased      Biased   Unbiased  Use
+ * 0x00000000     0     -1023     0 and subnormal
+ * 0x00000001     1     -1022     Smallest normal exponent
+ * 0x000007fe  2046      1023     Largest normal exponent
+ * 0x000007ff  2047      1024     NaN and Infinity  */
+#define DOUBLE_EXPONENT_BIAS        (1023)
+#define DOUBLE_EXPONENT_MAX         (DOUBLE_EXPONENT_BIAS)
+#define DOUBLE_EXPONENT_MIN         (-DOUBLE_EXPONENT_BIAS+1)
+#define DOUBLE_EXPONENT_ZERO        (-DOUBLE_EXPONENT_BIAS)
+#define DOUBLE_EXPONENT_INF_OR_NAN  (DOUBLE_EXPONENT_BIAS+1)
+
+
+
+
+/*
+ * Convenient functions to avoid type punning, compiler warnings and
+ * such. The optimizer reduces them to a simple assignment. This is a
+ * crusty corner of C. It shouldn't be this hard.
+ *
+ * These are also in UsefulBuf.h under a different name. They are copied
+ * here to avoid a dependency on UsefulBuf.h. There is no object code
+ * size impact because these always optimze down to a simple assignment.
+ */
+static inline uint32_t
+CopyFloatToUint32(float f)
+{
+   uint32_t u32;
+   memcpy(&u32, &f, sizeof(uint32_t));
+   return u32;
+}
+
+static inline uint64_t
+CopyDoubleToUint64(double d)
+{
+   uint64_t u64;
+   memcpy(&u64, &d, sizeof(uint64_t));
+   return u64;
+}
+
+static inline double
+CopyUint64ToDouble(uint64_t u64)
+{
+   double d;
+   memcpy(&d, &u64, sizeof(uint64_t));
+   return d;
+}
+
+static inline float
+CopyUint32ToSingle(uint32_t u32)
+{
+   float f;
+   memcpy(&f, &u32, sizeof(uint32_t));
+   return f;
+}
+
+
+
+
+/**
+ * @brief Assemble sign, significand and exponent into single precision float.
+ *
+ * @param[in] uDoubleSign              0 if positive, 1 if negative
+ * @pararm[in] uDoubleSignificand      Bits of the significand
+ * @param[in] nDoubleUnBiasedExponent  Exponent
+ *
+ * This returns the bits for a single-precision float, a binary64
+ * as specified in IEEE754.
+ */
+static double
+IEEE754_AssembleDouble(uint64_t uDoubleSign,
+                       uint64_t uDoubleSignificand,
+                       int64_t  nDoubleUnBiasedExponent)
+{
+   uint64_t uDoubleBiasedExponent;
+
+   uDoubleBiasedExponent = (uint64_t)(nDoubleUnBiasedExponent + DOUBLE_EXPONENT_BIAS);
+
+   return CopyUint64ToDouble(uDoubleSignificand |
+                             (uDoubleBiasedExponent << DOUBLE_EXPONENT_SHIFT) |
+                             (uDoubleSign << DOUBLE_SIGN_SHIFT));
+}
+
+
+double
+IEEE754_HalfToDouble(uint16_t uHalfPrecision)
+{
+   uint64_t uDoubleSignificand;
+   int64_t  nDoubleUnBiasedExponent;
+   double   dResult;
+
+   /* Pull out the three parts of the half-precision float.  Do all
+    * the work in 64 bits because that is what the end result is.  It
+    * may give smaller code size and will keep static analyzers
+    * happier.
+    */
+   const uint64_t uHalfSignificand      = uHalfPrecision & HALF_SIGNIFICAND_MASK;
+   const uint64_t uHalfBiasedExponent   = (uHalfPrecision & HALF_EXPONENT_MASK) >> HALF_EXPONENT_SHIFT;
+   const int64_t  nHalfUnBiasedExponent = (int64_t)uHalfBiasedExponent - HALF_EXPONENT_BIAS;
+   const uint64_t uHalfSign             = (uHalfPrecision & HALF_SIGN_MASK) >> HALF_SIGN_SHIFT;
+
+   if(nHalfUnBiasedExponent == HALF_EXPONENT_ZERO) {
+      /* 0 or subnormal */
+      if(uHalfSignificand) {
+         /* --- SUBNORMAL --- */
+         /* A half-precision subnormal can always be converted to a
+          * normal double-precision float because the ranges line up.
+          * The exponent of a subnormal starts out at the min exponent
+          * for a normal. As the sub normal significand bits are
+          * shifted, left to normalize, the exponent is
+          * decremented. Shifting continues until fully normalized.
+          */
+          nDoubleUnBiasedExponent = HALF_EXPONENT_MIN;
+          uDoubleSignificand      = uHalfSignificand;
+          do {
+             uDoubleSignificand <<= 1;
+             nDoubleUnBiasedExponent--;
+          } while ((uDoubleSignificand & (1ULL << HALF_NUM_SIGNIFICAND_BITS)) == 0);
+          /* A normal has an implied 1 in the most significant
+           * position that a subnormal doesn't. */
+          uDoubleSignificand -= 1ULL << HALF_NUM_SIGNIFICAND_BITS;
+          /* Must shift into place for a double significand */
+          uDoubleSignificand <<= DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS;
+
+          dResult = IEEE754_AssembleDouble(uHalfSign,
+                                           uDoubleSignificand,
+                                           nDoubleUnBiasedExponent);
+      } else {
+         /* --- ZERO --- */
+         dResult = IEEE754_AssembleDouble(uHalfSign,
+                                          0,
+                                          DOUBLE_EXPONENT_ZERO);
+      }
+   } else if(nHalfUnBiasedExponent == HALF_EXPONENT_INF_OR_NAN) {
+      /* NaN or Inifinity */
+      if(uHalfSignificand) {
+         /* --- NaN --- */
+         /* Half-precision payloads always fit into double precision
+          * payloads. They are shifted left the same as a normal
+          * number significand.
+          */
+         uDoubleSignificand = uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+         dResult = IEEE754_AssembleDouble(uHalfSign,
+                                          uDoubleSignificand,
+                                          DOUBLE_EXPONENT_INF_OR_NAN);
+      } else {
+         /* --- INFINITY --- */
+         dResult = IEEE754_AssembleDouble(uHalfSign,
+                                          0,
+                                          DOUBLE_EXPONENT_INF_OR_NAN);
+      }
+   } else {
+      /* --- NORMAL NUMBER --- */
+      uDoubleSignificand = uHalfSignificand << (DOUBLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+      dResult = IEEE754_AssembleDouble(uHalfSign,
+                                       uDoubleSignificand,
+                                       nHalfUnBiasedExponent);
+   }
+
+   return dResult;
+}
+
+
+/**
+ * @brief Assemble sign, significand and exponent into single precision float.
+ *
+ * @param[in] uHalfSign              0 if positive, 1 if negative
+ * @pararm[in] uHalfSignificand      Bits of the significand
+ * @param[in] nHalfUnBiasedExponent  Exponent
+ *
+ * This returns the bits for a single-precision float, a binary32 as
+ * specified in IEEE754. It is returned as a uint64_t rather than a
+ * uint32_t or a float for convenience of usage.
+ */
+static uint32_t
+IEEE754_AssembleHalf(uint32_t uHalfSign,
+                     uint32_t uHalfSignificand,
+                     int32_t nHalfUnBiasedExponent)
+{
+   uint32_t uHalfUnbiasedExponent;
+
+   uHalfUnbiasedExponent = (uint32_t)(nHalfUnBiasedExponent + HALF_EXPONENT_BIAS);
+
+   return uHalfSignificand |
+          (uHalfUnbiasedExponent << HALF_EXPONENT_SHIFT) |
+          (uHalfSign << HALF_SIGN_SHIFT);
+}
+
+
+/*  Public function; see ieee754.h */
+IEEE754_union
+IEEE754_SingleToHalf(float f)
+{
+   IEEE754_union result;
+   uint32_t      uDroppedBits;
+   int32_t       nExponentDifference;
+   int32_t       nShiftAmount;
+   uint32_t      uHalfSignificand;
+
+   /* Pull the three parts out of the double-precision float Most work
+    * is done with uint32_t which helps avoid integer promotions and
+    * static analyzer complaints.
+    */
+   const uint32_t uSingle                 = CopyFloatToUint32(f);
+   const uint32_t uSingleBiasedExponent   = (uSingle & SINGLE_EXPONENT_MASK) >> SINGLE_EXPONENT_SHIFT;
+   const int32_t  nSingleUnbiasedExponent = (int32_t)uSingleBiasedExponent - SINGLE_EXPONENT_BIAS;
+   const uint32_t uSingleSignificand      = uSingle & SINGLE_SIGNIFICAND_MASK;
+   const uint32_t uSingleSign             = (uSingle & SINGLE_SIGN_MASK) >> SINGLE_SIGN_SHIFT;
+
+   if(nSingleUnbiasedExponent == SINGLE_EXPONENT_ZERO) {
+      if(uSingleSignificand == 0) {
+         /* --- IS ZERO --- */
+         result.uSize  = IEEE754_UNION_IS_HALF;
+         result.uValue = IEEE754_AssembleHalf(uSingleSign,
+                                              0,
+                                              HALF_EXPONENT_ZERO);
+      } else {
+         /* --- IS SINGLE SUBNORMAL --- */
+         /* The largest single subnormal is slightly less than the
+          * largest single normal which is 2^-149 or
+          * 2.2040517676619426e-38.  The smallest half subnormal is
+          * 2^-14 or 5.9604644775390625E-8.  There is no overlap so
+          * single subnormals can't be converted to halfs of any sort.
+          */
+         result.uSize   = IEEE754_UNION_IS_SINGLE;
+         result.uValue  = uSingle;
+      }
+   } else if(nSingleUnbiasedExponent == SINGLE_EXPONENT_INF_OR_NAN) {
+      if(uSingleSignificand == 0) {
+         /* ---- IS INFINITY ---- */
+         result.uSize  = IEEE754_UNION_IS_HALF;
+         result.uValue = IEEE754_AssembleHalf(uSingleSign, 0, HALF_EXPONENT_INF_OR_NAN);
+      } else {
+         /* The NaN can only be converted if no payload bits are lost
+          * per RFC 8949 section 4.1 that defines Preferred
+          * Serializaton. Note that Deterministically Encode CBOR in
+          * section 4.2 allows for some variation of this rule, but at
+          * the moment this implementation is of Preferred
+          * Serialization, not CDE. As of December 2023, we are also
+          * expecting an update to CDE. This code may need to be
+          * updated for CDE.
+          */
+         uDroppedBits = uSingleSignificand & (SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS);
+         if(uDroppedBits == 0) {
+            /* --- IS CONVERTABLE NAN --- */
+            uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+            result.uSize  = IEEE754_UNION_IS_HALF;
+            result.uValue = IEEE754_AssembleHalf(uSingleSign,
+                                                 uHalfSignificand,
+                                                 HALF_EXPONENT_INF_OR_NAN);
+
+         } else {
+            /* --- IS UNCONVERTABLE NAN --- */
+            result.uSize   = IEEE754_UNION_IS_SINGLE;
+            result.uValue  = uSingle;
+         }
+      }
+   } else {
+      /* ---- REGULAR NUMBER ---- */
+      /* A regular single can be converted to a regular half if the
+       * single's exponent is in the smaller range of a half and if no
+       * precision is lost in the significand.
+       */
+      if(nSingleUnbiasedExponent >= HALF_EXPONENT_MIN &&
+         nSingleUnbiasedExponent <= HALF_EXPONENT_MAX &&
+        (uSingleSignificand & (SINGLE_SIGNIFICAND_MASK >> HALF_NUM_SIGNIFICAND_BITS)) == 0) {
+         uHalfSignificand = uSingleSignificand >> (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+
+         /* --- CONVERT TO HALF NORMAL --- */
+         result.uSize  = IEEE754_UNION_IS_HALF;
+         result.uValue = IEEE754_AssembleHalf(uSingleSign,
+                                              uHalfSignificand,
+                                              nSingleUnbiasedExponent);
+      } else {
+         /* Unable to convert to a half normal. See if it can be
+          * converted to a half subnormal. To do that, the exponent
+          * must be in range and no precision can be lost in the
+          * signficand.
+          *
+          * This is more complicated because the number is not
+          * normalized.  The signficand must be shifted proprotionally
+          * to the exponent and 1 must be added in.  See
+          * https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Exponent_encoding
+          *
+          * Exponents -14 to -24 map to a shift of 0 to 10 of the
+          * significand.  The largest value of a half subnormal has an
+          * exponent of -14. Subnormals are not normalized like
+          * normals meaning they lose precision as the numbers get
+          * smaller. Normals don't lose precision because the exponent
+          * allows all the bits of the significand to be significant.
+          */
+         /* The exponent of the largest possible half-precision
+          * subnormal is HALF_EXPONENT_MIN (-14).  Exponents larger
+          * than this are normal and handled above. We're going to
+          * shift the significand right by at least this amount.
+          */
+         nExponentDifference = -(nSingleUnbiasedExponent - HALF_EXPONENT_MIN);
+
+         /* In addition to the shift based on the exponent's value,
+          * the single significand has to be shifted right to fit into
+          * a half-precision significand */
+         nShiftAmount = nExponentDifference + (SINGLE_NUM_SIGNIFICAND_BITS - HALF_NUM_SIGNIFICAND_BITS);
+
+         /* Must add 1 in to the possible significand because there is
+          * an implied 1 for normal values and not for subnormal
+          * values. See equations here:
+          * https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Exponent_encoding
+          */
+         uHalfSignificand = (uSingleSignificand + (1 << SINGLE_NUM_SIGNIFICAND_BITS)) >> nShiftAmount;
+
+         /* If only zero bits get shifted out, this can be converted
+          * to subnormal */
+         if(nSingleUnbiasedExponent < HALF_EXPONENT_MIN &&
+            nSingleUnbiasedExponent >= HALF_EXPONENT_MIN - HALF_NUM_SIGNIFICAND_BITS &&
+            uHalfSignificand << nShiftAmount == uSingleSignificand + (1 << SINGLE_NUM_SIGNIFICAND_BITS)) {
+            /* --- CONVERTABLE TO HALF SUBNORMAL --- */
+            result.uSize  = IEEE754_UNION_IS_HALF;
+            result.uValue = IEEE754_AssembleHalf(uSingleSign,
+                                                 uHalfSignificand,
+                                                 HALF_EXPONENT_ZERO);
+         } else {
+            /* --- DO NOT CONVERT --- */
+            result.uSize   = IEEE754_UNION_IS_SINGLE;
+            result.uValue  = uSingle;
+         }
+      }
+   }
+
+   return result;
+}
+
+
+/**
+ * @brief Assemble sign, significand and exponent into single precision float.
+ *
+ * @param[in] uSingleSign              0 if positive, 1 if negative
+ * @pararm[in] uSingleSignificand      Bits of the significand
+ * @param[in] nSingleUnBiasedExponent  Exponent
+ *
+ * This returns the bits for a single-precision float, a binary32 as
+ * specified in IEEE754. It is returned as a uint64_t rather than a
+ * uint32_t or a float for convenience of usage.
+ */
+static uint64_t
+IEEE754_AssembleSingle(uint64_t uSingleSign,
+                       uint64_t uSingleSignificand,
+                       int64_t  nSingleUnBiasedExponent)
+{
+   uint64_t uSingleBiasedExponent;
+
+   uSingleBiasedExponent = (uint64_t)(nSingleUnBiasedExponent + SINGLE_EXPONENT_BIAS);
+
+   return uSingleSignificand |
+          (uSingleBiasedExponent << SINGLE_EXPONENT_SHIFT) |
+          (uSingleSign << SINGLE_SIGN_SHIFT);
+}
+
+
+/**
+ * @brief Convert a double-precision float to single-precision.
+ *
+ * @param[in] d  The value to convert.
+ *
+ * @returns Either unconverted value or value converted to single-precision.
+ *
+ * This always succeeds. If the value cannot be converted without the
+ * loss of precision, it is not converted.
+ *
+ * This handles all subnormals and NaN payloads.
+ */
+static IEEE754_union
+IEEE754_DoubleToSingle(double d)
+{
+   IEEE754_union Result;
+   int64_t       nExponentDifference;
+   int64_t       nShiftAmount;
+   uint64_t      uSingleSignificand;
+   uint64_t      uDroppedBits;
+
+
+   /* Pull the three parts out of the double-precision float. Most
+    * work is done with uint64_t which helps avoid integer promotions
+    * and static analyzer complaints.
+    */
+   const uint64_t uDouble                 = CopyDoubleToUint64(d);
+   const uint64_t uDoubleBiasedExponent   = (uDouble & DOUBLE_EXPONENT_MASK) >> DOUBLE_EXPONENT_SHIFT;
+   const int64_t  nDoubleUnbiasedExponent = (int64_t)uDoubleBiasedExponent - DOUBLE_EXPONENT_BIAS;
+   const uint64_t uDoubleSign             = (uDouble & DOUBLE_SIGN_MASK) >> DOUBLE_SIGN_SHIFT;
+   const uint64_t uDoubleSignificand      = uDouble & DOUBLE_SIGNIFICAND_MASK;
+
+
+    if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_ZERO) {
+        if(uDoubleSignificand == 0) {
+            /* --- IS ZERO --- */
+            Result.uSize  = IEEE754_UNION_IS_SINGLE;
+            Result.uValue = IEEE754_AssembleSingle(uDoubleSign,
+                                                   0,
+                                                   SINGLE_EXPONENT_ZERO);
+        } else {
+            /* --- IS DOUBLE SUBNORMAL --- */
+            /* The largest double subnormal is slightly less than the
+             * largest double normal which is 2^-1022 or
+             * 2.2250738585072014e-308.  The smallest single subnormal
+             * is 2^-149 or 1.401298464324817e-45.  There is no
+             * overlap so double subnormals can't be converted to
+             * singles of any sort.
+             */
+            Result.uSize   = IEEE754_UNION_IS_DOUBLE;
+            Result.uValue  = uDouble;
+         }
+    } else if(nDoubleUnbiasedExponent == DOUBLE_EXPONENT_INF_OR_NAN) {
+         if(uDoubleSignificand == 0) {
+             /* ---- IS INFINITY ---- */
+             Result.uSize  = IEEE754_UNION_IS_SINGLE;
+             Result.uValue = IEEE754_AssembleSingle(uDoubleSign,
+                                                    0,
+                                                    SINGLE_EXPONENT_INF_OR_NAN);
+         } else {
+             /* The NaN can only be converted if no payload bits are
+              * lost per RFC 8949 section 4.1 that defines Preferred
+              * Serializaton. Note that Deterministically Encode CBOR
+              * in section 4.2 allows for some variation of this rule,
+              * but at the moment this implementation is of Preferred
+              * Serialization, not CDE. As of December 2023, we are
+              * also expecting an update to CDE. This code may need to
+              * be updated for CDE.
+              */
+             uDroppedBits = uDoubleSignificand & (DOUBLE_SIGNIFICAND_MASK >> SINGLE_NUM_SIGNIFICAND_BITS);
+             if(uDroppedBits == 0) {
+                /* --- IS CONVERTABLE NAN --- */
+                uSingleSignificand = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - SINGLE_NUM_SIGNIFICAND_BITS);
+                Result.uSize  = IEEE754_UNION_IS_SINGLE;
+                Result.uValue = IEEE754_AssembleSingle(uDoubleSign,
+                                                       uSingleSignificand,
+                                                       SINGLE_EXPONENT_INF_OR_NAN);
+            } else {
+               /* --- IS UNCONVERTABLE NAN --- */
+               Result.uSize   = IEEE754_UNION_IS_DOUBLE;
+               Result.uValue  = uDouble;
+            }
+         }
+    } else {
+        /* ---- REGULAR NUMBER ---- */
+        /* A regular double can be converted to a regular single if
+         * the double's exponent is in the smaller range of a single
+         * and if no precision is lost in the significand.
+         */
+        uDroppedBits = uDoubleSignificand & (DOUBLE_SIGNIFICAND_MASK >> SINGLE_NUM_SIGNIFICAND_BITS);
+        if(nDoubleUnbiasedExponent >= SINGLE_EXPONENT_MIN &&
+           nDoubleUnbiasedExponent <= SINGLE_EXPONENT_MAX &&
+           uDroppedBits == 0) {
+            /* --- IS CONVERTABLE TO SINGLE --- */
+            uSingleSignificand = uDoubleSignificand >> (DOUBLE_NUM_SIGNIFICAND_BITS - SINGLE_NUM_SIGNIFICAND_BITS);
+            Result.uSize  = IEEE754_UNION_IS_SINGLE;
+            Result.uValue = IEEE754_AssembleSingle(uDoubleSign,
+                                                   uSingleSignificand,
+                                                   nDoubleUnbiasedExponent);
+        } else {
+            /* Unable to convert to a single normal. See if it can be
+             * converted to a single subnormal. To do that, the
+             * exponent must be in range and no precision can be lost
+             * in the signficand.
+             *
+             * This is more complicated because the number is not
+             * normalized.  The signficand must be shifted
+             * proprotionally to the exponent and 1 must be added
+             * in. See
+             * https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Exponent_encoding
+             */
+            nExponentDifference = -(nDoubleUnbiasedExponent - SINGLE_EXPONENT_MIN);
+            nShiftAmount        = nExponentDifference + (DOUBLE_NUM_SIGNIFICAND_BITS - SINGLE_NUM_SIGNIFICAND_BITS);
+            uSingleSignificand  = (uDoubleSignificand + (1ULL << DOUBLE_NUM_SIGNIFICAND_BITS)) >> nShiftAmount;
+
+            if(nDoubleUnbiasedExponent < SINGLE_EXPONENT_MIN &&
+               nDoubleUnbiasedExponent >= SINGLE_EXPONENT_MIN - SINGLE_NUM_SIGNIFICAND_BITS &&
+               uSingleSignificand << nShiftAmount == uDoubleSignificand + (1ULL << DOUBLE_NUM_SIGNIFICAND_BITS)) {
+               /* --- IS CONVERTABLE TO SINGLE SUBNORMAL --- */
+               Result.uSize  = IEEE754_UNION_IS_SINGLE;
+               Result.uValue = IEEE754_AssembleSingle(uDoubleSign,
+                                                      uSingleSignificand,
+                                                      SINGLE_EXPONENT_ZERO);
+            } else {
+               /* --- CAN NOT BE CONVERTED --- */
+               Result.uSize   = IEEE754_UNION_IS_DOUBLE;
+               Result.uValue  = uDouble;
+            }
+        }
+    }
+
+    return Result;
+}
+
+
+/* Public function; see ieee754.h */
+IEEE754_union
+IEEE754_DoubleToSmaller(double d, int bAllowHalfPrecision)
+{
+   IEEE754_union result;
+
+   result = IEEE754_DoubleToSingle(d);
+
+   if(result.uSize == IEEE754_UNION_IS_SINGLE && bAllowHalfPrecision) {
+      /* Cast to uint32_t is OK, because value was just successfully
+       * converted to single. */
+      float uSingle = CopyUint32ToSingle((uint32_t)result.uValue);
+      result = IEEE754_SingleToHalf(uSingle);
+   }
+
+   return result;
+}
+
+
+#else /* QCBOR_DISABLE_PREFERRED_FLOAT */
+
+int ieee754_dummy_place_holder;
+
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/core/lib/qcbor/src/ieee754.h b/core/lib/qcbor/src/ieee754.h
new file mode 100644
index 0000000000000000000000000000000000000000..5bdda3f96f7d787ef09cb449ec78b15ee501cf59
--- /dev/null
+++ b/core/lib/qcbor/src/ieee754.h
@@ -0,0 +1,127 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * ieee754.h -- Conversion between half, double & single-precision floats
+ *
+ * Copyright (c) 2018-2024, Laurence Lundblade. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Created on 7/23/18
+ * ========================================================================== */
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+
+#ifndef ieee754_h
+#define ieee754_h
+
+#include <stdint.h>
+
+
+/** @file ieee754.h
+ *
+ * This implements floating-point conversion between half, single and
+ * double precision floating-point numbers, in particular convesion to
+ * smaller representation (e.g., double to single) that does not lose
+ * precision for CBOR preferred serialization.
+ *
+ * This implementation works entirely with shifts and masks and does
+ * not require any floating-point HW or library.
+ *
+ * This conforms to IEEE 754-2008, but note that it doesn't specify
+ * conversions, just the encodings.
+ *
+ * This is complete, supporting +/- infinity, +/- zero, subnormals and
+ * NaN payloads. NaN payloads are converted to smaller by dropping the
+ * right most bits if they are zero and shifting to the right. If the
+ * rightmost bits are not zero the conversion is not performed. When
+ * converting from smaller to larger, the payload is shifted left and
+ * zero-padded. This is what is specified by CBOR preferred
+ * serialization and what modern HW conversion instructions do. CBOR
+ * CDE handling for NaN is not clearly specified, but upcoming
+ * documents may clarify this.
+ *
+ * There is no special handling of silent and quiet NaNs. It probably
+ * isn't necessary to transmit these special NaNs as there purpose is
+ * more for propgating errors up through some calculation. In many
+ * cases the handlng of the NaN payload will work for silent and quiet
+ * NaNs.
+ *
+ * A previous version of this was usable as a general library for
+ * conversion. This version is reduced to what is needed for CBOR.
+ */
+
+
+/**
+ * @brief Convert half-precision float to double-precision float.
+ *
+ * @param[in] uHalfPrecision   Half-prevision number to convert.
+ *
+ * @returns double-presion value.
+ *
+ * This is a lossless conversion because every half-precision value
+ * can be represented as a double. There is no error condition.
+ *
+ * There is no half-precision type in C, so it is represented here as
+ * a @c uint16_t. The bits of @c uHalfPrecision are as described for
+ * half-precision by IEEE 754.
+ */
+double
+IEEE754_HalfToDouble(uint16_t uHalfPrecision);
+
+
+/** Holds a floating-point value that could be half, single or
+ * double-precision.  The value is in a @c uint64_t that may be copied
+ * to a float or double.  Simply casting uValue will usually work but
+ * may generate compiler or static analyzer warnings. Using
+ * UsefulBufUtil_CopyUint64ToDouble() or
+ * UsefulBufUtil_CopyUint32ToFloat() will not (and will not generate
+ * any extra code).
+ */
+typedef struct {
+   enum {IEEE754_UNION_IS_HALF   = 2,
+         IEEE754_UNION_IS_SINGLE = 4,
+         IEEE754_UNION_IS_DOUBLE = 8,
+   } uSize; /* Size of uValue */
+   uint64_t uValue;
+} IEEE754_union;
+
+
+/**
+ * @brief Convert a double to either single or half-precision.
+ *
+ * @param[in] d                    The value to convert.
+ * @param[in] bAllowHalfPrecision  If true, convert to either half or
+ *                                 single precision.
+ *
+ * @returns Unconverted value, or value converted to single or half-precision.
+ *
+ * This always succeeds. If the value cannot be converted without the
+ * loss of precision, it is not converted.
+ *
+ * This handles all subnormals and NaN payloads.
+ */
+IEEE754_union
+IEEE754_DoubleToSmaller(double d, int bAllowHalfPrecision);
+
+
+/**
+ * @brief Convert a single-precision float to half-precision.
+ *
+ * @param[in] f  The value to convert.
+ *
+ * @returns Either unconverted value or value converted to half-precision.
+ *
+ * This always succeeds. If the value cannot be converted without the
+ * loss of precision, it is not converted.
+ *
+ * This handles all subnormals and NaN payloads.
+ */
+IEEE754_union
+IEEE754_SingleToHalf(float f);
+
+
+#endif /* ieee754_h */
+
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
diff --git a/core/lib/qcbor/src/qcbor_decode.c b/core/lib/qcbor/src/qcbor_decode.c
new file mode 100644
index 0000000000000000000000000000000000000000..8603e7aea1601b07e860ba12cb7948db895f1000
--- /dev/null
+++ b/core/lib/qcbor/src/qcbor_decode.c
@@ -0,0 +1,7298 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*==============================================================================
+ Copyright (c) 2016-2018, The Linux Foundation.
+ Copyright (c) 2018-2024, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors, nor the name "Laurence Lundblade" may be used to
+      endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ =============================================================================*/
+
+
+#include "qcbor/qcbor_decode.h"
+#include "qcbor/qcbor_spiffy_decode.h"
+#include "ieee754.h" /* Does not use math.h */
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+
+#include <math.h> /* For isnan(), llround(), llroudf(), round(), roundf(),
+                   * pow(), exp2()
+                   */
+#include <fenv.h> /* feclearexcept(), fetestexcept() */
+
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+
+#if (defined(__GNUC__) && !defined(__clang__))
+/*
+ * This is how the -Wmaybe-uninitialized compiler warning is
+ * handled. It can’t be ignored because some version of gcc enable it
+ * with -Wall which is a common and useful gcc warning option. It also
+ * can’t be ignored because it is the goal of QCBOR to compile clean
+ * out of the box in all environments.
+ *
+ * The big problem with -Wmaybe-uninitialized is that it generates
+ * false positives. It complains things are uninitialized when they
+ * are not. This is because it is not a thorough static analyzer. This
+ * is why “maybe” is in its name. The problem is it is just not
+ * thorough enough to understand all the code (and someone saw fit to
+ * put it in gcc and worse to enable it with -Wall).
+ *
+ * One solution would be to change the code so -Wmaybe-uninitialized
+ * doesn’t get confused, for example adding an unnecessary extra
+ * initialization to zero. (If variables were truly uninitialized, the
+ * correct path is to understand the code thoroughly and set them to
+ * the correct value at the correct time; in essence this is already
+ * done; -Wmaybe-uninitialized just can’t tell). This path is not
+ * taken because it makes the code bigger and is kind of the tail
+ * wagging the dog.
+ *
+ * The solution here is to just use a pragma to disable it for the
+ * whole file. Disabling it for each line makes the code fairly ugly
+ * requiring #pragma to push, pop and ignore. Another reason is the
+ * warnings issues vary by version of gcc and which optimization
+ * optimizations are selected. Another reason is that compilers other
+ * than gcc don’t have -Wmaybe-uninitialized.
+ *
+ * One may ask how to be sure these warnings are false positives and
+ * not real issues. 1) The code has been read carefully to check. 2)
+ * Testing is pretty thorough. 3) This code has been run through
+ * thorough high-quality static analyzers.
+ *
+ * In particularly, most of the warnings are about
+ * Item.Item->uDataType being uninitialized. QCBORDecode_GetNext()
+ * *always* sets this value and test case confirm
+ * this. -Wmaybe-uninitialized just can't tell.
+ *
+ * https://stackoverflow.com/questions/5080848/disable-gcc-may-be-used-uninitialized-on-a-particular-variable
+ */
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
+
+
+
+
+#define SIZEOF_C_ARRAY(array,type) (sizeof(array)/sizeof(type))
+
+
+
+
+static bool
+QCBORItem_IsMapOrArray(const QCBORItem Item)
+{
+   const uint8_t uDataType = Item.uDataType;
+   return uDataType == QCBOR_TYPE_MAP ||
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+          uDataType == QCBOR_TYPE_MAP_AS_ARRAY ||
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+          uDataType == QCBOR_TYPE_ARRAY;
+}
+
+static bool
+QCBORItem_IsEmptyDefiniteLengthMapOrArray(const QCBORItem Item)
+{
+   if(!QCBORItem_IsMapOrArray(Item)){
+      return false;
+   }
+
+   if(Item.val.uCount != 0) {
+      return false;
+   }
+   return true;
+}
+
+static bool
+QCBORItem_IsIndefiniteLengthMapOrArray(const QCBORItem Item)
+{
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   if(!QCBORItem_IsMapOrArray(Item)){
+      return false;
+   }
+
+   if(Item.val.uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
+      return false;
+   }
+   return true;
+#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+   (void)Item;
+   return false;
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+}
+
+/* Return true if the labels in Item1 and Item2 are the same.
+   Works only for integer and string labels. Returns false
+   for any other type. */
+static bool
+QCBORItem_MatchLabel(const QCBORItem Item1, const QCBORItem Item2)
+{
+   if(Item1.uLabelType == QCBOR_TYPE_INT64) {
+      if(Item2.uLabelType == QCBOR_TYPE_INT64 && Item1.label.int64 == Item2.label.int64) {
+         return true;
+      }
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   } else if(Item1.uLabelType == QCBOR_TYPE_TEXT_STRING) {
+      if(Item2.uLabelType == QCBOR_TYPE_TEXT_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
+         return true;
+      }
+   } else if(Item1.uLabelType == QCBOR_TYPE_BYTE_STRING) {
+      if(Item2.uLabelType == QCBOR_TYPE_BYTE_STRING && !UsefulBuf_Compare(Item1.label.string, Item2.label.string)) {
+         return true;
+      }
+   } else if(Item1.uLabelType == QCBOR_TYPE_UINT64) {
+      if(Item2.uLabelType == QCBOR_TYPE_UINT64 && Item1.label.uint64 == Item2.label.uint64) {
+         return true;
+      }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+   }
+
+   /* Other label types are never matched */
+   return false;
+}
+
+
+/*
+ Returns true if Item1 and Item2 are the same type
+ or if either are of QCBOR_TYPE_ANY.
+ */
+static bool
+QCBORItem_MatchType(const QCBORItem Item1, const QCBORItem Item2)
+{
+   if(Item1.uDataType == Item2.uDataType) {
+      return true;
+   } else if(Item1.uDataType == QCBOR_TYPE_ANY) {
+      return true;
+   } else if(Item2.uDataType == QCBOR_TYPE_ANY) {
+      return true;
+   }
+   return false;
+}
+
+
+/*===========================================================================
+   DecodeNesting -- Tracking array/map/sequence/bstr-wrapped nesting
+  ===========================================================================*/
+
+/*
+ * See comments about and typedef of QCBORDecodeNesting in qcbor_private.h,
+ * the data structure all these functions work on.
+ */
+
+
+static uint8_t
+DecodeNesting_GetCurrentLevel(const QCBORDecodeNesting *pNesting)
+{
+   const ptrdiff_t nLevel = pNesting->pCurrent - &(pNesting->pLevels[0]);
+   /* Limit in DecodeNesting_Descend against more than
+    * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
+    */
+   return (uint8_t)nLevel;
+}
+
+
+static uint8_t
+DecodeNesting_GetBoundedModeLevel(const QCBORDecodeNesting *pNesting)
+{
+   const ptrdiff_t nLevel = pNesting->pCurrentBounded - &(pNesting->pLevels[0]);
+   /* Limit in DecodeNesting_Descend against more than
+    * QCBOR_MAX_ARRAY_NESTING gaurantees cast is safe
+    */
+   return (uint8_t)nLevel;
+}
+
+
+static uint32_t
+DecodeNesting_GetMapOrArrayStart(const QCBORDecodeNesting *pNesting)
+{
+   return pNesting->pCurrentBounded->u.ma.uStartOffset;
+}
+
+
+static bool
+DecodeNesting_IsBoundedEmpty(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrentBounded->u.ma.uCountCursor == QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static bool
+DecodeNesting_IsCurrentAtTop(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent == &(pNesting->pLevels[0])) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static bool
+DecodeNesting_IsCurrentDefiniteLength(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* Not a map or array */
+      return false;
+   }
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   if(pNesting->pCurrent->u.ma.uCountTotal == QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH) {
+      /* Is indefinite */
+      return false;
+   }
+
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+   /* All checks passed; is a definte length map or array */
+   return true;
+}
+
+static bool
+DecodeNesting_IsCurrentBstrWrapped(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* is a byte string */
+      return true;
+   }
+   return false;
+}
+
+
+static bool
+DecodeNesting_IsCurrentBounded(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      return true;
+   }
+   if(pNesting->pCurrent->u.ma.uStartOffset != QCBOR_NON_BOUNDED_OFFSET) {
+      return true;
+   }
+   return false;
+}
+
+
+static void
+DecodeNesting_SetMapOrArrayBoundedMode(QCBORDecodeNesting *pNesting, bool bIsEmpty, size_t uStart)
+{
+   /* Should be only called on maps and arrays */
+   /*
+    * DecodeNesting_EnterBoundedMode() checks to be sure uStart is not
+    * larger than DecodeNesting_EnterBoundedMode which keeps it less than
+    * uin32_t so the cast is safe.
+    */
+   pNesting->pCurrent->u.ma.uStartOffset = (uint32_t)uStart;
+
+   if(bIsEmpty) {
+      pNesting->pCurrent->u.ma.uCountCursor = QCBOR_COUNT_INDICATES_ZERO_LENGTH;
+   }
+}
+
+
+static void
+DecodeNesting_ClearBoundedMode(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent->u.ma.uStartOffset = QCBOR_NON_BOUNDED_OFFSET;
+}
+
+
+static bool
+DecodeNesting_IsAtEndOfBoundedLevel(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrentBounded == NULL) {
+      /* No bounded map or array set up */
+      return false;
+   }
+   if(pNesting->pCurrent->uLevelType == QCBOR_TYPE_BYTE_STRING) {
+      /* Not a map or array; end of those is by byte count */
+      return false;
+   }
+   if(!DecodeNesting_IsCurrentBounded(pNesting)) {
+      /* In a traveral at a level deeper than the bounded level */
+      return false;
+   }
+   /* Works for both definite- and indefinitelength maps/arrays */
+   if(pNesting->pCurrentBounded->u.ma.uCountCursor != 0 &&
+      pNesting->pCurrentBounded->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      /* Count is not zero, still unconsumed item */
+      return false;
+   }
+   /* All checks passed, got to the end of an array or map*/
+   return true;
+}
+
+
+static bool
+DecodeNesting_IsEndOfDefiniteLengthMapOrArray(const QCBORDecodeNesting *pNesting)
+{
+   /* Must only be called on map / array */
+   if(pNesting->pCurrent->u.ma.uCountCursor == 0) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static bool
+DecodeNesting_IsCurrentTypeMap(const QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->uLevelType == CBOR_MAJOR_TYPE_MAP) {
+      return true;
+   } else {
+      return false;
+   }
+}
+
+
+static bool
+DecodeNesting_IsBoundedType(const QCBORDecodeNesting *pNesting, uint8_t uType)
+{
+   if(pNesting->pCurrentBounded == NULL) {
+      return false;
+   }
+
+   uint8_t uItemDataType = pNesting->pCurrentBounded->uLevelType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   if(uItemDataType != uType) {
+      return false;
+   }
+
+   return true;
+}
+
+
+static void
+DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   /* Only call on a definite-length array / map */
+   pNesting->pCurrent->u.ma.uCountCursor--;
+}
+
+
+static void
+DecodeNesting_ReverseDecrement(QCBORDecodeNesting *pNesting)
+{
+   /* Only call on a definite-length array / map */
+   pNesting->pCurrent->u.ma.uCountCursor++;
+}
+
+
+static void
+DecodeNesting_Ascend(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent--;
+}
+
+
+static QCBORError
+DecodeNesting_Descend(QCBORDecodeNesting *pNesting, uint8_t uType)
+{
+   /* Error out if nesting is too deep */
+   if(pNesting->pCurrent >= &(pNesting->pLevels[QCBOR_MAX_ARRAY_NESTING])) {
+      return QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP;
+   }
+
+   /* The actual descend */
+   pNesting->pCurrent++;
+
+   pNesting->pCurrent->uLevelType = uType;
+
+   return QCBOR_SUCCESS;
+}
+
+
+static QCBORError
+DecodeNesting_EnterBoundedMapOrArray(QCBORDecodeNesting *pNesting,
+                                     bool                bIsEmpty,
+                                     size_t              uOffset)
+{
+   /*
+    * Should only be called on map/array.
+    *
+    * Have descended into this before this is called. The job here is
+    * just to mark it in bounded mode.
+    *
+    * Check against QCBOR_MAX_DECODE_INPUT_SIZE make sure that
+    * uOffset doesn't collide with QCBOR_NON_BOUNDED_OFFSET.
+    *
+    * Cast of uOffset to uint32_t for cases where SIZE_MAX < UINT32_MAX.
+    */
+   if((uint32_t)uOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
+      return QCBOR_ERR_INPUT_TOO_LARGE;
+   }
+
+   pNesting->pCurrentBounded = pNesting->pCurrent;
+
+   DecodeNesting_SetMapOrArrayBoundedMode(pNesting, bIsEmpty, uOffset);
+
+   return QCBOR_SUCCESS;
+}
+
+
+static QCBORError
+DecodeNesting_DescendMapOrArray(QCBORDecodeNesting *pNesting,
+                                uint8_t             uQCBORType,
+                                uint64_t            uCount)
+{
+   QCBORError uError = QCBOR_SUCCESS;
+
+   if(uCount == 0) {
+      /* Nothing to do for empty definite-length arrays. They are just are
+       * effectively the same as an item that is not a map or array.
+       */
+      goto Done;
+      /* Empty indefinite-length maps and arrays are handled elsewhere */
+   }
+
+   /* Error out if arrays is too long to handle */
+   if(uCount != QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH &&
+      uCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
+      uError = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
+      goto Done;
+   }
+
+   uError = DecodeNesting_Descend(pNesting, uQCBORType);
+   if(uError != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   /* Fill in the new map/array level. Check above makes casts OK. */
+   pNesting->pCurrent->u.ma.uCountCursor  = (uint16_t)uCount;
+   pNesting->pCurrent->u.ma.uCountTotal   = (uint16_t)uCount;
+
+   DecodeNesting_ClearBoundedMode(pNesting);
+
+Done:
+   return uError;;
+}
+
+
+static void
+DecodeNesting_LevelUpCurrent(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent = pNesting->pCurrentBounded - 1;
+}
+
+
+static void
+DecodeNesting_LevelUpBounded(QCBORDecodeNesting *pNesting)
+{
+   while(pNesting->pCurrentBounded != &(pNesting->pLevels[0])) {
+      pNesting->pCurrentBounded--;
+      if(DecodeNesting_IsCurrentBounded(pNesting)) {
+         break;
+      }
+   }
+}
+
+
+static void
+DecodeNesting_SetCurrentToBoundedLevel(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent = pNesting->pCurrentBounded;
+}
+
+
+static QCBORError
+DecodeNesting_DescendIntoBstrWrapped(QCBORDecodeNesting *pNesting,
+                                     uint32_t            uEndOffset,
+                                     uint32_t            uStartOffset)
+{
+   QCBORError uError;
+
+   uError = DecodeNesting_Descend(pNesting, QCBOR_TYPE_BYTE_STRING);
+   if(uError != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   /* Fill in the new byte string level */
+   pNesting->pCurrent->u.bs.uSavedEndOffset  = uEndOffset;
+   pNesting->pCurrent->u.bs.uBstrStartOffset = uStartOffset;
+
+   /* Bstr wrapped levels are always bounded */
+   pNesting->pCurrentBounded = pNesting->pCurrent;
+
+Done:
+   return uError;;
+}
+
+
+static void
+DecodeNesting_ZeroMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   pNesting->pCurrent->u.ma.uCountCursor = 0;
+}
+
+
+static void
+DecodeNesting_ResetMapOrArrayCount(QCBORDecodeNesting *pNesting)
+{
+   if(pNesting->pCurrent->u.ma.uCountCursor != QCBOR_COUNT_INDICATES_ZERO_LENGTH) {
+      pNesting->pCurrentBounded->u.ma.uCountCursor = pNesting->pCurrentBounded->u.ma.uCountTotal;
+   }
+}
+
+
+static void
+DecodeNesting_Init(QCBORDecodeNesting *pNesting)
+{
+   /* Assumes that *pNesting has been zero'd before this call. */
+   pNesting->pLevels[0].uLevelType = QCBOR_TYPE_BYTE_STRING;
+   pNesting->pCurrent = &(pNesting->pLevels[0]);
+}
+
+
+static void
+DecodeNesting_PrepareForMapSearch(QCBORDecodeNesting *pNesting,
+                                  QCBORDecodeNesting *pSave)
+{
+   *pSave = *pNesting;
+}
+
+
+static void
+DecodeNesting_RestoreFromMapSearch(QCBORDecodeNesting *pNesting,
+                                   const QCBORDecodeNesting *pSave)
+{
+   *pNesting = *pSave;
+}
+
+
+static uint32_t
+DecodeNesting_GetPreviousBoundedEnd(const QCBORDecodeNesting *pMe)
+{
+   return pMe->pCurrentBounded->u.bs.uSavedEndOffset;
+}
+
+
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+/*===========================================================================
+   QCBORStringAllocate -- STRING ALLOCATOR INVOCATION
+
+   The following four functions are pretty wrappers for invocation of
+   the string allocator supplied by the caller.
+
+  ===========================================================================*/
+
+static void
+StringAllocator_Free(const QCBORInternalAllocator *pMe, const void *pMem)
+{
+   /* This cast to uintptr_t suppresses the "-Wcast-qual" warnings.
+    * This is the one place where the const needs to be cast away so const can
+    * be use in the rest of the code.
+    */
+   (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, 0);
+}
+
+// StringAllocator_Reallocate called with pMem NULL is
+// equal to StringAllocator_Allocate()
+static UsefulBuf
+StringAllocator_Reallocate(const QCBORInternalAllocator *pMe,
+                           const void *pMem,
+                           size_t uSize)
+{
+   /* See comment in StringAllocator_Free() */
+   return (pMe->pfAllocator)(pMe->pAllocateCxt, (void *)(uintptr_t)pMem, uSize);
+}
+
+static UsefulBuf
+StringAllocator_Allocate(const QCBORInternalAllocator *pMe, size_t uSize)
+{
+   return (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, uSize);
+}
+
+static void
+StringAllocator_Destruct(const QCBORInternalAllocator *pMe)
+{
+   /* See comment in StringAllocator_Free() */
+   if(pMe->pfAllocator) {
+      (pMe->pfAllocator)(pMe->pAllocateCxt, NULL, 0);
+   }
+}
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+
+
+
+/*===========================================================================
+ QCBORDecode -- The main implementation of CBOR decoding
+
+ See qcbor/qcbor_decode.h for definition of the object
+ used here: QCBORDecodeContext
+  ===========================================================================*/
+/*
+ * Public function, see header file
+ */
+void
+QCBORDecode_Init(QCBORDecodeContext *pMe,
+                 UsefulBufC          EncodedCBOR,
+                 QCBORDecodeMode     nDecodeMode)
+{
+   memset(pMe, 0, sizeof(QCBORDecodeContext));
+   UsefulInputBuf_Init(&(pMe->InBuf), EncodedCBOR);
+   /* Don't bother with error check on decode mode. If a bad value is
+    * passed it will just act as if the default normal mode of 0 was set.
+    */
+   pMe->uDecodeMode = (uint8_t)nDecodeMode;
+   DecodeNesting_Init(&(pMe->nesting));
+
+   /* Inialize me->auMappedTags to CBOR_TAG_INVALID16. See
+    * GetNext_TaggedItem() and MapTagNumber(). */
+   memset(pMe->auMappedTags, 0xff, sizeof(pMe->auMappedTags));
+}
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+
+/*
+ * Public function, see header file
+ */
+void
+QCBORDecode_SetUpAllocator(QCBORDecodeContext *pMe,
+                           QCBORStringAllocate pfAllocateFunction,
+                           void               *pAllocateContext,
+                           bool                bAllStrings)
+{
+   pMe->StringAllocator.pfAllocator   = pfAllocateFunction;
+   pMe->StringAllocator.pAllocateCxt  = pAllocateContext;
+   pMe->bStringAllocateAll            = bAllStrings;
+}
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+
+
+
+/*
+ * Deprecated public function, see header file
+ */
+void
+QCBORDecode_SetCallerConfiguredTagList(QCBORDecodeContext   *pMe,
+                                       const QCBORTagListIn *pTagList)
+{
+   /* This does nothing now. It is retained for backwards compatibility */
+   (void)pMe;
+   (void)pTagList;
+}
+
+
+
+
+/*
+ * Decoding items is done in six layers, one calling the next one
+ * down. If a layer has no work to do for a particular item, it
+ * returns quickly.
+ *
+ * 1. QCBORDecode_Private_GetNextTagContent - The top layer processes
+ * tagged data items, turning them into the local C representation.
+ * For the most simple it is just associating a QCBOR_TYPE with the
+ * data. For the complex ones that an aggregate of data items, there
+ * is some further decoding and some limited recursion.
+ *
+ * 2. QCBORDecode_Private_GetNextMapOrArray - This manages the
+ * beginnings and ends of maps and arrays. It tracks descending into
+ * and ascending out of maps/arrays. It processes breaks that
+ * terminate indefinite-length maps and arrays.
+ *
+ * 3. QCBORDecode_Private_GetNextMapEntry - This handles the combining
+ * of two items, the label and the data, that make up a map entry.  It
+ * only does work on maps. It combines the label and data items into
+ * one labeled item.
+ *
+ * 4. QCBORDecode_Private_GetNextTagNumber - This decodes type 6 tag
+ * numbers. It turns the tag numbers into bit flags associated with
+ * the data item. No actual decoding of the contents of the tag is
+ * performed here.
+ *
+ * 5. QCBORDecode_Private_GetNextFullString - This assembles the
+ * sub-items that make up an indefinite-length string into one string
+ * item. It uses the string allocator to create contiguous space for
+ * the item. It processes all breaks that are part of
+ * indefinite-length strings.
+ *
+ * 6. QCBOR_Private_DecodeAtomicDataItem - This decodes the atomic
+ * data items in CBOR. Each atomic data item has a "major type", an
+ * integer "argument" and optionally some content. For text and byte
+ * strings, the content is the bytes that make up the string. These
+ * are the smallest data items that are considered to be well-formed.
+ * The content may also be other data items in the case of aggregate
+ * types. They are not handled in this layer.
+ *
+ * This uses about 350 bytes of stack. This number comes from
+ * instrumenting (printf address of stack variables) the code on x86
+ * compiled for size optimization.
+ */
+
+
+/*
+ * Note about use of int and unsigned variables.
+ *
+ * See http://www.unix.org/whitepapers/64bit.html for reasons int is
+ * used carefully here, and in particular why it isn't used in the
+ * public interface.  Also see
+ * https://stackoverflow.com/questions/17489857/why-is-int-typically-32-bit-on-64-bit-compilers
+ *
+ * Int is used for values that need less than 16-bits and would be
+ * subject to integer promotion and result in complaining from static
+ * analyzers.
+ */
+
+
+/**
+ * @brief Decode the CBOR head, the type and argument.
+ *
+ * @param[in] pUInBuf            The input buffer to read from.
+ * @param[out] pnMajorType       The decoded major type.
+ * @param[out] puArgument        The decoded argument.
+ * @param[out] pnAdditionalInfo  The decoded Lower 5 bits of initial byte.
+ *
+ * @retval QCBOR_ERR_UNSUPPORTED Encountered unsupported/reserved features
+ * @retval QCBOR_ERR_HIT_END Unexpected end of input
+ *
+ * This decodes the CBOR "head" that every CBOR data item has. See
+ * longer explaination of the head in documentation for
+ * QCBOREncode_EncodeHead().
+ *
+ * This does the network->host byte order conversion. The conversion
+ * here also results in the conversion for floats in addition to that
+ * for lengths, tags and integer values.
+ *
+ * The int type is preferred to uint8_t for some variables as this
+ * avoids integer promotions, can reduce code size and makes static
+ * analyzers happier.
+ */
+static QCBORError
+QCBOR_Private_DecodeHead(UsefulInputBuf *pUInBuf,
+                         int            *pnMajorType,
+                         uint64_t       *puArgument,
+                         int            *pnAdditionalInfo)
+{
+   QCBORError uReturn;
+
+   /* Get the initial byte that every CBOR data item has and break it
+    * down. */
+   const int nInitialByte    = (int)UsefulInputBuf_GetByte(pUInBuf);
+   const int nTmpMajorType   = nInitialByte >> 5;
+   const int nAdditionalInfo = nInitialByte & 0x1f;
+
+   /* Where the argument accumulates */
+   uint64_t uArgument;
+
+   if(nAdditionalInfo >= LEN_IS_ONE_BYTE && nAdditionalInfo <= LEN_IS_EIGHT_BYTES) {
+      /* Need to get 1,2,4 or 8 additional argument bytes. Map
+       * LEN_IS_ONE_BYTE..LEN_IS_EIGHT_BYTES to actual length.
+       */
+      static const uint8_t aIterate[] = {1,2,4,8};
+
+      /* Loop getting all the bytes in the argument */
+      uArgument = 0;
+      for(int i = aIterate[nAdditionalInfo - LEN_IS_ONE_BYTE]; i; i--) {
+         /* This shift and add gives the endian conversion. */
+         uArgument = (uArgument << 8) + UsefulInputBuf_GetByte(pUInBuf);
+      }
+   } else if(nAdditionalInfo >= ADDINFO_RESERVED1 && nAdditionalInfo <= ADDINFO_RESERVED3) {
+      /* The reserved and thus-far unused additional info values */
+      uReturn = QCBOR_ERR_UNSUPPORTED;
+      goto Done;
+   } else {
+      /* Less than 24, additional info is argument or 31, an
+       * indefinite-length.  No more bytes to get.
+       */
+      uArgument = (uint64_t)nAdditionalInfo;
+   }
+
+   if(UsefulInputBuf_GetError(pUInBuf)) {
+      uReturn = QCBOR_ERR_HIT_END;
+      goto Done;
+   }
+
+   /* All successful if arrived here. */
+   uReturn           = QCBOR_SUCCESS;
+   *pnMajorType      = nTmpMajorType;
+   *puArgument       = uArgument;
+   *pnAdditionalInfo = nAdditionalInfo;
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode integer types, major types 0 and 1.
+ *
+ * @param[in] nMajorType       The CBOR major type (0 or 1).
+ * @param[in] uArgument        The argument from the head.
+ * @param[in] nAdditionalInfo  So it can be error-checked.
+ * @param[out] pDecodedItem    The filled in decoded item.
+ *
+ * @retval QCBOR_ERR_INT_OVERFLOW  Too-large negative encountered.
+ * @retval QCBOR_ERR_BAD_INT       nAdditionalInfo indicated indefinte.
+ *
+ * Must only be called when major type is 0 or 1.
+ *
+ * CBOR doesn't explicitly specify two's compliment for integers but
+ * all CPUs use it these days and the test vectors in the RFC are
+ * so. All integers in the CBOR structure are positive and the major
+ * type indicates positive or negative.  CBOR can express positive
+ * integers up to 2^x - 1 where x is the number of bits and negative
+ * integers down to 2^x.  Note that negative numbers can be one more
+ * away from zero than positive.  Stdint, as far as I can tell, uses
+ * two's compliment to represent negative integers.
+ */
+static QCBORError
+QCBOR_Private_DecodeInteger(const int      nMajorType,
+                            const uint64_t uArgument,
+                            const int      nAdditionalInfo,
+                            QCBORItem     *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      uReturn = QCBOR_ERR_BAD_INT;
+      goto Done;
+   }
+
+   if(nMajorType == CBOR_MAJOR_TYPE_POSITIVE_INT) {
+      if (uArgument <= INT64_MAX) {
+         pDecodedItem->val.int64 = (int64_t)uArgument;
+         pDecodedItem->uDataType = QCBOR_TYPE_INT64;
+
+      } else {
+         pDecodedItem->val.uint64 = uArgument;
+         pDecodedItem->uDataType  = QCBOR_TYPE_UINT64;
+      }
+
+   } else {
+      if(uArgument <= INT64_MAX) {
+         /* CBOR's representation of negative numbers lines up with
+          * the two-compliment representation. A negative integer has
+          * one more in range than a positive integer. INT64_MIN is
+          * equal to (-INT64_MAX) - 1.
+          */
+         pDecodedItem->val.int64 = (-(int64_t)uArgument) - 1;
+         pDecodedItem->uDataType = QCBOR_TYPE_INT64;
+
+      } else {
+         /* C can't represent a negative integer in this range so it
+          * is an error.
+          */
+         uReturn = QCBOR_ERR_INT_OVERFLOW;
+      }
+   }
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode text and byte strings
+ *
+ * @param[in] pMe              Decoder context.
+ * @param[in] bAllocate        Whether to allocate and copy string.
+ * @param[in] nMajorType       Whether it is a byte or text string.
+ * @param[in] uStrLen          The length of the string.
+ * @param[in] nAdditionalInfo  Whether it is an indefinite-length string.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_HIT_END          Unexpected end of input.
+ * @retval QCBOR_ERR_STRING_ALLOCATE  Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG  String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR  Allocation requested, but no allocator
+ *
+ * This reads @c uStrlen bytes from the input and fills in @c
+ * pDecodedItem. If @c bAllocate is true, then memory for the string
+ * is allocated.
+ */
+static QCBORError
+QCBOR_Private_DecodeString(QCBORDecodeContext  *pMe,
+                           const bool           bAllocate,
+                           const int            nMajorType,
+                           const uint64_t       uStrLen,
+                           const int            nAdditionalInfo,
+                           QCBORItem           *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   /* ---- Figure out the major type ---- */
+   #if CBOR_MAJOR_TYPE_BYTE_STRING + 4 != QCBOR_TYPE_BYTE_STRING
+   #error QCBOR_TYPE_BYTE_STRING not lined up with major type
+   #endif
+
+   #if CBOR_MAJOR_TYPE_TEXT_STRING + 4 != QCBOR_TYPE_TEXT_STRING
+   #error QCBOR_TYPE_TEXT_STRING not lined up with major type
+   #endif
+   pDecodedItem->uDataType = (uint8_t)(nMajorType + 4);
+
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      /* --- Just the head of an indefinite-length string --- */
+      pDecodedItem->val.string = (UsefulBufC){NULL, QCBOR_STRING_LENGTH_INDEFINITE};
+
+   } else {
+      /* --- A definite-length string --- */
+      /* --- (which might be a chunk of an indefinte-length string) --- */
+
+      /* CBOR lengths can be 64 bits, but size_t is not 64 bits on all
+       * CPUs.  This check makes the casts to size_t below safe.
+       *
+       * The max is 4 bytes less than the largest sizeof() so this can be
+       * tested by putting a SIZE_MAX length in the CBOR test input (no
+       * one will care the limit on strings is 4 bytes shorter).
+       */
+      if(uStrLen > SIZE_MAX-4) {
+         uReturn = QCBOR_ERR_STRING_TOO_LONG;
+         goto Done;
+      }
+
+      const UsefulBufC Bytes = UsefulInputBuf_GetUsefulBuf(&(pMe->InBuf), (size_t)uStrLen);
+      if(UsefulBuf_IsNULLC(Bytes)) {
+         /* Failed to get the bytes for this string item */
+         uReturn = QCBOR_ERR_HIT_END;
+         goto Done;
+      }
+
+      if(bAllocate) {
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+         /* --- Put string in allocated memory --- */
+
+         /* Note that this is not where allocation to coalesce
+          * indefinite-length strings is done. This is for when the
+          * caller has requested all strings be allocated. Disabling
+          * indefinite length strings also disables this allocate-all
+          * option.
+          */
+
+         if(pMe->StringAllocator.pfAllocator == NULL) {
+            uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
+            goto Done;
+         }
+         UsefulBuf NewMem = StringAllocator_Allocate(&(pMe->StringAllocator), (size_t)uStrLen);
+         if(UsefulBuf_IsNULL(NewMem)) {
+            uReturn = QCBOR_ERR_STRING_ALLOCATE;
+            goto Done;
+         }
+         pDecodedItem->val.string = UsefulBuf_Copy(NewMem, Bytes);
+         pDecodedItem->uDataAlloc = 1;
+#else
+         uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
+#endif /*  ! QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+      } else {
+         /* --- Normal case with no string allocator --- */
+         pDecodedItem->val.string = Bytes;
+      }
+   }
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode array or map.
+ *
+ * @param[in] uMode            Decoder mode.
+ * @param[in] nMajorType       Whether it is a byte or text string.
+ * @param[in] uItemCount       The length of the string.
+ * @param[in] nAdditionalInfo  Whether it is an indefinite-length.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED Indefinites disabled.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG     Too many items in array/map.
+ *
+ * Not much to do for arrays and maps. Just the type item count (but a
+ * little messy because of ifdefs for indefinite-lengths and
+ * map-as-array decoding).
+ *
+ * This also does the bulk of the work for @ref
+ * QCBOR_DECODE_MODE_MAP_AS_ARRAY, a special mode to handle
+ * arbitrarily complex map labels. This ifdefs out with
+ * QCBOR_DISABLE_NON_INTEGER_LABELS.
+ */
+static QCBORError
+QCBOR_Private_DecodeArrayOrMap(const uint8_t  uMode,
+                               const int      nMajorType,
+                               const uint64_t uItemCount,
+                               const int      nAdditionalInfo,
+                               QCBORItem     *pDecodedItem)
+{
+   QCBORError uReturn;
+
+   /* ------ Sort out the data type ------ */
+   #if QCBOR_TYPE_ARRAY != CBOR_MAJOR_TYPE_ARRAY
+   #error QCBOR_TYPE_ARRAY value not lined up with major type
+   #endif
+
+   #if QCBOR_TYPE_MAP != CBOR_MAJOR_TYPE_MAP
+   #error QCBOR_TYPE_MAP value not lined up with major type
+   #endif
+   pDecodedItem->uDataType = (uint8_t)nMajorType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+      pDecodedItem->uDataType = QCBOR_TYPE_MAP_AS_ARRAY;
+   }
+#else
+   (void)uMode;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   uReturn = QCBOR_SUCCESS;
+
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      /* ------ Indefinite-length array/map ----- */
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+      pDecodedItem->val.uCount = QCBOR_COUNT_INDICATES_INDEFINITE_LENGTH;
+#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+      uReturn = QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED;
+#endif /* ! QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+   } else {
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      if(uMode == QCBOR_DECODE_MODE_MAP_AS_ARRAY && nMajorType == QCBOR_TYPE_MAP) {
+         /* ------ Definite-length map as array ------ */
+
+         if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY/2) {
+            uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
+         } else {
+            /* cast OK because of check above */
+            pDecodedItem->val.uCount = (uint16_t)uItemCount*2;
+         }
+
+      } else
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+      {
+         /* ------ Definite-length array/map ------ */
+         if(uItemCount > QCBOR_MAX_ITEMS_IN_ARRAY) {
+            uReturn = QCBOR_ERR_ARRAY_DECODE_TOO_LONG;
+         } else {
+            /* cast OK because of check above */
+            pDecodedItem->val.uCount = (uint16_t)uItemCount;
+         }
+      }
+   }
+
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode a tag number.
+ *
+ * @param[in] uTagNumber       The length of the string.
+ * @param[in] nAdditionalInfo  So this can be error-checked.
+ * @param[out] pDecodedItem    The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_BAD_INT        nAdditionalInfo is LEN_IS_INDEFINITE.
+ * @retval QCBOR_ERR_TAGS_DISABLED  QCBOR_DISABLE_TAGS is defined.
+ *
+ * Not much to do for tags, but fill in pDecodedItem and check for
+ * error in nAdditionalInfo.
+ */
+static QCBORError
+QCBOR_Private_DecodeTag(const uint64_t uTagNumber,
+                        const int      nAdditionalInfo,
+                        QCBORItem     *pDecodedItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   if(nAdditionalInfo == LEN_IS_INDEFINITE) {
+      return QCBOR_ERR_BAD_INT;
+   } else {
+      pDecodedItem->val.uTagV = uTagNumber;
+      pDecodedItem->uDataType = QCBOR_TYPE_TAG;
+      return QCBOR_SUCCESS;
+   }
+#else /* QCBOR_DISABLE_TAGS */
+   (void)nAdditionalInfo;
+   (void)uTagNumber;
+   (void)pDecodedItem;
+   return QCBOR_ERR_TAGS_DISABLED;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+/* Make sure #define value line up as DecodeSimple counts on this. */
+#if QCBOR_TYPE_FALSE != CBOR_SIMPLEV_FALSE
+#error QCBOR_TYPE_FALSE macro value wrong
+#endif
+
+#if QCBOR_TYPE_TRUE != CBOR_SIMPLEV_TRUE
+#error QCBOR_TYPE_TRUE macro value wrong
+#endif
+
+#if QCBOR_TYPE_NULL != CBOR_SIMPLEV_NULL
+#error QCBOR_TYPE_NULL macro value wrong
+#endif
+
+#if QCBOR_TYPE_UNDEF != CBOR_SIMPLEV_UNDEF
+#error QCBOR_TYPE_UNDEF macro value wrong
+#endif
+
+#if QCBOR_TYPE_BREAK != CBOR_SIMPLE_BREAK
+#error QCBOR_TYPE_BREAK macro value wrong
+#endif
+
+#if QCBOR_TYPE_DOUBLE != DOUBLE_PREC_FLOAT
+#error QCBOR_TYPE_DOUBLE macro value wrong
+#endif
+
+#if QCBOR_TYPE_FLOAT != SINGLE_PREC_FLOAT
+#error QCBOR_TYPE_FLOAT macro value wrong
+#endif
+
+
+/**
+ * @brief Decode major type 7 -- true, false, floating-point, break...
+ *
+ * @param[in] nAdditionalInfo   The lower five bits from the initial byte.
+ * @param[in] uArgument         The argument from the head.
+ * @param[out] pDecodedItem     The filled in decoded item.
+ *
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all float
+ *                                           decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of simple
+ *                                           type in input.
+ */
+static QCBORError
+QCBOR_Private_DecodeType7(const int      nAdditionalInfo,
+                          const uint64_t uArgument,
+                          QCBORItem     *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   /* uAdditionalInfo is 5 bits from the initial byte. Compile time
+    * checks above make sure uAdditionalInfo values line up with
+    * uDataType values.  DecodeHead() never returns an AdditionalInfo
+    * > 0x1f so cast is safe.
+    */
+   pDecodedItem->uDataType = (uint8_t)nAdditionalInfo;
+
+   switch(nAdditionalInfo) {
+      /* No check for ADDINFO_RESERVED1 - ADDINFO_RESERVED3 as they
+       * are caught before this is called.
+       */
+
+      case HALF_PREC_FLOAT: /* 25 */
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+         /* Half-precision is returned as a double.  The cast to
+          * uint16_t is safe because the encoded value was 16 bits. It
+          * was widened to 64 bits to be passed in here.
+          */
+         pDecodedItem->val.dfnum = IEEE754_HalfToDouble((uint16_t)uArgument);
+         pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
+#endif /* QCBOR_DISABLE_PREFERRED_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_HALF_PREC(QCBOR_SUCCESS);
+         break;
+      case SINGLE_PREC_FLOAT: /* 26 */
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+         /* Single precision is normally returned as a double since
+          * double is widely supported, there is no loss of precision,
+          * it makes it easy for the caller in most cases and it can
+          * be converted back to single with no loss of precision
+          *
+          * The cast to uint32_t is safe because the encoded value was
+          * 32 bits. It was widened to 64 bits to be passed in here.
+          */
+         {
+            const float f = UsefulBufUtil_CopyUint32ToFloat((uint32_t)uArgument);
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+            /* In the normal case, use HW to convert float to
+             * double. */
+            pDecodedItem->val.dfnum = (double)f;
+            pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+            /* Use of float HW is disabled, return as a float. */
+            pDecodedItem->val.fnum = f;
+            pDecodedItem->uDataType = QCBOR_TYPE_FLOAT;
+
+            /* IEEE754_FloatToDouble() could be used here to return as
+             * a double, but it adds object code and most likely
+             * anyone disabling FLOAT HW use doesn't care about floats
+             * and wants to save object code.
+             */
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         }
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
+         break;
+
+      case DOUBLE_PREC_FLOAT: /* 27 */
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+         pDecodedItem->val.dfnum = UsefulBufUtil_CopyUint64ToDouble(uArgument);
+         pDecodedItem->uDataType = QCBOR_TYPE_DOUBLE;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+         uReturn = FLOAT_ERR_CODE_NO_FLOAT(QCBOR_SUCCESS);
+         break;
+
+      case CBOR_SIMPLEV_FALSE: /* 20 */
+      case CBOR_SIMPLEV_TRUE:  /* 21 */
+      case CBOR_SIMPLEV_NULL:  /* 22 */
+      case CBOR_SIMPLEV_UNDEF: /* 23 */
+      case CBOR_SIMPLE_BREAK:  /* 31 */
+         break; /* nothing to do */
+
+      case CBOR_SIMPLEV_ONEBYTE: /* 24 */
+         if(uArgument <= CBOR_SIMPLE_BREAK) {
+            /* This takes out f8 00 ... f8 1f which should be encoded
+             * as e0 … f7
+             */
+            uReturn = QCBOR_ERR_BAD_TYPE_7;
+            goto Done;
+         }
+         /* FALLTHROUGH */
+
+      default: /* 0-19 */
+         pDecodedItem->uDataType   = QCBOR_TYPE_UKNOWN_SIMPLE;
+         /* DecodeHead() will make uArgument equal to
+          * nAdditionalInfo when nAdditionalInfo is < 24. This cast is
+          * safe because the 2, 4 and 8 byte lengths of uNumber are in
+          * the double/float cases above
+          */
+         pDecodedItem->val.uSimple = (uint8_t)uArgument;
+         break;
+   }
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Decode a single primitive data item (decode layer 6).
+ *
+ * @param[in] pMe                Decoder context.
+ * @param[in] bAllocateStrings   If true, use allocator for strings.
+ * @param[out] pDecodedItem      The filled-in decoded item.
+ *
+ * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
+ *                                           features
+ * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
+ * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
+ * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Allocation requested, but no allocator
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
+ *                                           float decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
+ *                                           simple type in input.
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
+ *                                              in input, but indefinite
+ *                                              lengths disabled.
+ * @retval QCBOR_ERR_BAD_INT                 nAdditionalInfo indicated indefinte.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array/map.
+ * @retval QCBOR_ERR_TAGS_DISABLED           QCBOR_DISABLE_TAGS is defined.
+ *
+ * This decodes the most primitive/atomic data item. It does no
+ * combining of data items.
+ */
+static QCBORError
+QCBOR_Private_DecodeAtomicDataItem(QCBORDecodeContext  *pMe,
+                                   const bool           bAllocateStrings,
+                                   QCBORItem           *pDecodedItem)
+{
+   QCBORError uReturn;
+   int        nMajorType = 0;
+   uint64_t   uArgument = 0;
+   int        nAdditionalInfo = 0;
+
+   memset(pDecodedItem, 0, sizeof(QCBORItem));
+
+   /* Decode the "head" that every CBOR item has into the major type,
+    * argument and the additional info.
+    */
+   uReturn = QCBOR_Private_DecodeHead(&(pMe->InBuf), &nMajorType, &uArgument, &nAdditionalInfo);
+   if(uReturn != QCBOR_SUCCESS) {
+      return uReturn;
+   }
+
+   /* All the functions below get inlined by the optimizer. This code
+    * is easier to read with them all being similar functions, even if
+    * some functions don't do much.
+    */
+   switch (nMajorType) {
+      case CBOR_MAJOR_TYPE_POSITIVE_INT: /* Major type 0 */
+      case CBOR_MAJOR_TYPE_NEGATIVE_INT: /* Major type 1 */
+         return QCBOR_Private_DecodeInteger(nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
+         break;
+
+      case CBOR_MAJOR_TYPE_BYTE_STRING: /* Major type 2 */
+      case CBOR_MAJOR_TYPE_TEXT_STRING: /* Major type 3 */
+         return QCBOR_Private_DecodeString(pMe, bAllocateStrings, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
+         break;
+
+      case CBOR_MAJOR_TYPE_ARRAY: /* Major type 4 */
+      case CBOR_MAJOR_TYPE_MAP:   /* Major type 5 */
+         return QCBOR_Private_DecodeArrayOrMap(pMe->uDecodeMode, nMajorType, uArgument, nAdditionalInfo, pDecodedItem);
+         break;
+
+      case CBOR_MAJOR_TYPE_TAG: /* Major type 6, tag numbers */
+         return QCBOR_Private_DecodeTag(uArgument, nAdditionalInfo, pDecodedItem);
+         break;
+
+      case CBOR_MAJOR_TYPE_SIMPLE:
+         /* Major type 7: float, double, true, false, null... */
+         return QCBOR_Private_DecodeType7(nAdditionalInfo, uArgument, pDecodedItem);
+         break;
+
+      default:
+         /* Never happens because DecodeHead() should never return > 7 */
+         return QCBOR_ERR_UNSUPPORTED;
+         break;
+   }
+}
+
+
+/**
+ * @brief Process indefinite-length strings (decode layer 5).
+ *
+ * @param[in] pMe   Decoder context
+ * @param[out] pDecodedItem  The decoded item that work is done on.
+ *
+ * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
+ *                                           features
+ * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
+ * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
+ * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
+ *                                           float decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
+ *                                           simple type in input.
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
+ *                                              in input, but indefinite
+ *                                              lengths disabled.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
+ *                                           but no string allocator.
+ * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
+ * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
+ *                                               input, but indefinite-length
+ *                                               strings are disabled.
+ *
+ * If @c pDecodedItem is not an indefinite-length string, this does nothing.
+ *
+ * If it is, this loops getting the subsequent chunk data items that
+ * make up the string.  The string allocator is used to make a
+ * contiguous buffer for the chunks.  When this completes @c
+ * pDecodedItem contains the put-together string.
+ *
+ * Code Reviewers: THIS FUNCTION DOES A LITTLE POINTER MATH
+ */
+static QCBORError
+QCBORDecode_Private_GetNextFullString(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pDecodedItem)
+{
+   /* Aproximate stack usage
+    *                                             64-bit      32-bit
+    *   local vars                                    32          16
+    *   2 UsefulBufs                                  32          16
+    *   QCBORItem                                     56          52
+    *   TOTAL                                        120          74
+    */
+   QCBORError uReturn;
+
+   /* A note about string allocation -- Memory for strings is
+    * allocated either because 1) indefinte-length string chunks are
+    * being coalecsed or 2) caller has requested all strings be
+    * allocated.  The first case is handed below here. The second case
+    * is handled in DecodeString if the bAllocate is true. That
+    * boolean originates here with pMe->bStringAllocateAll immediately
+    * below. That is, QCBOR_Private_DecodeAtomicDataItem() is called
+    * in two different contexts here 1) main-line processing which is
+    * where definite-length strings need to be allocated if
+    * bStringAllocateAll is true and 2) processing chunks of
+    * indefinite-lengths strings in in which case there must be no
+    * allocation.
+    */
+
+
+   uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, pMe->bStringAllocateAll, pDecodedItem);
+   if(uReturn != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+
+   /* This is where out-of-place break is detected for the whole
+    * decoding stack. Break is an error for everything that calls
+    * QCBORDecode_Private_GetNextFullString(), so the check is
+    * centralized here.
+    */
+   if(pDecodedItem->uDataType == QCBOR_TYPE_BREAK) {
+      uReturn = QCBOR_ERR_BAD_BREAK;
+      goto Done;
+   }
+
+
+   /* Skip out if not an indefinite-length string */
+   const uint8_t uStringType = pDecodedItem->uDataType;
+   if(uStringType != QCBOR_TYPE_BYTE_STRING &&
+      uStringType != QCBOR_TYPE_TEXT_STRING) {
+      goto Done;
+   }
+   if(pDecodedItem->val.string.len != QCBOR_STRING_LENGTH_INDEFINITE) {
+      goto Done;
+   }
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+   /* Can't decode indefinite-length strings without a string allocator */
+   if(!pMe->StringAllocator.pfAllocator) {
+      uReturn = QCBOR_ERR_NO_STRING_ALLOCATOR;
+      goto Done;
+   }
+
+   /* Loop getting chunks of the indefinite-length string */
+   UsefulBufC FullString = NULLUsefulBufC;
+
+   for(;;) {
+      /* Get QCBORItem for next chunk */
+      QCBORItem StringChunkItem;
+      /* Pass false to DecodeAtomicDataItem() because the individual
+       * string chunks in an indefinite-length must not be
+       * allocated. They are always copied into the allocated
+       * contiguous buffer allocated here.
+       */
+      uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &StringChunkItem);
+      if(uReturn) {
+         break;
+      }
+
+      /* Is item is the marker for end of the indefinite-length string? */
+      if(StringChunkItem.uDataType == QCBOR_TYPE_BREAK) {
+         /* String is complete */
+         pDecodedItem->val.string = FullString;
+         pDecodedItem->uDataAlloc = 1;
+         break;
+      }
+
+      /* All chunks must be of the same type, the type of the item
+       * that introduces the indefinite-length string. This also
+       * catches errors where the chunk is not a string at all and an
+       * indefinite-length string inside an indefinite-length string.
+       */
+      if(StringChunkItem.uDataType != uStringType ||
+         StringChunkItem.val.string.len == QCBOR_STRING_LENGTH_INDEFINITE) {
+         uReturn = QCBOR_ERR_INDEFINITE_STRING_CHUNK;
+         break;
+      }
+
+      if (StringChunkItem.val.string.len > 0) {
+         /* The first time throurgh FullString.ptr is NULL and this is
+          * equivalent to StringAllocator_Allocate(). Subsequently it is
+          * not NULL and a reallocation happens.
+          */
+         UsefulBuf NewMem = StringAllocator_Reallocate(&(pMe->StringAllocator),
+                                                       FullString.ptr,
+                                                       FullString.len + StringChunkItem.val.string.len);
+         if(UsefulBuf_IsNULL(NewMem)) {
+            uReturn = QCBOR_ERR_STRING_ALLOCATE;
+            break;
+         }
+
+         /* Copy new string chunk to the end of accumulated string */
+         FullString = UsefulBuf_CopyOffset(NewMem, FullString.len, StringChunkItem.val.string);
+      }
+   }
+
+   if(uReturn != QCBOR_SUCCESS && !UsefulBuf_IsNULLC(FullString)) {
+      /* Getting the item failed, clean up the allocated memory */
+      StringAllocator_Free(&(pMe->StringAllocator), FullString.ptr);
+   }
+#else /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+   uReturn = QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED;
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+Done:
+   return uReturn;
+}
+
+
+#ifndef QCBOR_DISABLE_TAGS
+/**
+ * @brief This converts a tag number to a shorter mapped value for storage.
+ *
+ * @param[in] pMe                The decode context.
+ * @param[in] uUnMappedTag       The tag number to map
+ * @param[out] puMappedTagNumer  The stored tag number.
+ *
+ * @return error code.
+ *
+ * The main point of mapping tag numbers is make QCBORItem
+ * smaller. With this mapping storage of 4 tags takes up 8
+ * bytes. Without, it would take up 32 bytes.
+ *
+ * This maps tag numbers greater than QCBOR_LAST_UNMAPPED_TAG.
+ * QCBOR_LAST_UNMAPPED_TAG is a little smaller than MAX_UINT16.
+ *
+ * See also UnMapTagNumber() and @ref QCBORItem.
+ */
+static QCBORError
+QCBORDecode_Private_MapTagNumber(QCBORDecodeContext *pMe,
+                                 const uint64_t      uUnMappedTag,
+                                 uint16_t           *puMappedTagNumer)
+{
+   if(uUnMappedTag > QCBOR_LAST_UNMAPPED_TAG) {
+      unsigned uTagMapIndex;
+      /* Is there room in the tag map, or is it in it already? */
+      for(uTagMapIndex = 0; uTagMapIndex < QCBOR_NUM_MAPPED_TAGS; uTagMapIndex++) {
+         if(pMe->auMappedTags[uTagMapIndex] == CBOR_TAG_INVALID64) {
+            break;
+         }
+         if(pMe->auMappedTags[uTagMapIndex] == uUnMappedTag) {
+            break;
+         }
+      }
+      if(uTagMapIndex >= QCBOR_NUM_MAPPED_TAGS) {
+         return QCBOR_ERR_TOO_MANY_TAGS;
+      }
+
+      /* Covers the cases where tag is new and were it is already in the map */
+      pMe->auMappedTags[uTagMapIndex] = uUnMappedTag;
+      *puMappedTagNumer = (uint16_t)(uTagMapIndex + QCBOR_LAST_UNMAPPED_TAG + 1);
+
+   } else {
+      *puMappedTagNumer = (uint16_t)uUnMappedTag;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief This converts a mapped tag number to the actual tag number.
+ *
+ * @param[in] pMe               The decode context.
+ * @param[in] uMappedTagNumber  The stored tag number.
+ *
+ * @return The actual tag number is returned or
+ *         @ref CBOR_TAG_INVALID64 on error.
+ *
+ * This is the reverse of MapTagNumber()
+ */
+static uint64_t
+QCBORDecode_Private_UnMapTagNumber(const QCBORDecodeContext *pMe,
+                                   const uint16_t            uMappedTagNumber)
+{
+   if(uMappedTagNumber <= QCBOR_LAST_UNMAPPED_TAG) {
+      return uMappedTagNumber;
+   } else if(uMappedTagNumber == CBOR_TAG_INVALID16) {
+      return CBOR_TAG_INVALID64;
+   } else {
+      /* This won't be negative because of code below in
+       * MapTagNumber()
+       */
+      const unsigned uIndex = uMappedTagNumber - (QCBOR_LAST_UNMAPPED_TAG + 1);
+      return pMe->auMappedTags[uIndex];
+   }
+}
+#endif /* QCBOR_DISABLE_TAGS */
+
+
+/**
+ * @brief Aggregate all tags wrapping a data item (decode layer 4).
+ *
+ * @param[in] pMe            Decoder context
+ * @param[out] pDecodedItem  The decoded item that work is done on.
+ *
+ * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
+ *                                           features
+ * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
+ * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
+ * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
+ *                                           float decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
+ *                                           simple type in input.
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
+ *                                              in input, but indefinite
+ *                                              lengths disabled.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
+ *                                           but no string allocator.
+ * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
+ * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
+ *                                               input, but indefinite-length
+ *                                               strings are disabled.
+ * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
+ *
+ * This loops getting atomic data items until one is not a tag
+ * number.  Usually this is largely pass-through because most
+ * item are not tag numbers.
+ */
+static QCBORError
+QCBORDecode_Private_GetNextTagNumber(QCBORDecodeContext *pMe,
+                                     QCBORItem          *pDecodedItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   /* Accummulate the tags from multiple items here and then copy them
+    * into the last item, the non-tag item.
+    */
+   uint16_t auItemsTags[QCBOR_MAX_TAGS_PER_ITEM];
+
+   /* Initialize to CBOR_TAG_INVALID16 */
+   #if CBOR_TAG_INVALID16 != 0xffff
+   /* Be sure the memset does the right thing. */
+   #err CBOR_TAG_INVALID16 tag not defined as expected
+   #endif
+   memset(auItemsTags, 0xff, sizeof(auItemsTags));
+
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   /* Loop fetching data items until the item fetched is not a tag */
+   for(;;) {
+      QCBORError uErr = QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
+      if(uErr != QCBOR_SUCCESS) {
+         uReturn = uErr;
+         goto Done;
+      }
+
+      if(pDecodedItem->uDataType != QCBOR_TYPE_TAG) {
+         /* Successful exit from loop; maybe got some tags, maybe not */
+         memcpy(pDecodedItem->uTags, auItemsTags, sizeof(auItemsTags));
+         break;
+      }
+
+      if(auItemsTags[QCBOR_MAX_TAGS_PER_ITEM - 1] != CBOR_TAG_INVALID16) {
+         /* No room in the tag list */
+         uReturn = QCBOR_ERR_TOO_MANY_TAGS;
+         /* Continue on to get all tags wrapping this item even though
+          * it is erroring out in the end. This allows decoding to
+          * continue. This is a resource limit error, not a problem
+          * with being well-formed CBOR.
+          */
+         continue;
+      }
+      /* Slide tags over one in the array to make room at index 0.
+       * Must use memmove because the move source and destination
+       * overlap.
+       */
+      memmove(&auItemsTags[1],
+              auItemsTags,
+              sizeof(auItemsTags) - sizeof(auItemsTags[0]));
+
+      /* Map the tag */
+      uint16_t uMappedTagNumber = 0;
+      uReturn = QCBORDecode_Private_MapTagNumber(pMe, pDecodedItem->val.uTagV, &uMappedTagNumber);
+      /* Continue even on error so as to consume all tags wrapping
+       * this data item so decoding can go on. If MapTagNumber()
+       * errors once it will continue to error.
+       */
+      auItemsTags[0] = uMappedTagNumber;
+   }
+
+Done:
+   return uReturn;
+
+#else /* QCBOR_DISABLE_TAGS */
+
+   return QCBORDecode_Private_GetNextFullString(pMe, pDecodedItem);
+
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+/**
+ * @brief Combine a map entry label and value into one item (decode layer 3).
+ *
+ * @param[in] pMe            Decoder context
+ * @param[out] pDecodedItem  The decoded item that work is done on.
+ *
+ * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
+ *                                           features
+ * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
+ * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
+ * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
+ *                                           float decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
+ *                                           simple type in input.
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
+ *                                              in input, but indefinite
+ *                                              lengths disabled.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
+ *                                           but no string allocator.
+ * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
+ * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
+ *                                               input, but indefinite-length
+ *                                               strings are disabled.
+ * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array.
+ * @retval QCBOR_ERR_MAP_LABEL_TYPE          Map label not string or integer.
+ *
+ * If the current nesting level is a map, then this combines pairs of
+ * items into one data item with a label and value.
+ *
+ * This is passthrough if the current nesting level is not a map.
+ *
+ * This also implements maps-as-array mode where a map is treated like
+ * an array to allow caller to do their own label processing.
+ */
+
+static QCBORError
+QCBORDecode_Private_GetNextMapEntry(QCBORDecodeContext *pMe,
+                                    QCBORItem          *pDecodedItem)
+{
+   QCBORItem  LabelItem;
+   QCBORError uErr;
+
+   uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+   if(QCBORDecode_IsUnrecoverableError(uErr)) {
+      goto Done;
+   }
+
+   if(!DecodeNesting_IsCurrentTypeMap(&(pMe->nesting))) {
+      /* Not decoding a map. Nothing to do. */
+      /* When decoding maps-as-arrays, the type will be
+       * QCBOR_TYPE_MAP_AS_ARRAY and this function will exit
+       * here. This is now map processing for maps-as-arrays is not
+       * done. */
+      goto Done;
+   }
+
+   /* Decoding a map entry, so the item decoded above was the label */
+   LabelItem = *pDecodedItem;
+
+   /* Get the value of the map item */
+   uErr = QCBORDecode_Private_GetNextTagNumber(pMe, pDecodedItem);
+   if(QCBORDecode_IsUnrecoverableError(uErr)) {
+      goto Done;
+   }
+
+   /* Combine the label item and value item into one */
+   pDecodedItem->uLabelAlloc = LabelItem.uDataAlloc;
+   pDecodedItem->uLabelType  = LabelItem.uDataType;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   /* QCBOR_DECODE_MODE_MAP_STRINGS_ONLY might have been a bad idea. Maybe
+    * get rid of it in QCBOR 2.0
+    */
+   if(pMe->uDecodeMode == QCBOR_DECODE_MODE_MAP_STRINGS_ONLY &&
+      LabelItem.uDataType != QCBOR_TYPE_TEXT_STRING) {
+      uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+      goto Done;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   switch(LabelItem.uDataType) {
+      case QCBOR_TYPE_INT64:
+         pDecodedItem->label.int64 = LabelItem.val.int64;
+         break;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+      case QCBOR_TYPE_UINT64:
+         pDecodedItem->label.uint64 = LabelItem.val.uint64;
+         break;
+
+      case QCBOR_TYPE_TEXT_STRING:
+      case QCBOR_TYPE_BYTE_STRING:
+         pDecodedItem->label.string = LabelItem.val.string;
+         break;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+      default:
+         uErr = QCBOR_ERR_MAP_LABEL_TYPE;
+         goto Done;
+   }
+
+Done:
+   return uErr;
+}
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+/**
+ * @brief Peek and see if next data item is a break;
+ *
+ * param[in]  pUIB            UsefulInputBuf to read from.
+ * @param[out] pbNextIsBreak   Indicate if next was a break or not.
+ *
+ * @return  Any decoding error.
+ *
+ * See if next item is a CBOR break. If it is, it is consumed,
+ * if not it is not consumed.
+*/
+static QCBORError
+QCBOR_Private_NextIsBreak(QCBORDecodeContext *pMe, bool *pbNextIsBreak)
+{
+   *pbNextIsBreak = false;
+   if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) != 0) {
+      QCBORItem Peek;
+      size_t uPeek = UsefulInputBuf_Tell(&(pMe->InBuf));
+      QCBORError uReturn = QCBOR_Private_DecodeAtomicDataItem(pMe, false, &Peek);
+      if(uReturn != QCBOR_SUCCESS) {
+         return uReturn;
+      }
+      if(Peek.uDataType != QCBOR_TYPE_BREAK) {
+         /* It is not a break, rewind so it can be processed normally. */
+         UsefulInputBuf_Seek(&(pMe->InBuf), uPeek);
+      } else {
+         *pbNextIsBreak = true;
+      }
+   }
+
+   return QCBOR_SUCCESS;
+}
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+
+/**
+ * @brief Ascend up nesting levels if all items in them have been consumed.
+ *
+ * @param[in] pMe       The decode context.
+ * @param[in] bMarkEnd  If true mark end of maps/arrays with count of zero.
+ * @param[out] pbBreak  Set to true if extra break was consumed.
+ *
+ * An item was just consumed, now figure out if it was the
+ * end of an array/map map that can be closed out. That
+ * may in turn close out the above array/map...
+ *
+ * When ascending indefinite-length arrays and maps, this will correctly
+ * consume the break for the level above. This is a problem for the
+ * implementation of QCBORDecode_GetArray() that must not return
+ * that break. @c pbBreak is set to true to indicate that one
+ * byte should be removed.
+ *
+ * Improvement: this could reduced further if indef is disabled
+ */
+static QCBORError
+QCBORDecode_Private_NestLevelAscender(QCBORDecodeContext *pMe, bool bMarkEnd, bool *pbBreak)
+{
+   QCBORError uReturn;
+
+   /* Loop ascending nesting levels as long as there is ascending to do */
+   while(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
+      if(pbBreak) {
+         *pbBreak = false;
+      }
+
+      if(DecodeNesting_IsCurrentBstrWrapped(&(pMe->nesting))) {
+         /* Nesting level is bstr-wrapped CBOR */
+
+         /* Ascent for bstr-wrapped CBOR is always by explicit call
+          * so no further ascending can happen.
+          */
+         break;
+
+      } else if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
+         /* Level is a definite-length array/map */
+
+         /* Decrement the item count the definite-length array/map */
+         DecodeNesting_DecrementDefiniteLengthMapOrArrayCount(&(pMe->nesting));
+         if(!DecodeNesting_IsEndOfDefiniteLengthMapOrArray(&(pMe->nesting))) {
+             /* Didn't close out array/map, so all work here is done */
+             break;
+          }
+          /* All items in a definite-length array were consumed so it
+           * is time to ascend one level. This happens below.
+           */
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+      } else {
+         /* Level is an indefinite-length array/map. */
+
+         /* Check for a break which is what ends indefinite-length arrays/maps */
+         bool bIsBreak = false;
+         uReturn = QCBOR_Private_NextIsBreak(pMe, &bIsBreak);
+         if(uReturn != QCBOR_SUCCESS) {
+            goto Done;
+         }
+
+         if(!bIsBreak) {
+            /* Not a break so array/map does not close out. All work is done */
+            break;
+         }
+
+         /* It was a break in an indefinitelength map / array so
+          * it is time to ascend one level.
+          */
+         if(pbBreak) {
+            *pbBreak = true;
+         }
+
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+      }
+
+
+      /* All items in the array/map have been consumed. */
+
+      /* But ascent in bounded mode is only by explicit call to
+       * QCBORDecode_ExitBoundedMode().
+       */
+      if(DecodeNesting_IsCurrentBounded(&(pMe->nesting))) {
+         /* Set the count to zero for definite-length arrays to indicate
+         * cursor is at end of bounded array/map */
+         if(bMarkEnd) {
+            /* Used for definite and indefinite to signal end */
+            DecodeNesting_ZeroMapOrArrayCount(&(pMe->nesting));
+
+         }
+         break;
+      }
+
+      /* Finally, actually ascend one level. */
+      DecodeNesting_Ascend(&(pMe->nesting));
+   }
+
+   uReturn = QCBOR_SUCCESS;
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+Done:
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+
+   return uReturn;
+}
+
+
+/**
+ * @brief Ascending & Descending out of nesting levels (decode layer 2).
+ *
+ * @param[in] pMe            Decoder context
+ * @param[out] pbBreak       Set to true if extra break was consumed.
+ * @param[out] pDecodedItem  The decoded item that work is done on.
+
+ * @retval QCBOR_ERR_UNSUPPORTED             Encountered unsupported/reserved
+ *                                           features
+ * @retval QCBOR_ERR_HIT_END                 Unexpected end of input
+ * @retval QCBOR_ERR_INT_OVERFLOW            Too-large negative encountered
+ * @retval QCBOR_ERR_STRING_ALLOCATE         Out of memory.
+ * @retval QCBOR_ERR_STRING_TOO_LONG         String longer than SIZE_MAX - 4.
+ * @retval QCBOR_ERR_HALF_PRECISION_DISABLED Half-precision in input, but decode
+ *                                           of half-precision disabled
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED      Float-point in input, but all
+ *                                           float decode is disabled.
+ * @retval QCBOR_ERR_BAD_TYPE_7              Not-allowed representation of
+ *                                           simple type in input.
+ * @retval QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED  Indefinite length map/array
+ *                                              in input, but indefinite
+ *                                              lengths disabled.
+ * @retval QCBOR_ERR_NO_STRING_ALLOCATOR     Indefinite-length string in input,
+ *                                           but no string allocator.
+ * @retval QCBOR_ERR_INDEFINITE_STRING_CHUNK  Error in indefinite-length string.
+ * @retval QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED  Indefinite-length string in
+ *                                               input, but indefinite-length
+ *                                               strings are disabled.
+ * @retval QCBOR_ERR_TOO_MANY_TAGS           Too many tag numbers on item.
+ * @retval QCBOR_ERR_ARRAY_DECODE_TOO_LONG   Too many items in array.
+ * @retval QCBOR_ERR_MAP_LABEL_TYPE          Map label not string or integer.
+ * @retval QCBOR_ERR_NO_MORE_ITEMS           Need more items for map or array.
+ * @retval QCBOR_ERR_BAD_BREAK               Indefinite-length break in wrong
+ *                                           place.
+ * @retval QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP  Nesting deeper than QCBOR
+ *                                                  can handle.
+ *
+ * This handles the traversal descending into and asecnding out of
+ * maps, arrays and bstr-wrapped CBOR. It figures out the ends of
+ * definite- and indefinte-length maps and arrays by looking at the
+ * item count or finding CBOR breaks.  It detects the ends of the
+ * top-level sequence and of bstr-wrapped CBOR by byte count.
+ */
+static QCBORError
+QCBORDecode_Private_GetNextMapOrArray(QCBORDecodeContext *pMe,
+                                      bool               *pbBreak,
+                                      QCBORItem          *pDecodedItem)
+{
+   QCBORError uReturn;
+   /* ==== First: figure out if at the end of a traversal ==== */
+
+   /* If out of bytes to consume, it is either the end of the
+    * top-level sequence of some bstr-wrapped CBOR that was entered.
+    *
+    * In the case of bstr-wrapped CBOR, the length of the
+    * UsefulInputBuf was set to that of the bstr-wrapped CBOR. When
+    * the bstr-wrapped CBOR is exited, the length is set back to the
+    * top-level's length or to the next highest bstr-wrapped CBOR.
+   */
+   if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf)) == 0) {
+      uReturn = QCBOR_ERR_NO_MORE_ITEMS;
+      goto Done;
+   }
+
+   /* Check to see if at the end of a bounded definite-length map or
+    * array. The check for a break ending indefinite-length array is
+    * later in QCBORDecode_NestLevelAscender().
+    */
+   if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
+      uReturn = QCBOR_ERR_NO_MORE_ITEMS;
+      goto Done;
+   }
+
+   /* ==== Next: not at the end, so get another item ==== */
+   uReturn = QCBORDecode_Private_GetNextMapEntry(pMe, pDecodedItem);
+   if(QCBORDecode_IsUnrecoverableError(uReturn)) {
+      /* Error is so bad that traversal is not possible. */
+      goto Done;
+   }
+
+   /* Record the nesting level for this data item before processing
+    * any of decrementing and descending.
+    */
+   pDecodedItem->uNestingLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
+
+
+   /* ==== Next: Process the item for descent, ascent, decrement... ==== */
+   if(QCBORItem_IsMapOrArray(*pDecodedItem)) {
+      /* If the new item is a map or array, descend.
+       *
+       * Empty indefinite-length maps and arrays are descended into,
+       * but then ascended out of in the next chunk of code.
+       *
+       * Maps and arrays do count as items in the map/array that
+       * encloses them so a decrement needs to be done for them too,
+       * but that is done only when all the items in them have been
+       * processed, not when they are opened with the exception of an
+       * empty map or array.
+       */
+      QCBORError uDescendErr;
+      uDescendErr = DecodeNesting_DescendMapOrArray(&(pMe->nesting),
+                                                pDecodedItem->uDataType,
+                                                pDecodedItem->val.uCount);
+      if(uDescendErr != QCBOR_SUCCESS) {
+         /* This error is probably a traversal error and it overrides
+          * the non-traversal error.
+          */
+         uReturn = uDescendErr;
+         goto Done;
+      }
+   }
+
+   if(!QCBORItem_IsMapOrArray(*pDecodedItem) ||
+       QCBORItem_IsEmptyDefiniteLengthMapOrArray(*pDecodedItem) ||
+       QCBORItem_IsIndefiniteLengthMapOrArray(*pDecodedItem)) {
+      /* The following cases are handled here:
+       *  - A non-aggregate item like an integer or string
+       *  - An empty definite-length map or array
+       *  - An indefinite-length map or array that might be empty or might not.
+       *
+       * QCBORDecode_NestLevelAscender() does the work of decrementing the count
+       * for an definite-length map/array and break detection for an
+       * indefinite-0length map/array. If the end of the map/array was
+       * reached, then it ascends nesting levels, possibly all the way
+       * to the top level.
+       */
+      QCBORError uAscendErr;
+      uAscendErr = QCBORDecode_Private_NestLevelAscender(pMe, true, pbBreak);
+      if(uAscendErr != QCBOR_SUCCESS) {
+         /* This error is probably a traversal error and it overrides
+          * the non-traversal error.
+          */
+         uReturn = uAscendErr;
+         goto Done;
+      }
+   }
+
+   /* ==== Last: tell the caller the nest level of the next item ==== */
+   /* Tell the caller what level is next. This tells them what
+    * maps/arrays were closed out and makes it possible for them to
+    * reconstruct the tree with just the information returned in a
+    * QCBORItem.
+   */
+   if(DecodeNesting_IsAtEndOfBoundedLevel(&(pMe->nesting))) {
+      /* At end of a bounded map/array; uNextNestLevel 0 to indicate this */
+      pDecodedItem->uNextNestLevel = 0;
+   } else {
+      pDecodedItem->uNextNestLevel = DecodeNesting_GetCurrentLevel(&(pMe->nesting));
+   }
+
+Done:
+   return uReturn;
+}
+
+
+#ifndef QCBOR_DISABLE_TAGS
+/**
+ * @brief Shift 0th tag out of the tag list.
+ *
+ * pDecodedItem[in,out]  The data item to convert.
+ *
+ * The 0th tag is discarded. \ref CBOR_TAG_INVALID16 is
+ * shifted into empty slot at the end of the tag list.
+ */
+static void
+QCBOR_Private_ShiftTags(QCBORItem *pDecodedItem)
+{
+   for(int i = 0; i < QCBOR_MAX_TAGS_PER_ITEM-1; i++) {
+      pDecodedItem->uTags[i] = pDecodedItem->uTags[i+1];
+   }
+   pDecodedItem->uTags[QCBOR_MAX_TAGS_PER_ITEM-1] = CBOR_TAG_INVALID16;
+}
+#endif /* QCBOR_DISABLE_TAGS */
+
+
+/**
+ * @brief Convert different epoch date formats in to the QCBOR epoch date format
+ *
+ * pDecodedItem[in,out]  The data item to convert.
+ *
+ * @retval QCBOR_ERR_DATE_OVERFLOW              65-bit negative integer.
+ * @retval QCBOR_ERR_FLOAT_DATE_DISABLED        Float-point date in input,
+ *                                              floating-point date disabled.
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED         Float-point date in input,
+ *                                              all floating-point disabled.
+ * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT  Unexpected and unrecoverable
+ *                                              error decoding date.
+ *
+ * The epoch date tag defined in QCBOR allows for floating-point
+ * dates. It even allows a protocol to flop between date formats when
+ * ever it wants.  Floating-point dates aren't that useful as they are
+ * only needed for dates beyond the age of the earth.
+ *
+ * This converts all the date formats into one format of an unsigned
+ * integer plus a floating-point fraction.
+ */
+static QCBORError
+QCBOR_Private_DecodeDateEpoch(QCBORItem *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+   pDecodedItem->val.epochDate.fSecondsFraction = 0;
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+   switch (pDecodedItem->uDataType) {
+
+      case QCBOR_TYPE_INT64:
+         pDecodedItem->val.epochDate.nSeconds = pDecodedItem->val.int64;
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         /* This only happens for CBOR type 0 > INT64_MAX so it is
+          * always an overflow.
+          */
+         uReturn = QCBOR_ERR_DATE_OVERFLOW;
+         goto Done;
+         break;
+
+      case QCBOR_TYPE_DOUBLE:
+      case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+      {
+         /* Convert working value to double if input was a float */
+         const double d = pDecodedItem->uDataType == QCBOR_TYPE_DOUBLE ?
+                   pDecodedItem->val.dfnum :
+                   (double)pDecodedItem->val.fnum;
+
+         /* The conversion from float to integer requires overflow
+          * detection since floats can be much larger than integers.
+          * This implementation errors out on these large float values
+          * since they are beyond the age of the earth.
+          *
+          * These constants for the overflow check are computed by the
+          * compiler. They are not computed at run time.
+          *
+          * The factor of 0x7ff is added/subtracted to avoid a
+          * rounding error in the wrong direction when the compiler
+          * computes these constants. There is rounding because a
+          * 64-bit integer has 63 bits of precision where a double
+          * only has 53 bits. Without the 0x7ff factor, the compiler
+          * may round up and produce a double for the bounds check
+          * that is larger than can be stored in a 64-bit integer. The
+          * amount of 0x7ff is picked because it has 11 bits set.
+          *
+          * Without the 0x7ff there is a ~30 minute range of time
+          * values 10 billion years in the past and in the future
+          * where this code could go wrong. Some compilers
+          * generate a warning or error without the 0x7ff.
+          */
+         const double dDateMax = (double)(INT64_MAX - 0x7ff);
+         const double dDateMin = (double)(INT64_MIN + 0x7ff);
+
+         if(isnan(d) || d > dDateMax || d < dDateMin) {
+            uReturn = QCBOR_ERR_DATE_OVERFLOW;
+            goto Done;
+         }
+
+         /* The actual conversion */
+         pDecodedItem->val.epochDate.nSeconds = (int64_t)d;
+         pDecodedItem->val.epochDate.fSecondsFraction =
+                           d - (double)pDecodedItem->val.epochDate.nSeconds;
+      }
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+         uReturn = QCBOR_ERR_HW_FLOAT_DISABLED;
+         goto Done;
+
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      default:
+         /* It's the arrays and maps that are unrecoverable because
+          * they are not consumed here. Since this is just an error
+          * condition, no extra code is added here to make the error
+          * recoverable for non-arrays and maps like strings. */
+         uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
+         goto Done;
+   }
+
+   pDecodedItem->uDataType = QCBOR_TYPE_DATE_EPOCH;
+
+Done:
+   return uReturn;
+}
+
+
+/**
+ * @brief Convert the days epoch date.
+ *
+ * pDecodedItem[in,out]  The data item to convert.
+ *
+ * @retval QCBOR_ERR_DATE_OVERFLOW              65-bit negative integer.
+ * @retval QCBOR_ERR_FLOAT_DATE_DISABLED        Float-point date in input,
+ *                                              floating-point date disabled.
+ * @retval QCBOR_ERR_ALL_FLOAT_DISABLED         Float-point date in input,
+ *                                              all floating-point disabled.
+ * @retval QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT  Unexpected and unrecoverable
+ *                                              error decoding date.
+ *
+ * This is much simpler than the other epoch date format because
+ * floating-porint is not allowed. This is mostly a simple type check.
+ */
+static QCBORError
+QCBOR_Private_DecodeDaysEpoch(QCBORItem *pDecodedItem)
+{
+   QCBORError uReturn = QCBOR_SUCCESS;
+
+   switch (pDecodedItem->uDataType) {
+
+      case QCBOR_TYPE_INT64:
+         pDecodedItem->val.epochDays = pDecodedItem->val.int64;
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         /* This only happens for CBOR type 0 > INT64_MAX so it is
+          * always an overflow.
+          */
+         uReturn = QCBOR_ERR_DATE_OVERFLOW;
+         goto Done;
+         break;
+
+      default:
+         /* It's the arrays and maps that are unrecoverable because
+          * they are not consumed here. Since this is just an error
+          * condition, no extra code is added here to make the error
+          * recoverable for non-arrays and maps like strings. */
+         uReturn = QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
+         goto Done;
+         break;
+   }
+
+   pDecodedItem->uDataType = QCBOR_TYPE_DAYS_EPOCH;
+
+Done:
+   return uReturn;
+}
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+/* Forward declaration is necessary for
+ * QCBORDecode_MantissaAndExponent().  to be able to decode bignum
+ * tags in the mantissa. If the mantissa is a decimal fraction or big
+ * float in error, this will result in a recurive call to
+ * QCBORDecode_MantissaAndExponent(), but the recursion will unwined
+ * correctly and the correct error is returned.
+ */
+static QCBORError
+QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pDecodedItem);
+
+
+/**
+ * @brief Decode decimal fractions and big floats.
+ *
+ * @param[in] pMe               The decode context.
+ * @param[in,out] pDecodedItem  On input the array data item that
+ *                              holds the mantissa and exponent.  On
+ *                              output the decoded mantissa and
+ *                              exponent.
+ *
+ * @returns  Decoding errors from getting primitive data items or
+ *           \ref QCBOR_ERR_BAD_EXP_AND_MANTISSA.
+ *
+ * When called pDecodedItem must be the array with two members, the
+ * exponent and mantissa.
+ *
+ * This will fetch and decode the exponent and mantissa and put the
+ * result back into pDecodedItem.
+ *
+ * This does no checking or processing of tag numbers. That is to be
+ * done by the code that calls this.
+ *
+ * This stuffs the type of the mantissa into pDecodedItem with the expectation
+ * the caller will process it.
+ */
+static QCBORError
+QCBORDecode_Private_ExpMantissa(QCBORDecodeContext *pMe,
+                                QCBORItem          *pDecodedItem)
+{
+   QCBORError uReturn;
+
+   /* --- Make sure it is an array; track nesting level of members --- */
+   if(pDecodedItem->uDataType != QCBOR_TYPE_ARRAY) {
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+
+   /* A check for pDecodedItem->val.uCount == 2 would work for
+    * definite-length arrays, but not for indefinite. Instead remember
+    * the nesting level the two integers must be at, which is one
+    * deeper than that of the array.
+    */
+   const int nNestLevel = pDecodedItem->uNestingLevel + 1;
+
+   /* --- Get the exponent --- */
+   QCBORItem exponentItem;
+   uReturn = QCBORDecode_GetNext(pMe, &exponentItem);
+   if(uReturn != QCBOR_SUCCESS) {
+      goto Done;
+   }
+   if(exponentItem.uNestingLevel != nNestLevel) {
+      /* Array is empty or a map/array encountered when expecting an int */
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+   if(exponentItem.uDataType == QCBOR_TYPE_INT64) {
+     /* Data arriving as an unsigned int < INT64_MAX has been
+      * converted to QCBOR_TYPE_INT64 and thus handled here. This is
+      * also means that the only data arriving here of type
+      * QCBOR_TYPE_UINT64 data will be too large for this to handle
+      * and thus an error that will get handled in the next else.
+      */
+     pDecodedItem->val.expAndMantissa.nExponent = exponentItem.val.int64;
+   } else {
+      /* Wrong type of exponent or a QCBOR_TYPE_UINT64 > INT64_MAX */
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+
+   /* --- Get the mantissa --- */
+   QCBORItem mantissaItem;
+   uReturn = QCBORDecode_GetNext(pMe, &mantissaItem);
+   if(uReturn != QCBOR_SUCCESS) {
+      goto Done;
+   }
+   if(mantissaItem.uNestingLevel != nNestLevel) {
+      /* Mantissa missing or map/array encountered when expecting number */
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+   /* Stuff the mantissa data type into the item to send it up to the
+    * the next level. */
+   pDecodedItem->uDataType = mantissaItem.uDataType;
+   if(mantissaItem.uDataType == QCBOR_TYPE_INT64) {
+      /* Data arriving as an unsigned int < INT64_MAX has been
+       * converted to QCBOR_TYPE_INT64 and thus handled here. This is
+       * also means that the only data arriving here of type
+       * QCBOR_TYPE_UINT64 data will be too large for this to handle
+       * and thus an error that will get handled in an else below.
+       */
+      pDecodedItem->val.expAndMantissa.Mantissa.nInt = mantissaItem.val.int64;
+#ifndef QCBOR_DISABLE_TAGS
+      /* With tags fully disabled a big number mantissa will error out
+       * in the call to QCBORDecode_GetNextWithTags() because it has
+       * a tag number.
+       */
+   }  else if(mantissaItem.uDataType == QCBOR_TYPE_POSBIGNUM ||
+              mantissaItem.uDataType == QCBOR_TYPE_NEGBIGNUM) {
+      /* Got a good big num mantissa */
+      pDecodedItem->val.expAndMantissa.Mantissa.bigNum = mantissaItem.val.bigNum;
+#endif /* QCBOR_DISABLE_TAGS */
+   } else {
+      /* Wrong type of mantissa or a QCBOR_TYPE_UINT64 > INT64_MAX */
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+
+   /* --- Check that array only has the two numbers --- */
+   if(mantissaItem.uNextNestLevel == nNestLevel) {
+      /* Extra items in the decimal fraction / big float */
+      /* Improvement: this should probably be an unrecoverable error. */
+      uReturn = QCBOR_ERR_BAD_EXP_AND_MANTISSA;
+      goto Done;
+   }
+   pDecodedItem->uNextNestLevel = mantissaItem.uNextNestLevel;
+
+Done:
+  return uReturn;
+}
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+#ifndef QCBOR_DISABLE_TAGS
+
+#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
+/**
+ * @brief Decode the MIME type tag
+ *
+ * @param[in,out] pDecodedItem   The item to decode.
+ *
+ *  Handle the text and binary MIME type tags. Slightly too complicated
+ *  f or ProcessTaggedString() because the RFC 7049 MIME type was
+ *  incorreclty text-only.
+ */
+static QCBORError
+QCBOR_Private_DecodeMIME(QCBORItem *pDecodedItem)
+{
+   if(pDecodedItem->uDataType == QCBOR_TYPE_TEXT_STRING) {
+      pDecodedItem->uDataType = QCBOR_TYPE_MIME;
+   } else if(pDecodedItem->uDataType == QCBOR_TYPE_BYTE_STRING) {
+      pDecodedItem->uDataType = QCBOR_TYPE_BINARY_MIME;
+   } else {
+      /* It's the arrays and maps that are unrecoverable because
+       * they are not consumed here. Since this is just an error
+       * condition, no extra code is added here to make the error
+       * recoverable for non-arrays and maps like strings. */
+      return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
+   }
+
+   return QCBOR_SUCCESS;
+}
+#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
+
+/**
+ * Table of CBOR tags whose content is either a text string or a byte
+ * string. The table maps the CBOR tag to the QCBOR type. The high-bit
+ * of uQCBORtype indicates the content should be a byte string rather
+ * than a text string
+ */
+struct StringTagMapEntry {
+   uint16_t uTagNumber;
+   uint8_t  uQCBORtype;
+};
+
+#define IS_BYTE_STRING_BIT 0x80
+#define QCBOR_TYPE_MASK   ~IS_BYTE_STRING_BIT
+
+static const struct StringTagMapEntry QCBOR_Private_StringTagMap[] = {
+   {CBOR_TAG_DATE_STRING,   QCBOR_TYPE_DATE_STRING},
+   {CBOR_TAG_DAYS_STRING,   QCBOR_TYPE_DAYS_STRING},
+   {CBOR_TAG_POS_BIGNUM,    QCBOR_TYPE_POSBIGNUM | IS_BYTE_STRING_BIT},
+   {CBOR_TAG_NEG_BIGNUM,    QCBOR_TYPE_NEGBIGNUM | IS_BYTE_STRING_BIT},
+   {CBOR_TAG_CBOR,          QBCOR_TYPE_WRAPPED_CBOR | IS_BYTE_STRING_BIT},
+   {CBOR_TAG_URI,           QCBOR_TYPE_URI},
+#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
+   {CBOR_TAG_B64URL,        QCBOR_TYPE_BASE64URL},
+   {CBOR_TAG_B64,           QCBOR_TYPE_BASE64},
+   {CBOR_TAG_REGEX,         QCBOR_TYPE_REGEX},
+   {CBOR_TAG_BIN_UUID,      QCBOR_TYPE_UUID | IS_BYTE_STRING_BIT},
+#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
+   {CBOR_TAG_CBOR_SEQUENCE, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE | IS_BYTE_STRING_BIT},
+   {CBOR_TAG_INVALID16,     QCBOR_TYPE_NONE}
+};
+
+
+/**
+ * @brief Process standard CBOR tags whose content is a string
+ *
+ * @param[in] uTag              The tag.
+ * @param[in,out] pDecodedItem  The data item.
+ *
+ * @returns  This returns QCBOR_SUCCESS if the tag was procssed,
+ *           \ref QCBOR_ERR_UNSUPPORTED if the tag was not processed and
+ *           \ref QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT if the content type was wrong for the tag.
+ *
+ * Process the CBOR tags that whose content is a byte string or a text
+ * string and for which the string is just passed on to the caller.
+ *
+ * This maps the CBOR tag to the QCBOR type and checks the content
+ * type.  Nothing more. It may not be the most important
+ * functionality, but it part of implementing as much of RFC 8949 as
+ * possible.
+ */
+static QCBORError
+QCBOR_Private_ProcessTaggedString(uint16_t uTag, QCBORItem *pDecodedItem)
+{
+   /* This only works on tags that were not mapped; no need for other yet */
+   if(uTag > QCBOR_LAST_UNMAPPED_TAG) {
+      return QCBOR_ERR_UNSUPPORTED;
+   }
+
+   unsigned uIndex;
+   for(uIndex = 0; QCBOR_Private_StringTagMap[uIndex].uTagNumber != CBOR_TAG_INVALID16; uIndex++) {
+      if(QCBOR_Private_StringTagMap[uIndex].uTagNumber == uTag) {
+         break;
+      }
+   }
+
+   const uint8_t uQCBORType = QCBOR_Private_StringTagMap[uIndex].uQCBORtype;
+   if(uQCBORType == QCBOR_TYPE_NONE) {
+      /* repurpose this error to mean not handled here */
+      return QCBOR_ERR_UNSUPPORTED;
+   }
+
+   uint8_t uExpectedType = QCBOR_TYPE_TEXT_STRING;
+   if(uQCBORType & IS_BYTE_STRING_BIT) {
+      uExpectedType = QCBOR_TYPE_BYTE_STRING;
+   }
+
+   if(pDecodedItem->uDataType != uExpectedType) {
+      /* It's the arrays and maps that are unrecoverable because
+       * they are not consumed here. Since this is just an error
+       * condition, no extra code is added here to make the error
+       * recoverable for non-arrays and maps like strings. */
+      return QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT;
+   }
+
+   pDecodedItem->uDataType = (uint8_t)(uQCBORType & QCBOR_TYPE_MASK);
+   return QCBOR_SUCCESS;
+}
+#endif /* QCBOR_DISABLE_TAGS */
+
+
+#ifndef QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA
+/**
+ * @brief Figures out data type for exponent mantissa tags.
+ *
+ * @param[in] uTagToProcess  Either @ref CBOR_TAG_DECIMAL_FRACTION or
+ *                           @ref CBOR_TAG_BIG_FLOAT.
+ * @param[in] pDecodedItem   Item being decoded.
+ *
+ * @returns One of the 6 values between \ref QCBOR_TYPE_DECIMAL_FRACTION
+ *          and @ref QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM.
+ *
+ * Does mapping between a CBOR tag number and a QCBOR type.  with a
+ * little bit of logic and arithmatic.
+ *
+ * Used in serveral contexts. Does the work where sometimes the data
+ * item is explicitly tagged and sometimes not.
+ */
+static uint8_t
+QCBOR_Private_ExpMantissaDataType(const uint16_t   uTagToProcess,
+                                  const QCBORItem *pDecodedItem)
+{
+   uint8_t uBase = uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ?
+                                       QCBOR_TYPE_DECIMAL_FRACTION :
+                                       QCBOR_TYPE_BIGFLOAT;
+   if(pDecodedItem->uDataType != QCBOR_TYPE_INT64) {
+      uBase = (uint8_t)(uBase + pDecodedItem->uDataType - QCBOR_TYPE_POSBIGNUM + 1);
+   }
+   return uBase;
+}
+#endif /* QCBOR_CONFIG_DISABLE_EXP_AND_MANTISSA */
+
+
+/**
+ * @brief Decode tag content for select tags (decoding layer 1).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[out] pDecodedItem  The decoded item.
+ *
+ * @return Decoding error code.
+ *
+ * CBOR tag numbers for the item were decoded in GetNext_TaggedItem(),
+ * but the whole tag was not decoded. Here, the whole tags (tag number
+ * and tag content) that are supported by QCBOR are decoded. This is a
+ * quick pass through for items that are not tags.
+ */
+static QCBORError
+QCBORDecode_Private_GetNextTagContent(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pDecodedItem)
+{
+   QCBORError uReturn;
+
+   uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pDecodedItem);
+   if(uReturn != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+#ifndef QCBOR_DISABLE_TAGS
+   /* When there are no tag numbers for the item, this exits first
+    * thing and effectively does nothing.
+    *
+    * This loops over all the tag numbers accumulated for this item
+    * trying to decode and interpret them. This stops at the end of
+    * the list or at the first tag number that can't be interpreted by
+    * this code. This is effectively a recursive processing of the
+    * tags number list that handles nested tags.
+    */
+   while(1) {
+      /* Don't bother to unmap tags via QCBORITem.uTags since this
+       * code only works on tags less than QCBOR_LAST_UNMAPPED_TAG.
+       */
+      const uint16_t uTagToProcess = pDecodedItem->uTags[0];
+
+      if(uTagToProcess == CBOR_TAG_INVALID16) {
+         /* Hit the end of the tag list. A successful exit. */
+         break;
+
+      } else if(uTagToProcess == CBOR_TAG_DATE_EPOCH) {
+         uReturn = QCBOR_Private_DecodeDateEpoch(pDecodedItem);
+
+      } else if(uTagToProcess == CBOR_TAG_DAYS_EPOCH) {
+         uReturn = QCBOR_Private_DecodeDaysEpoch(pDecodedItem);
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      } else if(uTagToProcess == CBOR_TAG_DECIMAL_FRACTION ||
+                uTagToProcess == CBOR_TAG_BIGFLOAT) {
+         uReturn = QCBORDecode_Private_ExpMantissa(pMe, pDecodedItem);
+         /* --- Which is it, decimal fraction or a bigfloat? --- */
+         pDecodedItem->uDataType = QCBOR_Private_ExpMantissaDataType(uTagToProcess, pDecodedItem);
+
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+#ifndef QCBOR_DISABLE_UNCOMMON_TAGS
+      } else if(uTagToProcess == CBOR_TAG_MIME ||
+                uTagToProcess == CBOR_TAG_BINARY_MIME) {
+         uReturn = QCBOR_Private_DecodeMIME(pDecodedItem);
+#endif /* QCBOR_DISABLE_UNCOMMON_TAGS */
+
+      } else {
+         /* See if it is a passthrough byte/text string tag; process if so */
+         uReturn = QCBOR_Private_ProcessTaggedString(pDecodedItem->uTags[0], pDecodedItem);
+
+         if(uReturn == QCBOR_ERR_UNSUPPORTED) {
+            /* It wasn't a passthrough byte/text string tag so it is
+             * an unknown tag. This is the exit from the loop on the
+             * first unknown tag.  It is a successful exit.
+             */
+            uReturn = QCBOR_SUCCESS;
+            break;
+         }
+      }
+
+      if(uReturn != QCBOR_SUCCESS) {
+         /* Error exit from the loop */
+         break;
+      }
+
+      /* A tag was successfully processed, shift it out of the list of
+       * tags returned. This is the loop increment.
+       */
+      QCBOR_Private_ShiftTags(pDecodedItem);
+   }
+#endif /* QCBOR_DISABLE_TAGS */
+
+Done:
+   return uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_GetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   QCBORError uErr;
+   uErr =  QCBORDecode_Private_GetNextTagContent(pMe, pDecodedItem);
+   if(uErr != QCBOR_SUCCESS) {
+      pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
+      pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
+   }
+   return uErr;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_PeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   const QCBORDecodeNesting SaveNesting = pMe->nesting;
+   const UsefulInputBuf Save = pMe->InBuf;
+
+   QCBORError uErr = QCBORDecode_GetNext(pMe, pDecodedItem);
+
+   pMe->nesting = SaveNesting;
+   pMe->InBuf = Save;
+
+   return uErr;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_VPeekNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
+      pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_PeekNext(pMe, pDecodedItem);
+}
+
+
+static void
+QCBORDecode_Private_CopyTags(QCBORDecodeContext *pMe, const QCBORItem *pItem)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   memcpy(pMe->uLastTags, pItem->uTags, sizeof(pItem->uTags));
+#else
+   (void)pMe;
+   (void)pItem;
+#endif
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_VGetNext(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      pDecodedItem->uDataType  = QCBOR_TYPE_NONE;
+      pDecodedItem->uLabelType = QCBOR_TYPE_NONE;
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, pDecodedItem);
+   QCBORDecode_Private_CopyTags(pMe, pDecodedItem);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_GetNextWithTags(QCBORDecodeContext *pMe,
+                            QCBORItem          *pDecodedItem,
+                            QCBORTagListOut    *pTags)
+{
+#ifndef QCBOR_DISABLE_TAGS
+
+   QCBORError uReturn;
+
+   uReturn = QCBORDecode_GetNext(pMe, pDecodedItem);
+   if(uReturn != QCBOR_SUCCESS) {
+      return uReturn;
+   }
+
+   if(pTags != NULL) {
+      pTags->uNumUsed = 0;
+      /* Reverse the order because pTags is reverse of QCBORItem.uTags. */
+      for(int nTagIndex = QCBOR_MAX_TAGS_PER_ITEM-1; nTagIndex >=0; nTagIndex--) {
+         if(pDecodedItem->uTags[nTagIndex] == CBOR_TAG_INVALID16) {
+            continue;
+         }
+         if(pTags->uNumUsed >= pTags->uNumAllocated) {
+            return QCBOR_ERR_TOO_MANY_TAGS;
+         }
+         pTags->puTags[pTags->uNumUsed] = QCBORDecode_Private_UnMapTagNumber(pMe,pDecodedItem->uTags[nTagIndex]);
+         pTags->uNumUsed++;
+      }
+   }
+
+   return QCBOR_SUCCESS;
+
+#else /* QCBOR_DISABLE_TAGS */
+   (void)pMe;
+   (void)pDecodedItem;
+   (void)pTags;
+   return QCBOR_ERR_TAGS_DISABLED;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+bool
+QCBORDecode_IsTagged(QCBORDecodeContext *pMe,
+                     const QCBORItem   *pItem,
+                     uint64_t           uTag)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   for(unsigned uTagIndex = 0; uTagIndex < QCBOR_MAX_TAGS_PER_ITEM; uTagIndex++) {
+      if(pItem->uTags[uTagIndex] == CBOR_TAG_INVALID16) {
+         break;
+      }
+      if(QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uTagIndex]) == uTag) {
+         return true;
+      }
+   }
+#else /* QCBOR_TAGS_DISABLED */
+   (void)pMe;
+   (void)pItem;
+   (void)uTag;
+#endif /* QCBOR_TAGS_DISABLED */
+
+   return false;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_PartialFinish(QCBORDecodeContext *pMe, size_t *puConsumed)
+{
+   if(puConsumed != NULL) {
+      *puConsumed = pMe->InBuf.cursor;
+   }
+
+   QCBORError uReturn = pMe->uLastError;
+
+   if(uReturn != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   /* Error out if all the maps/arrays are not closed out */
+   if(!DecodeNesting_IsCurrentAtTop(&(pMe->nesting))) {
+      uReturn = QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED;
+      goto Done;
+   }
+
+   /* Error out if not all the bytes are consumed */
+   if(UsefulInputBuf_BytesUnconsumed(&(pMe->InBuf))) {
+      uReturn = QCBOR_ERR_EXTRA_BYTES;
+   }
+
+Done:
+   return uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_Finish(QCBORDecodeContext *pMe)
+{
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+   /* Call the destructor for the string allocator if there is one.
+    * Always called, even if there are errors; always have to clean up.
+    */
+   StringAllocator_Destruct(&(pMe->StringAllocator));
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+   return QCBORDecode_PartialFinish(pMe, NULL);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+uint64_t
+QCBORDecode_GetNthTag(QCBORDecodeContext *pMe,
+                      const QCBORItem    *pItem,
+                      uint32_t            uIndex)
+{
+#ifndef QCBOR_DISABLE_TAGS
+   if(pItem->uDataType == QCBOR_TYPE_NONE) {
+      return CBOR_TAG_INVALID64;
+   }
+   if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
+      return CBOR_TAG_INVALID64;
+   } else {
+      return QCBORDecode_Private_UnMapTagNumber(pMe, pItem->uTags[uIndex]);
+   }
+#else /* QCBOR_DISABLE_TAGS */
+   (void)pMe;
+   (void)pItem;
+   (void)uIndex;
+
+   return CBOR_TAG_INVALID64;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+uint64_t
+QCBORDecode_GetNthTagOfLast(const QCBORDecodeContext *pMe,
+                            uint32_t                  uIndex)
+{
+#ifndef QCBOR_DISABLE_TAGS
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return CBOR_TAG_INVALID64;
+   }
+   if(uIndex >= QCBOR_MAX_TAGS_PER_ITEM) {
+      return CBOR_TAG_INVALID64;
+   } else {
+      return QCBORDecode_Private_UnMapTagNumber(pMe, pMe->uLastTags[uIndex]);
+   }
+#else /* QCBOR_DISABLE_TAGS */
+   (void)pMe;
+   (void)uIndex;
+
+   return CBOR_TAG_INVALID64;
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS
+
+/* ===========================================================================
+   MemPool -- BUILT-IN SIMPLE STRING ALLOCATOR
+
+   This implements a simple sting allocator for indefinite-length
+   strings that can be enabled by calling QCBORDecode_SetMemPool(). It
+   implements the function type QCBORStringAllocate and allows easy
+   use of it.
+
+   This particular allocator is built-in for convenience. The caller
+   can implement their own.  All of this following code will get
+   dead-stripped if QCBORDecode_SetMemPool() is not called.
+
+   This is a very primitive memory allocator. It does not track
+   individual allocations, only a high-water mark. A free or
+   reallocation must be of the last chunk allocated.
+
+   The size of the pool and offset to free memory are packed into the
+   first 8 bytes of the memory pool so we don't have to keep them in
+   the decode context. Since the address of the pool may not be
+   aligned, they have to be packed and unpacked as if they were
+   serialized data of the wire or such.
+
+   The sizes packed in are uint32_t to be the same on all CPU types
+   and simplify the code.
+   ========================================================================== */
+
+
+static int
+MemPool_Unpack(const void *pMem, uint32_t *puPoolSize, uint32_t *puFreeOffset)
+{
+   // Use of UsefulInputBuf is overkill, but it is convenient.
+   UsefulInputBuf UIB;
+
+   // Just assume the size here. It was checked during SetUp so
+   // the assumption is safe.
+   UsefulInputBuf_Init(&UIB, (UsefulBufC){pMem,QCBOR_DECODE_MIN_MEM_POOL_SIZE});
+   *puPoolSize     = UsefulInputBuf_GetUint32(&UIB);
+   *puFreeOffset   = UsefulInputBuf_GetUint32(&UIB);
+   return UsefulInputBuf_GetError(&UIB);
+}
+
+
+static int
+MemPool_Pack(UsefulBuf Pool, uint32_t uFreeOffset)
+{
+   // Use of UsefulOutBuf is overkill, but convenient. The
+   // length check performed here is useful.
+   UsefulOutBuf UOB;
+
+   UsefulOutBuf_Init(&UOB, Pool);
+   UsefulOutBuf_AppendUint32(&UOB, (uint32_t)Pool.len); // size of pool
+   UsefulOutBuf_AppendUint32(&UOB, uFreeOffset); // first free position
+   return UsefulOutBuf_GetError(&UOB);
+}
+
+
+/*
+ Internal function for an allocation, reallocation free and destuct.
+
+ Having only one function rather than one each per mode saves space in
+ QCBORDecodeContext.
+
+ Code Reviewers: THIS FUNCTION DOES POINTER MATH
+ */
+static UsefulBuf
+MemPool_Function(void *pPool, void *pMem, size_t uNewSize)
+{
+   UsefulBuf ReturnValue = NULLUsefulBuf;
+
+   uint32_t uPoolSize;
+   uint32_t uFreeOffset;
+
+   if(uNewSize > UINT32_MAX) {
+      // This allocator is only good up to 4GB.  This check should
+      // optimize out if sizeof(size_t) == sizeof(uint32_t)
+      goto Done;
+   }
+   const uint32_t uNewSize32 = (uint32_t)uNewSize;
+
+   if(MemPool_Unpack(pPool, &uPoolSize, &uFreeOffset)) {
+      goto Done;
+   }
+
+   if(uNewSize) {
+      if(pMem) {
+         // REALLOCATION MODE
+         // Calculate pointer to the end of the memory pool.  It is
+         // assumed that pPool + uPoolSize won't wrap around by
+         // assuming the caller won't pass a pool buffer in that is
+         // not in legitimate memory space.
+         const void *pPoolEnd = (uint8_t *)pPool + uPoolSize;
+
+         // Check that the pointer for reallocation is in the range of the
+         // pool. This also makes sure that pointer math further down
+         // doesn't wrap under or over.
+         if(pMem >= pPool && pMem < pPoolEnd) {
+            // Offset to start of chunk for reallocation. This won't
+            // wrap under because of check that pMem >= pPool.  Cast
+            // is safe because the pool is always less than UINT32_MAX
+            // because of check in QCBORDecode_SetMemPool().
+            const uint32_t uMemOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
+
+            // Check to see if the allocation will fit. uPoolSize -
+            // uMemOffset will not wrap under because of check that
+            // pMem is in the range of the uPoolSize by check above.
+            if(uNewSize <= uPoolSize - uMemOffset) {
+               ReturnValue.ptr = pMem;
+               ReturnValue.len = uNewSize;
+
+               // Addition won't wrap around over because uNewSize was
+               // checked to be sure it is less than the pool size.
+               uFreeOffset = uMemOffset + uNewSize32;
+            }
+         }
+      } else {
+         // ALLOCATION MODE
+         // uPoolSize - uFreeOffset will not underflow because this
+         // pool implementation makes sure uFreeOffset is always
+         // smaller than uPoolSize through this check here and
+         // reallocation case.
+         if(uNewSize <= uPoolSize - uFreeOffset) {
+            ReturnValue.len = uNewSize;
+            ReturnValue.ptr = (uint8_t *)pPool + uFreeOffset;
+            uFreeOffset    += (uint32_t)uNewSize;
+         }
+      }
+   } else {
+      if(pMem) {
+         // FREE MODE
+         // Cast is safe because of limit on pool size in
+         // QCBORDecode_SetMemPool()
+         uFreeOffset = (uint32_t)((uint8_t *)pMem - (uint8_t *)pPool);
+      } else {
+         // DESTRUCT MODE
+         // Nothing to do for this allocator
+      }
+   }
+
+   UsefulBuf Pool = {pPool, uPoolSize};
+   MemPool_Pack(Pool, uFreeOffset);
+
+Done:
+   return ReturnValue;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_SetMemPool(QCBORDecodeContext *pMe,
+                       UsefulBuf           Pool,
+                       bool                bAllStrings)
+{
+   // The pool size and free mem offset are packed into the beginning
+   // of the pool memory. This compile time check makes sure the
+   // constant in the header is correct.  This check should optimize
+   // down to nothing.
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4127) // conditional expression is constant
+#endif
+   if(QCBOR_DECODE_MIN_MEM_POOL_SIZE < 2 * sizeof(uint32_t)) {
+      return QCBOR_ERR_MEM_POOL_SIZE;
+   }
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+   // The pool size and free offset packed in to the beginning of pool
+   // memory are only 32-bits. This check will optimize out on 32-bit
+   // machines.
+   if(Pool.len > UINT32_MAX) {
+      return QCBOR_ERR_MEM_POOL_SIZE;
+   }
+
+   // This checks that the pool buffer given is big enough.
+   if(MemPool_Pack(Pool, QCBOR_DECODE_MIN_MEM_POOL_SIZE)) {
+      return QCBOR_ERR_MEM_POOL_SIZE;
+   }
+
+   QCBORDecode_SetUpAllocator(pMe, MemPool_Function, Pool.ptr, bAllStrings);
+
+   return QCBOR_SUCCESS;
+}
+#endif /* QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS */
+
+
+
+
+/**
+ * @brief Consume an entire map or array including its contents.
+ *
+ * @param[in]  pMe              The decoder context.
+ * @param[in]  pItemToConsume   The array/map whose contents are to be
+ *                              consumed.
+ * @param[out] puNextNestLevel  The next nesting level after the item was
+ *                              fully consumed.
+ *
+ * This may be called when @c pItemToConsume is not an array or
+ * map. In that case, this is just a pass through for @c puNextNestLevel
+ * since there is nothing to do.
+ */
+static QCBORError
+QCBORDecode_Private_ConsumeItem(QCBORDecodeContext *pMe,
+                                const QCBORItem    *pItemToConsume,
+                                bool               *pbBreak,
+                                uint8_t            *puNextNestLevel)
+{
+   QCBORError uReturn;
+   QCBORItem  Item;
+
+   /* If it is a map or array, this will tell if it is empty. */
+   const bool bIsEmpty = (pItemToConsume->uNextNestLevel <= pItemToConsume->uNestingLevel);
+
+   if(QCBORItem_IsMapOrArray(*pItemToConsume) && !bIsEmpty) {
+      /* There is only real work to do for non-empty maps and arrays */
+
+      /* This works for definite- and indefinite-length maps and
+       * arrays by using the nesting level
+       */
+      do {
+         uReturn = QCBORDecode_Private_GetNextMapOrArray(pMe, pbBreak, &Item);
+         if(QCBORDecode_IsUnrecoverableError(uReturn) ||
+            uReturn == QCBOR_ERR_NO_MORE_ITEMS) {
+            goto Done;
+         }
+      } while(Item.uNextNestLevel >= pItemToConsume->uNextNestLevel);
+
+      *puNextNestLevel = Item.uNextNestLevel;
+
+      uReturn = QCBOR_SUCCESS;
+
+   } else {
+      /* pItemToConsume is not a map or array. Just pass the nesting
+       * level through. */
+      *puNextNestLevel = pItemToConsume->uNextNestLevel;
+
+      uReturn = QCBOR_SUCCESS;
+   }
+
+Done:
+    return uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_VGetNextConsume(QCBORDecodeContext *pMe, QCBORItem *pDecodedItem)
+{
+   QCBORDecode_VGetNext(pMe, pDecodedItem);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)QCBORDecode_Private_ConsumeItem(pMe, pDecodedItem, NULL,
+         &pDecodedItem->uNextNestLevel);
+   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+QCBORError
+QCBORDecode_EndCheck(QCBORDecodeContext *pMe)
+{
+   size_t     uCursorOffset;
+   QCBORError uErr;
+
+   uErr = QCBORDecode_GetError(pMe);
+   if(uErr != QCBOR_SUCCESS) {
+      return uErr;
+   }
+
+   uCursorOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
+
+   if(uCursorOffset == UsefulInputBuf_GetBufferLength(&(pMe->InBuf))) {
+      return QCBOR_ERR_NO_MORE_ITEMS;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Rewind cursor to start as if map or array were just entered.
+ *
+ * @param[in]  pMe   The decoding context
+ *
+ * This affects the nesting tracking and the UsefulInputBuf.
+ */
+static void
+QCBORDecode_Private_RewindMapOrArray(QCBORDecodeContext *pMe)
+{
+   /* Reset nesting tracking to the deepest bounded level */
+   DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
+
+   DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
+
+   /* Reposition traversal cursor to the start of the map/array */
+   UsefulInputBuf_Seek(&(pMe->InBuf),
+                       DecodeNesting_GetMapOrArrayStart(&(pMe->nesting)));
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_Rewind(QCBORDecodeContext *pMe)
+{
+   if(pMe->nesting.pCurrentBounded != NULL) {
+      /* In a bounded map, array or bstr-wrapped CBOR */
+
+      if(DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
+         /* In bstr-wrapped CBOR. */
+
+         /* Reposition traversal cursor to start of wrapping byte string */
+         UsefulInputBuf_Seek(&(pMe->InBuf),
+                             pMe->nesting.pCurrentBounded->u.bs.uBstrStartOffset);
+         DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
+
+      } else {
+         /* In a map or array */
+         QCBORDecode_Private_RewindMapOrArray(pMe);
+      }
+
+   } else {
+      /* Not in anything bounded */
+
+      /* Reposition traversal cursor to the start of input CBOR */
+      UsefulInputBuf_Seek(&(pMe->InBuf), 0ULL);
+
+      /* Reset nesting tracking to beginning of input. */
+      DecodeNesting_Init(&(pMe->nesting));
+   }
+
+   pMe->uLastError = QCBOR_SUCCESS;
+}
+
+
+
+
+
+typedef struct {
+   void               *pCBContext;
+   QCBORItemCallback   pfCallback;
+} MapSearchCallBack;
+
+typedef struct {
+   size_t   uStartOffset;
+   uint16_t uItemCount;
+} MapSearchInfo;
+
+
+/**
+ * @brief Search a map for a set of items.
+ *
+ * @param[in]  pMe           The decode context to search.
+ * @param[in,out] pItemArray The items to search for and the items found.
+ * @param[out] pInfo         Several bits of meta-info returned by search.
+ * @param[in] pCallBack      Callback object or @c NULL.
+ *
+ * @retval QCBOR_ERR_NOT_ENTERED     Trying to search without entering a map.
+ *
+ * @retval QCBOR_ERR_DUPLICATE_LABEL Duplicate items (items with the same label)
+ *                                   were found for one of the labels being
+ *                                   search for. This duplicate detection is
+ *                                   only performed for items in pItemArray,
+ *                                   not every item in the map.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE A label was matched, but the type was
+ *                                   wrong for the matchd label.
+ *
+ * @retval Also errors returned by QCBORDecode_GetNext().
+ *
+ * On input, \c pItemArray contains a list of labels and data types of
+ * items to be found.
+ *
+ * On output, the fully retrieved items are filled in with values and
+ * such. The label was matched, so it never changes.
+ *
+ * If an item was not found, its data type is set to @ref QCBOR_TYPE_NONE.
+ *
+ * This also finds the ends of maps and arrays when they are exited.
+ */
+static QCBORError
+QCBORDecode_Private_MapSearch(QCBORDecodeContext *pMe,
+                              QCBORItem          *pItemArray,
+                              MapSearchInfo      *pInfo,
+                              MapSearchCallBack  *pCallBack)
+{
+   QCBORError uReturn;
+   uint64_t   uFoundItemBitMap = 0;
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      uReturn = pMe->uLastError;
+      goto Done2;
+   }
+
+   if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_MAP) &&
+      pItemArray->uLabelType != QCBOR_TYPE_NONE) {
+      /* QCBOR_TYPE_NONE as first item indicates just looking
+         for the end of an array, so don't give error. */
+      uReturn = QCBOR_ERR_MAP_NOT_ENTERED;
+      goto Done2;
+   }
+
+   if(DecodeNesting_IsBoundedEmpty(&(pMe->nesting))) {
+      // It is an empty bounded array or map
+      if(pItemArray->uLabelType == QCBOR_TYPE_NONE) {
+         // Just trying to find the end of the map or array
+         pMe->uMapEndOffsetCache = DecodeNesting_GetMapOrArrayStart(&(pMe->nesting));
+         uReturn = QCBOR_SUCCESS;
+      } else {
+         // Nothing is ever found in an empty array or map. All items
+         // are marked as not found below.
+         uReturn = QCBOR_SUCCESS;
+      }
+      goto Done2;
+   }
+
+   QCBORDecodeNesting SaveNesting;
+   size_t uSavePos = UsefulInputBuf_Tell(&(pMe->InBuf));
+   DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
+
+   /* Reposition to search from the start of the map / array */
+   QCBORDecode_Private_RewindMapOrArray(pMe);
+
+   /*
+    Loop over all the items in the map or array. Each item
+    could be a map or array, but label matching is only at
+    the main level. This handles definite- and indefinite-
+    length maps and arrays. The only reason this is ever
+    called on arrays is to find their end position.
+
+    This will always run over all items in order to do
+    duplicate detection.
+
+    This will exit with failure if it encounters an
+    unrecoverable error, but continue on for recoverable
+    errors.
+
+    If a recoverable error occurs on a matched item, then
+    that error code is returned.
+    */
+   const uint8_t uMapNestLevel = DecodeNesting_GetBoundedModeLevel(&(pMe->nesting));
+   if(pInfo) {
+      pInfo->uItemCount = 0;
+   }
+   uint8_t       uNextNestLevel;
+   do {
+      /* Remember offset of the item because sometimes it has to be returned */
+      const size_t uOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
+
+      /* Get the item */
+      QCBORItem Item;
+      /* QCBORDecode_Private_GetNextTagContent() rather than GetNext()
+       * because a label match is performed on recoverable errors to
+       * be able to return the the error code for the found item. */
+      QCBORError uResult = QCBORDecode_Private_GetNextTagContent(pMe, &Item);
+      if(QCBORDecode_IsUnrecoverableError(uResult)) {
+         /* The map/array can't be decoded when unrecoverable errors occur */
+         uReturn = uResult;
+         goto Done;
+      }
+      if(uResult == QCBOR_ERR_NO_MORE_ITEMS) {
+         /* Unexpected end of map or array. */
+         uReturn = uResult;
+         goto Done;
+      }
+
+      /* See if item has one of the labels that are of interest */
+      bool bMatched = false;
+      for(int nIndex = 0; pItemArray[nIndex].uLabelType != QCBOR_TYPE_NONE; nIndex++) {
+         if(QCBORItem_MatchLabel(Item, pItemArray[nIndex])) {
+            /* A label match has been found */
+            if(uFoundItemBitMap & (0x01ULL << nIndex)) {
+               uReturn = QCBOR_ERR_DUPLICATE_LABEL;
+               goto Done;
+            }
+            if(uResult != QCBOR_SUCCESS) {
+               /* The label matches, but the data item is in error.
+                * It is OK to have recoverable errors on items that
+                * are not matched. */
+               uReturn = uResult;
+               goto Done;
+            }
+            if(!QCBORItem_MatchType(Item, pItemArray[nIndex])) {
+               /* The data item is not of the type(s) requested */
+               uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
+               goto Done;
+            }
+
+            /* Successful match. Return the item. */
+            pItemArray[nIndex] = Item;
+            uFoundItemBitMap |= 0x01ULL << nIndex;
+            if(pInfo) {
+               pInfo->uStartOffset = uOffset;
+            }
+            bMatched = true;
+         }
+      }
+
+
+      if(!bMatched && pCallBack != NULL) {
+         /*
+          Call the callback on unmatched labels.
+          (It is tempting to do duplicate detection here, but that would
+          require dynamic memory allocation because the number of labels
+          that might be encountered is unbounded.)
+         */
+         uReturn = (*(pCallBack->pfCallback))(pCallBack->pCBContext, &Item);
+         if(uReturn != QCBOR_SUCCESS) {
+            goto Done;
+         }
+      }
+
+      /*
+       Consume the item whether matched or not. This
+       does the work of traversing maps and array and
+       everything in them. In this loop only the
+       items at the current nesting level are examined
+       to match the labels.
+       */
+      uReturn = QCBORDecode_Private_ConsumeItem(pMe, &Item, NULL, &uNextNestLevel);
+      if(uReturn != QCBOR_SUCCESS) {
+         goto Done;
+      }
+
+      if(pInfo) {
+         pInfo->uItemCount++;
+      }
+
+   } while (uNextNestLevel >= uMapNestLevel);
+
+   uReturn = QCBOR_SUCCESS;
+
+   const size_t uEndOffset = UsefulInputBuf_Tell(&(pMe->InBuf));
+
+   // Check here makes sure that this won't accidentally be
+   // QCBOR_MAP_OFFSET_CACHE_INVALID which is larger than
+   // QCBOR_MAX_DECODE_INPUT_SIZE.
+   // Cast to uint32_t to possibly address cases where SIZE_MAX < UINT32_MAX
+   if((uint32_t)uEndOffset >= QCBOR_MAX_DECODE_INPUT_SIZE) {
+      uReturn = QCBOR_ERR_INPUT_TOO_LARGE;
+      goto Done;
+   }
+   /* Cast OK because encoded CBOR is limited to UINT32_MAX */
+   pMe->uMapEndOffsetCache = (uint32_t)uEndOffset;
+
+ Done:
+   DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
+   UsefulInputBuf_Seek(&(pMe->InBuf), uSavePos);
+
+ Done2:
+   /* For all items not found, set the data and label type to QCBOR_TYPE_NONE */
+   for(int i = 0; pItemArray[i].uLabelType != 0; i++) {
+      if(!(uFoundItemBitMap & (0x01ULL << i))) {
+         pItemArray[i].uDataType  = QCBOR_TYPE_NONE;
+         pItemArray[i].uLabelType = QCBOR_TYPE_NONE;
+      }
+   }
+
+   return uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetItemInMapN(QCBORDecodeContext *pMe,
+                          int64_t             nLabel,
+                          uint8_t             uQcborType,
+                          QCBORItem          *pItem)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
+   OneItemSeach[0].label.int64 = nLabel;
+   OneItemSeach[0].uDataType   = uQcborType;
+   OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE; // Indicates end of array
+
+   QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
+
+   if(uReturn != QCBOR_SUCCESS) {
+      pItem->uDataType  = QCBOR_TYPE_NONE;
+      pItem->uLabelType = QCBOR_TYPE_NONE;
+      goto Done;
+   }
+
+   if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
+      uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
+   }
+
+   *pItem = OneItemSeach[0];
+   QCBORDecode_Private_CopyTags(pMe, pItem);
+
+ Done:
+   pMe->uLastError = (uint8_t)uReturn;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetItemInMapSZ(QCBORDecodeContext *pMe,
+                           const char         *szLabel,
+                           uint8_t             uQcborType,
+                           QCBORItem          *pItem)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
+   OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+   OneItemSeach[0].uDataType    = uQcborType;
+   OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE; // Indicates end of array
+
+   QCBORError uReturn = QCBORDecode_Private_MapSearch(pMe, OneItemSeach, NULL, NULL);
+
+   if(uReturn != QCBOR_SUCCESS) {
+      pItem->uDataType  = QCBOR_TYPE_NONE;
+      pItem->uLabelType = QCBOR_TYPE_NONE;
+      goto Done;
+   }
+   if(OneItemSeach[0].uDataType == QCBOR_TYPE_NONE) {
+      uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
+      goto Done;
+   }
+
+   *pItem = OneItemSeach[0];
+   QCBORDecode_Private_CopyTags(pMe, pItem);
+
+Done:
+#else
+   (void)pMe;
+   (void)szLabel;
+   (void)uQcborType;
+   (void)pItem;
+   QCBORError uReturn = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   pMe->uLastError = (uint8_t)uReturn;
+}
+
+
+
+/**
+ * @brief Semi-private. Get pointer, length and item for an array or map.
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uType          CBOR major type, either array/map.
+ * @param[out] pItem         The item for the array/map.
+ * @param[out] pEncodedCBOR  Pointer and length of the encoded map or array.
+ *
+ * The next item to be decoded must be a map or array as specified by \c uType.
+ *
+ * \c pItem will be filled in with the label and tags of the array or map
+ * in addition to \c pEncodedCBOR giving the pointer and length of the
+ * encoded CBOR.
+ *
+ * When this is complete, the traversal cursor is at the end of the array or
+ * map that was retrieved.
+ */
+void
+QCBORDecode_Private_GetArrayOrMap(QCBORDecodeContext *pMe,
+                                  const uint8_t       uType,
+                                  QCBORItem          *pItem,
+                                  UsefulBufC         *pEncodedCBOR)
+{
+   QCBORError uErr;
+   uint8_t    uNestLevel;
+   size_t     uStartingCursor;
+   size_t     uStartOfReturned;
+   size_t     uEndOfReturned;
+   size_t     uTempSaveCursor;
+   bool       bInMap;
+   QCBORItem  LabelItem;
+   bool       EndedByBreak;
+
+   uStartingCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
+   bInMap = DecodeNesting_IsCurrentTypeMap(&(pMe->nesting));
+
+   /* Could call GetNext here, but don't need to because this
+    * is only interested in arrays and maps. */
+   uErr = QCBORDecode_Private_GetNextMapOrArray(pMe, NULL, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)uErr;
+      return;
+   }
+
+   uint8_t uItemDataType = pItem->uDataType;
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   if(uItemDataType != uType) {
+      pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+      return;
+   }
+
+   if(bInMap) {
+      /* If the item is in a map, the start of the array/map
+       * itself, not the label, must be found. Do this by
+       * rewinding to the starting position and fetching
+       * just the label data item. QCBORDecode_Private_GetNextTagNumber()
+       * doesn't do any of the array/map item counting or nesting
+       * level tracking. Used here it will just fetech the label
+       * data item.
+       *
+       * Have to save the cursor and put it back to the position
+       * after the full item once the label as been fetched by
+       * itself.
+       */
+      uTempSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
+      UsefulInputBuf_Seek(&(pMe->InBuf), uStartingCursor);
+
+      /* Item has been fetched once so safe to ignore error */
+      (void)QCBORDecode_Private_GetNextTagNumber(pMe, &LabelItem);
+
+      uStartOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
+      UsefulInputBuf_Seek(&(pMe->InBuf), uTempSaveCursor);
+   } else {
+      uStartOfReturned = uStartingCursor;
+   }
+
+   /* Consume the entire array/map to find the end */
+   uErr = QCBORDecode_Private_ConsumeItem(pMe, pItem, &EndedByBreak, &uNestLevel);
+   if(uErr != QCBOR_SUCCESS) {
+      pMe->uLastError = (uint8_t)uErr;
+      goto Done;
+   }
+
+   /* Fill in returned values */
+   uEndOfReturned = UsefulInputBuf_Tell(&(pMe->InBuf));
+   if(EndedByBreak) {
+      /* When ascending nesting levels, a break for the level above
+       * was consumed. That break is not a part of what is consumed here. */
+      uEndOfReturned--;
+   }
+   pEncodedCBOR->ptr = UsefulInputBuf_OffsetToPointer(&(pMe->InBuf), uStartOfReturned);
+   pEncodedCBOR->len = uEndOfReturned - uStartOfReturned;
+
+Done:
+   return;
+}
+
+
+/**
+ * @brief Semi-private. Get pointer, length and item count of an array or map.
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] pTarget        The label and type of the array or map to retrieve.
+ * @param[out] pItem         The item for the array/map.
+ * @param[out] pEncodedCBOR  Pointer and length of the encoded map or array.
+ *
+ * The next item to be decoded must be a map or array as specified by \c uType.
+ *
+ * When this is complete, the traversal cursor is unchanged.
+ */void
+QCBORDecode_Private_SearchAndGetArrayOrMap(QCBORDecodeContext *pMe,
+                                           QCBORItem          *pTarget,
+                                           QCBORItem          *pItem,
+                                           UsefulBufC         *pEncodedCBOR)
+{
+   MapSearchInfo      Info;
+   QCBORDecodeNesting SaveNesting;
+   size_t             uSaveCursor;
+
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pTarget, &Info, NULL);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   /* Save the whole position of things so they can be restored.
+    * so the cursor position is unchanged by this operation, like
+    * all the other GetXxxxInMap() operations. */
+   DecodeNesting_PrepareForMapSearch(&(pMe->nesting), &SaveNesting);
+   uSaveCursor = UsefulInputBuf_Tell(&(pMe->InBuf));
+
+   DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
+   UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
+   QCBORDecode_Private_GetArrayOrMap(pMe, pTarget[0].uDataType, pItem, pEncodedCBOR);
+
+   UsefulInputBuf_Seek(&(pMe->InBuf), uSaveCursor);
+   DecodeNesting_RestoreFromMapSearch(&(pMe->nesting), &SaveNesting);
+}
+
+
+
+
+/**
+ * @brief Is a QCBOR_TYPE in the type list?
+ *
+ * @param[in] uDataType  Type to check for.
+ * @param[in] puTypeList  List to check.
+ *
+ * @retval  QCBOR_SUCCESS             If in the list.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Not in the list.
+ */
+static QCBORError
+QCBOR_Private_CheckTypeList(const int     uDataType,
+                            const uint8_t puTypeList[QCBOR_TAGSPEC_NUM_TYPES])
+{
+   for(size_t i = 0; i < QCBOR_TAGSPEC_NUM_TYPES; i++) {
+      if(uDataType == puTypeList[i]) { /* -Wmaybe-uninitialized falsly warns here */
+         return QCBOR_SUCCESS;
+      }
+   }
+   return QCBOR_ERR_UNEXPECTED_TYPE;
+}
+
+
+/**
+ * Match a tag/type specification against the type of the item.
+ *
+ * @param[in] TagSpec  Specification for matching tags.
+ * @param[in] pItem    The item to check.
+ *
+ * @retval QCBOR_SUCCESS   \c uDataType is allowed by @c TagSpec
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE \c uDataType is not allowed by @c TagSpec
+ *
+ * This checks the item data type of untagged items as well as of
+ * tagged items against a specification to see if decoding should
+ * proceed.
+ *
+ * This relies on the automatic tag decoding done by QCBOR that turns
+ * tag numbers into particular QCBOR_TYPEs so there is no actual
+ * comparsion of tag numbers, just of QCBOR_TYPEs.
+ *
+ * This checks the data item type as possibly representing the tag
+ * number or as the tag content type.
+ *
+ * If QCBOR_DISABLE_TAGS is #defined,  this primarily checks the item
+ * data type against the allowed tag content types. It will also error out
+ * if the caller tries to require a tag because there is no way that can
+ * ever be fulfilled.
+ */
+static QCBORError
+QCBOR_Private_CheckTagRequirement(const QCBOR_Private_TagSpec TagSpec,
+                                  const QCBORItem            *pItem)
+{
+   const int nItemType = pItem->uDataType; /* -Wmaybe-uninitialized falsly warns here */
+   const int nTagReq = TagSpec.uTagRequirement & ~QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS;
+
+#ifndef QCBOR_DISABLE_TAGS
+   /* -Wmaybe-uninitialized falsly warns here */
+   if(!(TagSpec.uTagRequirement & QCBOR_TAG_REQUIREMENT_ALLOW_ADDITIONAL_TAGS) &&
+      pItem->uTags[0] != CBOR_TAG_INVALID16) {
+      /* There are tags that QCBOR couldn't process on this item and
+       * the caller has told us there should not be.
+       */
+      return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
+      /* Must match the tag number and only the tag */
+      return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
+   }
+
+   QCBORError uReturn = QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
+   if(uReturn == QCBOR_SUCCESS) {
+      return QCBOR_SUCCESS;
+   }
+
+   if(nTagReq == QCBOR_TAG_REQUIREMENT_NOT_A_TAG) {
+      /* Must match the content type and only the content type.
+       * There was no match just above so it is a fail. */
+      return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   /* QCBOR_TAG_REQUIREMENT_OPTIONAL_TAG: If here it can match either the tag or the content
+    * and it hasn't matched the content, so the end
+    * result is whether it matches the tag. This is
+    * the tag optional case that the CBOR standard discourages.
+    */
+
+   return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uTaggedTypes);
+
+#else /* QCBOR_DISABLE_TAGS */
+   if(nTagReq == QCBOR_TAG_REQUIREMENT_TAG) {
+      return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return QCBOR_Private_CheckTypeList(nItemType, TagSpec.uAllowedContentTypes);
+
+#endif /* QCBOR_DISABLE_TAGS */
+}
+
+
+/**
+ * @brief Get an item by label to match a tag specification.
+ *
+ * @param[in] pMe      The decode context.
+ * @param[in] nLabel   The label to search map for.
+ * @param[in] TagSpec  The tag number specification to match.
+ * @param[out] pItem   The item found.
+ *
+ * This finds the item with the given label in currently open
+ * map. Then checks that its tag number and types matches the tag
+ * specification. If not, an error is set in the decode context.
+ */
+static void
+QCBORDecode_GetTaggedItemInMapN(QCBORDecodeContext         *pMe,
+                                const int64_t               nLabel,
+                                const QCBOR_Private_TagSpec TagSpec,
+                                QCBORItem                  *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+}
+
+
+/**
+ * @brief Get an item by label to match a tag specification.
+ *
+ * @param[in] pMe      The decode context.
+ * @param[in] szLabel   The label to search map for.
+ * @param[in] TagSpec  The tag number specification to match.
+ * @param[out] pItem   The item found.
+ *
+ * This finds the item with the given label in currently open
+ * map. Then checks that its tag number and types matches the tag
+ * specification. If not, an error is set in the decode context.
+ */
+static void
+QCBORDecode_GetTaggedItemInMapSZ(QCBORDecodeContext          *pMe,
+                                 const char                  *szLabel,
+                                 const QCBOR_Private_TagSpec  TagSpec,
+                                 QCBORItem                   *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+}
+
+
+/**
+ * @brief Semi-private to get an string by label to match a tag specification.
+ *
+ * @param[in] pMe      The decode context.
+ * @param[in] nLabel   The label to search map for.
+ * @param[in] TagSpec  The tag number specification to match.
+ * @param[out] pString   The string found.
+ *
+ * This finds the string  with the given label in currently open
+ * map. Then checks that its tag number and types matches the tag
+ * specification. If not, an error is set in the decode context.
+ */
+void
+QCBORDecode_Private_GetTaggedStringInMapN(QCBORDecodeContext         *pMe,
+                                          const int64_t               nLabel,
+                                          const QCBOR_Private_TagSpec TagSpec,
+                                          UsefulBufC                 *pString)
+{
+   QCBORItem Item;
+   QCBORDecode_GetTaggedItemInMapN(pMe, nLabel, TagSpec, &Item);
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      *pString = Item.val.string;
+   }
+}
+
+
+/**
+ * @brief Semi-private to get an string by label to match a tag specification.
+ *
+ * @param[in] pMe      The decode context.
+ * @param[in] szLabel   The label to search map for.
+ * @param[in] TagSpec  The tag number specification to match.
+ * @param[out] pString   The string found.
+ *
+ * This finds the string  with the given label in currently open
+ * map. Then checks that its tag number and types matches the tag
+ * specification. If not, an error is set in the decode context.
+ */void
+QCBORDecode_Private_GetTaggedStringInMapSZ(QCBORDecodeContext         *pMe,
+                                           const char *                szLabel,
+                                           const QCBOR_Private_TagSpec TagSpec,
+                                           UsefulBufC                 *pString)
+{
+   QCBORItem Item;
+   QCBORDecode_GetTaggedItemInMapSZ(pMe, szLabel, TagSpec, &Item);
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      *pString = Item.val.string;
+   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetItemsInMap(QCBORDecodeContext *pMe, QCBORItem *pItemList)
+{
+   QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, NULL);
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetItemsInMapWithCallback(QCBORDecodeContext *pMe,
+                                      QCBORItem          *pItemList,
+                                      void               *pCallbackCtx,
+                                      QCBORItemCallback   pfCB)
+{
+   MapSearchCallBack CallBack;
+   CallBack.pCBContext = pCallbackCtx;
+   CallBack.pfCallback = pfCB;
+
+   QCBORError uErr = QCBORDecode_Private_MapSearch(pMe, pItemList, NULL, &CallBack);
+
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/**
+ * @brief Search for a map/array by label and enter it
+ *
+ * @param[in] pMe  The decode context.
+ * @param[in] pSearch The map/array to search for.
+ *
+ * @c pSearch is expected to contain one item of type map or array
+ * with the label specified. The current bounded map will be searched for
+ * this and if found  will be entered.
+ *
+ * If the label is not found, or the item found is not a map or array,
+ * the error state is set.
+ */
+static void
+QCBORDecode_Private_SearchAndEnter(QCBORDecodeContext *pMe, QCBORItem pSearch[])
+{
+   // The first item in pSearch is the one that is to be
+   // entered. It should be the only one filled in. Any other
+   // will be ignored unless it causes an error.
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   MapSearchInfo Info;
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_MapSearch(pMe, pSearch, &Info, NULL);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   if(pSearch->uDataType == QCBOR_TYPE_NONE) {
+      pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+      return;
+   }
+
+
+   /* The map or array was found. Now enter it.
+    *
+    * QCBORDecode_EnterBoundedMapOrArray() used here, requires the
+    * next item for the pre-order traversal cursor to be the map/array
+    * found by MapSearch(). The next few lines of code force the
+    * cursor to that.
+    *
+    * There is no need to retain the old cursor because
+    * QCBORDecode_EnterBoundedMapOrArray() will set it to the
+    * beginning of the map/array being entered.
+    *
+    * The cursor is forced by: 1) setting the input buffer position to
+    * the item offset found by MapSearch(), 2) setting the map/array
+    * counter to the total in the map/array, 3) setting the nesting
+    * level. Setting the map/array counter to the total is not
+    * strictly correct, but this is OK because this cursor only needs
+    * to be used to get one item and MapSearch() has already found it
+    * confirming it exists.
+    */
+   UsefulInputBuf_Seek(&(pMe->InBuf), Info.uStartOffset);
+
+   DecodeNesting_ResetMapOrArrayCount(&(pMe->nesting));
+
+   DecodeNesting_SetCurrentToBoundedLevel(&(pMe->nesting));
+
+   QCBORDecode_Private_EnterBoundedMapOrArray(pMe, pSearch->uDataType, NULL);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterMapFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
+{
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
+   OneItemSeach[0].label.int64 = nLabel;
+   OneItemSeach[0].uDataType   = QCBOR_TYPE_MAP;
+   OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
+
+   /* The map to enter was found, now finish off entering it. */
+   QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterMapFromMapSZ(QCBORDecodeContext *pMe, const char  *szLabel)
+{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
+   OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+   OneItemSeach[0].uDataType    = QCBOR_TYPE_MAP;
+   OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+   (void)szLabel;
+   pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterArrayFromMapN(QCBORDecodeContext *pMe, int64_t nLabel)
+{
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType  = QCBOR_TYPE_INT64;
+   OneItemSeach[0].label.int64 = nLabel;
+   OneItemSeach[0].uDataType   = QCBOR_TYPE_ARRAY;
+   OneItemSeach[1].uLabelType  = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterArrayFromMapSZ(QCBORDecodeContext *pMe, const char  *szLabel)
+{
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   QCBORItem OneItemSeach[2];
+   OneItemSeach[0].uLabelType   = QCBOR_TYPE_TEXT_STRING;
+   OneItemSeach[0].label.string = UsefulBuf_FromSZ(szLabel);
+   OneItemSeach[0].uDataType    = QCBOR_TYPE_ARRAY;
+   OneItemSeach[1].uLabelType   = QCBOR_TYPE_NONE;
+
+   QCBORDecode_Private_SearchAndEnter(pMe, OneItemSeach);
+#else
+   (void)szLabel;
+   pMe->uLastError = QCBOR_ERR_LABEL_NOT_FOUND;
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+}
+
+
+/**
+ * @brief Semi-private to do the the work for EnterMap() and EnterArray().
+ *
+ * @param[in] pMe     The decode context
+ * @param[in] uType   QCBOR_TYPE_MAP or QCBOR_TYPE_ARRAY.
+ * @param[out] pItem  The data item for the map or array entered.
+ *
+ * The next item in the traversal must be a map or array.  This
+ * consumes that item and does the book keeping to enter the map or
+ * array.
+ */
+void
+QCBORDecode_Private_EnterBoundedMapOrArray(QCBORDecodeContext *pMe,
+                                           const uint8_t       uType,
+                                           QCBORItem          *pItem)
+{
+    QCBORError uErr;
+
+   /* Must only be called on maps and arrays. */
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state; do nothing.
+      return;
+   }
+
+   /* Get the data item that is the map or array being entered. */
+   QCBORItem Item;
+   uErr = QCBORDecode_GetNext(pMe, &Item);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   uint8_t uItemDataType = Item.uDataType;
+
+#ifndef QCBOR_DISABLE_NON_INTEGER_LABELS
+   if(uItemDataType == QCBOR_TYPE_MAP_AS_ARRAY ) {
+      uItemDataType = QCBOR_TYPE_ARRAY;
+   }
+#endif /* ! QCBOR_DISABLE_NON_INTEGER_LABELS */
+
+   if(uItemDataType != uType) {
+      uErr = QCBOR_ERR_UNEXPECTED_TYPE;
+      goto Done;
+   }
+
+   QCBORDecode_Private_CopyTags(pMe, &Item);
+
+
+   const bool bIsEmpty = (Item.uNextNestLevel <= Item.uNestingLevel);
+   if(bIsEmpty) {
+      if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
+         // Undo decrement done by QCBORDecode_GetNext() so the the
+         // the decrement when exiting the map/array works correctly
+         pMe->nesting.pCurrent->u.ma.uCountCursor++;
+      }
+      // Special case to increment nesting level for zero-length maps
+      // and arrays entered in bounded mode.
+      DecodeNesting_Descend(&(pMe->nesting), uType);
+   }
+
+   pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
+
+   uErr = DecodeNesting_EnterBoundedMapOrArray(&(pMe->nesting), bIsEmpty,
+                                               UsefulInputBuf_Tell(&(pMe->InBuf)));
+
+   if(pItem != NULL) {
+      *pItem = Item;
+   }
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/**
+ * @brief Exit a bounded map, array or bstr (semi-private).
+ *
+ * @param[in] pMe         Decode context.
+ * @param[in] uEndOffset  The input buffer offset of the end of item exited.
+ *
+ * @returns  QCBOR_SUCCESS or an error code.
+ *
+ * This is the common work for exiting a level that is a bounded map,
+ * array or bstr wrapped CBOR.
+ *
+ * One chunk of work is to set up the pre-order traversal so it is at
+ * the item just after the bounded map, array or bstr that is being
+ * exited. This is somewhat complex.
+ *
+ * The other work is to level-up the bounded mode to next higest
+ * bounded mode or the top level if there isn't one.
+ */
+static QCBORError
+QCBORDecode_Private_ExitBoundedLevel(QCBORDecodeContext *pMe,
+                                     const uint32_t      uEndOffset)
+{
+   QCBORError uErr;
+
+   /*
+    * First the pre-order-traversal byte offset is positioned to the
+    * item just after the bounded mode item that was just consumed.
+    */
+   UsefulInputBuf_Seek(&(pMe->InBuf), uEndOffset);
+
+   /*
+    * Next, set the current nesting level to one above the bounded
+    * level that was just exited.
+    *
+    * DecodeNesting_CheckBoundedType() is always called before this
+    * and makes sure pCurrentBounded is valid.
+    */
+   DecodeNesting_LevelUpCurrent(&(pMe->nesting));
+
+   /*
+    * This does the complex work of leveling up the pre-order
+    * traversal when the end of a map or array or another bounded
+    * level is reached.  It may do nothing, or ascend all the way to
+    * the top level.
+    */
+   uErr = QCBORDecode_Private_NestLevelAscender(pMe, NULL, false);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   /*
+    * This makes the next highest bounded level the current bounded
+    * level. If there is no next highest level, then no bounded mode
+    * is in effect.
+    */
+   DecodeNesting_LevelUpBounded(&(pMe->nesting));
+
+   pMe->uMapEndOffsetCache = QCBOR_MAP_OFFSET_CACHE_INVALID;
+
+Done:
+   return uErr;
+}
+
+
+/**
+ * @brief Get started exiting a map or array (semi-private)
+ *
+ * @param[in] pMe  The decode context
+ * @param[in] uType  QCBOR_TYPE_ARRAY or QCBOR_TYPE_MAP
+ *
+ * This does some work for map and array exiting (but not
+ * bstr exiting). Then QCBORDecode_Private_ExitBoundedLevel()
+ * is called to do the rest.
+ */
+void
+QCBORDecode_Private_ExitBoundedMapOrArray(QCBORDecodeContext *pMe,
+                                          const uint8_t       uType)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state; do nothing. */
+      return;
+   }
+
+   QCBORError uErr;
+
+   if(!DecodeNesting_IsBoundedType(&(pMe->nesting), uType)) {
+      uErr = QCBOR_ERR_EXIT_MISMATCH;
+      goto Done;
+   }
+
+   /*
+    Have to set the offset to the end of the map/array
+    that is being exited. If there is no cached value,
+    from previous map search, then do a dummy search.
+    */
+   if(pMe->uMapEndOffsetCache == QCBOR_MAP_OFFSET_CACHE_INVALID) {
+      QCBORItem Dummy;
+      Dummy.uLabelType = QCBOR_TYPE_NONE;
+      uErr = QCBORDecode_Private_MapSearch(pMe, &Dummy, NULL, NULL);
+      if(uErr != QCBOR_SUCCESS) {
+         goto Done;
+      }
+   }
+
+   uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, pMe->uMapEndOffsetCache);
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/**
+ * @brief The main work of entering some byte-string wrapped CBOR.
+ *
+ * @param[in] pMe             The decode context.
+ * @param[in] pItem           The byte string item.
+ * @param[in] uTagRequirement One of @c QCBOR_TAG_REQUIREMENT_XXX
+ * @param[out] pBstr          Pointer and length of byte string entered.
+ *
+ * This is called once the byte string item has been decoded to do all
+ * the book keeping work for descending a nesting level into the
+ * nested CBOR.
+ *
+ * See QCBORDecode_EnterBstrWrapped() for details on uTagRequirement.
+ */
+static QCBORError
+QCBORDecode_Private_EnterBstrWrapped(QCBORDecodeContext *pMe,
+                                     const QCBORItem    *pItem,
+                                     const uint8_t       uTagRequirement,
+                                     UsefulBufC         *pBstr)
+{
+   if(pBstr) {
+      *pBstr = NULLUsefulBufC;
+   }
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state; do nothing. */
+      return pMe->uLastError;
+   }
+
+   QCBORError uError;
+
+   const QCBOR_Private_TagSpec TagSpec =
+      {
+         uTagRequirement,
+         {QBCOR_TYPE_WRAPPED_CBOR, QBCOR_TYPE_WRAPPED_CBOR_SEQUENCE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   uError = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+   if(uError != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   if(DecodeNesting_IsCurrentDefiniteLength(&(pMe->nesting))) {
+      /* Reverse the decrement done by GetNext() for the bstr so the
+       * increment in QCBORDecode_NestLevelAscender() called by
+       * ExitBoundedLevel() will work right.
+       */
+      DecodeNesting_ReverseDecrement(&(pMe->nesting));
+   }
+
+   if(pBstr) {
+      *pBstr = pItem->val.string;
+   }
+
+   /* This saves the current length of the UsefulInputBuf and then
+    * narrows the UsefulInputBuf to start and length of the wrapped
+    * CBOR that is being entered.
+    *
+    * Most of these calls are simple inline accessors so this doesn't
+    * amount to much code.
+    */
+
+   const size_t uPreviousLength = UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
+   /* This check makes the cast of uPreviousLength to uint32_t below safe. */
+   if(uPreviousLength >= QCBOR_MAX_DECODE_INPUT_SIZE) {
+      uError = QCBOR_ERR_INPUT_TOO_LARGE;
+      goto Done;
+   }
+
+   const size_t uStartOfBstr = UsefulInputBuf_PointerToOffset(&(pMe->InBuf),
+                                                              pItem->val.string.ptr);
+   /* This check makes the cast of uStartOfBstr to uint32_t below safe. */
+   if(uStartOfBstr == SIZE_MAX || uStartOfBstr > QCBOR_MAX_DECODE_INPUT_SIZE) {
+      /* This should never happen because pItem->val.string.ptr should
+       * always be valid since it was just returned.
+       */
+      uError = QCBOR_ERR_INPUT_TOO_LARGE;
+      goto Done;
+   }
+
+   const size_t uEndOfBstr = uStartOfBstr + pItem->val.string.len;
+
+   UsefulInputBuf_Seek(&(pMe->InBuf), uStartOfBstr);
+   UsefulInputBuf_SetBufferLength(&(pMe->InBuf), uEndOfBstr);
+
+   uError = DecodeNesting_DescendIntoBstrWrapped(&(pMe->nesting),
+                                                 (uint32_t)uPreviousLength,
+                                                 (uint32_t)uStartOfBstr);
+Done:
+   return uError;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterBstrWrapped(QCBORDecodeContext *pMe,
+                             const uint8_t       uTagRequirement,
+                             UsefulBufC         *pBstr)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state; do nothing.
+      return;
+   }
+
+   /* Get the data item that is the byte string being entered */
+   QCBORItem Item;
+   pMe->uLastError = (uint8_t)QCBORDecode_GetNext(pMe, &Item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   if(Item.uDataAlloc) {
+      pMe->uLastError = QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING;
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
+                                                                  &Item,
+                                                                   uTagRequirement,
+                                                                   pBstr);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterBstrWrappedFromMapN(QCBORDecodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint8_t       uTagRequirement,
+                                     UsefulBufC         *pBstr)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
+                                                                  &Item,
+                                                                   uTagRequirement,
+                                                                   pBstr);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_EnterBstrWrappedFromMapSZ(QCBORDecodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint8_t       uTagRequirement,
+                                      UsefulBufC         *pBstr)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   pMe->uLastError = (uint8_t)QCBORDecode_Private_EnterBstrWrapped(pMe,
+                                                                  &Item,
+                                                                   uTagRequirement,
+                                                                   pBstr);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_ExitBstrWrapped(QCBORDecodeContext *pMe)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state; do nothing.
+      return;
+   }
+
+   if(!DecodeNesting_IsBoundedType(&(pMe->nesting), QCBOR_TYPE_BYTE_STRING)) {
+      pMe->uLastError = QCBOR_ERR_EXIT_MISMATCH;
+      return;
+   }
+
+   const uint32_t uEndOfBstr = (uint32_t)UsefulInputBuf_GetBufferLength(&(pMe->InBuf));
+
+   /*
+    Reset the length of the UsefulInputBuf to what it was before
+    the bstr wrapped CBOR was entered.
+    */
+   UsefulInputBuf_SetBufferLength(&(pMe->InBuf),
+                               DecodeNesting_GetPreviousBoundedEnd(&(pMe->nesting)));
+
+
+   QCBORError uErr = QCBORDecode_Private_ExitBoundedLevel(pMe, uEndOfBstr);
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+
+/**
+ * @brief Process simple type true and false, a boolean
+ *
+ * @param[in] pMe     The decode context.
+ * @param[in] pItem   The item with either true or false.
+ * @param[out] pBool  The boolean value output.
+ *
+ * Sets the internal error if the item isn't a true or a false. Also
+ * records any tag numbers as the tag numbers of the last item.
+ */
+static void
+QCBORDecode_Private_ProcessBool(QCBORDecodeContext *pMe,
+                                const QCBORItem    *pItem,
+                                bool               *pBool)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state, do nothing */
+      return;
+   }
+
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_TRUE:
+         *pBool = true;
+         break;
+
+      case QCBOR_TYPE_FALSE:
+         *pBool = false;
+         break;
+
+      default:
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         break;
+   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBool(QCBORDecodeContext *pMe, bool *pValue)
+{
+   QCBORItem  Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+   QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBoolInMapN(QCBORDecodeContext *pMe,
+                          const int64_t       nLabel,
+                          bool               *pValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBoolInMapSZ(QCBORDecodeContext *pMe,
+                           const char         *szLabel,
+                           bool               *pValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessBool(pMe, &Item, pValue);
+}
+
+
+/**
+ * @brief Process simple values.
+ *
+ * @param[in] pMe     The decode context.
+ * @param[in] pItem   The item with the simple value.
+ * @param[out] puSimple  The simple value output.
+ *
+ * Sets the internal error if the item isn't a true or a false. Also
+ * records any tag numbers as the tag numbers of the last item.
+ */
+static void
+QCBORDecode_Private_ProcessSimple(QCBORDecodeContext *pMe,
+                                  const QCBORItem    *pItem,
+                                  uint8_t            *puSimple)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   /* It's kind of lame to remap true...undef back to simple values, but
+    * this function isn't used much and to not do it would require
+    * changing GetNext() behavior in an incompatible way.
+    */
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_UKNOWN_SIMPLE:
+         *puSimple = pItem->val.uSimple;
+         break;
+
+      case QCBOR_TYPE_TRUE:
+         *puSimple = CBOR_SIMPLEV_TRUE;
+         break;
+
+      case QCBOR_TYPE_FALSE:
+         *puSimple = CBOR_SIMPLEV_FALSE;
+         break;
+
+      case QCBOR_TYPE_NULL:
+         *puSimple = CBOR_SIMPLEV_NULL;
+         break;
+
+      case QCBOR_TYPE_UNDEF:
+         *puSimple = CBOR_SIMPLEV_UNDEF;
+         break;
+
+      default:
+         pMe->uLastError = QCBOR_ERR_UNEXPECTED_TYPE;
+         return;
+   }
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimple(QCBORDecodeContext *pMe, uint8_t *puSimple)
+{
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimple);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapN(QCBORDecodeContext *pMe,
+                            int64_t             nLabel,
+                            uint8_t            *puSimpleValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetSimpleInMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             uint8_t            *puSimpleValue)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessSimple(pMe, &Item, puSimpleValue);
+}
+
+
+
+/**
+ * @brief Common processing for an epoch date.
+ *
+ * @param[in] pMe              The decode context.
+ * @param[in] pItem            The item with the date.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnTime          The returned date.
+ *
+ * Common processing for the date tag. Mostly make sure the tag
+ * content is correct and copy forward any further other tag numbers.
+ */
+static void
+QCBORDecode_Private_ProcessEpochDate(QCBORDecodeContext *pMe,
+                                     QCBORItem          *pItem,
+                                     const uint8_t       uTagRequirement,
+                                     int64_t            *pnTime)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      // Already in error state, do nothing
+      return;
+   }
+
+   QCBORError uErr;
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DATE_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_INT64, QCBOR_TYPE_DOUBLE, QCBOR_TYPE_FLOAT, QCBOR_TYPE_UINT64}
+   };
+
+   uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   if(pItem->uDataType != QCBOR_TYPE_DATE_EPOCH) {
+      uErr = QCBOR_Private_DecodeDateEpoch(pItem);
+      if(uErr != QCBOR_SUCCESS) {
+         goto Done;
+      }
+   }
+
+   *pnTime = pItem->val.epochDate.nSeconds;
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h file
+ */
+void
+QCBORDecode_GetEpochDate(QCBORDecodeContext *pMe,
+                         uint8_t             uTagRequirement,
+                         int64_t            *pnTime)
+{
+   QCBORItem  Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+   QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h file
+ */
+void
+QCBORDecode_GetEpochDateInMapN(QCBORDecodeContext *pMe,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnTime)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h file
+ */
+void
+QCBORDecode_GetEpochDateInMapSZ(QCBORDecodeContext *pMe,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t            *pnTime)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessEpochDate(pMe, &Item, uTagRequirement, pnTime);
+}
+
+
+
+/**
+ * @brief Common processing for an epoch date.
+ *
+ * @param[in] pMe              The decode context.
+ * @param[in] pItem            The item with the date.
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[out] pnDays          The returned day count.
+ *
+ * Common processing for the RFC 8943 day-count tag. Mostly make sure
+ * the tag content is correct and copy forward any further other tag
+ * numbers.
+ */
+static void
+QCBORDecode_Private_ProcessEpochDays(QCBORDecodeContext *pMe,
+                                     QCBORItem          *pItem,
+                                     uint8_t             uTagRequirement,
+                                     int64_t            *pnDays)
+{
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      /* Already in error state, do nothing */
+      return;
+   }
+
+   QCBORError uErr;
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DAYS_EPOCH, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_INT64, QCBOR_TYPE_UINT64, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   if(pItem->uDataType != QCBOR_TYPE_DAYS_EPOCH) {
+      uErr = QCBOR_Private_DecodeDaysEpoch(pItem);
+      if(uErr != QCBOR_SUCCESS) {
+         goto Done;
+      }
+   }
+
+   *pnDays = pItem->val.epochDays;
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetEpochDays(QCBORDecodeContext *pMe,
+                         uint8_t             uTagRequirement,
+                         int64_t            *pnDays)
+{
+   QCBORItem  Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+   QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetEpochDaysInMapN(QCBORDecodeContext *pMe,
+                               int64_t             nLabel,
+                               uint8_t             uTagRequirement,
+                               int64_t            *pnDays)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h
+ */
+void
+QCBORDecode_GetEpochDaysInMapSZ(QCBORDecodeContext *pMe,
+                                const char         *szLabel,
+                                uint8_t             uTagRequirement,
+                                int64_t            *pnDays)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   QCBORDecode_Private_ProcessEpochDays(pMe, &Item, uTagRequirement, pnDays);
+}
+
+
+
+/*
+ * @brief Get a string that matches the type/tag specification.
+ */
+void
+QCBORDecode_Private_GetTaggedString(QCBORDecodeContext         *pMe,
+                                    const QCBOR_Private_TagSpec TagSpec,
+                                    UsefulBufC                 *pBstr)
+{
+   QCBORItem  Item;
+
+   QCBORDecode_VGetNext(pMe, &Item);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_CheckTagRequirement(TagSpec, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      *pBstr = Item.val.string;
+   } else {
+      *pBstr = NULLUsefulBufC;
+   }
+}
+
+
+
+
+/**
+ * @brief Common processing for a big number tag.
+ *
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[in] pItem            The item with the date.
+ * @param[out] pValue          The returned big number
+ * @param[out] pbIsNegative  The returned sign of the big number.
+ *
+ * Common processing for the big number tag. Mostly make sure
+ * the tag content is correct and copy forward any further other tag
+ * numbers.
+ */
+static QCBORError
+QCBOR_Private_ProcessBigNum(const uint8_t   uTagRequirement,
+                            const QCBORItem *pItem,
+                            UsefulBufC      *pValue,
+                            bool            *pbIsNegative)
+{
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_POSBIGNUM, QCBOR_TYPE_NEGBIGNUM, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORError uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      return uErr;
+   }
+
+   *pValue = pItem->val.string;
+
+   if(pItem->uDataType == QCBOR_TYPE_POSBIGNUM) {
+      *pbIsNegative = false;
+   } else if(pItem->uDataType == QCBOR_TYPE_NEGBIGNUM) {
+      *pbIsNegative = true;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetBignum(QCBORDecodeContext *pMe,
+                      const uint8_t       uTagRequirement,
+                      UsefulBufC         *pValue,
+                      bool               *pbIsNegative)
+{
+   QCBORItem  Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
+                                                          &Item,
+                                                          pValue,
+                                                          pbIsNegative);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetBignumInMapN(QCBORDecodeContext *pMe,
+                            const int64_t       nLabel,
+                            const uint8_t       uTagRequirement,
+                            UsefulBufC         *pValue,
+                            bool               *pbIsNegative)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
+                                                          &Item,
+                                                          pValue,
+                                                          pbIsNegative);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_spiffy_decode.h
+ */
+void
+QCBORDecode_GetBignumInMapSZ(QCBORDecodeContext *pMe,
+                             const char         *szLabel,
+                             const uint8_t       uTagRequirement,
+                             UsefulBufC         *pValue,
+                             bool               *pbIsNegative)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ProcessBigNum(uTagRequirement,
+                                                          &Item,
+                                                          pValue,
+                                                          pbIsNegative);
+}
+
+
+
+/**
+ * @brief Common processing for MIME tag (semi-private).
+ *
+ * @param[in] uTagRequirement  One of @c QCBOR_TAG_REQUIREMENT_XXX.
+ * @param[in] pItem            The item with the date.
+ * @param[out] pMessage        The returned MIME message.
+ * @param[out] pbIsTag257      If true, binary MIME, if not, text MIME.
+ *
+ * Common processing for the MIME tag. Mostly make sure the tag
+ * content is correct and copy forward any further other tag
+ * numbers. See QCBORDecode_GetMIMEMessage().
+ */
+QCBORError
+QCBORDecode_Private_GetMIME(const uint8_t     uTagRequirement,
+                            const QCBORItem  *pItem,
+                            UsefulBufC       *pMessage,
+                            bool             *pbIsTag257)
+{
+   const QCBOR_Private_TagSpec TagSpecText =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_TEXT_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+   const QCBOR_Private_TagSpec TagSpecBinary =
+      {
+         uTagRequirement,
+         {QCBOR_TYPE_BINARY_MIME, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE},
+         {QCBOR_TYPE_BYTE_STRING, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+      };
+
+   QCBORError uReturn;
+
+   if(QCBOR_Private_CheckTagRequirement(TagSpecText, pItem) == QCBOR_SUCCESS) {
+      *pMessage = pItem->val.string;
+      if(pbIsTag257 != NULL) {
+         *pbIsTag257 = false;
+      }
+      uReturn = QCBOR_SUCCESS;
+   } else if(QCBOR_Private_CheckTagRequirement(TagSpecBinary, pItem) == QCBOR_SUCCESS) {
+      *pMessage = pItem->val.string;
+      if(pbIsTag257 != NULL) {
+         *pbIsTag257 = true;
+      }
+      uReturn = QCBOR_SUCCESS;
+
+   } else {
+      uReturn = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return uReturn;
+}
+
+// Improvement: add methods for wrapped CBOR, a simple alternate
+// to EnterBstrWrapped
+
+
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+/**
+ * @brief Prototype for conversion of exponent and mantissa to unsigned integer.
+ *
+ * @param[in] uMantissa    The mantissa.
+ * @param[in] nExponent    The exponent.
+ * @param[out] puResult  The resulting integer.
+ *
+ * Concrete implementations of this are for exponent base 10 and 2 supporting
+ * decimal fractions and big floats.
+ */
+typedef QCBORError (*fExponentiator)(uint64_t uMantissa, int64_t nExponent, uint64_t *puResult);
+
+
+/**
+ * @brief  Base 10 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
+ *
+ * @param[in] uMantissa  The unsigned integer mantissa.
+ * @param[in] nExponent  The signed integer exponent.
+ * @param[out] puResult  Place to return the unsigned integer result.
+ *
+ * This computes: mantissa * 10 ^^ exponent as for a decimal fraction. The output is a 64-bit
+ * unsigned integer.
+ *
+ * There are many inputs for which the result will not fit in the
+ * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
+ * be returned.
+ */
+static QCBORError
+QCBOR_Private_Exponentitate10(const uint64_t uMantissa,
+                              int64_t        nExponent,
+                              uint64_t      *puResult)
+{
+   uint64_t uResult = uMantissa;
+
+   if(uResult != 0) {
+      /* This loop will run a maximum of 19 times because
+       * UINT64_MAX < 10 ^^ 19. More than that will cause
+       * exit with the overflow error
+       */
+      for(; nExponent > 0; nExponent--) {
+         if(uResult > UINT64_MAX / 10) {
+            return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+         }
+         uResult = uResult * 10;
+      }
+
+      for(; nExponent < 0; nExponent++) {
+         uResult = uResult / 10;
+         if(uResult == 0) {
+            return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+         }
+      }
+   }
+   /* else, mantissa is zero so this returns zero */
+
+   *puResult = uResult;
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief  Base 2 exponentiate a mantissa and exponent into an unsigned 64-bit integer.
+ *
+ * @param[in] uMantissa  The unsigned integer mantissa.
+ * @param[in] nExponent  The signed integer exponent.
+ * @param[out] puResult  Place to return the unsigned integer result.
+ *
+ * This computes: mantissa * 2 ^^ exponent as for a big float. The
+ * output is a 64-bit unsigned integer.
+ *
+ * There are many inputs for which the result will not fit in the
+ * 64-bit integer and \ref QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW will
+ * be returned.
+ */
+static QCBORError
+QCBOR_Private_Exponentitate2(const uint64_t uMantissa,
+                             int64_t        nExponent,
+                             uint64_t      *puResult)
+{
+   uint64_t uResult;
+
+   uResult = uMantissa;
+
+   /* This loop will run a maximum of 64 times because INT64_MAX <
+    * 2^31. More than that will cause exit with the overflow error
+    */
+   while(nExponent > 0) {
+      if(uResult > UINT64_MAX >> 1) {
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+      }
+      uResult = uResult << 1;
+      nExponent--;
+   }
+
+   while(nExponent < 0 ) {
+      if(uResult == 0) {
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+      }
+      uResult = uResult >> 1;
+      nExponent++;
+   }
+
+   *puResult = uResult;
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Exponentiate a signed mantissa and signed exponent to produce a signed result.
+ *
+ * @param[in] nMantissa  Signed integer mantissa.
+ * @param[in] nExponent  Signed integer exponent.
+ * @param[out] pnResult  Place to put the signed integer result.
+ * @param[in] pfExp      Exponentiation function.
+ *
+ * @returns Error code
+ *
+ * \c pfExp performs exponentiation on and unsigned mantissa and
+ * produces an unsigned result. This converts the mantissa from signed
+ * and converts the result to signed. The exponentiation function is
+ * either for base 2 or base 10 (and could be other if needed).
+ */
+static QCBORError
+QCBOR_Private_ExponentiateNN(const int64_t  nMantissa,
+                             const int64_t  nExponent,
+                             int64_t       *pnResult,
+                             fExponentiator pfExp)
+{
+   uint64_t uResult;
+   uint64_t uMantissa;
+
+   /* Take the absolute value and put it into an unsigned. */
+   if(nMantissa >= 0) {
+      /* Positive case is straightforward */
+      uMantissa = (uint64_t)nMantissa;
+   } else if(nMantissa != INT64_MIN) {
+      /* The common negative case. See next. */
+      uMantissa = (uint64_t)-nMantissa;
+   } else {
+      /* int64_t and uint64_t are always two's complement per the
+       * C standard (and since QCBOR uses these it only works with
+       * two's complement, which is pretty much universal these
+       * days). The range of a negative two's complement integer is
+       * one more that than a positive, so the simple code above might
+       * not work all the time because you can't simply negate the
+       * value INT64_MIN because it can't be represented in an
+       * int64_t. -INT64_MIN can however be represented in a
+       * uint64_t. Some compilers seem to recognize this case for the
+       * above code and put the correct value in uMantissa, however
+       * they are not required to do this by the C standard. This next
+       * line does however work for all compilers.
+       *
+       * This does assume two's complement where -INT64_MIN ==
+       * INT64_MAX + 1 (which wouldn't be true for one's complement or
+       * sign and magnitude (but we know we're using two's complement
+       * because int64_t requires it)).
+       *
+       * See these, particularly the detailed commentary:
+       * https://stackoverflow.com/questions/54915742/does-c99-mandate-a-int64-t-type-be-available-always
+       * https://stackoverflow.com/questions/37301078/is-negating-int-min-undefined-behaviour
+       */
+      uMantissa = (uint64_t)INT64_MAX+1;
+   }
+
+   /* Call the exponentiator passed for either base 2 or base 10.
+    * Here is where most of the overflow errors are caught. */
+   QCBORError uReturn = (*pfExp)(uMantissa, nExponent, &uResult);
+   if(uReturn) {
+      return uReturn;
+   }
+
+   /* Convert back to the sign of the original mantissa */
+   if(nMantissa >= 0) {
+      if(uResult > INT64_MAX) {
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+      }
+      *pnResult = (int64_t)uResult;
+   } else {
+      /* (uint64_t)INT64_MAX+1 is used to represent the absolute value
+       * of INT64_MIN. This assumes two's compliment representation
+       * where INT64_MIN is one increment farther from 0 than
+       * INT64_MAX.  Trying to write -INT64_MIN doesn't work to get
+       * this because the compiler makes it an int64_t which can't
+       * represent -INT64_MIN. Also see above.
+       */
+      if(uResult > (uint64_t)INT64_MAX+1) {
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+      }
+      *pnResult = -(int64_t)uResult;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Exponentiate an unsigned mantissa and signed exponent to produce an unsigned result.
+ *
+ * @param[in] nMantissa  Signed integer mantissa.
+ * @param[in] nExponent  Signed integer exponent.
+ * @param[out] puResult  Place to put the signed integer result.
+ * @param[in] pfExp      Exponentiation function.
+ *
+ * @returns Error code
+ *
+ * \c pfExp performs exponentiation on and unsigned mantissa and
+ * produces an unsigned result. This errors out if the mantissa
+ * is negative because the output is unsigned.
+ */
+static QCBORError
+QCBOR_Private_ExponentitateNU(const int64_t  nMantissa,
+                              const int64_t  nExponent,
+                              uint64_t      *puResult,
+                              fExponentiator pfExp)
+{
+   if(nMantissa < 0) {
+      return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+   }
+
+   /* Cast to unsigned is OK because of check for negative.
+    * Cast to unsigned is OK because UINT64_MAX > INT64_MAX.
+    * Exponentiation is straight forward
+    */
+   return (*pfExp)((uint64_t)nMantissa, nExponent, puResult);
+}
+
+
+/**
+ * @brief Exponentiate an usnigned mantissa and unsigned exponent to produce an unsigned result.
+ *
+ * @param[in] uMantissa  Unsigned integer mantissa.
+ * @param[in] nExponent  Unsigned integer exponent.
+ * @param[out] puResult  Place to put the unsigned integer result.
+ * @param[in] pfExp      Exponentiation function.
+ *
+ * @returns Error code
+ *
+ * \c pfExp performs exponentiation on and unsigned mantissa and
+ * produces an unsigned result so this is just a wrapper that does
+ * nothing (and is likely inlined).
+ */
+static QCBORError
+QCBOR_Private_ExponentitateUU(const uint64_t uMantissa,
+                              const int64_t  nExponent,
+                              uint64_t      *puResult,
+                              fExponentiator pfExp)
+{
+   return (*pfExp)(uMantissa, nExponent, puResult);
+}
+
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+
+
+/**
+ * @brief Convert a CBOR big number to a uint64_t.
+ *
+ * @param[in] BigNum  Bytes of the big number to convert.
+ * @param[in] uMax  Maximum value allowed for the result.
+ * @param[out] pResult  Place to put the unsigned integer result.
+ *
+ * @returns Error code
+ *
+ * Many values will overflow because  a big num can represent a much
+ * larger range than uint64_t.
+ */
+static QCBORError
+QCBOR_Private_ConvertBigNumToUnsigned(const UsefulBufC BigNum,
+                                      const uint64_t   uMax,
+                                      uint64_t        *pResult)
+{
+   uint64_t uResult;
+
+   uResult = 0;
+   const uint8_t *pByte = BigNum.ptr;
+   size_t uLen = BigNum.len;
+   while(uLen--) {
+      if(uResult > (uMax >> 8)) {
+         return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+      }
+      uResult = (uResult << 8) + *pByte++;
+   }
+
+   *pResult = uResult;
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Convert a CBOR postive big number to a uint64_t.
+ *
+ * @param[in] BigNum  Bytes of the big number to convert.
+ * @param[out] pResult  Place to put the unsigned integer result.
+ *
+ * @returns Error code
+ *
+ * Many values will overflow because  a big num can represent a much
+ * larger range than uint64_t.
+ */
+static QCBORError
+QCBOR_Private_ConvertPositiveBigNumToUnsigned(const UsefulBufC BigNum,
+                                              uint64_t        *pResult)
+{
+   return QCBOR_Private_ConvertBigNumToUnsigned(BigNum, UINT64_MAX, pResult);
+}
+
+
+/**
+ * @brief Convert a CBOR positive big number to an int64_t.
+ *
+ * @param[in] BigNum  Bytes of the big number to convert.
+ * @param[out] pResult  Place to put the signed integer result.
+ *
+ * @returns Error code
+ *
+ * Many values will overflow because  a big num can represent a much
+ * larger range than int64_t.
+ */
+static QCBORError
+QCBOR_Private_ConvertPositiveBigNumToSigned(const UsefulBufC BigNum,
+                                            int64_t         *pResult)
+{
+   uint64_t uResult;
+   QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
+                                                             INT64_MAX,
+                                                             &uResult);
+   if(uError) {
+      return uError;
+   }
+   /* Cast is safe because ConvertBigNumToUnsigned limits to INT64_MAX */
+   *pResult = (int64_t)uResult;
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Convert a CBOR negative big number to an int64_t.
+ *
+ * @param[in] BigNum  Bytes of the big number to convert.
+ * @param[out] pnResult  Place to put the signed integer result.
+ *
+ * @returns Error code
+ *
+ * Many values will overflow because  a big num can represent a much
+ * larger range than int64_t.
+ */
+static QCBORError
+QCBOR_Private_ConvertNegativeBigNumToSigned(const UsefulBufC BigNum,
+                                            int64_t         *pnResult)
+{
+   uint64_t uResult;
+   /* The negative integer furthest from zero for a C int64_t is
+    * INT64_MIN which is expressed as -INT64_MAX - 1. The value of a
+    * negative number in CBOR is computed as -n - 1 where n is the
+    * encoded integer, where n is what is in the variable BigNum. When
+    * converting BigNum to a uint64_t, the maximum value is thus
+    * INT64_MAX, so that when it -n - 1 is applied to it the result
+    * will never be further from 0 than INT64_MIN.
+    *
+    *   -n - 1 <= INT64_MIN.
+    *   -n - 1 <= -INT64_MAX - 1
+    *    n     <= INT64_MAX.
+    */
+   QCBORError uError = QCBOR_Private_ConvertBigNumToUnsigned(BigNum,
+                                                             INT64_MAX,
+                                                             &uResult);
+   if(uError != QCBOR_SUCCESS) {
+      return uError;
+   }
+
+   /* Now apply -n - 1. The cast is safe because
+    * ConvertBigNumToUnsigned() is limited to INT64_MAX which does fit
+    * is the largest positive integer that an int64_t can
+    * represent. */
+   *pnResult =  -(int64_t)uResult - 1;
+
+   return QCBOR_SUCCESS;
+}
+
+
+
+
+/**
+ * @brief Convert integers and floats to an int64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_ConvertInt64(const QCBORItem *pItem,
+                           const uint32_t   uConvertTypes,
+                           int64_t         *pnValue)
+{
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_FLOAT:
+      case QCBOR_TYPE_DOUBLE:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            /* https://pubs.opengroup.org/onlinepubs/009695399/functions/llround.html
+             http://www.cplusplus.com/reference/cmath/llround/
+             */
+            // Not interested in FE_INEXACT
+            feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
+            if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
+               *pnValue = llround(pItem->val.dfnum);
+            } else {
+               *pnValue = lroundf(pItem->val.fnum);
+            }
+            if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
+               // llround() shouldn't result in divide by zero, but catch
+               // it here in case it unexpectedly does.  Don't try to
+               // distinguish between the various exceptions because it seems
+               // they vary by CPU, compiler and OS.
+               return QCBOR_ERR_FLOAT_EXCEPTION;
+            }
+         } else {
+            return  QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_INT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            *pnValue = pItem->val.int64;
+         } else {
+            return  QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            if(pItem->val.uint64 < INT64_MAX) {
+               *pnValue = pItem->val.int64;
+            } else {
+               return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+            }
+         } else {
+            return  QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      default:
+         return  QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64Convert().
+ */
+void
+QCBORDecode_Private_GetInt64Convert(QCBORDecodeContext *pMe,
+                                    uint32_t            uConvertTypes,
+                                    int64_t            *pnValue,
+                                    QCBORItem          *pItem)
+{
+   QCBORDecode_VGetNext(pMe, pItem);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64ConvertInMapN().
+ */
+void
+QCBORDecode_Private_GetInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                          int64_t             nLabel,
+                                          uint32_t            uConvertTypes,
+                                          int64_t            *pnValue,
+                                          QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
+
+/**
+ * @brief Almost-public method to decode a number and convert to int64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel        Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetInt64ConvertInMapSZ().
+ */
+void
+QCBORDecode_Private_GetInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                           const char *         szLabel,
+                                           uint32_t             uConvertTypes,
+                                           int64_t             *pnValue,
+                                           QCBORItem           *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertInt64(pItem,
+                                                         uConvertTypes,
+                                                         pnValue);
+}
+
+
+/**
+ * @brief Convert many number types to an int64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pnValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_Int64ConvertAll(const QCBORItem *pItem,
+                              const uint32_t   uConvertTypes,
+                              int64_t         *pnValue)
+{
+   switch(pItem->uDataType) {
+
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.bigNum, pnValue);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.bigNum, pnValue);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                 &QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            return QCBOR_Private_ExponentiateNN(pItem->val.expAndMantissa.Mantissa.nInt,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            int64_t    nMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, &nMantissa);
+            if(uErr) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentiateNN(nMantissa,
+                                  pItem->val.expAndMantissa.nExponent,
+                                  pnValue,
+                                  QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAll(QCBORDecodeContext *pMe,
+                               const uint32_t      uConvertTypes,
+                               int64_t            *pnValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetInt64Convert(pMe, uConvertTypes, pnValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint32_t      uConvertTypes,
+                                     int64_t            *pnValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetInt64ConvertInMapN(pMe,
+                                             nLabel,
+                                             uConvertTypes,
+                                             pnValue,
+                                             &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint32_t      uConvertTypes,
+                                      int64_t            *pnValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetInt64ConvertInMapSZ(pMe,
+                                              szLabel,
+                                              uConvertTypes,
+                                              pnValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_Int64ConvertAll(&Item,
+                                                            uConvertTypes,
+                                                            pnValue);
+}
+
+
+/**
+ * @brief Convert many number types to an uint64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_ConvertUInt64(const QCBORItem *pItem,
+                            const uint32_t   uConvertTypes,
+                            uint64_t        *puValue)
+{
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_DOUBLE:
+      case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            // Can't use llround here because it will not convert values
+            // greater than INT64_MAX and less than UINT64_MAX that
+            // need to be converted so it is more complicated.
+            feclearexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO);
+            if(pItem->uDataType == QCBOR_TYPE_DOUBLE) {
+               if(isnan(pItem->val.dfnum)) {
+                  return QCBOR_ERR_FLOAT_EXCEPTION;
+               } else if(pItem->val.dfnum < 0) {
+                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+               } else {
+                  double dRounded = round(pItem->val.dfnum);
+                  // See discussion in DecodeDateEpoch() for
+                  // explanation of - 0x7ff
+                  if(dRounded > (double)(UINT64_MAX- 0x7ff)) {
+                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+                  }
+                  *puValue = (uint64_t)dRounded;
+               }
+            } else {
+               if(isnan(pItem->val.fnum)) {
+                  return QCBOR_ERR_FLOAT_EXCEPTION;
+               } else if(pItem->val.fnum < 0) {
+                  return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+               } else {
+                  float fRounded = roundf(pItem->val.fnum);
+                  // See discussion in DecodeDateEpoch() for
+                  // explanation of - 0x7ff
+                  if(fRounded > (float)(UINT64_MAX- 0x7ff)) {
+                     return QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW;
+                  }
+                  *puValue = (uint64_t)fRounded;
+               }
+            }
+            if(fetestexcept(FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW|FE_DIVBYZERO)) {
+               // round() and roundf() shouldn't result in exceptions here, but
+               // catch them to be robust and thorough. Don't try to
+               // distinguish between the various exceptions because it seems
+               // they vary by CPU, compiler and OS.
+               return QCBOR_ERR_FLOAT_EXCEPTION;
+            }
+
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_INT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            if(pItem->val.int64 >= 0) {
+               *puValue = (uint64_t)pItem->val.int64;
+            } else {
+               return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+            }
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_UINT64:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            *puValue =  pItem->val.uint64;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64Convert().
+ */
+void
+QCBORDecode_Private_GetUInt64Convert(QCBORDecodeContext *pMe,
+                                     const uint32_t      uConvertTypes,
+                                     uint64_t           *puValue,
+                                     QCBORItem          *pItem)
+{
+   QCBORDecode_VGetNext(pMe, pItem);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64ConvertInMapN().
+ */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapN(QCBORDecodeContext *pMe,
+                                           const int64_t       nLabel,
+                                           const uint32_t      uConvertTypes,
+                                           uint64_t            *puValue,
+                                           QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
+
+
+/**
+ * @brief Almost-public method to decode a number and convert to uint64_t (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue       Result of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetUInt64ConvertInMapSZ().
+ */
+void
+QCBORDecode_Private_GetUInt64ConvertInMapSZ(QCBORDecodeContext *pMe,
+                                            const char         *szLabel,
+                                            const uint32_t      uConvertTypes,
+                                            uint64_t           *puValue,
+                                            QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertUInt64(pItem,
+                                                          uConvertTypes,
+                                                          puValue);
+}
+
+
+/**
+ * @brief Convert many number types to an unt64_t.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] puValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_UInt64ConvertAll(const QCBORItem *pItem,
+                               const uint32_t   uConvertTypes,
+                               uint64_t        *puValue)
+{
+   switch(pItem->uDataType) { /* -Wmaybe-uninitialized falsly warns here */
+
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.bigNum, puValue);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
+                                   pItem->val.expAndMantissa.nExponent,
+                                   puValue,
+                                   QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+            return QCBOR_Private_ExponentitateNU(pItem->val.expAndMantissa.Mantissa.nInt,
+                                   pItem->val.expAndMantissa.nExponent,
+                                   puValue,
+                                   QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            uint64_t   uMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum, &uMantissa);
+            if(uErr != QCBOR_SUCCESS) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentitateUU(uMantissa,
+                                                 pItem->val.expAndMantissa.nExponent,
+                                                 puValue,
+                                                 QCBOR_Private_Exponentitate10);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            uint64_t   uMantissa;
+            QCBORError uErr;
+            uErr = QCBOR_Private_ConvertPositiveBigNumToUnsigned(pItem->val.expAndMantissa.Mantissa.bigNum,
+                                                                 &uMantissa);
+            if(uErr != QCBOR_SUCCESS) {
+               return uErr;
+            }
+            return QCBOR_Private_ExponentitateUU(uMantissa,
+                                                 pItem->val.expAndMantissa.nExponent,
+                                                 puValue,
+                                                 QCBOR_Private_Exponentitate2);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            return QCBOR_ERR_NUMBER_SIGN_CONVERSION;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAll(QCBORDecodeContext *pMe,
+                                const uint32_t      uConvertTypes,
+                                uint64_t           *puValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetUInt64Convert(pMe, uConvertTypes, puValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAllInMapN(QCBORDecodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const uint32_t      uConvertTypes,
+                                      uint64_t           *puValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetUInt64ConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              puValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetUInt64ConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                       const char         *szLabel,
+                                       const uint32_t      uConvertTypes,
+                                       uint64_t           *puValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetUInt64ConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               puValue,
+                                               &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_UInt64ConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             puValue);
+}
+
+
+
+
+#ifndef USEFULBUF_DISABLE_ALL_FLOAT
+/**
+ * @brief Basic conversions to a double.
+ *
+ * @param[in] pItem          The item to convert
+ * @param[in] uConvertTypes  Bit flags indicating source types for conversion
+ * @param[out] pdValue       The value converted to a double
+ *
+ * This does the conversions that don't need much object code,
+ * the conversions from int, uint and float to double.
+ *
+ * See QCBOR_Private_DoubleConvertAll() for the full set
+ * of conversions.
+ */
+static QCBORError
+QCBOR_Private_ConvertDouble(const QCBORItem *pItem,
+                            const uint32_t   uConvertTypes,
+                            double          *pdValue)
+{
+   switch(pItem->uDataType) {
+      case QCBOR_TYPE_FLOAT:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+               // Simple cast does the job.
+               *pdValue = (double)pItem->val.fnum;
+            } else {
+               return QCBOR_ERR_UNEXPECTED_TYPE;
+            }
+         }
+#else /* QCBOR_DISABLE_FLOAT_HW_USE */
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_DOUBLE:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+            if(uConvertTypes & QCBOR_CONVERT_TYPE_FLOAT) {
+               *pdValue = pItem->val.dfnum;
+            } else {
+               return QCBOR_ERR_UNEXPECTED_TYPE;
+            }
+         }
+         break;
+
+      case QCBOR_TYPE_INT64:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            // A simple cast seems to do the job with no worry of exceptions.
+            // There will be precision loss for some values.
+            *pdValue = (double)pItem->val.int64;
+
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+         break;
+
+      case QCBOR_TYPE_UINT64:
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_XINT64) {
+            // A simple cast seems to do the job with no worry of exceptions.
+            // There will be precision loss for some values.
+            *pdValue = (double)pItem->val.uint64;
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#else
+         return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return QCBOR_SUCCESS;
+}
+
+
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvert().
+ */
+void
+QCBORDecode_Private_GetDoubleConvert(QCBORDecodeContext *pMe,
+                                     const uint32_t      uConvertTypes,
+                                     double             *pdValue,
+                                     QCBORItem          *pItem)
+{
+   QCBORDecode_VGetNext(pMe, pItem);
+   if(pMe->uLastError) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
+}
+
+
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] nLabel         Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvertInMapN().
+ */
+void
+QCBORDecode_Private_GetDoubleConvertInMapN(QCBORDecodeContext *pMe,
+                                           const int64_t       nLabel,
+                                           const uint32_t      uConvertTypes,
+                                           double             *pdValue,
+                                           QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
+}
+
+
+/**
+ * @brief  Almost-public method to decode a number and convert to double (semi-private).
+ *
+ * @param[in] pMe            The decode context.
+ * @param[in] szLabel        Label to find in map.
+ * @param[in] uConvertTypes  Bit mask list of conversion options
+ * @param[out] pdValue       The output of the conversion.
+ * @param[in,out] pItem      Temporary space to store Item, returned item.
+ *
+ * See QCBORDecode_GetDoubleConvertInMapSZ().
+ */
+void
+QCBORDecode_Private_GetDoubleConvertInMapSZ(QCBORDecodeContext *pMe,
+                                            const char         *szLabel,
+                                            const uint32_t      uConvertTypes,
+                                            double             *pdValue,
+                                            QCBORItem          *pItem)
+{
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, pItem);
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_ConvertDouble(pItem,
+                                                          uConvertTypes,
+                                                          pdValue);
+}
+
+
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+/**
+ * @brief Convert a big number to double-precision float.
+ *
+ * @param[in] BigNum   The big number to convert
+ *
+ * @returns  The double value.
+ *
+ * This will always succeed. It will lose precision for larger
+ * numbers. If the big number is too large to fit (more than
+ * 1.7976931348623157E+308) infinity will be returned. NaN is never
+ * returned.
+ */
+static double
+QCBOR_Private_ConvertBigNumToDouble(const UsefulBufC BigNum)
+{
+   double dResult;
+
+   dResult = 0.0;
+   const uint8_t *pByte = BigNum.ptr;
+   size_t uLen = BigNum.len;
+   /* This will overflow and become the float value INFINITY if the number
+    * is too large to fit. */
+   while(uLen--) {
+      dResult = (dResult * 256.0) + (double)*pByte++;
+   }
+
+   return dResult;
+}
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+
+
+
+/**
+ * @brief Convert many number types to a double.
+ *
+ * @param[in] pItem   The item to convert.
+ * @param[in] uConvertTypes  Bit mask list of conversion options.
+ * @param[out] pdValue  The resulting converted value.
+ *
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Conversion, possible, but not requested
+ *                                    in uConvertTypes.
+ * @retval QCBOR_ERR_UNEXPECTED_TYPE  Of a type that can't be converted
+ * @retval QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW  Conversion result is too large
+ *                                               or too small.
+ */
+static QCBORError
+QCBOR_Private_DoubleConvertAll(const QCBORItem *pItem,
+                               const uint32_t   uConvertTypes,
+                               double          *pdValue)
+{
+#ifndef QCBOR_DISABLE_FLOAT_HW_USE
+   /*
+    * What Every Computer Scientist Should Know About Floating-Point Arithmetic
+    * https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
+    */
+   switch(pItem->uDataType) {
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            // Underflow gives 0, overflow gives infinity
+            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
+                        pow(10.0, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT ) {
+            // Underflow gives 0, overflow gives infinity
+            *pdValue = (double)pItem->val.expAndMantissa.Mantissa.nInt *
+                              exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+      case QCBOR_TYPE_POSBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pdValue = QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_NEGBIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_BIG_NUM) {
+            *pdValue = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.bigNum);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+         if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+            double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+            *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+        if(uConvertTypes & QCBOR_CONVERT_TYPE_DECIMAL_FRACTION) {
+         double dMantissa = -QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+         *pdValue = dMantissa * pow(10, (double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+        if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+         double dMantissa = QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+         *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+        if(uConvertTypes & QCBOR_CONVERT_TYPE_BIGFLOAT) {
+         double dMantissa = -1-QCBOR_Private_ConvertBigNumToDouble(pItem->val.expAndMantissa.Mantissa.bigNum);
+         *pdValue = dMantissa * exp2((double)pItem->val.expAndMantissa.nExponent);
+         } else {
+            return QCBOR_ERR_UNEXPECTED_TYPE;
+         }
+         break;
+#endif /* ndef QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+      default:
+         return QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   return QCBOR_SUCCESS;
+
+#else
+   (void)pItem;
+   (void)uConvertTypes;
+   (void)pdValue;
+   return QCBOR_ERR_HW_FLOAT_DISABLED;
+#endif /* QCBOR_DISABLE_FLOAT_HW_USE */
+
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAll(QCBORDecodeContext *pMe,
+                                const uint32_t      uConvertTypes,
+                                double             *pdValue)
+{
+
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetDoubleConvert(pMe, uConvertTypes, pdValue, &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+
+
+/*
+ *  Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAllInMapN(QCBORDecodeContext *pMe,
+                                      const int64_t       nLabel,
+                                      const uint32_t      uConvertTypes,
+                                      double             *pdValue)
+{
+   QCBORItem Item;
+
+   QCBORDecode_Private_GetDoubleConvertInMapN(pMe,
+                                              nLabel,
+                                              uConvertTypes,
+                                              pdValue,
+                                              &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDoubleConvertAllInMapSZ(QCBORDecodeContext *pMe,
+                                       const char         *szLabel,
+                                       const uint32_t      uConvertTypes,
+                                       double             *pdValue)
+{
+   QCBORItem Item;
+   QCBORDecode_Private_GetDoubleConvertInMapSZ(pMe,
+                                               szLabel,
+                                               uConvertTypes,
+                                               pdValue,
+                                               &Item);
+
+   if(pMe->uLastError == QCBOR_SUCCESS) {
+      // The above conversion succeeded
+      return;
+   }
+
+   if(pMe->uLastError != QCBOR_ERR_UNEXPECTED_TYPE) {
+      // The above conversion failed in a way that code below can't correct
+      return;
+   }
+
+   pMe->uLastError = (uint8_t)QCBOR_Private_DoubleConvertAll(&Item,
+                                                             uConvertTypes,
+                                                             pdValue);
+}
+#endif /* USEFULBUF_DISABLE_ALL_FLOAT */
+
+
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+/**
+ * @brief Convert an integer to a big number
+ *
+ * @param[in] uInt  The integer to convert.
+ * @param[in] Buffer  The buffer to output the big number to.
+ *
+ * @returns The big number or NULLUsefulBufC is the buffer is to small.
+ *
+ * This always succeeds unless the buffer is too small.
+ */
+static UsefulBufC
+QCBOR_Private_ConvertIntToBigNum(uint64_t uInt, const UsefulBuf Buffer)
+{
+   while((uInt & 0xff00000000000000UL) == 0) {
+      uInt = uInt << 8;
+   };
+
+   UsefulOutBuf UOB;
+
+   UsefulOutBuf_Init(&UOB, Buffer);
+
+   while(uInt) {
+      UsefulOutBuf_AppendByte(&UOB, (uint8_t)((uInt & 0xff00000000000000UL) >> 56));
+      uInt = uInt << 8;
+   }
+
+   return UsefulOutBuf_OutUBuf(&UOB);
+}
+
+
+/**
+ * @brief Check and/or complete exponent and mantissa item.
+ *
+ * @param[in] pMe        The decoder context.
+ * @param[in] TagSpec    Expected type(s).
+ * @param[in,out] pItem  See below.
+ *
+ * This is for decimal fractions and big floats, both of which are an
+ * exponent and mantissa.
+ *
+ * If the item item had a tag number indicating it was a
+ * decimal fraction or big float, then the input @c pItem will
+ * have been decoded as exponent and mantissa. If there was
+ * no tag number, the caller is asking this be decoded as a
+ * big float or decimal fraction and @c pItem just has the
+ * first item in an exponent and mantissa.
+ *
+ * On output, the item is always a fully decoded decimal fraction or
+ * big float.
+ *
+ * This errors out if the input type does not meet the TagSpec.
+ */
+static QCBORError
+QCBOR_Private_ExpMantissaTypeHandler(QCBORDecodeContext         *pMe,
+                                     const QCBOR_Private_TagSpec TagSpec,
+                                     QCBORItem                  *pItem)
+{
+   QCBORError uErr;
+
+   /* pItem could either be a decoded exponent and mantissa or
+    * the opening array of an undecoded exponent and mantissa. This
+    * check will succeed on either, but doesn't say which it was.
+    */
+   uErr = QCBOR_Private_CheckTagRequirement(TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   if(pItem->uDataType == QCBOR_TYPE_ARRAY) {
+      /* The item is an array, which means is is an undecoded exponent
+       * and mantissa. This call consumes the items in the array and
+       * results in a decoded exponent and mantissa in pItem. This is
+       * the case where there was no tag.
+       */
+      uErr = QCBORDecode_Private_ExpMantissa(pMe, pItem);
+      if(uErr != QCBOR_SUCCESS) {
+         goto Done;
+      }
+
+      /* The above decode didn't determine whether it is a decimal
+       * fraction or big num. Which of these two depends on what the
+       * caller wants it decoded as since there is no tag, so fish the
+       * type out of the TagSpec. */
+      pItem->uDataType = QCBOR_Private_ExpMantissaDataType(TagSpec.uTaggedTypes[0], pItem);
+
+      /* No need to check the type again. All that we need to know was
+       * that it decoded correctly as a exponent and mantissa. The
+       * QCBOR type is set out by what was requested.
+       */
+   }
+
+   /* If the item was not an array and the check passed, then
+    * it is a fully decoded big float or decimal fraction and
+    * matches what is requested.
+    */
+
+Done:
+   return uErr;
+}
+
+
+/* Some notes from the work to disable tags.
+ *
+ * The API for big floats and decimal fractions seems good.
+ * If there's any issue with it it's that the code size to
+ * implement is a bit large because of the conversion
+ * to/from int and bignum that is required. There is no API
+ * that doesn't do the conversion so dead stripping will never
+ * leave that code out.
+ *
+ * The implementation itself seems correct, but not as clean
+ * and neat as it could be. It could probably be smaller too.
+ *
+ * The implementation has three main parts / functions
+ *  - The decoding of the array of two
+ *  - All the tag and type checking for the various API functions
+ *  - Conversion to/from bignum and int
+ *
+ * The type checking seems like it wastes the most code for
+ * what it needs to do.
+ *
+ * The inlining for the conversion is probably making the
+ * overall code base larger.
+ *
+ * The tests cases could be organized a lot better and be
+ * more thorough.
+ *
+ * Seems also like there could be more common code in the
+ * first tier part of the public API. Some functions only
+ * vary by a TagSpec.
+ */
+
+/**
+ * @brief Common processor for exponent and mantissa.
+ *
+ * @param[in] pMe          The decode context.
+ * @param[in] TagSpec      The expected/allowed tags.
+ * @param[in] pItem        The data item to process.
+ * @param[out] pnMantissa  The returned mantissa as an int64_t.
+ * @param[out] pnExponent  The returned exponent as an int64_t.
+ *
+ * This handles exponent and mantissa for base 2 and 10. This
+ * is limited to a mantissa that is an int64_t. See also
+ * QCBORDecode_Private_ProcessExpMantissaBig().
+ */
+static void
+QCBOR_Private_ProcessExpMantissa(QCBORDecodeContext         *pMe,
+                                 const QCBOR_Private_TagSpec TagSpec,
+                                 QCBORItem                  *pItem,
+                                 int64_t                    *pnMantissa,
+                                 int64_t                    *pnExponent)
+{
+   QCBORError uErr;
+
+   if(pMe->uLastError) {
+      return;
+   }
+
+   uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   switch (pItem->uDataType) {
+
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+      case QCBOR_TYPE_BIGFLOAT:
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         *pnMantissa = pItem->val.expAndMantissa.Mantissa.nInt;
+         break;
+
+#ifndef QCBOR_DISABLE_TAGS
+      /* If tags are disabled, mantissas can never be big nums */
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         uErr = QCBOR_Private_ConvertPositiveBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         uErr = QCBOR_Private_ConvertNegativeBigNumToSigned(pItem->val.expAndMantissa.Mantissa.bigNum, pnMantissa);
+         break;
+#endif /* QCBOR_DISABLE_TAGS */
+
+      default:
+         uErr = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+   Done:
+      pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/**
+ * @brief Decode exponent and mantissa into a big number.
+ *
+ * @param[in] pMe                The decode context.
+ * @param[in] TagSpec            The expected/allowed tags.
+ * @param[in] pItem              Item to decode and convert.
+ * @param[in] BufferForMantissa  Buffer to output mantissa into.
+ * @param[out] pMantissa         The output mantissa.
+ * @param[out] pbIsNegative      The sign of the output.
+ * @param[out] pnExponent        The mantissa of the output.
+ *
+ * This is the common processing of a decimal fraction or a big float
+ * into a big number. This will decode and consume all the CBOR items
+ * that make up the decimal fraction or big float.
+ */
+static void
+QCBORDecode_Private_ProcessExpMantissaBig(QCBORDecodeContext          *pMe,
+                                          const QCBOR_Private_TagSpec  TagSpec,
+                                          QCBORItem                   *pItem,
+                                          const UsefulBuf              BufferForMantissa,
+                                          UsefulBufC                  *pMantissa,
+                                          bool                        *pbIsNegative,
+                                          int64_t                     *pnExponent)
+{
+   QCBORError uErr;
+
+   if(pMe->uLastError != QCBOR_SUCCESS) {
+      return;
+   }
+
+   uErr = QCBOR_Private_ExpMantissaTypeHandler(pMe, TagSpec, pItem);
+   if(uErr != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+   uint64_t uMantissa;
+
+   switch (pItem->uDataType) {
+
+      case QCBOR_TYPE_DECIMAL_FRACTION:
+      case QCBOR_TYPE_BIGFLOAT:
+         /* See comments in ExponentiateNN() on handling INT64_MIN */
+         if(pItem->val.expAndMantissa.Mantissa.nInt >= 0) {
+            uMantissa = (uint64_t)pItem->val.expAndMantissa.Mantissa.nInt;
+            *pbIsNegative = false;
+         } else if(pItem->val.expAndMantissa.Mantissa.nInt != INT64_MIN) {
+            uMantissa = (uint64_t)-pItem->val.expAndMantissa.Mantissa.nInt;
+            *pbIsNegative = true;
+         } else {
+            uMantissa = (uint64_t)INT64_MAX+1;
+            *pbIsNegative = true;
+         }
+         *pMantissa = QCBOR_Private_ConvertIntToBigNum(uMantissa,
+                                                       BufferForMantissa);
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         break;
+
+#ifndef QCBOR_DISABLE_TAGS
+      /* If tags are disabled, mantissas can never be big nums */
+      case QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM:
+      case QCBOR_TYPE_BIGFLOAT_POS_BIGNUM:
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
+         *pbIsNegative = false;
+         break;
+
+      case QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM:
+      case QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM:
+         *pnExponent = pItem->val.expAndMantissa.nExponent;
+         *pMantissa = pItem->val.expAndMantissa.Mantissa.bigNum;
+         *pbIsNegative = true;
+         break;
+#endif /* QCBOR_DISABLE_TAGS */
+
+      default:
+         uErr = QCBOR_ERR_UNEXPECTED_TYPE;
+   }
+
+Done:
+   pMe->uLastError = (uint8_t)uErr;
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFraction(QCBORDecodeContext *pMe,
+                               const uint8_t       uTagRequirement,
+                               int64_t             *pnMantissa,
+                               int64_t             *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFractionInMapN(QCBORDecodeContext *pMe,
+                                     const int64_t       nLabel,
+                                     const uint8_t       uTagRequirement,
+                                     int64_t             *pnMantissa,
+                                     int64_t             *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFractionInMapSZ(QCBORDecodeContext *pMe,
+                                      const char         *szLabel,
+                                      const uint8_t       uTagRequirement,
+                                      int64_t             *pnMantissa,
+                                      int64_t             *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFractionBig(QCBORDecodeContext *pMe,
+                                  const uint8_t       uTagRequirement,
+                                  const UsefulBuf     MantissaBuffer,
+                                  UsefulBufC         *pMantissa,
+                                  bool               *pbMantissaIsNegative,
+                                  int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             MantissaBuffer,
+                                             pMantissa,
+                                             pbMantissaIsNegative,
+                                             pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFractionBigInMapN(QCBORDecodeContext *pMe,
+                                        const int64_t       nLabel,
+                                        const uint8_t       uTagRequirement,
+                                        const UsefulBuf     BufferForMantissa,
+                                        UsefulBufC         *pMantissa,
+                                        bool               *pbIsNegative,
+                                        int64_t            *pnExponent)
+{
+
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             BufferForMantissa,
+                                             pMantissa,
+                                             pbIsNegative,
+                                             pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetDecimalFractionBigInMapSZ(QCBORDecodeContext *pMe,
+                                         const char         *szLabel,
+                                         const uint8_t       uTagRequirement,
+                                         const UsefulBuf     BufferForMantissa,
+                                         UsefulBufC         *pMantissa,
+                                         bool               *pbIsNegative,
+                                         int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_DECIMAL_FRACTION, QCBOR_TYPE_DECIMAL_FRACTION_POS_BIGNUM,
+         QCBOR_TYPE_DECIMAL_FRACTION_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             BufferForMantissa,
+                                             pMantissa,
+                                             pbIsNegative,
+                                             pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloat(QCBORDecodeContext *pMe,
+                        const uint8_t       uTagRequirement,
+                        int64_t             *pnMantissa,
+                        int64_t             *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloatInMapN(QCBORDecodeContext *pMe,
+                              const int64_t       nLabel,
+                              const uint8_t       uTagRequirement,
+                              int64_t            *pnMantissa,
+                              int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloatInMapSZ(QCBORDecodeContext *pMe,
+                               const char         *szLabel,
+                               const uint8_t       uTagRequirement,
+                               int64_t            *pnMantissa,
+                               int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBOR_Private_ProcessExpMantissa(pMe,
+                                    TagSpec,
+                                   &Item,
+                                    pnMantissa,
+                                    pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloatBig(QCBORDecodeContext *pMe,
+                           const uint8_t       uTagRequirement,
+                           const UsefulBuf     MantissaBuffer,
+                           UsefulBufC         *pMantissa,
+                           bool               *pbMantissaIsNegative,
+                           int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_VGetNext(pMe, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             MantissaBuffer,
+                                             pMantissa,
+                                             pbMantissaIsNegative,
+                                             pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloatBigInMapN(QCBORDecodeContext *pMe,
+                                 const int64_t       nLabel,
+                                 const uint8_t       uTagRequirement,
+                                 const UsefulBuf     BufferForMantissa,
+                                 UsefulBufC         *pMantissa,
+                                 bool               *pbIsNegative,
+                                 int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapN(pMe, nLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             BufferForMantissa,
+                                             pMantissa,
+                                             pbIsNegative,
+                                             pnExponent);
+}
+
+
+/*
+ * Public function, see header qcbor/qcbor_decode.h file
+ */
+void
+QCBORDecode_GetBigFloatBigInMapSZ(QCBORDecodeContext *pMe,
+                                  const char         *szLabel,
+                                  const uint8_t       uTagRequirement,
+                                  const UsefulBuf     BufferForMantissa,
+                                  UsefulBufC         *pMantissa,
+                                  bool               *pbIsNegative,
+                                  int64_t            *pnExponent)
+{
+   QCBORItem Item;
+   QCBORDecode_GetItemInMapSZ(pMe, szLabel, QCBOR_TYPE_ANY, &Item);
+
+   const QCBOR_Private_TagSpec TagSpec =
+   {
+      uTagRequirement,
+      {QCBOR_TYPE_BIGFLOAT, QCBOR_TYPE_BIGFLOAT_POS_BIGNUM,
+         QCBOR_TYPE_BIGFLOAT_NEG_BIGNUM, QCBOR_TYPE_NONE},
+      {QCBOR_TYPE_ARRAY, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE, QCBOR_TYPE_NONE}
+   };
+
+   QCBORDecode_Private_ProcessExpMantissaBig(pMe,
+                                             TagSpec,
+                                            &Item,
+                                             BufferForMantissa,
+                                             pMantissa,
+                                             pbIsNegative,
+                                             pnExponent);
+}
+
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
diff --git a/core/lib/qcbor/src/qcbor_encode.c b/core/lib/qcbor/src/qcbor_encode.c
new file mode 100644
index 0000000000000000000000000000000000000000..e024dd2d390a94f6f6f61831db075125e479e7ad
--- /dev/null
+++ b/core/lib/qcbor/src/qcbor_encode.c
@@ -0,0 +1,1088 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*==============================================================================
+ Copyright (c) 2016-2018, The Linux Foundation.
+ Copyright (c) 2018-2024, Laurence Lundblade.
+ Copyright (c) 2021, Arm Limited.
+ All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+    * Neither the name of The Linux Foundation nor the names of its
+      contributors, nor the name "Laurence Lundblade" may be used to
+      endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ =============================================================================*/
+
+
+#include "qcbor/qcbor_encode.h"
+#include "ieee754.h"
+
+
+/**
+ * @file qcbor_encode.c
+ *
+ * The entire implementation of the QCBOR encoder.
+ */
+
+
+/*
+ * == Nesting Tracking ==
+ *
+ * The following functions and data type QCBORTrackNesting implement
+ * the nesting management for encoding.
+ *
+ * CBOR's two nesting types, arrays and maps, are tracked here. There
+ * is a limit of QCBOR_MAX_ARRAY_NESTING to the number of arrays and
+ * maps that can be nested in one encoding so the encoding context
+ * stays small enough to fit on the stack.
+ *
+ * When an array/map is opened, pCurrentNesting points to the element
+ * in pArrays that records the type, start position and accumulates a
+ * count of the number of items added. When closed the start position
+ * is used to go back and fill in the type and number of items in the
+ * array/map.
+ *
+ * Encoded output can be a CBOR Sequence (RFC 8742) in which case
+ * there is no top-level array or map. It starts out with a string,
+ * integer or other non-aggregate type. It may have an array or map
+ * other than at the start, in which case that nesting is tracked
+ * here.
+ *
+ * QCBOR has a special feature to allow constructing byte string
+ * wrapped CBOR directly into the output buffer, so no extra buffer is
+ * needed for byte string wrapping.  This is implemented as nesting
+ * with the type CBOR_MAJOR_TYPE_BYTE_STRING and is tracked here. Byte
+ * string wrapped CBOR is used by COSE for data that is to be hashed.
+ */
+static void
+Nesting_Init(QCBORTrackNesting *pNesting)
+{
+   /* Assumes pNesting has been zeroed. */
+   pNesting->pCurrentNesting = &pNesting->pArrays[0];
+   /* Implied CBOR array at the top nesting level. This is never
+    * returned, but makes the item count work correctly.
+    */
+   pNesting->pCurrentNesting->uMajorType = CBOR_MAJOR_TYPE_ARRAY;
+}
+
+static uint8_t
+Nesting_Increase(QCBORTrackNesting *pNesting,
+                 const uint8_t      uMajorType,
+                 const uint32_t     uPos)
+{
+   if(pNesting->pCurrentNesting == &pNesting->pArrays[QCBOR_MAX_ARRAY_NESTING]) {
+      return QCBOR_ERR_ARRAY_NESTING_TOO_DEEP;
+   } else {
+      pNesting->pCurrentNesting++;
+      pNesting->pCurrentNesting->uCount     = 0;
+      pNesting->pCurrentNesting->uStart     = uPos;
+      pNesting->pCurrentNesting->uMajorType = uMajorType;
+      return QCBOR_SUCCESS;
+   }
+}
+
+static void
+Nesting_Decrease(QCBORTrackNesting *pNesting)
+{
+   if(pNesting->pCurrentNesting > &pNesting->pArrays[0]) {
+      pNesting->pCurrentNesting--;
+   }
+}
+
+static uint8_t
+Nesting_Increment(QCBORTrackNesting *pNesting)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(1 >= QCBOR_MAX_ITEMS_IN_ARRAY - pNesting->pCurrentNesting->uCount) {
+      return QCBOR_ERR_ARRAY_TOO_LONG;
+   }
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   pNesting->pCurrentNesting->uCount++;
+
+   return QCBOR_SUCCESS;
+}
+
+static void
+Nesting_Decrement(QCBORTrackNesting *pNesting)
+{
+   /* No error check for going below 0 here needed because this
+    * is only used by QCBOREncode_CancelBstrWrap() and it checks
+    * the nesting level before calling this. */
+   pNesting->pCurrentNesting->uCount--;
+}
+
+static uint16_t
+Nesting_GetCount(QCBORTrackNesting *pNesting)
+{
+   /* The nesting count recorded is always the actual number of
+    * individual data items in the array or map. For arrays CBOR uses
+    * the actual item count. For maps, CBOR uses the number of pairs.
+    * This function returns the number needed for the CBOR encoding,
+    * so it divides the number of items by two for maps to get the
+    * number of pairs.
+    */
+   if(pNesting->pCurrentNesting->uMajorType == CBOR_MAJOR_TYPE_MAP) {
+      /* Cast back to uint16_t after integer promotion from bit shift */
+      return (uint16_t)(pNesting->pCurrentNesting->uCount >> 1);
+   } else {
+      return pNesting->pCurrentNesting->uCount;
+   }
+}
+
+static uint32_t
+Nesting_GetStartPos(QCBORTrackNesting *pNesting)
+{
+   return pNesting->pCurrentNesting->uStart;
+}
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+static uint8_t
+Nesting_GetMajorType(QCBORTrackNesting *pNesting)
+{
+   return pNesting->pCurrentNesting->uMajorType;
+}
+
+static bool
+Nesting_IsInNest(QCBORTrackNesting *pNesting)
+{
+   return pNesting->pCurrentNesting == &pNesting->pArrays[0] ? false : true;
+}
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+
+
+
+/*
+ * == Major CBOR Types ==
+ *
+ * Encoding of the major CBOR types is by these functions:
+ *
+ * CBOR Major Type  Public Function
+ * 0                QCBOREncode_AddUInt64()
+ * 0, 1             QCBOREncode_AddUInt64(), QCBOREncode_AddInt64()
+ * 2, 3             QCBOREncode_AddBuffer()
+ * 4, 5             QCBOREncode_OpenMapOrArray(), QCBOREncode_CloseMapOrArray(),
+ *                  QCBOREncode_OpenMapOrArrayIndefiniteLength(),
+ *                  QCBOREncode_CloseMapOrArrayIndefiniteLength()
+ * 6                QCBOREncode_AddTag()
+ * 7                QCBOREncode_AddDouble(), QCBOREncode_AddFloat(),
+ *                  QCBOREncode_AddDoubleNoPreferred(),
+ *                  QCBOREncode_AddFloatNoPreferred(), QCBOREncode_AddType7()
+ *
+ * Additionally, encoding of decimal fractions and bigfloats is by
+ * QCBOREncode_AddExponentAndMantissa() and byte strings that wrap
+ * encoded CBOR are handled by QCBOREncode_OpenMapOrArray() and
+ * QCBOREncode_CloseBstrWrap2().
+ *
+ *
+ * == Error Tracking Plan ==
+ *
+ * Errors are tracked internally and not returned until
+ * QCBOREncode_Finish() or QCBOREncode_GetErrorState() is called. The
+ * CBOR errors are in me->uError.  UsefulOutBuf also tracks whether
+ * the buffer is full or not in its context.  Once either of these
+ * errors is set they are never cleared. Only QCBOREncode_Init()
+ * resets them. Or said another way, they must never be cleared or
+ * we'll tell the caller all is good when it is not.
+ *
+ * Only one error code is reported by QCBOREncode_Finish() even if
+ * there are multiple errors. The last one set wins. The caller might
+ * have to fix one error to reveal the next one they have to fix.
+ * This is OK.
+ *
+ * The buffer full error tracked by UsefulBuf is only pulled out of
+ * UsefulBuf in QCBOREncode_Finish() so it is the one that usually
+ * wins.  UsefulBuf will never go off the end of the buffer even if it
+ * is called again and again when full.
+ *
+ * QCBOR_DISABLE_ENCODE_USAGE_GUARDS disables about half of the error
+ * checks here to reduce code size by about 150 bytes leaving only the
+ * checks for size to avoid buffer overflow. If the calling code is
+ * completely correct, checks are completely unnecessary.  For
+ * example, there is no need to check that all the opens are matched
+ * by a close.
+ *
+ * QCBOR_DISABLE_ENCODE_USAGE_GUARDS also disables the check for more
+ * than QCBOR_MAX_ITEMS_IN_ARRAY in an array. Since
+ * QCBOR_MAX_ITEMS_IN_ARRAY is very large (65,535) it is very unlikely
+ * to be reached. If it is reached, the count will wrap around to zero
+ * and CBOR that is not well formed will be produced, but there will
+ * be no buffers overrun and new security issues in the code.
+ *
+ * The 8 errors returned here fall into three categories:
+ *
+ * Sizes
+ *   QCBOR_ERR_BUFFER_TOO_LARGE        -- Encoded output exceeded UINT32_MAX
+ *   QCBOR_ERR_BUFFER_TOO_SMALL        -- Output buffer too small
+ *   QCBOR_ERR_ARRAY_NESTING_TOO_DEEP  -- Nesting > QCBOR_MAX_ARRAY_NESTING1
+ *   QCBOR_ERR_ARRAY_TOO_LONG          -- Too many items added to an array/map [1]
+ *
+ * Nesting constructed incorrectly
+ *   QCBOR_ERR_TOO_MANY_CLOSES         -- More close calls than opens [1]
+ *   QCBOR_ERR_CLOSE_MISMATCH          -- Type of close does not match open [1]
+ *   QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN -- Finish called without enough closes [1]
+ *
+ * Would generate not-well-formed CBOR
+ *   QCBOR_ERR_ENCODE_UNSUPPORTED      -- Simple type between 24 and 31 [1]
+ *
+ * [1] indicated disabled by QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+ */
+
+
+/*
+ * Public function for initialization. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_Init(QCBOREncodeContext *pMe, UsefulBuf Storage)
+{
+   memset(pMe, 0, sizeof(QCBOREncodeContext));
+   UsefulOutBuf_Init(&(pMe->OutBuf), Storage);
+   Nesting_Init(&(pMe->nesting));
+}
+
+
+/*
+ * Public function to encode a CBOR head. See qcbor/qcbor_encode.h
+ */
+UsefulBufC
+QCBOREncode_EncodeHead(UsefulBuf Buffer,
+                       uint8_t   uMajorType,
+                       uint8_t   uMinLen,
+                       uint64_t  uArgument)
+{
+   /*
+    * == Description of the CBOR Head ==
+    *
+    *    The head of a CBOR data item
+    *  +---+-----+ +--------+ +--------+ +--------+      +--------+
+    *  |M T|  A R G U M E N T . . .                               |
+    *  +---+-----+ +--------+ +--------+ +--------+ ...  +--------+
+    *
+    * Every CBOR data item has a "head". It is made up of the "major
+    * type" and the "argument".
+    *
+    * The major type indicates whether the data item is an integer,
+    * string, array or such. It is encoded in 3 bits giving it a range
+    * from 0 to 7.  0 indicates the major type is a positive integer,
+    * 1 a negative integer, 2 a byte string and so on.
+    *
+    * These 3 bits are the first part of the "initial byte" in a data
+    * item.  Every data item has an initial byte, and some only have
+    * the initial byte.
+    *
+    * The argument is essentially a number between 0 and UINT64_MAX
+    * (18446744073709551615). This number is interpreted to mean
+    * different things for the different major types. For major type
+    * 0, a positive integer, it is value of the data item. For major
+    * type 2, a byte string, it is the length in bytes of the byte
+    * string. For major type 4, an array, it is the number of data
+    * items in the array.
+    *
+    * Special encoding is used so that the argument values less than
+    * 24 can be encoded very compactly in the same byte as the major
+    * type is encoded. When the lower 5 bits of the initial byte have
+    * a value less than 24, then that is the value of the argument.
+    *
+    * If the lower 5 bits of the initial byte are less than 24, then
+    * they are the value of the argument. This allows integer values 0
+    * - 23 to be CBOR encoded in just one byte.
+    *
+    * When the value of lower 5 bits are 24, 25, 26, or 27 the
+    * argument is encoded in 1, 2, 4 or 8 bytes following the initial
+    * byte in network byte order (bit endian). The cases when it is
+    * 28, 29 and 30 are reserved for future use. The value 31 is a
+    * special indicator for indefinite length strings, arrays and
+    * maps.
+    *
+    * The lower 5 bits are called the "additional information."
+    *
+    * Thus the CBOR head may be 1, 2, 3, 5 or 9 bytes long.
+    *
+    * It is legal in CBOR to encode the argument using any of these
+    * lengths even if it could be encoded in a shorter length. For
+    * example it is legal to encode a data item representing the
+    * positive integer 0 in 9 bytes even though it could be encoded in
+    * only 0. This is legal to allow for for very simple code or even
+    * hardware-only implementations that just output a register
+    * directly.
+    *
+    * CBOR defines preferred encoding as the encoding of the argument
+    * in the smallest number of bytes needed to encode it.
+    *
+    * This function takes the major type and argument as inputs and
+    * outputs the encoded CBOR head for them. It does conversion to
+    * network byte order.  It implements CBOR preferred encoding,
+    * outputting the shortest representation of the argument.
+    *
+    * == Endian Conversion ==
+    *
+    * This code does endian conversion without hton() or knowing the
+    * endianness of the machine by using masks and shifts. This avoids
+    * the dependency on hton() and the mess of figuring out how to
+    * find the machine's endianness.
+    *
+    * This is a good efficient implementation on little-endian
+    * machines.  A faster and smaller implementation is possible on
+    * big-endian machines because CBOR/network byte order is
+    * big-endian. However big-endian machines are uncommon.
+    *
+    * On x86, this is about 150 bytes instead of 500 bytes for the
+    * original, more formal unoptimized code.
+    *
+    * This also does the CBOR preferred shortest encoding for integers
+    * and is called to do endian conversion for floats.
+    *
+    * It works backwards from the least significant byte to the most
+    * significant byte.
+    *
+    * == Floating Point ==
+    *
+    * When the major type is 7 and the 5 lower bits have the values
+    * 25, 26 or 27, the argument is a floating-point number that is
+    * half, single or double-precision. Note that it is not the
+    * conversion from a floating-point value to an integer value like
+    * converting 0x00 to 0.00, it is the interpretation of the bits in
+    * the argument as an IEEE 754 float-point number.
+    *
+    * Floating-point numbers must be converted to network byte
+    * order. That is accomplished here by exactly the same code that
+    * converts integer arguments to network byte order.
+    *
+    * There is preferred encoding for floating-point numbers in CBOR,
+    * but it is very different than for integers and it is not
+    * implemented here.  Half-precision is preferred to
+    * single-precision which is preferred to double-precision only if
+    * the conversion can be performed without loss of precision. Zero
+    * and infinity can always be converted to half-precision, without
+    * loss but 3.141592653589 cannot.
+    *
+    * The way this function knows to not do preferred encoding on the
+    * argument passed here when it is a floating point number is the
+    * uMinLen parameter. It should be 2, 4 or 8 for half, single and
+    * double precision floating point values. This prevents and the
+    * incorrect removal of leading zeros when encoding arguments that
+    * are floating-point numbers.
+    *
+    * == Use of Type int and Static Analyzers ==
+    *
+    * The type int is used here for several variables because of the
+    * way integer promotion works in C for variables that are uint8_t
+    * or uint16_t. The basic rule is that they will always be promoted
+    * to int if they will fit. These integer variables here need only
+    * hold values less than 255 so they will always fit into an int.
+    *
+    * Most of values stored are never negative, so one might think
+    * that unsigned int would be more correct than int. However the C
+    * integer promotion rules only promote to unsigned int if the
+    * result won't fit into an int even if the promotion is for an
+    * unsigned variable like uint8_t.
+    *
+    * By declaring these int, there are few implicit conversions and
+    * fewer casts needed. Code size is reduced a little. It makes
+    * static analyzers happier.
+    *
+    * Note also that declaring these uint8_t won't stop integer wrap
+    * around if the code is wrong. It won't make the code more
+    * correct.
+    *
+    * https://stackoverflow.com/questions/46073295/implicit-type-promotion-rules
+    * https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be
+    *
+    * Code Reviewers: THIS FUNCTION DOES POINTER MATH
+    */
+
+   /* The buffer must have room for the largest CBOR HEAD + one
+    * extra. The one extra is needed for this code to work as it does
+    * a pre-decrement.
+    */
+    if(Buffer.len < QCBOR_HEAD_BUFFER_SIZE) {
+        return NULLUsefulBufC;
+    }
+
+   /* Pointer to last valid byte in the buffer */
+   uint8_t * const pBufferEnd = &((uint8_t *)Buffer.ptr)[QCBOR_HEAD_BUFFER_SIZE-1];
+
+   /* Point to the last byte and work backwards */
+   uint8_t *pByte = pBufferEnd;
+   /* The 5 bits in the initial byte that are not the major type */
+   int nAdditionalInfo;
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+   if(uMajorType > QCBOR_INDEFINITE_LEN_TYPE_MODIFIER) {
+      /* Special case for start & end of indefinite length */
+      uMajorType  = uMajorType - QCBOR_INDEFINITE_LEN_TYPE_MODIFIER;
+      /* This takes advantage of design of CBOR where additional info
+       * is 31 for both opening and closing indefinite length
+       * maps and arrays.
+       */
+       #if CBOR_SIMPLE_BREAK != LEN_IS_INDEFINITE
+       #error additional info for opening array not the same as for closing
+       #endif
+      nAdditionalInfo = CBOR_SIMPLE_BREAK;
+
+   } else
+#endif /* !QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS */
+      if (uArgument < CBOR_TWENTY_FOUR && uMinLen == 0) {
+      /* Simple case where argument is < 24 */
+      nAdditionalInfo = (int)uArgument;
+
+   } else  {
+      /* This encodes the argument in 1,2,4 or 8 bytes. The outer loop
+       * runs once for 1 byte and 4 times for 8 bytes.  The inner loop
+       * runs 1, 2 or 4 times depending on outer loop counter. This
+       * works backwards shifting 8 bits off the argument being
+       * encoded at a time until all bits from uArgument have been
+       * encoded and the minimum encoding size is reached.  Minimum
+       * encoding size is for floating-point numbers that have some
+       * zero-value bytes that must be output.
+       */
+      static const uint8_t aIterate[] = {1,1,2,4};
+
+      /* uMinLen passed in is unsigned, but goes negative in the loop
+       * so it must be converted to a signed value.
+       */
+      int nMinLen = (int)uMinLen;
+      int i;
+      for(i = 0; uArgument || nMinLen > 0; i++) {
+         const int nIterations = (int)aIterate[i];
+         for(int j = 0; j < nIterations; j++) {
+            *--pByte = (uint8_t)(uArgument & 0xff);
+            uArgument = uArgument >> 8;
+         }
+         nMinLen -= nIterations;
+      }
+
+      nAdditionalInfo = LEN_IS_ONE_BYTE-1 + i;
+   }
+
+   /* This expression integer-promotes to type int. The code above in
+    * function guarantees that nAdditionalInfo will never be larger
+    * than 0x1f. The caller may pass in a too-large uMajor type. The
+    * conversion to uint8_t will cause an integer wrap around and
+    * incorrect CBOR will be generated, but no security issue will
+    * occur.
+    */
+   const int nInitialByte = (uMajorType << 5) + nAdditionalInfo;
+   *--pByte = (uint8_t)nInitialByte;
+
+#ifdef EXTRA_ENCODE_HEAD_CHECK
+   /* This is a sanity check that can be turned on to verify the
+    * pointer math in this function is not going wrong. Turn it on and
+    * run the whole test suite to perform the check.
+    */
+   if(pBufferEnd - pByte > 9 || pBufferEnd - pByte < 1 || pByte < (uint8_t *)buffer.ptr) {
+      return NULLUsefulBufC;
+   }
+#endif /* EXTRA_ENCODE_HEAD_CHECK */
+
+   /* Length will not go negative because the loops run for at most 8 decrements
+    * of pByte, only one other decrement is made, and the array is sized
+    * for this.
+    */
+   return (UsefulBufC){pByte, (size_t)(pBufferEnd - pByte)};
+}
+
+
+/**
+ * @brief Increment item counter for maps and arrays.
+ *
+ * @param pMe          QCBOR encoding context.
+ *
+ * This is mostly a separate function to make code more readable and
+ * to have fewer occurrences of #ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+ */
+static void
+QCBOREncode_Private_IncrementMapOrArrayCount(QCBOREncodeContext *pMe)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uError == QCBOR_SUCCESS) {
+      pMe->uError = Nesting_Increment(&(pMe->nesting));
+   }
+#else
+   (void)Nesting_Increment(&(pMe->nesting));
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+}
+
+
+/**
+ * @brief Append the CBOR head, the major type and argument
+ *
+ * @param pMe         Encoder context.
+ * @param uMajorType  Major type to insert.
+ * @param uArgument   The argument (an integer value or a length).
+ * @param uMinLen     The minimum number of bytes for encoding the CBOR argument.
+ *
+ * This formats the CBOR "head" and appends it to the output.
+ *
+ * This also increments the array/map item counter in most cases.
+ */
+void
+QCBOREncode_Private_AppendCBORHead(QCBOREncodeContext *pMe,
+                                   const uint8_t       uMajorType,
+                                   const uint64_t      uArgument,
+                                   const uint8_t       uMinLen)
+{
+   /* A stack buffer large enough for a CBOR head */
+   UsefulBuf_MAKE_STACK_UB  (pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
+
+   UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
+                                                    uMajorType,
+                                                    uMinLen,
+                                                    uArgument);
+
+   /* No check for EncodedHead == NULLUsefulBufC is performed here to
+    * save object code. It is very clear that pBufferForEncodedHead is
+    * the correct size. If EncodedHead == NULLUsefulBufC then
+    * UsefulOutBuf_AppendUsefulBuf() will do nothing so there is no
+    * security hole introduced.
+    */
+
+   UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), EncodedHead);
+
+   if(!(uMajorType & QCBOR_INDEFINITE_LEN_TYPE_MODIFIER || uMajorType == CBOR_MAJOR_TYPE_TAG)) {
+      /* Don't increment the map count for tag or break because that is
+       * not needed. Don't do it for indefinite-length arrays and maps
+       * because it is done elsewhere. This is never called for definite-length
+       * arrays and maps.
+       */
+      QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
+   }
+}
+
+
+/*
+ * Public functions for adding signed integers. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_AddInt64(QCBOREncodeContext *pMe, const int64_t nNum)
+{
+   uint8_t  uMajorType;
+   uint64_t uValue;
+
+   if(nNum < 0) {
+      /* In CBOR -1 encodes as 0x00 with major type negative int.
+       * First add one as a signed integer because that will not
+       * overflow. Then change the sign as needed for encoding.  (The
+       * opposite order, changing the sign and subtracting, can cause
+       * an overflow when encoding INT64_MIN. */
+      int64_t nTmp = nNum + 1;
+      uValue = (uint64_t)-nTmp;
+      uMajorType = CBOR_MAJOR_TYPE_NEGATIVE_INT;
+   } else {
+      uValue = (uint64_t)nNum;
+      uMajorType = CBOR_MAJOR_TYPE_POSITIVE_INT;
+   }
+   QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, uValue, 0);
+}
+
+
+/**
+ * @brief Semi-private method to add a buffer full of bytes to encoded output.
+ *
+ * @param[in] pMe       The encoding context to add the string to.
+ * @param[in] uMajorType The CBOR major type of the bytes.
+ * @param[in] Bytes      The bytes to add.
+ *
+ * Called by inline functions to add text and byte strings.
+ *
+ * (This used to support QCBOREncode_AddEncoded() and
+ * QCBOREncode_AddBytesLenOnly(), but that was pulled out to make this
+ * smaller. This is one of the most used methods and they are some of
+ * the least used).
+ */
+void
+QCBOREncode_Private_AddBuffer(QCBOREncodeContext *pMe,
+                              const uint8_t       uMajorType,
+                              const UsefulBufC    Bytes)
+{
+   QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, Bytes.len, 0);
+   UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Bytes);
+}
+
+
+/*
+ * Public functions for adding raw encoded CBOR. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_AddEncoded(QCBOREncodeContext *pMe, const UsefulBufC Encoded)
+{
+   UsefulOutBuf_AppendUsefulBuf(&(pMe->OutBuf), Encoded);
+   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
+}
+
+
+#ifndef QCBOR_DISABLE_PREFERRED_FLOAT
+/**
+ * @brief Semi-private method to add a double using preferred encoding.
+ *
+ * @param[in] pMe   The encode context.
+ * @param[in] dNum  The double to add.
+ *
+ * This converts the double to a float or half-precision if it can be done
+ * without a loss of precision. See QCBOREncode_AddDouble().
+ */
+void
+QCBOREncode_Private_AddPreferredDouble(QCBOREncodeContext *pMe, const double dNum)
+{
+   const IEEE754_union uNum = IEEE754_DoubleToSmaller(dNum, true);
+   QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
+}
+
+
+/**
+ * @brief Semi-private method to add a float using preferred encoding.
+ *
+ * @param[in] pMe   The encode context.
+ * @param[in] fNum  The float to add.
+ *
+ * This converts the float to a half-precision if it can be done
+ * without a loss of precision. See QCBOREncode_AddFloat().
+ */
+void
+QCBOREncode_Private_AddPreferredFloat(QCBOREncodeContext *pMe, const float fNum)
+{
+   const IEEE754_union uNum = IEEE754_SingleToHalf(fNum);
+   QCBOREncode_Private_AddType7(pMe, (uint8_t)uNum.uSize, uNum.uValue);
+}
+#endif /* !QCBOR_DISABLE_PREFERRED_FLOAT */
+
+
+#ifndef QCBOR_DISABLE_EXP_AND_MANTISSA
+/**
+ * @brief  Semi-private method to add bigfloats and decimal fractions.
+ *
+ * @param[in] pMe               The encoding context to add the value to.
+ * @param[in] uTag               The type 6 tag indicating what this is to be.
+ * @param[in] BigNumMantissa     Is @ref NULLUsefulBufC if mantissa is an
+ *                               @c int64_t or the actual big number mantissa
+ *                               if not.
+ * @param[in] bBigNumIsNegative  This is @c true if the big number is negative.
+ * @param[in] nMantissa          The @c int64_t mantissa if it is not a big number.
+ * @param[in] nExponent          The exponent.
+ *
+ * This outputs either the @ref CBOR_TAG_DECIMAL_FRACTION or
+ * @ref CBOR_TAG_BIGFLOAT tag. if @c uTag is @ref CBOR_TAG_INVALID64,
+ * then this outputs the "borrowed" content format.
+ *
+ * The tag content output by this is an array with two members, the
+ * exponent and then the mantissa. The mantissa can be either a big
+ * number or an @c int64_t.
+ *
+ * This implementation cannot output an exponent further from 0 than
+ * @c INT64_MAX.
+ *
+ * To output a mantissa that is between INT64_MAX and UINT64_MAX from 0,
+ * it must be as a big number.
+ *
+ * Typically, QCBOREncode_AddDecimalFraction(), QCBOREncode_AddBigFloat(),
+ * QCBOREncode_AddDecimalFractionBigNum() or QCBOREncode_AddBigFloatBigNum()
+ * is called instead of this.
+ */
+void
+QCBOREncode_Private_AddExpMantissa(QCBOREncodeContext *pMe,
+                                   const uint64_t      uTag,
+                                   const UsefulBufC    BigNumMantissa,
+                                   const bool          bBigNumIsNegative,
+                                   const int64_t       nMantissa,
+                                   const int64_t       nExponent)
+{
+   /* This is for encoding either a big float or a decimal fraction,
+    * both of which are an array of two items, an exponent and a
+    * mantissa.  The difference between the two is that the exponent
+    * is base-2 for big floats and base-10 for decimal fractions, but
+    * that has no effect on the code here.
+    */
+   if(uTag != CBOR_TAG_INVALID64) {
+      QCBOREncode_AddTag(pMe, uTag);
+   }
+   QCBOREncode_OpenArray(pMe);
+   QCBOREncode_AddInt64(pMe, nExponent);
+   if(!UsefulBuf_IsNULLC(BigNumMantissa)) {
+      if(bBigNumIsNegative) {
+         QCBOREncode_AddNegativeBignum(pMe, BigNumMantissa);
+      } else {
+         QCBOREncode_AddPositiveBignum(pMe, BigNumMantissa);
+      }
+   } else {
+      QCBOREncode_AddInt64(pMe, nMantissa);
+   }
+   QCBOREncode_CloseArray(pMe);
+}
+#endif /* QCBOR_DISABLE_EXP_AND_MANTISSA */
+
+
+/**
+ * @brief Semi-private method to open a map, array or bstr-wrapped CBOR
+ *
+ * @param[in] pMe        The context to add to.
+ * @param[in] uMajorType  The major CBOR type to close
+ *
+ * Call QCBOREncode_OpenArray(), QCBOREncode_OpenMap() or
+ * QCBOREncode_BstrWrap() instead of this.
+ */
+void
+QCBOREncode_Private_OpenMapOrArray(QCBOREncodeContext *pMe,
+                                   const uint8_t       uMajorType)
+{
+   /* Add one item to the nesting level we are in for the new map or array */
+   QCBOREncode_Private_IncrementMapOrArrayCount(pMe);
+
+   /* The offset where the length of an array or map will get written
+    * is stored in a uint32_t, not a size_t to keep stack usage
+    * smaller. This checks to be sure there is no wrap around when
+    * recording the offset.  Note that on 64-bit machines CBOR larger
+    * than 4GB can be encoded as long as no array/map offsets occur
+    * past the 4GB mark, but the public interface says that the
+    * maximum is 4GB to keep the discussion simpler.
+    */
+   size_t uEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
+
+   /* QCBOR_MAX_ARRAY_OFFSET is slightly less than UINT32_MAX so this
+    * code can run on a 32-bit machine and tests can pass on a 32-bit
+    * machine. If it was exactly UINT32_MAX, then this code would not
+    * compile or run on a 32-bit machine and an #ifdef or some machine
+    * size detection would be needed reducing portability.
+    */
+   if(uEndPosition >= QCBOR_MAX_ARRAY_OFFSET) {
+      pMe->uError = QCBOR_ERR_BUFFER_TOO_LARGE;
+
+   } else {
+      /* Increase nesting level because this is a map or array.  Cast
+       * from size_t to uin32_t is safe because of check above.
+       */
+      pMe->uError = Nesting_Increase(&(pMe->nesting), uMajorType, (uint32_t)uEndPosition);
+   }
+}
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+/**
+ * @brief Semi-private method to open a map, array with indefinite length
+ *
+ * @param[in] pMe        The context to add to.
+ * @param[in] uMajorType  The major CBOR type to close
+ *
+ * Call QCBOREncode_OpenArrayIndefiniteLength() or
+ * QCBOREncode_OpenMapIndefiniteLength() instead of this.
+ */
+void
+QCBOREncode_Private_OpenMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
+                                                   const uint8_t       uMajorType)
+{
+   /* Insert the indefinite length marker (0x9f for arrays, 0xbf for maps) */
+   QCBOREncode_Private_AppendCBORHead(pMe, uMajorType, 0, 0);
+
+   /* Call the definite-length opener just to do the bookkeeping for
+    * nesting.  It will record the position of the opening item in the
+    * encoded output but this is not used when closing this open.
+    */
+   QCBOREncode_Private_OpenMapOrArray(pMe, uMajorType);
+}
+#endif
+
+
+/**
+ * @brief Check for errors when decreasing nesting.
+ *
+ * @param pMe          QCBOR encoding context.
+ * @param uMajorType  The major type of the nesting.
+ *
+ * Check that there is no previous error, that there is actually some
+ * nesting and that the major type of the opening of the nesting
+ * matches the major type of the nesting being closed.
+ *
+ * This is called when closing maps, arrays, byte string wrapping and
+ * open/close of byte strings.
+ */
+static bool
+QCBOREncode_Private_CheckDecreaseNesting(QCBOREncodeContext *pMe,
+                                         const uint8_t       uMajorType)
+{
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(pMe->uError != QCBOR_SUCCESS) {
+      return true;
+   }
+
+   if(!Nesting_IsInNest(&(pMe->nesting))) {
+      pMe->uError = QCBOR_ERR_TOO_MANY_CLOSES;
+      return true;
+   }
+
+   if(Nesting_GetMajorType(&(pMe->nesting)) != uMajorType) {
+      pMe->uError = QCBOR_ERR_CLOSE_MISMATCH;
+      return true;
+   }
+
+#else /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+   /* None of these checks are performed if the encode guards are
+    * turned off as they all relate to correct calling.
+    *
+    * Turning off all these checks does not turn off any checking for
+    * buffer overflows or pointer issues.
+    */
+
+   (void)uMajorType;
+   (void)pMe;
+#endif /* !QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   return false;
+}
+
+
+/**
+ * @brief Insert the CBOR head for a map, array or wrapped bstr
+ *
+ * @param pMe         QCBOR encoding context.
+ * @param uMajorType  One of CBOR_MAJOR_TYPE_XXXX.
+ * @param uLen        The length of the data item.
+ *
+ * When an array, map or bstr was opened, nothing was done but note
+ * the position. This function goes back to that position and inserts
+ * the CBOR Head with the major type and length.
+ */
+static void
+QCBOREncode_Private_CloseAggregate(QCBOREncodeContext *pMe,
+                                   uint8_t             uMajorType,
+                                   size_t              uLen)
+{
+   if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
+      return;
+   }
+
+   if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
+      uMajorType = CBOR_MAJOR_TYPE_BYTE_STRING;
+   }
+
+   /* A stack buffer large enough for a CBOR head (9 bytes) */
+   UsefulBuf_MAKE_STACK_UB(pBufferForEncodedHead, QCBOR_HEAD_BUFFER_SIZE);
+
+   UsefulBufC EncodedHead = QCBOREncode_EncodeHead(pBufferForEncodedHead,
+                                                   uMajorType,
+                                                   0,
+                                                   uLen);
+
+   /* No check for EncodedHead == NULLUsefulBufC is performed here to
+    * save object code. It is very clear that pBufferForEncodedHead is
+    * the correct size. If EncodedHead == NULLUsefulBufC then
+    * UsefulOutBuf_InsertUsefulBuf() will do nothing so there is no
+    * security hole introduced.
+    */
+   UsefulOutBuf_InsertUsefulBuf(&(pMe->OutBuf),
+                                EncodedHead,
+                                Nesting_GetStartPos(&(pMe->nesting)));
+
+   Nesting_Decrease(&(pMe->nesting));
+}
+
+
+/**
+ * @brief Semi-private method to close a map, array or bstr wrapped CBOR
+ *
+ * @param[in] pMe           The context to add to.
+ * @param[in] uMajorType     The major CBOR type to close.
+ *
+ * Call QCBOREncode_CloseArray() or QCBOREncode_CloseMap() instead of this.
+ */
+void
+QCBOREncode_Private_CloseMapOrArray(QCBOREncodeContext *pMe,
+                                    const uint8_t       uMajorType)
+{
+   QCBOREncode_Private_CloseAggregate(pMe, uMajorType, Nesting_GetCount(&(pMe->nesting)));
+}
+
+
+/*
+ * Public functions for closing bstr wrapping. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_CloseBstrWrap2(QCBOREncodeContext *pMe,
+                           const bool          bIncludeCBORHead,
+                           UsefulBufC         *pWrappedCBOR)
+{
+   const size_t uInsertPosition = Nesting_GetStartPos(&(pMe->nesting));
+   const size_t uEndPosition    = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
+
+   /* This subtraction can't go negative because the UsefulOutBuf
+    * always only grows and never shrinks. UsefulOutBut itself also
+    * has defenses such that it won't write where it should not even
+    * if given incorrect input lengths.
+    */
+   const size_t uBstrLen = uEndPosition - uInsertPosition;
+
+   /* Actually insert */
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_TYPE_BYTE_STRING, uBstrLen);
+
+   if(pWrappedCBOR) {
+      /* Return pointer and length to the enclosed encoded CBOR. The
+       * intended use is for it to be hashed (e.g., SHA-256) in a COSE
+       * implementation.  This must be used right away, as the pointer
+       * and length go invalid on any subsequent calls to this
+       * function because there might be calls to
+       * InsertEncodedTypeAndNumber() that slides data to the right.
+       */
+      size_t uStartOfNew = uInsertPosition;
+      if(!bIncludeCBORHead) {
+         /* Skip over the CBOR head to just get the inserted bstr */
+         const size_t uNewEndPosition = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
+         uStartOfNew += uNewEndPosition - uEndPosition;
+      }
+      const UsefulBufC PartialResult = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
+      *pWrappedCBOR = UsefulBuf_Tail(PartialResult, uStartOfNew);
+   }
+}
+
+
+/*
+ * Public function for canceling a bstr wrap. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_CancelBstrWrap(QCBOREncodeContext *pMe)
+{
+   if(QCBOREncode_Private_CheckDecreaseNesting(pMe, CBOR_MAJOR_TYPE_BYTE_STRING)) {
+      return;
+   }
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   const size_t uCurrent = UsefulOutBuf_GetEndPosition(&(pMe->OutBuf));
+   if(pMe->nesting.pCurrentNesting->uStart != uCurrent) {
+      pMe->uError = QCBOR_ERR_CANNOT_CANCEL;
+      return;
+   }
+   /* QCBOREncode_CancelBstrWrap() can't correctly undo
+    * QCBOREncode_BstrWrapInMap() or QCBOREncode_BstrWrapInMapN(). It
+    * can't undo the labels they add. It also doesn't catch the error
+    * of using it this way.  QCBOREncode_CancelBstrWrap() is used
+    * infrequently and the the result is incorrect CBOR, not a
+    * security hole, so no extra code or state is added to handle this
+    * condition.
+    */
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   Nesting_Decrease(&(pMe->nesting));
+   Nesting_Decrement(&(pMe->nesting));
+}
+
+
+/*
+ * Public function for opening a byte string. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_OpenBytes(QCBOREncodeContext *pMe, UsefulBuf *pPlace)
+{
+   *pPlace = UsefulOutBuf_GetOutPlace(&(pMe->OutBuf));
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   uint8_t uMajorType = Nesting_GetMajorType(&(pMe->nesting));
+   if(uMajorType == CBOR_MAJOR_NONE_TYPE_OPEN_BSTR) {
+      /* It's OK to nest a byte string in any type but
+       * another open byte string. */
+      pMe->uError = QCBOR_ERR_OPEN_BYTE_STRING;
+      return;
+   }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   QCBOREncode_Private_OpenMapOrArray(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR);
+}
+
+
+/*
+ * Public function for closing a byte string. See qcbor/qcbor_encode.h
+ */
+void
+QCBOREncode_CloseBytes(QCBOREncodeContext *pMe, const size_t uAmount)
+{
+   UsefulOutBuf_Advance(&(pMe->OutBuf), uAmount);
+   if(UsefulOutBuf_GetError(&(pMe->OutBuf))) {
+      /* Advance too far. Normal off-end error handling in effect here. */
+      return;
+   }
+
+   QCBOREncode_Private_CloseAggregate(pMe, CBOR_MAJOR_NONE_TYPE_OPEN_BSTR, uAmount);
+}
+
+
+#ifndef QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS
+
+/**
+ * @brief Semi-private method to close a map, array with indefinite length
+ *
+ * @param[in] pMe           The context to add to.
+ * @param[in] uMajorType     The major CBOR type to close.
+ *
+ * Call QCBOREncode_CloseArrayIndefiniteLength() or
+ * QCBOREncode_CloseMapIndefiniteLength() instead of this.
+ */
+void
+QCBOREncode_Private_CloseMapOrArrayIndefiniteLength(QCBOREncodeContext *pMe,
+                                                    const uint8_t       uMajorType)
+{
+   if(QCBOREncode_Private_CheckDecreaseNesting(pMe, uMajorType)) {
+      return;
+   }
+
+   /* Append the break marker (0xff for both arrays and maps) */
+   QCBOREncode_Private_AppendCBORHead(pMe, CBOR_MAJOR_NONE_TYPE_SIMPLE_BREAK, CBOR_SIMPLE_BREAK, 0);
+   Nesting_Decrease(&(pMe->nesting));
+}
+#endif
+
+
+/*
+ * Public function to finish and get the encoded result. See qcbor/qcbor_encode.h
+ */
+QCBORError
+QCBOREncode_Finish(QCBOREncodeContext *pMe, UsefulBufC *pEncodedCBOR)
+{
+   if(QCBOREncode_GetErrorState(pMe) != QCBOR_SUCCESS) {
+      goto Done;
+   }
+
+#ifndef QCBOR_DISABLE_ENCODE_USAGE_GUARDS
+   if(Nesting_IsInNest(&(pMe->nesting))) {
+      pMe->uError = QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN;
+      goto Done;
+   }
+#endif /* QCBOR_DISABLE_ENCODE_USAGE_GUARDS */
+
+   *pEncodedCBOR = UsefulOutBuf_OutUBuf(&(pMe->OutBuf));
+
+Done:
+   return pMe->uError;
+}
+
+
+/*
+ * Public functions to get size of the encoded result. See qcbor/qcbor_encode.h
+ */
+QCBORError
+QCBOREncode_FinishGetSize(QCBOREncodeContext *pMe, size_t *puEncodedLen)
+{
+   UsefulBufC Enc;
+
+   QCBORError nReturn = QCBOREncode_Finish(pMe, &Enc);
+
+   if(nReturn == QCBOR_SUCCESS) {
+      *puEncodedLen = Enc.len;
+   }
+
+   return nReturn;
+}
diff --git a/core/lib/qcbor/src/qcbor_err_to_str.c b/core/lib/qcbor/src/qcbor_err_to_str.c
new file mode 100644
index 0000000000000000000000000000000000000000..13d96639737d4f954524478047c58fc343583481
--- /dev/null
+++ b/core/lib/qcbor/src/qcbor_err_to_str.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/* ==========================================================================
+ * err_to_str.c -- strings names for errors
+ *
+ * Copyright (c) 2020, Patrick Uiterwijk. All rights reserved.
+ * Copyright (c) 2020,2024, Laurence Lundblade.
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * See BSD-3-Clause license in README.md
+ *
+ * Created on 3/21/20
+ * ========================================================================== */
+
+#include "qcbor/qcbor_common.h"
+#include <string.h>
+
+#define ERR_TO_STR_CASE(errpart) case errpart: return #errpart;
+
+
+const char *
+qcbor_err_to_str(const QCBORError uErr) {
+   switch (uErr) {
+   ERR_TO_STR_CASE(QCBOR_SUCCESS)
+   ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_SMALL)
+   ERR_TO_STR_CASE(QCBOR_ERR_ENCODE_UNSUPPORTED)
+   ERR_TO_STR_CASE(QCBOR_ERR_BUFFER_TOO_LARGE)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_NESTING_TOO_DEEP)
+   ERR_TO_STR_CASE(QCBOR_ERR_CLOSE_MISMATCH)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_CLOSES)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_STILL_OPEN)
+   ERR_TO_STR_CASE(QCBOR_ERR_OPEN_BYTE_STRING)
+   ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_CANCEL)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_TYPE_7)
+   ERR_TO_STR_CASE(QCBOR_ERR_EXTRA_BYTES)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNSUPPORTED)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_OR_MAP_UNCONSUMED)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_INT)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEFINITE_STRING_CHUNK)
+   ERR_TO_STR_CASE(QCBOR_ERR_HIT_END)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_BREAK)
+   ERR_TO_STR_CASE(QCBOR_ERR_INPUT_TOO_LARGE)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_NESTING_TOO_DEEP)
+   ERR_TO_STR_CASE(QCBOR_ERR_ARRAY_DECODE_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_STRING_TOO_LONG)
+   ERR_TO_STR_CASE(QCBOR_ERR_BAD_EXP_AND_MANTISSA)
+   ERR_TO_STR_CASE(QCBOR_ERR_NO_STRING_ALLOCATOR)
+   ERR_TO_STR_CASE(QCBOR_ERR_STRING_ALLOCATE)
+   ERR_TO_STR_CASE(QCBOR_ERR_MAP_LABEL_TYPE)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNRECOVERABLE_TAG_CONTENT)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_STRINGS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_INDEF_LEN_ARRAYS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_TAGS_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_TOO_MANY_TAGS)
+   ERR_TO_STR_CASE(QCBOR_ERR_UNEXPECTED_TYPE)
+   ERR_TO_STR_CASE(QCBOR_ERR_DUPLICATE_LABEL)
+   ERR_TO_STR_CASE(QCBOR_ERR_MEM_POOL_SIZE)
+   ERR_TO_STR_CASE(QCBOR_ERR_INT_OVERFLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_DATE_OVERFLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_EXIT_MISMATCH)
+   ERR_TO_STR_CASE(QCBOR_ERR_NO_MORE_ITEMS)
+   ERR_TO_STR_CASE(QCBOR_ERR_LABEL_NOT_FOUND)
+   ERR_TO_STR_CASE(QCBOR_ERR_NUMBER_SIGN_CONVERSION)
+   ERR_TO_STR_CASE(QCBOR_ERR_CONVERSION_UNDER_OVER_FLOW)
+   ERR_TO_STR_CASE(QCBOR_ERR_MAP_NOT_ENTERED)
+   ERR_TO_STR_CASE(QCBOR_ERR_CALLBACK_FAIL)
+   ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_DATE_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_HALF_PRECISION_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_HW_FLOAT_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_FLOAT_EXCEPTION)
+   ERR_TO_STR_CASE(QCBOR_ERR_ALL_FLOAT_DISABLED)
+   ERR_TO_STR_CASE(QCBOR_ERR_RECOVERABLE_BAD_TAG_CONTENT)
+   ERR_TO_STR_CASE(QCBOR_ERR_CANNOT_ENTER_ALLOCATED_STRING)
+
+   default:
+      if(uErr >= QCBOR_ERR_FIRST_USER_DEFINED && uErr <= QCBOR_ERR_LAST_USER_DEFINED) {
+         /* Static buffer is not thread safe, but this is only a diagnostic */
+         static char buf[20];
+         strcpy(buf, "USER_DEFINED_");
+         size_t uEndOffset = strlen(buf);
+         buf[uEndOffset]   = (char)(uErr/100 + '0');
+         buf[uEndOffset+1] = (char)(((uErr/10) % 10) + '0');
+         buf[uEndOffset+2] = (char)((uErr % 10 )+ '0');
+         buf[uEndOffset+3] = '\0';
+         return buf;
+
+      } else {
+         return "Unidentified QCBOR error";
+      }
+   }
+}
diff --git a/core/lib/qcbor/sub.mk b/core/lib/qcbor/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..db013ac7a4ec474235157e645ce27c08acb15012
--- /dev/null
+++ b/core/lib/qcbor/sub.mk
@@ -0,0 +1,13 @@
+global-incdirs-y += inc
+
+cflags-y += -Wno-declaration-after-statement
+cflags-y += -Wno-redundant-decls
+global-cppflags-y += -DQCBOR_DISABLE_FLOAT_HW_USE
+global-cppflags-y += -DQCBOR_DISABLE_PREFERRED_FLOAT
+global-cppflags-y += -DUSEFULBUF_DISABLE_ALL_FLOAT
+
+srcs-y += src/ieee754.c
+srcs-y += src/qcbor_decode.c
+srcs-y += src/qcbor_encode.c
+srcs-y += src/qcbor_err_to_str.c
+srcs-y += src/UsefulBuf.c
diff --git a/core/lib/scmi-server/conf-optee-stm32mp1.mk b/core/lib/scmi-server/conf-optee-stm32mp1.mk
index 34ae07f9142b562d01748b08e0d027e038187add..72996b64b2dee3b424dfbff386e308f8087ad215 100644
--- a/core/lib/scmi-server/conf-optee-stm32mp1.mk
+++ b/core/lib/scmi-server/conf-optee-stm32mp1.mk
@@ -4,7 +4,11 @@ $(call force,CFG_SCPFW_MOD_OPTEE_CLOCK,y)
 $(call force,CFG_SCPFW_MOD_OPTEE_CONSOLE,y)
 $(call force,CFG_SCPFW_MOD_OPTEE_MBX,y)
 $(call force,CFG_SCPFW_MOD_OPTEE_RESET,y)
+ifeq ($(CFG_STM32MP1_SCMI_SHM_SYSRAM),y)
 $(call force,CFG_SCPFW_MOD_OPTEE_SMT,y)
+else
+$(call force,CFG_SCPFW_MOD_MSG_SMT,y)
+endif
 $(call force,CFG_SCPFW_MOD_SCMI,y)
 $(call force,CFG_SCPFW_MOD_SCMI_CLOCK,y)
 $(call force,CFG_SCPFW_MOD_SCMI_RESET_DOMAIN,y)
diff --git a/core/lib/scmi-server/conf.mk b/core/lib/scmi-server/conf.mk
index ba497481627796d384a4c2a3af3500bce7cd180f..85f1aac7d5684541f531fcfa0fdf935df95533d2 100644
--- a/core/lib/scmi-server/conf.mk
+++ b/core/lib/scmi-server/conf.mk
@@ -18,7 +18,7 @@
 # CFG_SCPFW_SENSOR_EXT_ATTRIBS
 # CFG_SCPFW_SENSOR_SIGNED_VALUE
 
-include core/lib/scmi-server/conf-$(CFG_SCMI_SCPFW_PRODUCT).mk
+include core/lib/scmi-server/conf-optee-$(CFG_SCMI_SCPFW_PRODUCT).mk
 
 # SCP-fmw log level: 0 trace/verbose, 1 info, 2 warning, 3 error, 4 critical
 ifeq ($(CFG_TEE_CORE_LOG_LEVEL),0)
diff --git a/core/lib/scmi-server/sub-optee-fvp.mk b/core/lib/scmi-server/sub-optee-fvp.mk
deleted file mode 100644
index 6600a613e88c2646326c2b2735249f05422c2385..0000000000000000000000000000000000000000
--- a/core/lib/scmi-server/sub-optee-fvp.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-incdirs_ext-y += $(scpfw-path)/product/optee-fvp/fw
-incdirs_ext-y += $(scpfw-path)/product/optee-fvp/include
-
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_clock.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_dvfs.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mbx_smt.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_clock.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_ppu.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_mock_psu.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_power_domain.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_psu.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_clock.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_perf.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_scmi_power_domain.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_sensor.c
-srcs-y += $(scpfw-path)/product/optee-fvp/fw/config_vpll.c
diff --git a/core/lib/scmi-server/sub-optee-stm32mp1.mk b/core/lib/scmi-server/sub-optee-stm32mp1.mk
deleted file mode 100644
index b0cddd6b12133048974804dc0d8a59b52b29ce8d..0000000000000000000000000000000000000000
--- a/core/lib/scmi-server/sub-optee-stm32mp1.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-incdirs_ext-y += $(scpfw-path)/product/optee-stm32mp1/include
-
-srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_mbx_smt.c
-srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi.c
-srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_clocks.c
-srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_reset_domains.c
-srcs-y += $(scpfw-path)/product/optee-stm32mp1/fw/config_scmi_voltage_domains.c
-
-$(eval $(call scpfw-embed-product-module,stm32_pmic_regu))
-$(eval $(call scpfw-embed-product-module,stm32_pwr_regu))
diff --git a/core/lib/scmi-server/sub.mk b/core/lib/scmi-server/sub.mk
index d719a1c8d92791a2cb519c212c6c41a389624936..1c72a3acff319c1c6d407d517844c58dccce3189 100644
--- a/core/lib/scmi-server/sub.mk
+++ b/core/lib/scmi-server/sub.mk
@@ -1,20 +1,18 @@
 # SCMI server library is built from SCP-firmware source tree.
 # The firmware is made of a framework, a product and modules.
 # Only modules used by firmware must be built, as stated by
-# CFG_SCPFW_MOD_* swtches. SCP-firmware needs a C source and
+# CFG_SCPFW_MOD_* switches. SCP-firmware needs a C source and
 # a header file to be generated to describe embedded modules.
 # This is done through cmake configuration of the package.
 # The toolchain build directive must also match the list of
 # embedded modules.
 
 scpfw-path = $(CFG_SCP_FIRMWARE)
-scpfw-product = $(CFG_SCMI_SCPFW_PRODUCT)
+scpfw-product = optee/$(CFG_SCMI_SCPFW_PRODUCT)
 scpfw-out-path := $(out-dir)/$(libdir)
 
-# This script was validated against SCP-firmware 2.11.0 development branch,
-# from commit f1d894921d76 ("product/optee-fvp: Add new OPTEE FVP product").
 scpfw-integ-version-maj = 2
-scpfw-integ-version-min = 11
+scpfw-integ-version-min = 14
 scpfw-integ-version-pat = 0
 scpfw-integ-version = $(scpfw-integ-version-maj).$(scpfw-integ-version-min).$(scpfw-integ-version-pat)
 
@@ -27,8 +25,12 @@ scpfw-cmake-flags-y = -DSCP_FIRMWARE_SOURCE_DIR:PATH=$(scpfw-product)/fw \
 		      -DSCP_LOG_LEVEL="TRACE" \
 		      -DDISABLE_CPPCHECK=1 \
 		      -DCFG_NUM_THREADS=$(CFG_NUM_THREADS) \
-		      -DSCP_OPTEE_DIR:PATH=$(CURDIR) \
-		      -DCFG_CROSS_COMPILE=$(lastword $(CROSS_COMPILE_core))
+		      -DSCP_OPTEE_DIR:PATH=$(CURDIR)
+
+# CMake does not need to check the cross compilation toolchain since we do not
+# compile any source file with CMake, we only generate some SCP-firmware
+# files.
+scpfw-cmake-flags-y += -DCMAKE_C_COMPILER_WORKS=1
 
 ifeq ($(cmd-echo-silent),true)
 scpfw-cmake-redirect = >/dev/null
@@ -102,125 +104,6 @@ cppflags-lib-$(CFG_SCPFW_SENSOR_EXT_ATTRIBS) += -DBUILD_HAS_SENSOR_EXT_ATTRIBS
 cppflags-lib-$(CFG_SCPFW_SENSOR_SIGNED_VALUE) += -DBUILD_HAS_SENSOR_SIGNED_VALUE
 cppflags-lib-$(CFG_SCPFW_INBAND_MSG_SUPPORT) += -DBUILD_HAS_INBAND_MSG_SUPPORT
 
-incdirs_ext-y += $(scpfw-path)/arch/none/optee/include
-srcs-y += $(scpfw-path)/arch/none/optee/src/arch_interrupt.c
-srcs-y += $(scpfw-path)/arch/none/optee/src/arch_main.c
-
-incdirs_ext-y += $(scpfw-path)/framework/include
-srcs-y += $(scpfw-path)/framework/src/fwk_arch.c
-srcs-y += $(scpfw-path)/framework/src/fwk_dlist.c
-srcs-y += $(scpfw-path)/framework/src/fwk_id.c
-srcs-y += $(scpfw-path)/framework/src/fwk_interrupt.c
-srcs-y += $(scpfw-path)/framework/src/fwk_io.c
-srcs-y += $(scpfw-path)/framework/src/fwk_log.c
-srcs-y += $(scpfw-path)/framework/src/fwk_mm.c
-srcs-y += $(scpfw-path)/framework/src/fwk_module.c
-srcs-y += $(scpfw-path)/framework/src/fwk_ring.c
-srcs-y += $(scpfw-path)/framework/src/fwk_slist.c
-srcs-y += $(scpfw-path)/framework/src/fwk_status.c
-srcs-y += $(scpfw-path)/framework/src/fwk_string.c
-srcs-y += $(scpfw-path)/framework/src/fwk_delayed_resp.c
-srcs-y += $(scpfw-path)/framework/src/fwk_time.c
-srcs-y += $(scpfw-path)/framework/src/fwk_core.c
-srcs-y += $(scpfw-path)/framework/src/assert.c
-srcs-y += $(scpfw-path)/framework/src/stdlib.c
-srcs-$(CFG_SCPFW_NOTIFICATION) += $(scpfw-path)/framework/src/fwk_notification.c
-
-# Helper macros for listing SCP-firmware modules source files (in srcs-y)
-# and header include paths (in incdirs_ext-y). Each module provides a C source
-# file named mod_<module-name>.c and possibly an include directory. Build
-# directive BUILD_HAS_MOD_<NAME> must be set for each embedded module.
-#
-# Standard modules source tree: <scp-path>/module/<name>/src/mod_<name>.c
-# Optee modules source tree:    <scp-path>/module/optee/<short-name>/src/mod_<name>.c
-# Product modules source tree:  <scp-path>/product/<product-name>/module/<name>/src/mod_<name>.c
-#
-# scpfw-embed-generic-module is to be used for standard modules.
-# scpfw-embed-optee-module is to be used for optee modules.
-# scpfw-embed-product-module is to be used for product modules.
-# For modules that implement other C source files aside mandatory mod_<name>.c we must
-# add to srcs-y the required source file paths.
-#
-# scpfw-embed-mod takes 4 arguments:
-# $1 module name, lowercase
-# $2 module directory name
-# $3 module parent directory relative path in scpfw tree
-# $4 module name, uppercase, relates to CFG_SCPFW_MOD_$4
-define scpfw-embed-mod
-ifneq (,$$(wildcard $(scpfw-path)/$3/$2/include/*))
-incdirs_ext-y += $(scpfw-path)/$3/$2/include
-endif
-srcs-$(CFG_SCPFW_MOD_$4) += $(scpfw-path)/$3/$2/src/mod_$1.c
-
-# SCMI_Perf in SCP-firmware has components that can be added conditionally at
-# build time.
-ifeq ($(1), scmi_perf)
-
-ifeq ($(CFG_SCPFW_SCMI_PERF_PROTOCOL_OPS),y)
-srcs-$(CFG_SCPFW_MOD_SCMI_PERF) += $(scpfw-path)/$3/$2/src/scmi_perf_protocol_ops.c
-endif
-
-ifeq ($(CFG_SCPFW_SCMI_PERF_FAST_CHANNELS),y)
-srcs-$(CFG_SCPFW_MOD_SCMI_PERF) += $(scpfw-path)/$3/$2/src/scmi_perf_fastchannels.c
-endif
-
-endif
-
-cflags-lib-$(CFG_SCPFW_MOD_$4) += -DBUILD_HAS_MOD_$4
-endef
-
-define scpfw-embed-generic-module
-$(eval $(call scpfw-embed-mod,$1,$1,module,$(shell echo $1 | tr a-z A-Z)))
-endef
-
-define scpfw-embed-optee-module
-$(eval $(call scpfw-embed-mod,optee_$1,$1,module/optee,OPTEE_$(shell echo $1 | tr a-z A-Z)))
-endef
-
-define scpfw-embed-product-module
-$(eval $(call scpfw-embed-mod,$1,$1,product/$(scpfw-product)/module,$(shell echo $1 | tr a-z A-Z)))
-endef
-
-$(eval $(call scpfw-embed-generic-module,clock))
-$(eval $(call scpfw-embed-generic-module,dvfs))
-$(eval $(call scpfw-embed-generic-module,mock_clock))
-$(eval $(call scpfw-embed-generic-module,mock_ppu))
-$(eval $(call scpfw-embed-generic-module,mock_psu))
-$(eval $(call scpfw-embed-generic-module,msg_smt))
-$(eval $(call scpfw-embed-generic-module,power_domain))
-$(eval $(call scpfw-embed-generic-module,psu))
-$(eval $(call scpfw-embed-generic-module,reg_sensor))
-$(eval $(call scpfw-embed-generic-module,reset_domain))
-$(eval $(call scpfw-embed-generic-module,sensor))
-$(eval $(call scpfw-embed-generic-module,scmi))
-$(eval $(call scpfw-embed-generic-module,scmi_apcore))
-$(eval $(call scpfw-embed-generic-module,scmi_clock))
-$(eval $(call scpfw-embed-generic-module,scmi_perf))
-$(eval $(call scpfw-embed-generic-module,scmi_power_domain))
-$(eval $(call scpfw-embed-generic-module,scmi_reset_domain))
-$(eval $(call scpfw-embed-generic-module,scmi_sensor))
-$(eval $(call scpfw-embed-generic-module,scmi_voltage_domain))
-$(eval $(call scpfw-embed-generic-module,system_pll))
-$(eval $(call scpfw-embed-generic-module,voltage_domain))
-$(eval $(call scpfw-embed-optee-module,clock))
-$(eval $(call scpfw-embed-optee-module,console))
-$(eval $(call scpfw-embed-optee-module,mbx))
-$(eval $(call scpfw-embed-optee-module,reset))
-$(eval $(call scpfw-embed-optee-module,smt))
-
-srcs-$(CFG_SCPFW_MOD_CLOCK) += $(scpfw-path)/module/clock/src/clock_tree_management.c
-srcs-$(CFG_SCPFW_MOD_POWER_DOMAIN) += $(scpfw-path)/module/power_domain/src/power_domain_utils.c
-srcs-$(CFG_SCPFW_MOD_SCMI) += $(scpfw-path)/module/scmi/src/mod_scmi_base.c
-srcs-$(CFG_SCPFW_MOD_SCMI_SENSOR) += $(scpfw-path)/module/scmi_sensor/src/mod_scmi_ext_attrib.c
-srcs-$(CFG_SCPFW_MOD_SENSOR) += $(scpfw-path)/module/sensor/src/sensor_extended.c
-
-# Architecture arch/none/optee requires optee mbx header file
-incdirs_ext-y += $(scpfw-path)/module/optee/mbx/include
-# Some modules require header files from module that are not embedded
-ifneq (,$(filter y, $(CFG_SCPFW_MOD_DVFS) $(CFG_SCPFW_MOD_MOCK_PSU) $(CFG_SCPFW_MOD_SCMI_PERF)))
-incdirs_ext-y += $(scpfw-path)/module/timer/include
-endif
-incdirs_ext-$(CFG_SCPFW_MOD_OPTEE_MBX) += $(scpfw-path)/module/msg_smt/include
-incdirs_ext-$(CFG_SCPFW_MOD_SCMI) += $(scpfw-path)/module/power_domain/include
+# Include SCP-firmware make files
+include $(scpfw-path)/product/optee/sub.mk
 
-include core/lib/scmi-server/sub-$(CFG_SCMI_SCPFW_PRODUCT).mk
diff --git a/core/lib/zlib/sub.mk b/core/lib/zlib/sub.mk
index d4f225dfbfc49c0c8e7aaaa601a4e518cad89ba8..399544d02e204a41c69894eb429119f0e74afd83 100644
--- a/core/lib/zlib/sub.mk
+++ b/core/lib/zlib/sub.mk
@@ -6,3 +6,5 @@ srcs-y += inftrees.c
 srcs-y += zutil.c
 cflags-remove-y += -Wold-style-definition
 cflags-remove-y += -Wswitch-default
+cflags-remove-y += -Wstrict-prototypes
+cflags-y += $(call cc-option,-Wno-deprecated-non-prototype)
diff --git a/core/mm/boot_mem.c b/core/mm/boot_mem.c
new file mode 100644
index 0000000000000000000000000000000000000000..04d56689b3779c7242e66c6fe7daf06e466a217e
--- /dev/null
+++ b/core/mm/boot_mem.c
@@ -0,0 +1,246 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <assert.h>
+#include <kernel/boot.h>
+#include <mm/core_memprot.h>
+#include <mm/core_mmu.h>
+#include <mm/phys_mem.h>
+#include <mm/tee_mm.h>
+#include <stdalign.h>
+#include <string.h>
+#include <util.h>
+
+/*
+ * struct boot_mem_reloc - Pointers relocated in memory during boot
+ * @ptrs: Array of relocation
+ * @count: Number of cells used in @ptrs
+ * @next: Next relocation array when @ptrs is fully used
+ */
+struct boot_mem_reloc {
+	void **ptrs[64];
+	size_t count;
+	struct boot_mem_reloc *next;
+};
+
+/*
+ * struct boot_mem_desc - Stack like boot memory allocation pool
+ * @orig_mem_start: Boot memory stack base address
+ * @orig_mem_end: Boot memory start end address
+ * @mem_start: Boot memory free space start address
+ * @mem_end: Boot memory free space end address
+ * @reloc: Boot memory pointers requiring relocation
+ */
+struct boot_mem_desc {
+	vaddr_t orig_mem_start;
+	vaddr_t orig_mem_end;
+	vaddr_t mem_start;
+	vaddr_t mem_end;
+	struct boot_mem_reloc *reloc;
+};
+
+static struct boot_mem_desc *boot_mem_desc;
+
+static void *mem_alloc_tmp(struct boot_mem_desc *desc, size_t len, size_t align)
+{
+	vaddr_t va = 0;
+
+	assert(desc && desc->mem_start && desc->mem_end);
+	assert(IS_POWER_OF_TWO(align) && !(len % align));
+	if (SUB_OVERFLOW(desc->mem_end, len, &va))
+		panic();
+	va = ROUNDDOWN2(va, align);
+	if (va < desc->mem_start)
+		panic();
+	desc->mem_end = va;
+	return (void *)va;
+}
+
+static void *mem_alloc(struct boot_mem_desc *desc, size_t len, size_t align)
+{
+	vaddr_t va = 0;
+	vaddr_t ve = 0;
+
+	runtime_assert(!IS_ENABLED(CFG_WITH_PAGER));
+	assert(desc && desc->mem_start && desc->mem_end);
+	assert(IS_POWER_OF_TWO(align) && !(len % align));
+	va = ROUNDUP2(desc->mem_start, align);
+	if (ADD_OVERFLOW(va, len, &ve))
+		panic();
+	if (ve > desc->mem_end)
+		panic();
+	desc->mem_start = ve;
+	return (void *)va;
+}
+
+void boot_mem_init(vaddr_t start, vaddr_t end, vaddr_t orig_end)
+{
+	struct boot_mem_desc desc = {
+		.orig_mem_start = start,
+		.orig_mem_end = orig_end,
+		.mem_start = start,
+		.mem_end = end,
+	};
+
+	boot_mem_desc = mem_alloc_tmp(&desc, sizeof(desc), alignof(desc));
+	*boot_mem_desc = desc;
+	boot_mem_desc->reloc = mem_alloc_tmp(boot_mem_desc,
+					     sizeof(*boot_mem_desc->reloc),
+					     alignof(*boot_mem_desc->reloc));
+	memset(boot_mem_desc->reloc, 0, sizeof(*boot_mem_desc->reloc));
+}
+
+void boot_mem_add_reloc(void *ptr)
+{
+	struct boot_mem_reloc *reloc = NULL;
+
+	assert(boot_mem_desc && boot_mem_desc->reloc);
+	reloc = boot_mem_desc->reloc;
+
+	/* If the reloc struct is full, allocate a new and link it first */
+	if (reloc->count == ARRAY_SIZE(reloc->ptrs)) {
+		reloc = boot_mem_alloc_tmp(sizeof(*reloc), alignof(*reloc));
+		reloc->next = boot_mem_desc->reloc;
+		boot_mem_desc->reloc = reloc;
+	}
+
+	reloc->ptrs[reloc->count] = ptr;
+	reloc->count++;
+}
+
+static void *add_offs(void *p, size_t offs)
+{
+	assert(p);
+	return (uint8_t *)p + offs;
+}
+
+void boot_mem_relocate(size_t offs)
+{
+	struct boot_mem_reloc *reloc = NULL;
+	size_t n = 0;
+
+	boot_mem_desc = add_offs(boot_mem_desc, offs);
+
+	boot_mem_desc->orig_mem_start += offs;
+	boot_mem_desc->orig_mem_end += offs;
+	boot_mem_desc->mem_start += offs;
+	boot_mem_desc->mem_end += offs;
+	boot_mem_desc->reloc = add_offs(boot_mem_desc->reloc, offs);
+
+	for (reloc = boot_mem_desc->reloc;; reloc = reloc->next) {
+		for (n = 0; n < reloc->count; n++) {
+			reloc->ptrs[n] = add_offs(reloc->ptrs[n], offs);
+			*reloc->ptrs[n] = add_offs(*reloc->ptrs[n], offs);
+		}
+		if (!reloc->next)
+			break;
+		reloc->next = add_offs(reloc->next, offs);
+	}
+}
+
+void *boot_mem_alloc(size_t len, size_t align)
+{
+	return mem_alloc(boot_mem_desc, len, align);
+}
+
+void *boot_mem_alloc_tmp(size_t len, size_t align)
+{
+	return mem_alloc_tmp(boot_mem_desc, len, align);
+}
+
+vaddr_t boot_mem_release_unused(void)
+{
+	tee_mm_entry_t *mm = NULL;
+	paddr_t pa = 0;
+	vaddr_t va = 0;
+	size_t n = 0;
+	vaddr_t tmp_va = 0;
+	paddr_t tmp_pa = 0;
+	size_t tmp_n = 0;
+
+	assert(boot_mem_desc);
+
+	n = boot_mem_desc->mem_start - boot_mem_desc->orig_mem_start;
+	DMSG("Allocated %zu bytes at va %#"PRIxVA" pa %#"PRIxPA,
+	     n, boot_mem_desc->orig_mem_start,
+	     vaddr_to_phys(boot_mem_desc->orig_mem_start));
+
+	DMSG("Tempalloc %zu bytes at va %#"PRIxVA,
+	     (size_t)(boot_mem_desc->orig_mem_end - boot_mem_desc->mem_end),
+	     boot_mem_desc->mem_end);
+
+	if (IS_ENABLED(CFG_WITH_PAGER))
+		goto out;
+
+	pa = vaddr_to_phys(ROUNDUP(boot_mem_desc->orig_mem_start,
+				   SMALL_PAGE_SIZE));
+	mm = nex_phys_mem_mm_find(pa);
+	if (!mm)
+		panic();
+
+	va = ROUNDUP(boot_mem_desc->mem_start, SMALL_PAGE_SIZE);
+
+	tmp_va = ROUNDDOWN(boot_mem_desc->mem_end, SMALL_PAGE_SIZE);
+	tmp_n = boot_mem_desc->orig_mem_end - tmp_va;
+	tmp_pa = vaddr_to_phys(tmp_va);
+
+	pa = tee_mm_get_smem(mm);
+	n = vaddr_to_phys(boot_mem_desc->mem_start) - pa;
+	tee_mm_free(mm);
+	DMSG("Carving out %#"PRIxPA"..%#"PRIxPA, pa, pa + n - 1);
+	mm = nex_phys_mem_alloc2(pa, n);
+	if (!mm)
+		panic();
+	mm = nex_phys_mem_alloc2(tmp_pa, tmp_n);
+	if (!mm)
+		panic();
+
+	n = tmp_va - boot_mem_desc->mem_start;
+	DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
+
+	/* Unmap the now unused pages */
+	core_mmu_unmap_pages(va, n / SMALL_PAGE_SIZE);
+
+out:
+	/* Stop further allocations. */
+	boot_mem_desc->mem_start = boot_mem_desc->mem_end;
+	return va;
+}
+
+void boot_mem_release_tmp_alloc(void)
+{
+	tee_mm_entry_t *mm = NULL;
+	vaddr_t va = 0;
+	paddr_t pa = 0;
+	size_t n = 0;
+
+	assert(boot_mem_desc &&
+	       boot_mem_desc->mem_start == boot_mem_desc->mem_end);
+
+	if (IS_ENABLED(CFG_WITH_PAGER)) {
+		n = boot_mem_desc->orig_mem_end - boot_mem_desc->mem_end;
+		va = boot_mem_desc->mem_end;
+		boot_mem_desc = NULL;
+		DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
+		return;
+	}
+
+	va = ROUNDDOWN(boot_mem_desc->mem_end, SMALL_PAGE_SIZE);
+	pa = vaddr_to_phys(va);
+
+	mm = nex_phys_mem_mm_find(pa);
+	if (!mm)
+		panic();
+	assert(pa == tee_mm_get_smem(mm));
+	n = tee_mm_get_bytes(mm);
+
+	/* Boot memory allocation is now done */
+	boot_mem_desc = NULL;
+
+	DMSG("Releasing %zu bytes from va %#"PRIxVA, n, va);
+
+	/* Unmap the now unused pages */
+	core_mmu_unmap_pages(va, n / SMALL_PAGE_SIZE);
+}
diff --git a/core/mm/core_mmu.c b/core/mm/core_mmu.c
index c894e3fc2fa81df0dd6ffde42b26be1f63c8b024..fad6ef08cfbd582ceabbf91a860761a3b8313b98 100644
--- a/core/mm/core_mmu.c
+++ b/core/mm/core_mmu.c
@@ -18,13 +18,16 @@
 #include <kernel/user_mode_ctx.h>
 #include <kernel/virtualization.h>
 #include <libfdt.h>
+#include <memtag.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <mm/mobj.h>
 #include <mm/pgt_cache.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_pager.h>
 #include <mm/vm.h>
 #include <platform_config.h>
+#include <stdalign.h>
 #include <string.h>
 #include <trace.h>
 #include <util.h>
@@ -35,6 +38,12 @@
 
 #define SHM_VASPACE_SIZE	(1024 * 1024 * 32)
 
+/* Virtual memory pool for core mappings */
+tee_mm_pool_t core_virt_mem_pool;
+
+/* Virtual memory pool for shared memory mappings */
+tee_mm_pool_t core_virt_shm_pool;
+
 #ifdef CFG_CORE_PHYS_RELOCATABLE
 unsigned long core_mmu_tee_load_pa __nex_bss;
 #else
@@ -53,11 +62,23 @@ unsigned long default_nsec_shm_size __nex_bss;
 unsigned long default_nsec_shm_paddr __nex_bss;
 #endif
 
-static struct tee_mmap_region static_memory_map[CFG_MMAP_REGIONS
+#ifdef CFG_BOOT_MEM
+static struct memory_map static_memory_map __nex_bss;
+#else
+static struct tee_mmap_region static_mmap_regions[CFG_MMAP_REGIONS
 #if defined(CFG_CORE_ASLR) || defined(CFG_CORE_PHYS_RELOCATABLE)
 						+ 1
 #endif
-						+ 1] __nex_bss;
+						+ 4] __nex_bss;
+static struct memory_map static_memory_map __nex_data = {
+	.map = static_mmap_regions,
+	.alloc_count = ARRAY_SIZE(static_mmap_regions),
+};
+#endif
+void (*memory_map_realloc_func)(struct memory_map *mem_map) __nex_bss;
+
+/* Offset of the first TEE RAM mapping from start of secure RAM */
+static size_t tee_ram_initial_offs __nex_bss;
 
 /* Define the platform's memory layout. */
 struct memaccess_area {
@@ -110,6 +131,47 @@ static void mmu_unlock(uint32_t exceptions)
 	cpu_spin_unlock_xrestore(&mmu_spinlock, exceptions);
 }
 
+static void heap_realloc_memory_map(struct memory_map *mem_map)
+{
+	struct tee_mmap_region *m = NULL;
+	struct tee_mmap_region *old = mem_map->map;
+	size_t old_sz = sizeof(*old) * mem_map->alloc_count;
+	size_t sz = old_sz + sizeof(*m);
+
+	assert(nex_malloc_buffer_is_within_alloced(old, old_sz));
+	m = nex_realloc(old, sz);
+	if (!m)
+		panic();
+	mem_map->map = m;
+	mem_map->alloc_count++;
+}
+
+static void boot_mem_realloc_memory_map(struct memory_map *mem_map)
+{
+	struct tee_mmap_region *m = NULL;
+	struct tee_mmap_region *old = mem_map->map;
+	size_t old_sz = sizeof(*old) * mem_map->alloc_count;
+	size_t sz = old_sz * 2;
+
+	m = boot_mem_alloc_tmp(sz, alignof(*m));
+	memcpy(m, old, old_sz);
+	mem_map->map = m;
+	mem_map->alloc_count *= 2;
+}
+
+static void grow_mem_map(struct memory_map *mem_map)
+{
+	if (mem_map->count == mem_map->alloc_count) {
+		if (!memory_map_realloc_func) {
+			EMSG("Out of entries (%zu) in mem_map",
+			     mem_map->alloc_count);
+			panic();
+		}
+		memory_map_realloc_func(mem_map);
+	}
+	mem_map->count++;
+}
+
 void core_mmu_get_secure_memory(paddr_t *base, paddr_size_t *size)
 {
 	/*
@@ -134,50 +196,16 @@ void core_mmu_set_secure_memory(paddr_t base, size_t size)
 	secure_only[0].size = size;
 }
 
-void core_mmu_get_ta_range(paddr_t *base, size_t *size)
-{
-	paddr_t b = 0;
-	size_t s = 0;
-
-	static_assert(!(TEE_RAM_VA_SIZE % SMALL_PAGE_SIZE));
-#ifdef TA_RAM_START
-	b = TA_RAM_START;
-	s = TA_RAM_SIZE;
-#else
-	static_assert(ARRAY_SIZE(secure_only) <= 2);
-	if (ARRAY_SIZE(secure_only) == 1) {
-		vaddr_t load_offs = 0;
-
-		assert(core_mmu_tee_load_pa >= secure_only[0].paddr);
-		load_offs = core_mmu_tee_load_pa - secure_only[0].paddr;
-
-		assert(secure_only[0].size >
-		       load_offs + TEE_RAM_VA_SIZE + TEE_SDP_TEST_MEM_SIZE);
-		b = secure_only[0].paddr + load_offs + TEE_RAM_VA_SIZE;
-		s = secure_only[0].size - load_offs - TEE_RAM_VA_SIZE -
-		    TEE_SDP_TEST_MEM_SIZE;
-	} else {
-		assert(secure_only[1].size > TEE_SDP_TEST_MEM_SIZE);
-		b = secure_only[1].paddr;
-		s = secure_only[1].size - TEE_SDP_TEST_MEM_SIZE;
-	}
-#endif
-	if (base)
-		*base = b;
-	if (size)
-		*size = s;
-}
-
-static struct tee_mmap_region *get_memory_map(void)
+static struct memory_map *get_memory_map(void)
 {
 	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
-		struct tee_mmap_region *map = virt_get_memory_map();
+		struct memory_map *map = virt_get_memory_map();
 
 		if (map)
 			return map;
 	}
 
-	return static_memory_map;
+	return &static_memory_map;
 }
 
 static bool _pbuf_intersects(struct memaccess_area *a, size_t alen,
@@ -235,52 +263,78 @@ static bool pbuf_inside_map_area(unsigned long p, size_t l,
 	return core_is_buffer_inside(p, l, map->pa, map->size);
 }
 
+TEE_Result core_mmu_for_each_map(void *ptr,
+				 TEE_Result (*fn)(struct tee_mmap_region *map,
+						  void *ptr))
+{
+	struct memory_map *mem_map = get_memory_map();
+	TEE_Result res = TEE_SUCCESS;
+	size_t n = 0;
+
+	for (n = 0; n < mem_map->count; n++) {
+		res = fn(mem_map->map + n, ptr);
+		if (res)
+			return res;
+	}
+
+	return TEE_SUCCESS;
+}
+
 static struct tee_mmap_region *find_map_by_type(enum teecore_memtypes type)
 {
-	struct tee_mmap_region *map;
+	struct memory_map *mem_map = get_memory_map();
+	size_t n = 0;
 
-	for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++)
-		if (map->type == type)
-			return map;
+	for (n = 0; n < mem_map->count; n++) {
+		if (mem_map->map[n].type == type)
+			return mem_map->map + n;
+	}
 	return NULL;
 }
 
 static struct tee_mmap_region *
 find_map_by_type_and_pa(enum teecore_memtypes type, paddr_t pa, size_t len)
 {
-	struct tee_mmap_region *map;
+	struct memory_map *mem_map = get_memory_map();
+	size_t n = 0;
 
-	for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) {
-		if (map->type != type)
+	for (n = 0; n < mem_map->count; n++) {
+		if (mem_map->map[n].type != type)
 			continue;
-		if (pa_is_in_map(map, pa, len))
-			return map;
+		if (pa_is_in_map(mem_map->map + n, pa, len))
+			return mem_map->map + n;
 	}
 	return NULL;
 }
 
 static struct tee_mmap_region *find_map_by_va(void *va)
 {
-	struct tee_mmap_region *map = get_memory_map();
-	unsigned long a = (unsigned long)va;
+	struct memory_map *mem_map = get_memory_map();
+	vaddr_t a = (vaddr_t)va;
+	size_t n = 0;
 
-	while (!core_mmap_is_end_of_table(map)) {
-		if (a >= map->va && a <= (map->va - 1 + map->size))
-			return map;
-		map++;
+	for (n = 0; n < mem_map->count; n++) {
+		if (a >= mem_map->map[n].va &&
+		    a <= (mem_map->map[n].va - 1 + mem_map->map[n].size))
+			return mem_map->map + n;
 	}
+
 	return NULL;
 }
 
 static struct tee_mmap_region *find_map_by_pa(unsigned long pa)
 {
-	struct tee_mmap_region *map = get_memory_map();
+	struct memory_map *mem_map = get_memory_map();
+	size_t n = 0;
 
-	while (!core_mmap_is_end_of_table(map)) {
-		if (pa >= map->pa && pa <= (map->pa + map->size - 1))
-			return map;
-		map++;
+	for (n = 0; n < mem_map->count; n++) {
+		/* Skip unmapped regions */
+		if ((mem_map->map[n].attr & TEE_MATTR_VALID_BLOCK) &&
+		    pa >= mem_map->map[n].pa &&
+		    pa <= (mem_map->map[n].pa - 1 + mem_map->map[n].size))
+			return mem_map->map + n;
 	}
+
 	return NULL;
 }
 
@@ -314,15 +368,8 @@ static bool dtb_get_sdp_region(void)
 			     fdt_get_name(fdt, tmp_node, NULL));
 	}
 
-	tmp_addr = fdt_reg_base_address(fdt, node);
-	if (tmp_addr == DT_INFO_INVALID_REG) {
-		EMSG("%s: Unable to get base addr from DT", tz_sdp_match);
-		return false;
-	}
-
-	tmp_size = fdt_reg_size(fdt, node);
-	if (tmp_size == DT_INFO_INVALID_REG_SIZE) {
-		EMSG("%s: Unable to get size of base addr from DT",
+	if (fdt_reg_info(fdt, node, &tmp_addr, &tmp_size)) {
+		EMSG("%s: Unable to get base addr or size from DT",
 		     tz_sdp_match);
 		return false;
 	}
@@ -431,7 +478,7 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start,
 {
 	struct core_mmu_phys_mem *m = start;
 	size_t num_elems = nelems;
-	struct tee_mmap_region *map = static_memory_map;
+	struct memory_map *mem_map = &static_memory_map;
 	const struct core_mmu_phys_mem __maybe_unused *pmem;
 	size_t n = 0;
 
@@ -464,10 +511,11 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start,
 		carve_out_phys_mem(&m, &num_elems, secure_only[n].paddr,
 				   secure_only[n].size);
 
-	for (map = static_memory_map; !core_mmap_is_end_of_table(map); map++) {
-		switch (map->type) {
+	for  (n = 0; n < mem_map->count; n++) {
+		switch (mem_map->map[n].type) {
 		case MEM_AREA_NSEC_SHM:
-			carve_out_phys_mem(&m, &num_elems, map->pa, map->size);
+			carve_out_phys_mem(&m, &num_elems, mem_map->map[n].pa,
+					   mem_map->map[n].size);
 			break;
 		case MEM_AREA_EXT_DT:
 		case MEM_AREA_MANIFEST_DT:
@@ -478,7 +526,8 @@ void core_mmu_set_discovered_nsec_ddr(struct core_mmu_phys_mem *start,
 		case MEM_AREA_PAGER_VASPACE:
 			break;
 		default:
-			check_phys_mem_is_outside(m, num_elems, map);
+			check_phys_mem_is_outside(m, num_elems,
+						  mem_map->map + n);
 		}
 	}
 
@@ -596,14 +645,14 @@ static bool pbuf_is_sdp_mem(paddr_t pbuf __unused, size_t len __unused)
 #endif /* CFG_SECURE_DATA_PATH */
 
 /* Check special memories comply with registered memories */
-static void verify_special_mem_areas(struct tee_mmap_region *mem_map,
+static void verify_special_mem_areas(struct memory_map *mem_map,
 				     const struct core_mmu_phys_mem *start,
 				     const struct core_mmu_phys_mem *end,
 				     const char *area_name __maybe_unused)
 {
-	const struct core_mmu_phys_mem *mem;
-	const struct core_mmu_phys_mem *mem2;
-	struct tee_mmap_region *mmap;
+	const struct core_mmu_phys_mem *mem = NULL;
+	const struct core_mmu_phys_mem *mem2 = NULL;
+	size_t n = 0;
 
 	if (start == end) {
 		DMSG("No %s memory area defined", area_name);
@@ -631,28 +680,62 @@ static void verify_special_mem_areas(struct tee_mmap_region *mem_map,
 	 * This is called before reserved VA space is loaded in mem_map.
 	 */
 	for (mem = start; mem < end; mem++) {
-		for (mmap = mem_map; mmap->type != MEM_AREA_END; mmap++) {
+		for (n = 0; n < mem_map->count; n++) {
 			if (core_is_buffer_intersect(mem->addr, mem->size,
-						     mmap->pa, mmap->size)) {
+						     mem_map->map[n].pa,
+						     mem_map->map[n].size)) {
 				MSG_MEM_INSTERSECT(mem->addr, mem->size,
-						   mmap->pa, mmap->size);
+						   mem_map->map[n].pa,
+						   mem_map->map[n].size);
 				panic("Special memory intersection");
 			}
 		}
 	}
 }
 
-static void add_phys_mem(struct tee_mmap_region *memory_map, size_t num_elems,
+static void merge_mmaps(struct tee_mmap_region *dst,
+			const struct tee_mmap_region *src)
+{
+	paddr_t end_pa = MAX(dst->pa + dst->size - 1, src->pa + src->size - 1);
+	paddr_t pa = MIN(dst->pa, src->pa);
+
+	DMSG("Merging %#"PRIxPA"..%#"PRIxPA" and %#"PRIxPA"..%#"PRIxPA,
+	     dst->pa, dst->pa + dst->size - 1, src->pa,
+	     src->pa + src->size - 1);
+	dst->pa = pa;
+	dst->size = end_pa - pa + 1;
+}
+
+static bool mmaps_are_mergeable(const struct tee_mmap_region *r1,
+				const struct tee_mmap_region *r2)
+{
+	if (r1->type != r2->type)
+		return false;
+
+	if (r1->pa == r2->pa)
+		return true;
+
+	if (r1->pa < r2->pa)
+		return r1->pa + r1->size >= r2->pa;
+	else
+		return r2->pa + r2->size >= r1->pa;
+}
+
+static void add_phys_mem(struct memory_map *mem_map,
 			 const char *mem_name __maybe_unused,
 			 enum teecore_memtypes mem_type,
-			 paddr_t mem_addr, paddr_size_t mem_size, size_t *last)
+			 paddr_t mem_addr, paddr_size_t mem_size)
 {
 	size_t n = 0;
-	paddr_t pa;
-	paddr_size_t size;
+	const struct tee_mmap_region m0 = {
+		.type = mem_type,
+		.pa = mem_addr,
+		.size = mem_size,
+	};
 
 	if (!mem_size)	/* Discard null size entries */
 		return;
+
 	/*
 	 * If some ranges of memory of the same type do overlap
 	 * each others they are coalesced into one entry. To help this
@@ -665,63 +748,61 @@ static void add_phys_mem(struct tee_mmap_region *memory_map, size_t num_elems,
 	 */
 	DMSG("%s type %s 0x%08" PRIxPA " size 0x%08" PRIxPASZ,
 	     mem_name, teecore_memtype_name(mem_type), mem_addr, mem_size);
-	while (true) {
-		if (n >= (num_elems - 1)) {
-			EMSG("Out of entries (%zu) in memory_map", num_elems);
-			panic();
-		}
-		if (n == *last)
-			break;
-		pa = memory_map[n].pa;
-		size = memory_map[n].size;
-		if (mem_type == memory_map[n].type &&
-		    ((pa <= (mem_addr + (mem_size - 1))) &&
-		    (mem_addr <= (pa + (size - 1))))) {
-			DMSG("Physical mem map overlaps 0x%" PRIxPA, mem_addr);
-			memory_map[n].pa = MIN(pa, mem_addr);
-			memory_map[n].size = MAX(size, mem_size) +
-					     (pa - memory_map[n].pa);
+	for  (n = 0; n < mem_map->count; n++) {
+		if (mmaps_are_mergeable(mem_map->map + n, &m0)) {
+			merge_mmaps(mem_map->map + n, &m0);
+			/*
+			 * The merged result might be mergeable with the
+			 * next or previous entry.
+			 */
+			if (n + 1 < mem_map->count &&
+			    mmaps_are_mergeable(mem_map->map + n,
+						mem_map->map + n + 1)) {
+				merge_mmaps(mem_map->map + n,
+					    mem_map->map + n + 1);
+				rem_array_elem(mem_map->map, mem_map->count,
+					       sizeof(*mem_map->map), n + 1);
+				mem_map->count--;
+			}
+			if (n > 0 && mmaps_are_mergeable(mem_map->map + n - 1,
+							 mem_map->map + n)) {
+				merge_mmaps(mem_map->map + n - 1,
+					    mem_map->map + n);
+				rem_array_elem(mem_map->map, mem_map->count,
+					       sizeof(*mem_map->map), n);
+				mem_map->count--;
+			}
 			return;
 		}
-		if (mem_type < memory_map[n].type ||
-		    (mem_type == memory_map[n].type && mem_addr < pa))
+		if (mem_type < mem_map->map[n].type ||
+		    (mem_type == mem_map->map[n].type &&
+		     mem_addr < mem_map->map[n].pa))
 			break; /* found the spot where to insert this memory */
-		n++;
 	}
 
-	memmove(memory_map + n + 1, memory_map + n,
-		sizeof(struct tee_mmap_region) * (*last - n));
-	(*last)++;
-	memset(memory_map + n, 0, sizeof(memory_map[0]));
-	memory_map[n].type = mem_type;
-	memory_map[n].pa = mem_addr;
-	memory_map[n].size = mem_size;
+	grow_mem_map(mem_map);
+	ins_array_elem(mem_map->map, mem_map->count, sizeof(*mem_map->map),
+		       n, &m0);
 }
 
-static void add_va_space(struct tee_mmap_region *memory_map, size_t num_elems,
-			 enum teecore_memtypes type, size_t size, size_t *last)
+static void add_va_space(struct memory_map *mem_map,
+			 enum teecore_memtypes type, size_t size)
 {
 	size_t n = 0;
 
 	DMSG("type %s size 0x%08zx", teecore_memtype_name(type), size);
-	while (true) {
-		if (n >= (num_elems - 1)) {
-			EMSG("Out of entries (%zu) in memory_map", num_elems);
-			panic();
-		}
-		if (n == *last)
+	for  (n = 0; n < mem_map->count; n++) {
+		if (type < mem_map->map[n].type)
 			break;
-		if (type < memory_map[n].type)
-			break;
-		n++;
 	}
 
-	memmove(memory_map + n + 1, memory_map + n,
-		sizeof(struct tee_mmap_region) * (*last - n));
-	(*last)++;
-	memset(memory_map + n, 0, sizeof(memory_map[0]));
-	memory_map[n].type = type;
-	memory_map[n].size = size;
+	grow_mem_map(mem_map);
+	ins_array_elem(mem_map->map, mem_map->count, sizeof(*mem_map->map),
+		       n, NULL);
+	mem_map->map[n] = (struct tee_mmap_region){
+		.type = type,
+		.size = size,
+	};
 }
 
 uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
@@ -751,8 +832,6 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged;
 	case MEM_AREA_TEE_COHERENT:
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRWX | noncache;
-	case MEM_AREA_TA_RAM:
-		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged;
 	case MEM_AREA_NSEC_SHM:
 	case MEM_AREA_NEX_NSEC_SHM:
 		return attr | TEE_MATTR_PRW | cached;
@@ -777,8 +856,9 @@ uint32_t core_mmu_type_to_attr(enum teecore_memtypes t)
 	case MEM_AREA_RAM_NSEC:
 		return attr | TEE_MATTR_PRW | cached;
 	case MEM_AREA_RAM_SEC:
-	case MEM_AREA_SEC_RAM_OVERALL:
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | cached;
+	case MEM_AREA_SEC_RAM_OVERALL:
+		return attr | TEE_MATTR_SECURE | TEE_MATTR_PRW | tagged;
 	case MEM_AREA_ROM_SEC:
 		return attr | TEE_MATTR_SECURE | TEE_MATTR_PR | cached;
 	case MEM_AREA_RES_VASPACE:
@@ -827,18 +907,17 @@ static int cmp_mmap_by_lower_va(const void *a, const void *b)
 	return CMP_TRILEAN(mm_a->va, mm_b->va);
 }
 
-static void dump_mmap_table(struct tee_mmap_region *memory_map)
+static void dump_mmap_table(struct memory_map *mem_map)
 {
-	struct tee_mmap_region *map;
+	size_t n = 0;
 
-	for (map = memory_map; !core_mmap_is_end_of_table(map); map++) {
-		vaddr_t __maybe_unused vstart;
+	for (n = 0; n < mem_map->count; n++) {
+		struct tee_mmap_region *map __maybe_unused = mem_map->map + n;
 
-		vstart = map->va + ((vaddr_t)map->pa & (map->region_size - 1));
 		DMSG("type %-12s va 0x%08" PRIxVA "..0x%08" PRIxVA
 		     " pa 0x%08" PRIxPA "..0x%08" PRIxPA " size 0x%08zx (%s)",
-		     teecore_memtype_name(map->type), vstart,
-		     vstart + map->size - 1, map->pa,
+		     teecore_memtype_name(map->type), map->va,
+		     map->va + map->size - 1, map->pa,
 		     (paddr_t)(map->pa + map->size - 1), map->size,
 		     map->region_size == SMALL_PAGE_SIZE ? "smallpg" : "pgdir");
 	}
@@ -908,8 +987,7 @@ static void dump_xlat_table(vaddr_t va __unused, int level __unused)
  * mapping for pager usage. This adds translation tables as needed for the
  * pager to operate.
  */
-static void add_pager_vaspace(struct tee_mmap_region *mmap, size_t num_elems,
-			      size_t *last)
+static void add_pager_vaspace(struct memory_map *mem_map)
 {
 	paddr_t begin = 0;
 	paddr_t end = 0;
@@ -917,33 +995,28 @@ static void add_pager_vaspace(struct tee_mmap_region *mmap, size_t num_elems,
 	size_t pos = 0;
 	size_t n = 0;
 
-	if (*last >= (num_elems - 1)) {
-		EMSG("Out of entries (%zu) in memory map", num_elems);
-		panic();
-	}
 
-	for (n = 0; !core_mmap_is_end_of_table(mmap + n); n++) {
-		if (map_is_tee_ram(mmap + n)) {
+	for (n = 0; n < mem_map->count; n++) {
+		if (map_is_tee_ram(mem_map->map + n)) {
 			if (!begin)
-				begin = mmap[n].pa;
+				begin = mem_map->map[n].pa;
 			pos = n + 1;
 		}
 	}
 
-	end = mmap[pos - 1].pa + mmap[pos - 1].size;
+	end = mem_map->map[pos - 1].pa + mem_map->map[pos - 1].size;
 	assert(end - begin < TEE_RAM_VA_SIZE);
 	size = TEE_RAM_VA_SIZE - (end - begin);
 
-	assert(pos <= *last);
-	memmove(mmap + pos + 1, mmap + pos,
-		sizeof(struct tee_mmap_region) * (*last - pos));
-	(*last)++;
-	memset(mmap + pos, 0, sizeof(mmap[0]));
-	mmap[pos].type = MEM_AREA_PAGER_VASPACE;
-	mmap[pos].va = 0;
-	mmap[pos].size = size;
-	mmap[pos].region_size = SMALL_PAGE_SIZE;
-	mmap[pos].attr = core_mmu_type_to_attr(MEM_AREA_PAGER_VASPACE);
+	grow_mem_map(mem_map);
+	ins_array_elem(mem_map->map, mem_map->count, sizeof(*mem_map->map),
+		       n, NULL);
+	mem_map->map[n] = (struct tee_mmap_region){
+		.type = MEM_AREA_PAGER_VASPACE,
+		.size = size,
+		.region_size = SMALL_PAGE_SIZE,
+		.attr = core_mmu_type_to_attr(MEM_AREA_PAGER_VASPACE),
+	};
 }
 
 static void check_sec_nsec_mem_config(void)
@@ -957,8 +1030,7 @@ static void check_sec_nsec_mem_config(void)
 	}
 }
 
-static void collect_device_mem_ranges(struct tee_mmap_region *memory_map,
-				      size_t num_elems, size_t *last)
+static void collect_device_mem_ranges(struct memory_map *mem_map)
 {
 	const char *compatible = "arm,ffa-manifest-device-regions";
 	void *fdt = get_manifest_dt();
@@ -968,6 +1040,8 @@ static void collect_device_mem_ranges(struct tee_mmap_region *memory_map,
 	int subnode = 0;
 	int node = 0;
 
+	assert(fdt);
+
 	node = fdt_node_offset_by_compatible(fdt, 0, compatible);
 	if (node < 0)
 		return;
@@ -994,26 +1068,33 @@ static void collect_device_mem_ranges(struct tee_mmap_region *memory_map,
 			continue;
 		}
 
-		add_phys_mem(memory_map, num_elems, name, MEM_AREA_IO_SEC,
-			     base, base + page_count * SMALL_PAGE_SIZE, last);
+		add_phys_mem(mem_map, name, MEM_AREA_IO_SEC,
+			     base, base + page_count * SMALL_PAGE_SIZE);
 	}
 }
 
-static size_t collect_mem_ranges(struct tee_mmap_region *memory_map,
-				 size_t num_elems)
+static void collect_mem_ranges(struct memory_map *mem_map)
 {
 	const struct core_mmu_phys_mem *mem = NULL;
 	vaddr_t ram_start = secure_only[0].paddr;
-	size_t last = 0;
-
+	size_t n = 0;
 
 #define ADD_PHYS_MEM(_type, _addr, _size) \
-		add_phys_mem(memory_map, num_elems, #_addr, (_type), \
-			     (_addr), (_size),  &last)
+		add_phys_mem(mem_map, #_addr, (_type), (_addr), (_size))
 
 	if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) {
-		ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, ram_start,
+		paddr_t next_pa = 0;
+
+		/*
+		 * Read-only and read-execute physical memory areas must
+		 * not be mapped by MEM_AREA_SEC_RAM_OVERALL, but all the
+		 * read/write should.
+		 */
+		ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, ram_start,
 			     VCORE_UNPG_RX_PA - ram_start);
+		assert(VCORE_UNPG_RX_PA >= ram_start);
+		tee_ram_initial_offs = VCORE_UNPG_RX_PA - ram_start;
+		DMSG("tee_ram_initial_offs %#zx", tee_ram_initial_offs);
 		ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RX, VCORE_UNPG_RX_PA,
 			     VCORE_UNPG_RX_SZ);
 		ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RO, VCORE_UNPG_RO_PA,
@@ -1022,37 +1103,63 @@ static size_t collect_mem_ranges(struct tee_mmap_region *memory_map,
 		if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
 			ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RO, VCORE_UNPG_RW_PA,
 				     VCORE_UNPG_RW_SZ);
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, VCORE_UNPG_RW_PA,
+				     VCORE_UNPG_RW_SZ);
+
 			ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RW, VCORE_NEX_RW_PA,
 				     VCORE_NEX_RW_SZ);
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, VCORE_NEX_RW_PA,
+				     VCORE_NEX_RW_SZ);
+
+			ADD_PHYS_MEM(MEM_AREA_NEX_RAM_RW, VCORE_FREE_PA,
+				     VCORE_FREE_SZ);
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, VCORE_FREE_PA,
+				     VCORE_FREE_SZ);
+			next_pa = VCORE_FREE_PA + VCORE_FREE_SZ;
 		} else {
 			ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RW, VCORE_UNPG_RW_PA,
 				     VCORE_UNPG_RW_SZ);
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, VCORE_UNPG_RW_PA,
+				     VCORE_UNPG_RW_SZ);
+
+			ADD_PHYS_MEM(MEM_AREA_TEE_RAM_RW, VCORE_FREE_PA,
+				     VCORE_FREE_SZ);
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, VCORE_FREE_PA,
+				     VCORE_FREE_SZ);
+			next_pa = VCORE_FREE_PA + VCORE_FREE_SZ;
 		}
 
 		if (IS_ENABLED(CFG_WITH_PAGER)) {
+			paddr_t pa = 0;
+			size_t sz = 0;
+
 			ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RX, VCORE_INIT_RX_PA,
 				     VCORE_INIT_RX_SZ);
 			ADD_PHYS_MEM(MEM_AREA_INIT_RAM_RO, VCORE_INIT_RO_PA,
 				     VCORE_INIT_RO_SZ);
+			/*
+			 * Core init mapping shall cover up to end of the
+			 * physical RAM.  This is required since the hash
+			 * table is appended to the binary data after the
+			 * firmware build sequence.
+			 */
+			pa = VCORE_INIT_RO_PA + VCORE_INIT_RO_SZ;
+			sz = TEE_RAM_START + TEE_RAM_PH_SIZE - pa;
+			ADD_PHYS_MEM(MEM_AREA_TEE_RAM, pa, sz);
+		} else {
+			ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, next_pa,
+				     secure_only[0].paddr +
+				     secure_only[0].size - next_pa);
 		}
 	} else {
 		ADD_PHYS_MEM(MEM_AREA_TEE_RAM, TEE_RAM_START, TEE_RAM_PH_SIZE);
+		ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, secure_only[n].paddr,
+			     secure_only[0].size);
 	}
 
-	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
-		ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, TRUSTED_DRAM_BASE,
-			     TRUSTED_DRAM_SIZE);
-	} else {
-		/*
-		 * Every guest will have own TA RAM if virtualization
-		 * support is enabled.
-		 */
-		paddr_t ta_base = 0;
-		size_t ta_size = 0;
-
-		core_mmu_get_ta_range(&ta_base, &ta_size);
-		ADD_PHYS_MEM(MEM_AREA_TA_RAM, ta_base, ta_size);
-	}
+	for (n = 1; n < ARRAY_SIZE(secure_only); n++)
+		ADD_PHYS_MEM(MEM_AREA_SEC_RAM_OVERALL, secure_only[n].paddr,
+			     secure_only[n].size);
 
 	if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS) &&
 	    IS_ENABLED(CFG_WITH_PAGER)) {
@@ -1067,51 +1174,42 @@ static size_t collect_mem_ranges(struct tee_mmap_region *memory_map,
 
 	/* Collect device memory info from SP manifest */
 	if (IS_ENABLED(CFG_CORE_SEL2_SPMC))
-		collect_device_mem_ranges(memory_map, num_elems, &last);
+		collect_device_mem_ranges(mem_map);
 
 	for (mem = phys_mem_map_begin; mem < phys_mem_map_end; mem++) {
 		/* Only unmapped virtual range may have a null phys addr */
 		assert(mem->addr || !core_mmu_type_to_attr(mem->type));
 
-		add_phys_mem(memory_map, num_elems, mem->name, mem->type,
-			     mem->addr, mem->size, &last);
+		add_phys_mem(mem_map, mem->name, mem->type,
+			     mem->addr, mem->size);
 	}
 
 	if (IS_ENABLED(CFG_SECURE_DATA_PATH))
-		verify_special_mem_areas(memory_map, phys_sdp_mem_begin,
+		verify_special_mem_areas(mem_map, phys_sdp_mem_begin,
 					 phys_sdp_mem_end, "SDP");
 
-	add_va_space(memory_map, num_elems, MEM_AREA_RES_VASPACE,
-		     CFG_RESERVED_VASPACE_SIZE, &last);
-
-	add_va_space(memory_map, num_elems, MEM_AREA_SHM_VASPACE,
-		     SHM_VASPACE_SIZE, &last);
-
-	memory_map[last].type = MEM_AREA_END;
-
-	return last;
+	add_va_space(mem_map, MEM_AREA_RES_VASPACE, CFG_RESERVED_VASPACE_SIZE);
+	add_va_space(mem_map, MEM_AREA_SHM_VASPACE, SHM_VASPACE_SIZE);
 }
 
-static void assign_mem_granularity(struct tee_mmap_region *memory_map)
+static void assign_mem_granularity(struct memory_map *mem_map)
 {
-	struct tee_mmap_region *map = NULL;
+	size_t n = 0;
 
 	/*
 	 * Assign region sizes, note that MEM_AREA_TEE_RAM always uses
 	 * SMALL_PAGE_SIZE.
 	 */
-	for (map = memory_map; !core_mmap_is_end_of_table(map); map++) {
-		paddr_t mask = map->pa | map->size;
+	for  (n = 0; n < mem_map->count; n++) {
+		paddr_t mask = mem_map->map[n].pa | mem_map->map[n].size;
 
-		if (!(mask & CORE_MMU_PGDIR_MASK))
-			map->region_size = CORE_MMU_PGDIR_SIZE;
-		else if (!(mask & SMALL_PAGE_MASK))
-			map->region_size = SMALL_PAGE_SIZE;
-		else
+		if (mask & SMALL_PAGE_MASK)
 			panic("Impossible memory alignment");
 
-		if (map_is_tee_ram(map))
-			map->region_size = SMALL_PAGE_SIZE;
+		if (map_is_tee_ram(mem_map->map + n))
+			mem_map->map[n].region_size = SMALL_PAGE_SIZE;
+		else
+			mem_map->map[n].region_size = CORE_MMU_PGDIR_SIZE;
 	}
 }
 
@@ -1129,13 +1227,13 @@ bool __weak core_mmu_prefer_tee_ram_at_top(paddr_t paddr)
 	return place_tee_ram_at_top(paddr);
 }
 
-static bool assign_mem_va_dir(vaddr_t tee_ram_va,
-			      struct tee_mmap_region *memory_map,
+static bool assign_mem_va_dir(vaddr_t tee_ram_va, struct memory_map *mem_map,
 			      bool tee_ram_at_top)
 {
 	struct tee_mmap_region *map = NULL;
 	vaddr_t va = 0;
 	bool va_is_secure = true;
+	size_t n = 0;
 
 	/*
 	 * tee_ram_va might equals 0 when CFG_CORE_ASLR=y.
@@ -1145,8 +1243,8 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 		return false;
 
 	/* Clear eventual previous assignments */
-	for (map = memory_map; !core_mmap_is_end_of_table(map); map++)
-		map->va = 0;
+	for (n = 0; n < mem_map->count; n++)
+		mem_map->map[n].va = 0;
 
 	/*
 	 * TEE RAM regions are always aligned with region_size.
@@ -1155,8 +1253,9 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 	 * since it handles virtual memory which covers the part of the ELF
 	 * that cannot fit directly into memory.
 	 */
-	va = tee_ram_va;
-	for (map = memory_map; !core_mmap_is_end_of_table(map); map++) {
+	va = tee_ram_va + tee_ram_initial_offs;
+	for (n = 0; n < mem_map->count; n++) {
+		map = mem_map->map + n;
 		if (map_is_tee_ram(map) ||
 		    map->type == MEM_AREA_PAGER_VASPACE) {
 			assert(!(va & (map->region_size - 1)));
@@ -1175,7 +1274,8 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 		 * ram region.
 		 */
 		va = tee_ram_va;
-		for (map = memory_map; !core_mmap_is_end_of_table(map); map++) {
+		for (n = 0; n < mem_map->count; n++) {
+			map = mem_map->map + n;
 			map->attr = core_mmu_type_to_attr(map->type);
 			if (map->va)
 				continue;
@@ -1188,7 +1288,7 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 
 			if (SUB_OVERFLOW(va, map->size, &va))
 				return false;
-			va = ROUNDDOWN(va, map->region_size);
+			va = ROUNDDOWN2(va, map->region_size);
 			/*
 			 * Make sure that va is aligned with pa for
 			 * efficient pgdir mapping. Basically pa &
@@ -1206,7 +1306,8 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 		 * Map non-tee ram regions at addresses higher than the tee
 		 * ram region.
 		 */
-		for (map = memory_map; !core_mmap_is_end_of_table(map); map++) {
+		for (n = 0; n < mem_map->count; n++) {
+			map = mem_map->map + n;
 			map->attr = core_mmu_type_to_attr(map->type);
 			if (map->va)
 				continue;
@@ -1219,7 +1320,7 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 					return false;
 			}
 
-			if (ROUNDUP_OVERFLOW(va, map->region_size, &va))
+			if (ROUNDUP2_OVERFLOW(va, map->region_size, &va))
 				return false;
 			/*
 			 * Make sure that va is aligned with pa for
@@ -1245,8 +1346,7 @@ static bool assign_mem_va_dir(vaddr_t tee_ram_va,
 	return true;
 }
 
-static bool assign_mem_va(vaddr_t tee_ram_va,
-			  struct tee_mmap_region *memory_map)
+static bool assign_mem_va(vaddr_t tee_ram_va, struct memory_map *mem_map)
 {
 	bool tee_ram_at_top = place_tee_ram_at_top(tee_ram_va);
 
@@ -1274,11 +1374,11 @@ static bool assign_mem_va(vaddr_t tee_ram_va,
 
 		/* Try whole mapping covered by a single base xlat entry */
 		if (prefered_dir != tee_ram_at_top &&
-		    assign_mem_va_dir(tee_ram_va, memory_map, prefered_dir))
+		    assign_mem_va_dir(tee_ram_va, mem_map, prefered_dir))
 			return true;
 	}
 
-	return assign_mem_va_dir(tee_ram_va, memory_map, tee_ram_at_top);
+	return assign_mem_va_dir(tee_ram_va, mem_map, tee_ram_at_top);
 }
 
 static int cmp_init_mem_map(const void *a, const void *b)
@@ -1301,25 +1401,22 @@ static int cmp_init_mem_map(const void *a, const void *b)
 	return rc;
 }
 
-static bool mem_map_add_id_map(struct tee_mmap_region *memory_map,
-			       size_t num_elems, size_t *last,
+static bool mem_map_add_id_map(struct memory_map *mem_map,
 			       vaddr_t id_map_start, vaddr_t id_map_end)
 {
-	struct tee_mmap_region *map = NULL;
 	vaddr_t start = ROUNDDOWN(id_map_start, SMALL_PAGE_SIZE);
 	vaddr_t end = ROUNDUP(id_map_end, SMALL_PAGE_SIZE);
 	size_t len = end - start;
+	size_t n = 0;
 
-	if (*last >= num_elems - 1) {
-		EMSG("Out of entries (%zu) in memory map", num_elems);
-		panic();
-	}
 
-	for (map = memory_map; !core_mmap_is_end_of_table(map); map++)
-		if (core_is_buffer_intersect(map->va, map->size, start, len))
+	for (n = 0; n < mem_map->count; n++)
+		if (core_is_buffer_intersect(mem_map->map[n].va,
+					     mem_map->map[n].size, start, len))
 			return false;
 
-	*map = (struct tee_mmap_region){
+	grow_mem_map(mem_map);
+	mem_map->map[mem_map->count - 1] = (struct tee_mmap_region){
 		.type = MEM_AREA_IDENTITY_MAP_RX,
 		/*
 		 * Could use CORE_MMU_PGDIR_SIZE to potentially save a
@@ -1333,13 +1430,12 @@ static bool mem_map_add_id_map(struct tee_mmap_region *memory_map,
 		.attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX),
 	};
 
-	(*last)++;
-
 	return true;
 }
 
-static unsigned long init_mem_map(struct tee_mmap_region *memory_map,
-				  size_t num_elems, unsigned long seed)
+static struct memory_map *init_mem_map(struct memory_map *mem_map,
+				       unsigned long seed,
+				       unsigned long *ret_offs)
 {
 	/*
 	 * @id_map_start and @id_map_end describes a physical memory range
@@ -1350,20 +1446,19 @@ static unsigned long init_mem_map(struct tee_mmap_region *memory_map,
 	vaddr_t id_map_end = (vaddr_t)__identity_map_init_end;
 	vaddr_t start_addr = secure_only[0].paddr;
 	unsigned long offs = 0;
-	size_t last = 0;
 
-	last = collect_mem_ranges(memory_map, num_elems);
-	assign_mem_granularity(memory_map);
+	collect_mem_ranges(mem_map);
+	assign_mem_granularity(mem_map);
 
 	/*
 	 * To ease mapping and lower use of xlat tables, sort mapping
 	 * description moving small-page regions after the pgdir regions.
 	 */
-	qsort(memory_map, last, sizeof(struct tee_mmap_region),
+	qsort(mem_map->map, mem_map->count, sizeof(struct tee_mmap_region),
 	      cmp_init_mem_map);
 
 	if (IS_ENABLED(CFG_WITH_PAGER))
-		add_pager_vaspace(memory_map, num_elems, &last);
+		add_pager_vaspace(mem_map);
 
 	if (IS_ENABLED(CFG_CORE_ASLR) && seed) {
 		vaddr_t base_addr = start_addr + seed;
@@ -1377,9 +1472,9 @@ static unsigned long init_mem_map(struct tee_mmap_region *memory_map,
 			if (n)
 				ba = base_addr ^ BIT64(va_width - n);
 			ba &= va_mask;
-			if (assign_mem_va(ba, memory_map) &&
-			    mem_map_add_id_map(memory_map, num_elems, &last,
-					       id_map_start, id_map_end)) {
+			if (assign_mem_va(ba, mem_map) &&
+			    mem_map_add_id_map(mem_map, id_map_start,
+					       id_map_end)) {
 				offs = ba - start_addr;
 				DMSG("Mapping core at %#"PRIxVA" offs %#lx",
 				     ba, offs);
@@ -1391,23 +1486,26 @@ static unsigned long init_mem_map(struct tee_mmap_region *memory_map,
 		EMSG("Failed to map core with seed %#lx", seed);
 	}
 
-	if (!assign_mem_va(start_addr, memory_map))
+	if (!assign_mem_va(start_addr, mem_map))
 		panic();
 
 out:
-	qsort(memory_map, last, sizeof(struct tee_mmap_region),
+	qsort(mem_map->map, mem_map->count, sizeof(struct tee_mmap_region),
 	      cmp_mmap_by_lower_va);
 
-	dump_mmap_table(memory_map);
+	dump_mmap_table(mem_map);
 
-	return offs;
+	*ret_offs = offs;
+	return mem_map;
 }
 
-static void check_mem_map(struct tee_mmap_region *map)
+static void check_mem_map(struct memory_map *mem_map)
 {
 	struct tee_mmap_region *m = NULL;
+	size_t n = 0;
 
-	for (m = map; !core_mmap_is_end_of_table(m); m++) {
+	for (n = 0; n < mem_map->count; n++) {
+		m = mem_map->map + n;
 		switch (m->type) {
 		case MEM_AREA_TEE_RAM:
 		case MEM_AREA_TEE_RAM_RX:
@@ -1421,15 +1519,14 @@ static void check_mem_map(struct tee_mmap_region *map)
 			if (!pbuf_is_inside(secure_only, m->pa, m->size))
 				panic("TEE_RAM can't fit in secure_only");
 			break;
-		case MEM_AREA_TA_RAM:
+		case MEM_AREA_SEC_RAM_OVERALL:
 			if (!pbuf_is_inside(secure_only, m->pa, m->size))
-				panic("TA_RAM can't fit in secure_only");
+				panic("SEC_RAM_OVERALL can't fit in secure_only");
 			break;
 		case MEM_AREA_NSEC_SHM:
 			if (!pbuf_is_inside(nsec_shared, m->pa, m->size))
 				panic("NS_SHM can't fit in nsec_shared");
 			break;
-		case MEM_AREA_SEC_RAM_OVERALL:
 		case MEM_AREA_TEE_COHERENT:
 		case MEM_AREA_TEE_ASAN:
 		case MEM_AREA_IO_SEC:
@@ -1439,6 +1536,7 @@ static void check_mem_map(struct tee_mmap_region *map)
 		case MEM_AREA_TRANSFER_LIST:
 		case MEM_AREA_RAM_SEC:
 		case MEM_AREA_RAM_NSEC:
+		case MEM_AREA_ROM_SEC:
 		case MEM_AREA_RES_VASPACE:
 		case MEM_AREA_SHM_VASPACE:
 		case MEM_AREA_PAGER_VASPACE:
@@ -1450,20 +1548,6 @@ static void check_mem_map(struct tee_mmap_region *map)
 	}
 }
 
-static struct tee_mmap_region *get_tmp_mmap(void)
-{
-	struct tee_mmap_region *tmp_mmap = (void *)__heap1_start;
-
-#ifdef CFG_WITH_PAGER
-	if (__heap1_end - __heap1_start < (ptrdiff_t)sizeof(static_memory_map))
-		tmp_mmap = (void *)__heap2_start;
-#endif
-
-	memset(tmp_mmap, 0, sizeof(static_memory_map));
-
-	return tmp_mmap;
-}
-
 /*
  * core_init_mmu_map() - init tee core default memory mapping
  *
@@ -1485,7 +1569,8 @@ void __weak core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg)
 				  SMALL_PAGE_SIZE);
 #endif
 	vaddr_t len = ROUNDUP((vaddr_t)__nozi_end, SMALL_PAGE_SIZE) - start;
-	struct tee_mmap_region *tmp_mmap = get_tmp_mmap();
+	struct tee_mmap_region tmp_mmap_region = { };
+	struct memory_map mem_map = { };
 	unsigned long offs = 0;
 
 	if (IS_ENABLED(CFG_CORE_PHYS_RELOCATABLE) &&
@@ -1494,11 +1579,26 @@ void __weak core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg)
 
 	check_sec_nsec_mem_config();
 
+	if (IS_ENABLED(CFG_BOOT_MEM)) {
+		mem_map.alloc_count = CFG_MMAP_REGIONS;
+		mem_map.map = boot_mem_alloc_tmp(mem_map.alloc_count *
+							sizeof(*mem_map.map),
+						 alignof(*mem_map.map));
+		memory_map_realloc_func = boot_mem_realloc_memory_map;
+	} else {
+		mem_map = static_memory_map;
+	}
+
+	static_memory_map = (struct memory_map){
+		.map = &tmp_mmap_region,
+		.alloc_count = 1,
+		.count = 1,
+	};
 	/*
 	 * Add a entry covering the translation tables which will be
 	 * involved in some virt_to_phys() and phys_to_virt() conversions.
 	 */
-	static_memory_map[0] = (struct tee_mmap_region){
+	static_memory_map.map[0] = (struct tee_mmap_region){
 		.type = MEM_AREA_TEE_RAM,
 		.region_size = SMALL_PAGE_SIZE,
 		.pa = start,
@@ -1507,15 +1607,33 @@ void __weak core_init_mmu_map(unsigned long seed, struct core_mmu_config *cfg)
 		.attr = core_mmu_type_to_attr(MEM_AREA_IDENTITY_MAP_RX),
 	};
 
-	COMPILE_TIME_ASSERT(CFG_MMAP_REGIONS >= 13);
-	offs = init_mem_map(tmp_mmap, ARRAY_SIZE(static_memory_map), seed);
+	init_mem_map(&mem_map, seed, &offs);
 
-	check_mem_map(tmp_mmap);
-	core_init_mmu(tmp_mmap);
+	check_mem_map(&mem_map);
+	core_init_mmu(&mem_map);
 	dump_xlat_table(0x0, CORE_MMU_BASE_TABLE_LEVEL);
 	core_init_mmu_regs(cfg);
 	cfg->map_offset = offs;
-	memcpy(static_memory_map, tmp_mmap, sizeof(static_memory_map));
+	static_memory_map = mem_map;
+	boot_mem_add_reloc(&static_memory_map.map);
+}
+
+void core_mmu_save_mem_map(void)
+{
+	if (IS_ENABLED(CFG_BOOT_MEM)) {
+		size_t alloc_count = static_memory_map.count + 5;
+		size_t elem_sz = sizeof(*static_memory_map.map);
+		void *p = NULL;
+
+		p = nex_calloc(alloc_count, elem_sz);
+		if (!p)
+			panic();
+		memcpy(p, static_memory_map.map,
+		       static_memory_map.count * elem_sz);
+		static_memory_map.map = p;
+		static_memory_map.alloc_count = alloc_count;
+		memory_map_realloc_func = heap_realloc_memory_map;
+	}
 }
 
 bool core_mmu_mattr_is_ok(uint32_t mattr)
@@ -1544,8 +1662,6 @@ bool core_mmu_mattr_is_ok(uint32_t mattr)
  */
 bool core_pbuf_is(uint32_t attr, paddr_t pbuf, size_t len)
 {
-	paddr_t ta_base = 0;
-	size_t ta_size = 0;
 	struct tee_mmap_region *map;
 
 	/* Empty buffers complies with anything */
@@ -1561,9 +1677,6 @@ bool core_pbuf_is(uint32_t attr, paddr_t pbuf, size_t len)
 	case CORE_MEM_TEE_RAM:
 		return core_is_buffer_inside(pbuf, len, TEE_RAM_START,
 							TEE_RAM_PH_SIZE);
-	case CORE_MEM_TA_RAM:
-		core_mmu_get_ta_range(&ta_base, &ta_size);
-		return core_is_buffer_inside(pbuf, len, ta_base, ta_size);
 #ifdef CFG_CORE_RESERVED_SHM
 	case CORE_MEM_NSEC_SHM:
 		return core_is_buffer_inside(pbuf, len, TEE_SHMEM_START,
@@ -1778,7 +1891,7 @@ static void set_pg_region(struct core_mmu_table_info *dir_info,
 
 static bool can_map_at_level(paddr_t paddr, vaddr_t vaddr,
 			     size_t size_left, paddr_t block_size,
-			     struct tee_mmap_region *mm __maybe_unused)
+			     struct tee_mmap_region *mm)
 {
 	/* VA and PA are aligned to block size at current level */
 	if ((vaddr | paddr) & (block_size - 1))
@@ -1788,12 +1901,20 @@ static bool can_map_at_level(paddr_t paddr, vaddr_t vaddr,
 	if (size_left < block_size)
 		return false;
 
+	/*
+	 * The required block size of the region is compatible with the
+	 * block size of the current level.
+	 */
+	if (mm->region_size < block_size)
+		return false;
+
 #ifdef CFG_WITH_PAGER
 	/*
-	 * If pager is enabled, we need to map tee ram
+	 * If pager is enabled, we need to map TEE RAM and the whole pager
 	 * regions with small pages only
 	 */
-	if (map_is_tee_ram(mm) && block_size != SMALL_PAGE_SIZE)
+	if ((map_is_tee_ram(mm) || mm->type == MEM_AREA_PAGER_VASPACE) &&
+	    block_size != SMALL_PAGE_SIZE)
 		return false;
 #endif
 
@@ -2004,6 +2125,12 @@ TEE_Result core_mmu_map_contiguous_pages(vaddr_t vstart, paddr_t pstart,
 	return TEE_SUCCESS;
 }
 
+static bool mem_range_is_in_vcore_free(vaddr_t vstart, size_t num_pages)
+{
+	return core_is_buffer_inside(vstart, num_pages * SMALL_PAGE_SIZE,
+				     VCORE_FREE_PA, VCORE_FREE_SZ);
+}
+
 void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages)
 {
 	struct core_mmu_table_info tbl_info;
@@ -2018,7 +2145,8 @@ void core_mmu_unmap_pages(vaddr_t vstart, size_t num_pages)
 	if (!mm || !va_is_in_map(mm, vstart + num_pages * SMALL_PAGE_SIZE - 1))
 		panic("VA does not belong to any known mm region");
 
-	if (!core_mmu_is_dynamic_vaspace(mm))
+	if (!core_mmu_is_dynamic_vaspace(mm) &&
+	    !mem_range_is_in_vcore_free(vstart, num_pages))
 		panic("Trying to unmap static region");
 
 	for (i = 0; i < num_pages; i++, vstart += SMALL_PAGE_SIZE) {
@@ -2090,14 +2218,14 @@ TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr,
 		return TEE_ERROR_GENERIC;
 	granule = BIT(tbl_info.shift);
 
-	if (map < static_memory_map ||
-	    map >= static_memory_map + ARRAY_SIZE(static_memory_map))
+	if (map < static_memory_map.map ||
+	    map >= static_memory_map.map + static_memory_map.count)
 		return TEE_ERROR_GENERIC;
-	i = map - static_memory_map;
+	i = map - static_memory_map.map;
 
 	/* Check that we have a full match */
-	p = ROUNDDOWN(pa, granule);
-	l = ROUNDUP(len + pa - p, granule);
+	p = ROUNDDOWN2(pa, granule);
+	l = ROUNDUP2(len + pa - p, granule);
 	if (map->pa != p || map->size != l)
 		return TEE_ERROR_GENERIC;
 
@@ -2111,12 +2239,9 @@ TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr,
 	}
 
 	/* Remove the entry. */
-	memmove(map, map + 1,
-		(ARRAY_SIZE(static_memory_map) - i - 1) * sizeof(*map));
-
-	/* Clear the last new entry in case it was used */
-	memset(static_memory_map + ARRAY_SIZE(static_memory_map) - 1,
-	       0, sizeof(*map));
+	rem_array_elem(static_memory_map.map, static_memory_map.count,
+		       sizeof(*static_memory_map.map), i);
+	static_memory_map.count--;
 
 	return TEE_SUCCESS;
 }
@@ -2124,20 +2249,21 @@ TEE_Result core_mmu_remove_mapping(enum teecore_memtypes type, void *addr,
 struct tee_mmap_region *
 core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len)
 {
-	struct tee_mmap_region *map = NULL;
+	struct memory_map *mem_map = get_memory_map();
 	struct tee_mmap_region *map_found = NULL;
+	size_t n = 0;
 
 	if (!len)
 		return NULL;
 
-	for (map = get_memory_map(); !core_mmap_is_end_of_table(map); map++) {
-		if (map->type != type)
+	for (n = 0; n < mem_map->count; n++) {
+		if (mem_map->map[n].type != type)
 			continue;
 
 		if (map_found)
 			return NULL;
 
-		map_found = map;
+		map_found = mem_map->map + n;
 	}
 
 	if (!map_found || map_found->size < len)
@@ -2148,12 +2274,12 @@ core_mmu_find_mapping_exclusive(enum teecore_memtypes type, size_t len)
 
 void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len)
 {
-	struct core_mmu_table_info tbl_info;
-	struct tee_mmap_region *map;
-	size_t n;
-	size_t granule;
-	paddr_t p;
-	size_t l;
+	struct memory_map *mem_map = &static_memory_map;
+	struct core_mmu_table_info tbl_info = { };
+	struct tee_mmap_region *map = NULL;
+	size_t granule = 0;
+	paddr_t p = 0;
+	size_t l = 0;
 
 	if (!len)
 		return NULL;
@@ -2175,8 +2301,8 @@ void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len)
 		return NULL;
 
 	granule = BIT64(tbl_info.shift);
-	p = ROUNDDOWN(addr, granule);
-	l = ROUNDUP(len + addr - p, granule);
+	p = ROUNDDOWN2(addr, granule);
+	l = ROUNDUP2(len + addr - p, granule);
 
 	/* Ban overflowing virtual addresses */
 	if (map->size < l)
@@ -2190,30 +2316,21 @@ void *core_mmu_add_mapping(enum teecore_memtypes type, paddr_t addr, size_t len)
 	if (core_mmu_va2idx(&tbl_info, map->va + len) >= tbl_info.num_entries)
 		return NULL;
 
-	/* Find end of the memory map */
-	n = 0;
-	while (!core_mmap_is_end_of_table(static_memory_map + n))
-		n++;
+	if (static_memory_map.count >= static_memory_map.alloc_count)
+		return NULL;
 
-	if (n < (ARRAY_SIZE(static_memory_map) - 1)) {
-		/* There's room for another entry */
-		static_memory_map[n].va = map->va;
-		static_memory_map[n].size = l;
-		static_memory_map[n + 1].type = MEM_AREA_END;
-		map->va += l;
-		map->size -= l;
-		map = static_memory_map + n;
-	} else {
-		/*
-		 * There isn't room for another entry, steal the reserved
-		 * entry as it's not useful for anything else any longer.
-		 */
-		map->size = l;
-	}
-	map->type = type;
-	map->region_size = granule;
-	map->attr = core_mmu_type_to_attr(type);
-	map->pa = p;
+	mem_map->map[mem_map->count] = (struct tee_mmap_region){
+		.va = map->va,
+		.size = l,
+		.type = type,
+		.region_size = granule,
+		.attr = core_mmu_type_to_attr(type),
+		.pa = p,
+	};
+	map->va += l;
+	map->size -= l;
+	map = mem_map->map + mem_map->count;
+	mem_map->count++;
 
 	set_region(&tbl_info, map);
 
@@ -2325,11 +2442,18 @@ paddr_t virt_to_phys(void *va)
 
 	if (!arch_va2pa_helper(va, &pa))
 		pa = 0;
-	check_pa_matches_va(va, pa);
+	check_pa_matches_va(memtag_strip_tag(va), pa);
 	return pa;
 }
 
-#if defined(CFG_TEE_CORE_DEBUG)
+/*
+ * Don't use check_va_matches_pa() for RISC-V, as its callee
+ * arch_va2pa_helper() will call it eventually, this creates
+ * indirect recursion and can lead to a stack overflow.
+ * Moreover, if arch_va2pa_helper() returns true, it implies
+ * the va2pa mapping is matched, no need to check it again.
+ */
+#if defined(CFG_TEE_CORE_DEBUG) && !defined(__riscv)
 static void check_va_matches_pa(paddr_t pa, void *va)
 {
 	paddr_t p = 0;
@@ -2449,32 +2573,22 @@ vaddr_t core_mmu_get_va(paddr_t pa, enum teecore_memtypes type, size_t len)
 }
 
 #ifdef CFG_WITH_PAGER
-bool is_unpaged(void *va)
+bool is_unpaged(const void *va)
 {
 	vaddr_t v = (vaddr_t)va;
 
 	return v >= VCORE_START_VA && v < get_linear_map_end_va();
 }
-#else
-bool is_unpaged(void *va __unused)
-{
-	return true;
-}
 #endif
 
-void core_mmu_init_virtualization(void)
+#ifdef CFG_NS_VIRTUALIZATION
+bool is_nexus(const void *va)
 {
-	paddr_t b1 = 0;
-	paddr_size_t s1 = 0;
+	vaddr_t v = (vaddr_t)va;
 
-	static_assert(ARRAY_SIZE(secure_only) <= 2);
-	if (ARRAY_SIZE(secure_only) == 2) {
-		b1 = secure_only[1].paddr;
-		s1 = secure_only[1].size;
-	}
-	virt_init_memory(static_memory_map, secure_only[0].paddr,
-			 secure_only[0].size, b1, s1);
+	return v >= VCORE_START_VA && v < VCORE_NEX_RW_PA + VCORE_NEX_RW_SZ;
 }
+#endif
 
 vaddr_t io_pa_or_va(struct io_pa_va *p, size_t len)
 {
@@ -2545,38 +2659,72 @@ static TEE_Result teecore_init_pub_ram(void)
 early_init(teecore_init_pub_ram);
 #endif /*CFG_CORE_RESERVED_SHM*/
 
-void core_mmu_init_ta_ram(void)
+static void __maybe_unused carve_out_core_mem(paddr_t pa, paddr_t end_pa)
 {
-	vaddr_t s = 0;
-	vaddr_t e = 0;
-	paddr_t ps = 0;
-	size_t size = 0;
+	tee_mm_entry_t *mm __maybe_unused = NULL;
 
-	/*
-	 * Get virtual addr/size of RAM where TA are loaded/executedNSec
-	 * shared mem allocated from teecore.
-	 */
-	if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
-		virt_get_ta_ram(&s, &e);
-	else
-		core_mmu_get_mem_by_type(MEM_AREA_TA_RAM, &s, &e);
+	DMSG("%#"PRIxPA" .. %#"PRIxPA, pa, end_pa);
+	mm = phys_mem_alloc2(pa, end_pa - pa);
+	assert(mm);
+}
 
-	ps = virt_to_phys((void *)s);
-	size = e - s;
+void core_mmu_init_phys_mem(void)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		paddr_t b1 = 0;
+		paddr_size_t s1 = 0;
 
-	if (!ps || (ps & CORE_MMU_USER_CODE_MASK) ||
-	    !size || (size & CORE_MMU_USER_CODE_MASK))
-		panic("invalid TA RAM");
+		static_assert(ARRAY_SIZE(secure_only) <= 2);
 
-	/* extra check: we could rely on core_mmu_get_mem_by_type() */
-	if (!tee_pbuf_is_sec(ps, size))
-		panic("TA RAM is not secure");
+		if (ARRAY_SIZE(secure_only) == 2) {
+			b1 = secure_only[1].paddr;
+			s1 = secure_only[1].size;
+		}
+		virt_init_memory(&static_memory_map, secure_only[0].paddr,
+				 secure_only[0].size, b1, s1);
+	} else {
+#ifdef CFG_WITH_PAGER
+		/*
+		 * The pager uses all core memory so there's no need to add
+		 * it to the pool.
+		 */
+		static_assert(ARRAY_SIZE(secure_only) == 2);
+		phys_mem_init(0, 0, secure_only[1].paddr, secure_only[1].size);
+#else /*!CFG_WITH_PAGER*/
+		size_t align = BIT(CORE_MMU_USER_CODE_SHIFT);
+		paddr_t end_pa = 0;
+		size_t size = 0;
+		paddr_t ps = 0;
+		paddr_t pa = 0;
+
+		static_assert(ARRAY_SIZE(secure_only) <= 2);
+		if (ARRAY_SIZE(secure_only) == 2) {
+			ps = secure_only[1].paddr;
+			size = secure_only[1].size;
+		}
+		phys_mem_init(secure_only[0].paddr, secure_only[0].size,
+			      ps, size);
 
-	if (!tee_mm_is_empty(&tee_mm_sec_ddr))
-		panic("TA RAM pool is not empty");
+		/*
+		 * The VCORE macros are relocatable so we need to translate
+		 * the addresses now that the MMU is enabled.
+		 */
+		end_pa = vaddr_to_phys(ROUNDUP2(VCORE_FREE_END_PA,
+						align) - 1) + 1;
+		/* Carve out the part used by OP-TEE core */
+		carve_out_core_mem(vaddr_to_phys(VCORE_UNPG_RX_PA), end_pa);
+		if (IS_ENABLED(CFG_CORE_SANITIZE_KADDRESS)) {
+			pa = vaddr_to_phys(ROUNDUP2(ASAN_MAP_PA, align));
+			carve_out_core_mem(pa, pa + ASAN_MAP_SZ);
+		}
 
-	/* remove previous config and init TA ddr memory pool */
-	tee_mm_final(&tee_mm_sec_ddr);
-	tee_mm_init(&tee_mm_sec_ddr, ps, size, CORE_MMU_USER_CODE_SHIFT,
-		    TEE_MM_POOL_NO_FLAGS);
+		/* Carve out test SDP memory */
+#ifdef TEE_SDP_TEST_MEM_BASE
+		if (TEE_SDP_TEST_MEM_SIZE) {
+			pa = vaddr_to_phys(TEE_SDP_TEST_MEM_BASE);
+			carve_out_core_mem(pa, pa + TEE_SDP_TEST_MEM_SIZE);
+		}
+#endif
+#endif /*!CFG_WITH_PAGER*/
+	}
 }
diff --git a/core/mm/fobj.c b/core/mm/fobj.c
index e1397cccc6c2bff022d351494603581680ccf6c8..c70667036084fd4a7a85cdd60bcec42da9efa51b 100644
--- a/core/mm/fobj.c
+++ b/core/mm/fobj.c
@@ -13,6 +13,7 @@
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <mm/fobj.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_mm.h>
 #include <stdlib.h>
 #include <string.h>
@@ -152,10 +153,11 @@ static struct fobj *rwp_paged_iv_alloc(unsigned int num_pages)
 
 	if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size))
 		goto err;
-	mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
+	mm = nex_phys_mem_ta_alloc(size);
 	if (!mm)
 		goto err;
-	rwp->idx = (tee_mm_get_smem(mm) - tee_mm_sec_ddr.lo) / SMALL_PAGE_SIZE;
+	rwp->idx = (tee_mm_get_smem(mm) - nex_phys_mem_get_ta_base()) /
+		   SMALL_PAGE_SIZE;
 
 	memset(idx_to_state_padded(rwp->idx), 0,
 	       num_pages * sizeof(struct rwp_state_padded));
@@ -216,8 +218,8 @@ DECLARE_KEEP_PAGER(rwp_paged_iv_save_page);
 static void rwp_paged_iv_free(struct fobj *fobj)
 {
 	struct fobj_rwp_paged_iv *rwp = to_rwp_paged_iv(fobj);
-	paddr_t pa = rwp->idx * SMALL_PAGE_SIZE + tee_mm_sec_ddr.lo;
-	tee_mm_entry_t *mm = tee_mm_find(&tee_mm_sec_ddr, pa);
+	paddr_t pa = rwp->idx * SMALL_PAGE_SIZE + nex_phys_mem_get_ta_base();
+	tee_mm_entry_t *mm = nex_phys_mem_mm_find(pa);
 
 	assert(mm);
 
@@ -265,10 +267,11 @@ static struct fobj *rwp_unpaged_iv_alloc(unsigned int num_pages)
 
 	if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size))
 		goto err_free_state;
-	mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
+	mm = nex_phys_mem_ta_alloc(size);
 	if (!mm)
 		goto err_free_state;
-	rwp->store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM, size);
+	rwp->store = phys_to_virt(tee_mm_get_smem(mm),
+				  MEM_AREA_SEC_RAM_OVERALL, size);
 	assert(rwp->store);
 
 	fobj_init(&rwp->fobj, &ops_rwp_unpaged_iv, num_pages);
@@ -333,7 +336,7 @@ static void rwp_unpaged_iv_free(struct fobj *fobj)
 		panic();
 
 	rwp = to_rwp_unpaged_iv(fobj);
-	mm = tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rwp->store));
+	mm = nex_phys_mem_mm_find(virt_to_phys(rwp->store));
 
 	assert(mm);
 
@@ -356,6 +359,7 @@ __weak __relrodata_unpaged("ops_rwp_unpaged_iv") = {
 
 static TEE_Result rwp_init(void)
 {
+	paddr_size_t ta_size = nex_phys_mem_get_ta_size();
 	uint8_t key[RWP_AE_KEY_BITS / 8] = { 0 };
 	struct fobj *fobj = NULL;
 	size_t num_pool_pages = 0;
@@ -371,11 +375,11 @@ static TEE_Result rwp_init(void)
 	if (!IS_ENABLED(CFG_CORE_PAGE_TAG_AND_IV))
 		return TEE_SUCCESS;
 
-	assert(tee_mm_sec_ddr.size && !(tee_mm_sec_ddr.size & SMALL_PAGE_SIZE));
+	assert(ta_size && !(ta_size & SMALL_PAGE_SIZE));
 
-	num_pool_pages = tee_mm_sec_ddr.size / SMALL_PAGE_SIZE;
-	num_fobj_pages = ROUNDUP(num_pool_pages * sizeof(*rwp_state_base),
-				 SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
+	num_pool_pages = ta_size / SMALL_PAGE_SIZE;
+	num_fobj_pages = ROUNDUP_DIV(num_pool_pages * sizeof(*rwp_state_base),
+				     SMALL_PAGE_SIZE);
 
 	/*
 	 * Each page in the pool needs a struct rwp_state.
@@ -391,8 +395,8 @@ static TEE_Result rwp_init(void)
 	rwp_state_base = (void *)tee_pager_init_iv_region(fobj);
 	assert(rwp_state_base);
 
-	rwp_store_base = phys_to_virt(tee_mm_sec_ddr.lo, MEM_AREA_TA_RAM,
-				      tee_mm_sec_ddr.size);
+	rwp_store_base = phys_to_virt(nex_phys_mem_get_ta_base(),
+				      MEM_AREA_SEC_RAM_OVERALL, ta_size);
 	assert(rwp_store_base);
 
 	return TEE_SUCCESS;
@@ -451,7 +455,7 @@ static struct fobj_rop *to_rop(struct fobj *fobj)
 static void rop_uninit(struct fobj_rop *rop)
 {
 	fobj_uninit(&rop->fobj);
-	tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rop->store)));
+	tee_mm_free(nex_phys_mem_mm_find(virt_to_phys(rop->store)));
 	free(rop->hashes);
 }
 
@@ -759,11 +763,12 @@ struct fobj *fobj_sec_mem_alloc(unsigned int num_pages)
 	if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size))
 		goto err;
 
-	f->mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
+	f->mm = phys_mem_ta_alloc(size);
 	if (!f->mm)
 		goto err;
 
-	va = phys_to_virt(tee_mm_get_smem(f->mm), MEM_AREA_TA_RAM, size);
+	va = phys_to_virt(tee_mm_get_smem(f->mm), MEM_AREA_SEC_RAM_OVERALL,
+			  size);
 	if (!va)
 		goto err;
 
diff --git a/core/mm/mobj.c b/core/mm/mobj.c
index afc8176d15452eb754253a48ca6ba367368ae32c..50862429755bb2893fe5b223c1bb0646b437c67a 100644
--- a/core/mm/mobj.c
+++ b/core/mm/mobj.c
@@ -12,18 +12,15 @@
 #include <kernel/panic.h>
 #include <kernel/refcount.h>
 #include <kernel/spinlock.h>
-#include <kernel/tee_misc.h>
 #include <mm/core_mmu.h>
 #include <mm/mobj.h>
 #include <mm/tee_pager.h>
-#include <mm/vm.h>
 #include <optee_msg.h>
 #include <stdlib.h>
 #include <tee_api_types.h>
 #include <types_ext.h>
 #include <util.h>
 
-struct mobj *mobj_sec_ddr;
 struct mobj *mobj_tee_ram_rx;
 struct mobj *mobj_tee_ram_rw;
 
@@ -96,11 +93,10 @@ static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr)
 	switch (attr) {
 	case CORE_MEM_SEC:
 		return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM ||
-		       a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM;
+		       a == CORE_MEM_SDP_MEM;
 	case CORE_MEM_NON_SEC:
 		return a == CORE_MEM_NSEC_SHM;
 	case CORE_MEM_TEE_RAM:
-	case CORE_MEM_TA_RAM:
 	case CORE_MEM_NSEC_SHM:
 	case CORE_MEM_SDP_MEM:
 		return attr == a;
@@ -186,12 +182,6 @@ struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t mem_type,
 	enum teecore_memtypes area_type;
 
 	switch (battr) {
-	case CORE_MEM_TEE_RAM:
-		area_type = MEM_AREA_TEE_RAM_RW_DATA;
-		break;
-	case CORE_MEM_TA_RAM:
-		area_type = MEM_AREA_TA_RAM;
-		break;
 	case CORE_MEM_NSEC_SHM:
 		area_type = MEM_AREA_NSEC_SHM;
 		break;
@@ -500,13 +490,6 @@ bool mobj_is_paged(struct mobj *mobj)
 
 static TEE_Result mobj_init(void)
 {
-	mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo,
-				       tee_mm_sec_ddr.size,
-				       TEE_MATTR_MEM_TYPE_CACHED,
-				       CORE_MEM_TA_RAM);
-	if (!mobj_sec_ddr)
-		panic("Failed to register secure ta ram");
-
 	if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) {
 		mobj_tee_ram_rx = mobj_phys_init(0,
 						 VCORE_UNPG_RX_SZ,
@@ -527,7 +510,7 @@ static TEE_Result mobj_init(void)
 		mobj_tee_ram_rw = mobj_phys_init(TEE_RAM_START,
 						 VCORE_UNPG_RW_PA +
 						 VCORE_UNPG_RW_SZ -
-						 TEE_RAM_START,
+						 VCORE_START_VA,
 						 TEE_MATTR_MEM_TYPE_CACHED,
 						 CORE_MEM_TEE_RAM,
 						 MEM_AREA_TEE_RAM_RW_DATA);
diff --git a/core/arch/arm/mm/mobj_dyn_shm.c b/core/mm/mobj_dyn_shm.c
similarity index 97%
rename from core/arch/arm/mm/mobj_dyn_shm.c
rename to core/mm/mobj_dyn_shm.c
index c5bdc302d907f958572dc7d00342292e58bf9482..a808eca417722fac929468c4de6f473f78da0276 100644
--- a/core/arch/arm/mm/mobj_dyn_shm.c
+++ b/core/mm/mobj_dyn_shm.c
@@ -11,13 +11,10 @@
 #include <kernel/panic.h>
 #include <kernel/refcount.h>
 #include <kernel/spinlock.h>
-#include <kernel/tee_misc.h>
 #include <mm/core_mmu.h>
 #include <mm/mobj.h>
 #include <mm/tee_pager.h>
-#include <mm/vm.h>
 #include <optee_msg.h>
-#include <sm/optee_smc.h>
 #include <stdlib.h>
 #include <tee_api_types.h>
 #include <types_ext.h>
@@ -205,7 +202,7 @@ static TEE_Result mobj_reg_shm_inc_map(struct mobj *mobj)
 	 */
 	if (!r->mm) {
 		sz = ROUNDUP(mobj->size + r->page_offset, SMALL_PAGE_SIZE);
-		r->mm = tee_mm_alloc(&tee_mm_shm, sz);
+		r->mm = tee_mm_alloc(&core_virt_shm_pool, sz);
 		if (!r->mm) {
 			res = TEE_ERROR_OUT_OF_MEMORY;
 			goto out;
@@ -369,14 +366,17 @@ static struct mobj_reg_shm *reg_shm_find_unlocked(uint64_t cookie)
 
 struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie)
 {
-	uint32_t exceptions = cpu_spin_lock_xsave(&reg_shm_slist_lock);
-	struct mobj_reg_shm *r = reg_shm_find_unlocked(cookie);
+	struct mobj_reg_shm *r = NULL;
+	uint32_t exceptions = 0;
+	struct mobj *m = NULL;
 
+	exceptions = cpu_spin_lock_xsave(&reg_shm_slist_lock);
+	r = reg_shm_find_unlocked(cookie);
+	if (r)
+		m = mobj_get(&r->mobj);
 	cpu_spin_unlock_xrestore(&reg_shm_slist_lock, exceptions);
-	if (!r)
-		return NULL;
 
-	return mobj_get(&r->mobj);
+	return m;
 }
 
 TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie)
@@ -463,7 +463,7 @@ static TEE_Result mobj_mapped_shm_init(void)
 	if (!pool_start || !pool_end)
 		panic("Can't find region for shmem pool");
 
-	if (!tee_mm_init(&tee_mm_shm, pool_start, pool_end - pool_start,
+	if (!tee_mm_init(&core_virt_shm_pool, pool_start, pool_end - pool_start,
 			 SMALL_PAGE_SHIFT, TEE_MM_POOL_NO_FLAGS))
 		panic("Could not create shmem pool");
 
diff --git a/core/mm/pgt_cache.c b/core/mm/pgt_cache.c
index 79553c6d2183fe002ac01fb8bed8c5376f7633f7..cd8f11fbc4c897387ae8158936be5d642aefd6d6 100644
--- a/core/mm/pgt_cache.c
+++ b/core/mm/pgt_cache.c
@@ -11,6 +11,7 @@
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <mm/pgt_cache.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_pager.h>
 #include <stdlib.h>
 #include <trace.h>
@@ -106,12 +107,13 @@ static struct pgt_parent *alloc_pgt_parent(void)
 	parent = calloc(1, sz);
 	if (!parent)
 		return NULL;
-	parent->mm = tee_mm_alloc(&tee_mm_sec_ddr, PGT_PARENT_SIZE);
+	parent->mm = phys_mem_ta_alloc(PGT_PARENT_SIZE);
 	if (!parent->mm) {
 		free(parent);
 		return NULL;
 	}
-	tbl = phys_to_virt(tee_mm_get_smem(parent->mm), MEM_AREA_TA_RAM,
+	tbl = phys_to_virt(tee_mm_get_smem(parent->mm),
+			   MEM_AREA_SEC_RAM_OVERALL,
 			   PGT_PARENT_SIZE);
 	assert(tbl); /* "can't fail" */
 
@@ -338,6 +340,8 @@ prune_done:
 }
 #else /* !CFG_CORE_PREALLOC_EL0_TBLS */
 
+#define PGT_CACHE_SIZE	ROUNDUP(CFG_PGT_CACHE_ENTRIES, PGT_NUM_PGT_PER_PAGE)
+
 #if defined(CFG_WITH_PAGER) && !defined(CFG_WITH_LPAE)
 static struct pgt_parent pgt_parents[PGT_CACHE_SIZE / PGT_NUM_PGT_PER_PAGE];
 #else
diff --git a/core/mm/phys_mem.c b/core/mm/phys_mem.c
new file mode 100644
index 0000000000000000000000000000000000000000..25b522fd4c80ec94f7d01430cb2c931842d01451
--- /dev/null
+++ b/core/mm/phys_mem.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <kernel/panic.h>
+#include <kernel/tee_misc.h>
+#include <mm/core_mmu.h>
+#include <mm/phys_mem.h>
+#include <mm/tee_mm.h>
+#include <string.h>
+#include <types_ext.h>
+
+static tee_mm_pool_t *nex_core_pool __nex_bss;
+static tee_mm_pool_t *nex_ta_pool __nex_bss;
+
+static tee_mm_pool_t *init_pool(paddr_t b, paddr_size_t sz, uint32_t flags)
+{
+	tee_mm_pool_t *pool = NULL;
+
+	if (!b && !sz)
+		return NULL;
+
+	if (!b || (b & CORE_MMU_USER_CODE_MASK) ||
+	    !sz || (sz & CORE_MMU_USER_CODE_MASK))
+		panic("invalid phys mem");
+
+	if (flags & TEE_MM_POOL_NEX_MALLOC)
+		pool = nex_malloc(sizeof(*pool));
+	else
+		pool = malloc(sizeof(*pool));
+	if (!pool)
+		panic();
+
+	if (!tee_mm_init(pool, b, sz, CORE_MMU_USER_CODE_SHIFT, flags))
+		panic();
+
+	return pool;
+}
+
+void nex_phys_mem_init(paddr_t core_base, paddr_size_t core_size,
+		       paddr_t ta_base, paddr_size_t ta_size)
+{
+	uint32_t flags = TEE_MM_POOL_NEX_MALLOC;
+
+	assert(!nex_core_pool && !nex_ta_pool);
+
+	nex_core_pool = init_pool(core_base, core_size, flags);
+	nex_ta_pool = init_pool(ta_base, ta_size, flags);
+}
+
+paddr_size_t nex_phys_mem_get_ta_size(void)
+{
+	if (nex_ta_pool)
+		return nex_ta_pool->size;
+	assert(nex_core_pool);
+	return nex_core_pool->size - TEE_RAM_VA_SIZE;
+}
+
+paddr_t nex_phys_mem_get_ta_base(void)
+{
+	if (nex_ta_pool)
+		return nex_ta_pool->lo;
+	assert(nex_core_pool);
+	return nex_core_pool->lo;
+}
+
+static bool is_in_pool_range(tee_mm_pool_t *pool, paddr_t addr)
+{
+	return pool && core_is_buffer_inside(addr, 1, pool->lo, pool->size);
+}
+
+static tee_mm_entry_t *mm_find(tee_mm_pool_t *p0, tee_mm_pool_t *p1,
+			       paddr_t addr)
+{
+	if (is_in_pool_range(p0, addr))
+		return tee_mm_find(p0, addr);
+	if (is_in_pool_range(p1, addr))
+		return tee_mm_find(p1, addr);
+	return NULL;
+}
+
+tee_mm_entry_t *nex_phys_mem_mm_find(paddr_t addr)
+{
+	return mm_find(nex_core_pool, nex_ta_pool, addr);
+}
+
+static tee_mm_entry_t *mm_alloc(tee_mm_pool_t *p0, tee_mm_pool_t *p1,
+				size_t size)
+{
+	tee_mm_entry_t *mm = NULL;
+
+	if (p0)
+		mm = tee_mm_alloc(p0, size);
+	if (!mm && p1)
+		mm = tee_mm_alloc(p1, size);
+
+	return mm;
+}
+
+tee_mm_entry_t *nex_phys_mem_core_alloc(size_t size)
+{
+	return mm_alloc(nex_core_pool, NULL, size);
+}
+
+tee_mm_entry_t *nex_phys_mem_ta_alloc(size_t size)
+{
+	return mm_alloc(nex_ta_pool, nex_core_pool, size);
+}
+
+static tee_mm_entry_t *mm_alloc2(tee_mm_pool_t *p0, tee_mm_pool_t *p1,
+				 paddr_t base, size_t size)
+{
+	if (is_in_pool_range(p0, base))
+		return tee_mm_alloc2(p0, base, size);
+	if (is_in_pool_range(p1, base))
+		return tee_mm_alloc2(p1, base, size);
+	return NULL;
+}
+
+tee_mm_entry_t *nex_phys_mem_alloc2(paddr_t base, size_t size)
+{
+	return mm_alloc2(nex_core_pool, nex_ta_pool, base, size);
+}
+
+static void partial_carve_out(tee_mm_pool_t *pool, paddr_t base, size_t size)
+{
+	if (pool &&
+	    core_is_buffer_intersect(base, size, pool->lo, pool->size)) {
+		tee_mm_entry_t *mm __maybe_unused = NULL;
+		paddr_t end_pa = 0;
+		paddr_t pa = 0;
+		size_t sz = 0;
+
+		pa = MAX(base, pool->lo);
+		end_pa = MIN(base + size - 1, pool->lo + pool->size - 1);
+		sz = end_pa - pa + 1;
+
+		mm = tee_mm_alloc2(pool, pa, sz);
+		assert(mm);
+	}
+}
+
+void nex_phys_mem_partial_carve_out(paddr_t base, size_t size)
+{
+	partial_carve_out(nex_core_pool, base, size);
+	partial_carve_out(nex_ta_pool, base, size);
+}
+
+#ifdef CFG_WITH_STATS
+static void add_pool_stats(tee_mm_pool_t *pool, struct pta_stats_alloc *stats,
+			   bool reset)
+{
+	if (pool) {
+		struct pta_stats_alloc s = { };
+
+		tee_mm_get_pool_stats(pool, &s, reset);
+		stats->size += s.size;
+		if (s.max_allocated > stats->max_allocated)
+			stats->max_allocated = s.max_allocated;
+		stats->allocated += s.allocated;
+	}
+}
+
+void nex_phys_mem_stats(struct pta_stats_alloc *stats, bool reset)
+{
+	memset(stats, 0, sizeof(*stats));
+
+	add_pool_stats(nex_core_pool, stats, reset);
+	add_pool_stats(nex_ta_pool, stats, reset);
+}
+#endif /*CFG_WITH_STATS*/
+
+#if defined(CFG_NS_VIRTUALIZATION)
+
+static tee_mm_pool_t *core_pool;
+static tee_mm_pool_t *ta_pool;
+
+void phys_mem_init(paddr_t core_base, paddr_size_t core_size,
+		   paddr_t ta_base, paddr_size_t ta_size)
+{
+	uint32_t flags = TEE_MM_POOL_NO_FLAGS;
+
+	assert(!core_pool && !ta_pool);
+
+	core_pool = init_pool(core_base, core_size, flags);
+	ta_pool = init_pool(ta_base, ta_size, flags);
+}
+
+tee_mm_entry_t *phys_mem_mm_find(paddr_t addr)
+{
+	return mm_find(core_pool, ta_pool, addr);
+}
+
+tee_mm_entry_t *phys_mem_core_alloc(size_t size)
+{
+	/*
+	 * With CFG_NS_VIRTUALIZATION all memory is equally secure so we
+	 * should normally be able to use one pool only, but if we have two
+	 * make sure to use both even for core allocations.
+	 */
+	return mm_alloc(core_pool, ta_pool, size);
+}
+
+tee_mm_entry_t *phys_mem_ta_alloc(size_t size)
+{
+	return mm_alloc(ta_pool, core_pool, size);
+}
+
+tee_mm_entry_t *phys_mem_alloc2(paddr_t base, size_t size)
+{
+	return mm_alloc2(core_pool, ta_pool, base, size);
+}
+
+#ifdef CFG_WITH_STATS
+void phys_mem_stats(struct pta_stats_alloc *stats, bool reset)
+{
+	memset(stats, 0, sizeof(*stats));
+
+	add_pool_stats(core_pool, stats, reset);
+	add_pool_stats(ta_pool, stats, reset);
+}
+#endif /*CFG_WITH_STATS*/
+#endif /*CFG_NS_VIRTUALIZATION*/
diff --git a/core/mm/sub.mk b/core/mm/sub.mk
index 7d3c5ea0fa1c7b780f4494d93b28aa4a0cfb38f8..df6f22669a340f349db6a73faf233bd655f02e32 100644
--- a/core/mm/sub.mk
+++ b/core/mm/sub.mk
@@ -6,4 +6,8 @@ srcs-y += vm.c
 srcs-y += core_mmu.c
 srcs-y += pgt_cache.c
 srcs-y += tee_mm.c
-
+srcs-y += phys_mem.c
+ifneq ($(CFG_CORE_FFA),y)
+srcs-$(CFG_CORE_DYN_SHM) += mobj_dyn_shm.c
+endif
+srcs-$(CFG_BOOT_MEM) += boot_mem.c
diff --git a/core/mm/tee_mm.c b/core/mm/tee_mm.c
index 95084ca1e448756d8f60670a0d4415fb86a6f2e3..0596b724b254691619f13a6fde4c6204db7335de 100644
--- a/core/mm/tee_mm.c
+++ b/core/mm/tee_mm.c
@@ -45,18 +45,20 @@ bool tee_mm_init(tee_mm_pool_t *pool, paddr_t lo, paddr_size_t size,
 	if (pool == NULL)
 		return false;
 
-	lo = ROUNDUP(lo, 1 << shift);
+	lo = ROUNDUP2(lo, 1 << shift);
 	rounded = lo - initial_lo;
-	size = ROUNDDOWN(size - rounded, 1 << shift);
+	size = ROUNDDOWN2(size - rounded, 1 << shift);
 
 	assert(((uint64_t)size >> shift) < (uint64_t)UINT32_MAX);
 
-	pool->lo = lo;
-	pool->size = size;
-	pool->shift = shift;
-	pool->flags = flags;
-	pool->entry = pcalloc(pool, 1, sizeof(tee_mm_entry_t));
+	*pool = (tee_mm_pool_t){
+		.lo = lo,
+		.size = size,
+		.shift = shift,
+		.flags = flags,
+	};
 
+	pool->entry = pcalloc(pool, 1, sizeof(tee_mm_entry_t));
 	if (pool->entry == NULL)
 		return false;
 
@@ -354,15 +356,6 @@ bool tee_mm_is_empty(tee_mm_pool_t *pool)
 	return ret;
 }
 
-/* Physical Secure DDR pool */
-tee_mm_pool_t tee_mm_sec_ddr;
-
-/* Virtual eSRAM pool */
-tee_mm_pool_t tee_mm_vcore;
-
-/* Shared memory pool */
-tee_mm_pool_t tee_mm_shm;
-
 tee_mm_entry_t *tee_mm_find(const tee_mm_pool_t *pool, paddr_t addr)
 {
 	tee_mm_entry_t *entry = pool->entry;
diff --git a/core/mm/vm.c b/core/mm/vm.c
index 2863925fde29ff90afea3e43af4e0972de815683..9a545e9c193cec6a4caa692a823c54b384646d3e 100644
--- a/core/mm/vm.c
+++ b/core/mm/vm.c
@@ -14,7 +14,6 @@
 #include <kernel/tee_misc.h>
 #include <kernel/tlb_helpers.h>
 #include <kernel/user_mode_ctx.h>
-#include <kernel/virtualization.h>
 #include <mm/core_memprot.h>
 #include <mm/core_mmu.h>
 #include <mm/mobj.h>
@@ -76,7 +75,7 @@ static vaddr_t select_va_in_range(const struct vm_region *prev_reg,
 	if (ADD_OVERFLOW(prev_reg->va, prev_reg->size, &begin_va) ||
 	    ADD_OVERFLOW(begin_va, pad_begin, &begin_va) ||
 	    ADD_OVERFLOW(begin_va, pad, &begin_va) ||
-	    ROUNDUP_OVERFLOW(begin_va, granul, &begin_va))
+	    ROUNDUP2_OVERFLOW(begin_va, granul, &begin_va))
 		return 0;
 
 	if (reg->va) {
@@ -98,7 +97,7 @@ static vaddr_t select_va_in_range(const struct vm_region *prev_reg,
 	if (ADD_OVERFLOW(begin_va, reg->size, &end_va) ||
 	    ADD_OVERFLOW(end_va, pad_end, &end_va) ||
 	    ADD_OVERFLOW(end_va, pad, &end_va) ||
-	    ROUNDUP_OVERFLOW(end_va, granul, &end_va))
+	    ROUNDUP2_OVERFLOW(end_va, granul, &end_va))
 		return 0;
 
 	if (end_va <= next_reg->va) {
@@ -1179,7 +1178,7 @@ static TEE_Result tee_mmu_user_va2pa_attr(const struct user_mode_ctx *uctx,
 			assert(!granule || IS_POWER_OF_TWO(granule));
 
 			offset = region->offset +
-				 ROUNDDOWN((vaddr_t)ua - region->va, granule);
+				 ROUNDDOWN2((vaddr_t)ua - region->va, granule);
 
 			res = mobj_get_pa(region->mobj, offset, granule, &p);
 			if (res != TEE_SUCCESS)
@@ -1271,7 +1270,7 @@ TEE_Result vm_check_access_rights(const struct user_mode_ctx *uctx,
 	   !vm_buf_is_inside_um_private(uctx, (void *)uaddr, len))
 		return TEE_ERROR_ACCESS_DENIED;
 
-	for (a = ROUNDDOWN(uaddr, addr_incr); a < end_addr; a += addr_incr) {
+	for (a = ROUNDDOWN2(uaddr, addr_incr); a < end_addr; a += addr_incr) {
 		uint32_t attr;
 		TEE_Result res;
 
diff --git a/core/pta/benchmark.c b/core/pta/benchmark.c
deleted file mode 100644
index bfaa42696c9983a0fd36ff87d230e2c127b7157b..0000000000000000000000000000000000000000
--- a/core/pta/benchmark.c
+++ /dev/null
@@ -1,215 +0,0 @@
-// SPDX-License-Identifier: BSD-2-Clause
-/*
- * Copyright (c) 2017, Linaro Limited
- */
-#include <bench.h>
-#include <compiler.h>
-#include <kernel/misc.h>
-#include <kernel/mutex.h>
-#include <kernel/pseudo_ta.h>
-#include <malloc.h>
-#include <mm/core_memprot.h>
-#include <mm/mobj.h>
-#include <mm/tee_mm.h>
-#include <mm/tee_pager.h>
-#include <mm/vm.h>
-#include <optee_rpc_cmd.h>
-#include <pta_benchmark.h>
-#include <stdio.h>
-#include <string_ext.h>
-#include <string.h>
-#include <trace.h>
-
-#define TA_NAME		"benchmark.ta"
-#define TA_PRINT_PREFIX	"Benchmark: "
-
-static struct tee_ts_global *bench_ts_global;
-static size_t bench_ts_size;
-
-static struct mutex bench_reg_mu = MUTEX_INITIALIZER;
-static struct mobj *bench_mobj;
-
-static TEE_Result rpc_reg_global_buf(uint64_t type, paddr_t phta, size_t size)
-{
-	struct thread_param tpm = THREAD_PARAM_VALUE(IN, type, phta, size);
-
-	return thread_rpc_cmd(OPTEE_RPC_CMD_BENCH_REG, 1, &tpm);
-}
-
-static TEE_Result alloc_benchmark_buffer(uint32_t type,
-				TEE_Param p[TEE_NUM_PARAMS])
-{
-	TEE_Result res;
-
-	if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_INOUT) ||
-		(TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_VALUE_INPUT) ||
-		(TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) {
-		return TEE_ERROR_BAD_PARAMETERS;
-	}
-
-	mutex_lock(&bench_reg_mu);
-
-	/* Check if we have already registered buffer */
-	if (bench_ts_global) {
-		EMSG(TA_PRINT_PREFIX
-			"timestamp buffer was already registered");
-		mutex_unlock(&bench_reg_mu);
-		return TEE_ERROR_BAD_STATE;
-	}
-
-	bench_ts_size = sizeof(struct tee_ts_global) +
-		p[1].value.a * sizeof(struct tee_ts_cpu_buf);
-	if (!bench_ts_size) {
-		EMSG(TA_PRINT_PREFIX
-			"invalid timestamp buffer size");
-		mutex_unlock(&bench_reg_mu);
-		return TEE_ERROR_BAD_STATE;
-	}
-
-	bench_mobj = thread_rpc_alloc_global_payload(bench_ts_size);
-	if (!bench_mobj) {
-		EMSG(TA_PRINT_PREFIX
-			"can't create mobj for timestamp buffer");
-		mutex_unlock(&bench_reg_mu);
-		return TEE_ERROR_OUT_OF_MEMORY;
-	}
-
-	bench_ts_global = (struct tee_ts_global *)mobj_get_va(bench_mobj, 0,
-							      bench_ts_size);
-	if (!bench_ts_global) {
-		thread_rpc_free_global_payload(bench_mobj);
-		bench_mobj = NULL;
-
-		mutex_unlock(&bench_reg_mu);
-		return TEE_ERROR_BAD_STATE;
-	}
-
-	memset((void *)bench_ts_global, 0, bench_ts_size);
-	bench_ts_global->cores = p[1].value.a;
-
-	DMSG(TA_PRINT_PREFIX
-		"allocated timestamp buffer, addr = %p",
-		(void *)bench_ts_global);
-
-	mutex_unlock(&bench_reg_mu);
-
-	/* Send back to the optee linux kernel module */
-	res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_NEW,
-			virt_to_phys((void *)bench_ts_global),
-			bench_ts_size);
-
-	p[0].value.a = virt_to_phys((void *)bench_ts_global);
-	p[0].value.b = bench_ts_size;
-
-	return res;
-}
-
-static TEE_Result get_benchmark_memref(uint32_t type,
-				TEE_Param p[TEE_NUM_PARAMS])
-{
-	if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_VALUE_OUTPUT) ||
-		(TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) {
-		return TEE_ERROR_BAD_PARAMETERS;
-	}
-
-	mutex_lock(&bench_reg_mu);
-
-	DMSG(TA_PRINT_PREFIX "Sending back timestamp buffer paddr = %p",
-		(void *)virt_to_phys((void *)bench_ts_global));
-
-	if (bench_ts_global) {
-		p[0].value.a = virt_to_phys((void *)bench_ts_global);
-		p[0].value.b = bench_ts_size;
-	} else {
-		p[0].value.a = 0;
-		p[0].value.b = 0;
-	}
-
-	mutex_unlock(&bench_reg_mu);
-
-	return TEE_SUCCESS;
-}
-
-static TEE_Result unregister_benchmark(uint32_t type,
-				TEE_Param p[TEE_NUM_PARAMS] __unused)
-{
-	TEE_Result res;
-
-	if ((TEE_PARAM_TYPE_GET(type, 0) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 1) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 2) != TEE_PARAM_TYPE_NONE) ||
-		(TEE_PARAM_TYPE_GET(type, 3) != TEE_PARAM_TYPE_NONE)) {
-		return TEE_ERROR_BAD_PARAMETERS;
-	}
-	mutex_lock(&bench_reg_mu);
-
-	DMSG(TA_PRINT_PREFIX "Unregister benchmark ts buffer paddr = %p",
-		(void *)virt_to_phys((void *)bench_ts_global));
-	bench_ts_global = NULL;
-
-	mutex_unlock(&bench_reg_mu);
-
-	res = rpc_reg_global_buf(OPTEE_MSG_RPC_CMD_BENCH_REG_DEL, 0, 0);
-
-	thread_rpc_free_global_payload(bench_mobj);
-	bench_mobj = NULL;
-
-	return res;
-}
-
-static TEE_Result invoke_command(void *session_ctx __unused,
-		uint32_t cmd_id, uint32_t param_types,
-		TEE_Param params[TEE_NUM_PARAMS])
-{
-	switch (cmd_id) {
-	case BENCHMARK_CMD_ALLOCATE_BUF:
-		return alloc_benchmark_buffer(param_types, params);
-	case BENCHMARK_CMD_GET_MEMREF:
-		return get_benchmark_memref(param_types, params);
-	case BENCHMARK_CMD_UNREGISTER:
-		return unregister_benchmark(param_types, params);
-	default:
-		break;
-	}
-
-	return TEE_ERROR_BAD_PARAMETERS;
-}
-
-pseudo_ta_register(.uuid = BENCHMARK_UUID, .name = TA_NAME,
-		   .flags = PTA_DEFAULT_FLAGS,
-		   .invoke_command_entry_point = invoke_command);
-
-void bm_timestamp(void)
-{
-	struct tee_ts_cpu_buf *cpu_buf;
-	struct tee_time_st ts_data;
-	uint64_t ts_i;
-	void *ret_addr;
-	uint32_t cur_cpu;
-	uint32_t exceptions;
-
-	if (!bench_ts_global)
-		return;
-
-	exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
-	cur_cpu = get_core_pos();
-
-	if (cur_cpu >= bench_ts_global->cores) {
-		thread_unmask_exceptions(exceptions);
-		return;
-	}
-
-	ret_addr = __builtin_return_address(0);
-
-	cpu_buf = &bench_ts_global->cpu_buf[cur_cpu];
-	ts_i = cpu_buf->head++;
-	ts_data.cnt = read_pmccntr() * TEE_BENCH_DIVIDER;
-	ts_data.addr = (uintptr_t)ret_addr;
-	ts_data.src = TEE_BENCH_CORE;
-	cpu_buf->stamps[ts_i & TEE_BENCH_MAX_MASK] = ts_data;
-
-	thread_unmask_exceptions(exceptions);
-}
diff --git a/core/pta/device.c b/core/pta/device.c
index 1a026a62b7e3c70dc710351d53a352c15af9542a..279d49026eaee0ebe0b6f8b88de0bea287cdb76d 100644
--- a/core/pta/device.c
+++ b/core/pta/device.c
@@ -15,7 +15,7 @@
 #include <kernel/stmm_sp.h>
 #include <kernel/tee_ta_manager.h>
 #include <pta_device.h>
-#include <string.h>
+#include <tee/tee_fs.h>
 #include <tee/uuid.h>
 #include <user_ta_header.h>
 
@@ -24,8 +24,11 @@
 static void add_ta(uint32_t flags, const TEE_UUID *uuid, uint8_t *buf,
 		   uint32_t blen, uint32_t *pos, uint32_t rflags)
 {
-	if ((flags & TA_FLAG_DEVICE_ENUM) &&
-	    (flags & TA_FLAG_DEVICE_ENUM_SUPP)) {
+	flags &= (TA_FLAG_DEVICE_ENUM | TA_FLAG_DEVICE_ENUM_SUPP |
+		  TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE);
+	if (flags && flags != TA_FLAG_DEVICE_ENUM &&
+	    flags != TA_FLAG_DEVICE_ENUM_SUPP &&
+	    flags != TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE) {
 		EMSG(PTA_NAME ": skipping TA %pUl, inconsistent flags", uuid);
 		return;
 	}
@@ -83,18 +86,31 @@ static TEE_Result invoke_command(void *pSessionContext __unused,
 				 uint32_t nCommandID, uint32_t nParamTypes,
 				 TEE_Param pParams[TEE_NUM_PARAMS])
 {
+	TEE_Result res = TEE_SUCCESS;
+	uint32_t rflags = 0;
+
 	switch (nCommandID) {
 	case PTA_CMD_GET_DEVICES:
-		return get_devices(nParamTypes, pParams,
-				   TA_FLAG_DEVICE_ENUM);
+		rflags = TA_FLAG_DEVICE_ENUM;
+		break;
 	case PTA_CMD_GET_DEVICES_SUPP:
-		return get_devices(nParamTypes, pParams,
-				   TA_FLAG_DEVICE_ENUM_SUPP);
-	default:
+		rflags = TA_FLAG_DEVICE_ENUM_SUPP;
+		if (IS_ENABLED(CFG_REE_FS))
+			rflags |= TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE;
 		break;
+	case PTA_CMD_GET_DEVICES_RPMB:
+		if (!IS_ENABLED(CFG_REE_FS)) {
+			res = tee_rpmb_reinit();
+			if (res)
+				return TEE_ERROR_STORAGE_NOT_AVAILABLE;
+			rflags = TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE;
+		}
+		break;
+	default:
+		return TEE_ERROR_NOT_IMPLEMENTED;
 	}
 
-	return TEE_ERROR_NOT_IMPLEMENTED;
+	return get_devices(nParamTypes, pParams, rflags);
 }
 
 pseudo_ta_register(.uuid = PTA_DEVICE_UUID, .name = PTA_NAME,
diff --git a/core/pta/scmi.c b/core/pta/scmi.c
index 7686435dc0d220cf11b534dc8dbcbd649c7f02bf..1ef964defaab3806fd8d228d8f600ab5a8d456e1 100644
--- a/core/pta/scmi.c
+++ b/core/pta/scmi.c
@@ -152,10 +152,8 @@ static TEE_Result cmd_process_msg_channel(uint32_t ptypes,
 		res = scmi_server_msg_process_thread(channel_id, in_buf,
 						     in_size, out_buf,
 						     &out_size);
-		if (!res) {
+		if (!res)
 			params[2].memref.size = (uint32_t)out_size;
-			IMSG("scmi optee shm: out %zu", out_size);
-		}
 
 		return res;
 	}
diff --git a/core/pta/secstor_ta_mgmt.c b/core/pta/secstor_ta_mgmt.c
index 162de43bee303305ebb0b777f649d28d32589adc..b8dc9283c6c0042371645f753217842a7f92434b 100644
--- a/core/pta/secstor_ta_mgmt.c
+++ b/core/pta/secstor_ta_mgmt.c
@@ -44,7 +44,7 @@ static TEE_Result install_ta(struct shdr *shdr, const uint8_t *nw,
 	struct tee_tadb_ta_write *ta;
 	void *hash_ctx = NULL;
 	size_t offs;
-	const size_t buf_size = 2 * 4096;
+	const size_t buf_size = 1024;
 	void *buf;
 	struct tee_tadb_property property;
 	struct shdr_bootstrap_ta bs_ta;
diff --git a/core/pta/stats.c b/core/pta/stats.c
index 966592f008af6fba00c09845a4c97fb41846de30..93a3c1056da5aca485c872fac6e9bad8ef6cc4c2 100644
--- a/core/pta/stats.c
+++ b/core/pta/stats.c
@@ -8,10 +8,10 @@
 #include <kernel/pseudo_ta.h>
 #include <kernel/tee_time.h>
 #include <malloc.h>
+#include <mm/phys_mem.h>
 #include <mm/tee_mm.h>
 #include <mm/tee_pager.h>
 #include <pta_stats.h>
-#include <stdio.h>
 #include <string.h>
 #include <string_ext.h>
 #include <tee_api_types.h>
@@ -70,9 +70,9 @@ static TEE_Result get_alloc_stats(uint32_t type, TEE_Param p[TEE_NUM_PARAMS])
 			break;
 
 		case ALLOC_ID_TA_RAM:
-			tee_mm_get_pool_stats(&tee_mm_sec_ddr, stats,
-					      !!p[0].value.b);
-			strlcpy(stats->desc, "Secure DDR", sizeof(stats->desc));
+			phys_mem_stats(stats, p[0].value.b);
+			strlcpy(stats->desc, "Physical TA memory",
+				sizeof(stats->desc));
 			break;
 
 #ifdef CFG_NS_VIRTUALIZATION
diff --git a/core/pta/stm32mp/remoteproc_pta.c b/core/pta/stm32mp/remoteproc_pta.c
index b2eed7f257f8dc123f0cefc5b10f17f43f0f5ad3..30b9696abbeff8271d19eae329e1cf4d31f23dc3 100644
--- a/core/pta/stm32mp/remoteproc_pta.c
+++ b/core/pta/stm32mp/remoteproc_pta.c
@@ -293,6 +293,24 @@ static TEE_Result rproc_pta_verify_digest(uint32_t pt,
 					      keyinfo->algo);
 }
 
+static TEE_Result rproc_pta_release_resources(uint32_t pt,
+					      TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (rproc_ta_state != REMOTEPROC_OFF)
+		return TEE_ERROR_BAD_STATE;
+
+	/* Clean the resources */
+	return stm32_rproc_clean_up_memories(params[0].value.a);
+}
+
 static TEE_Result rproc_pta_invoke_command(void *session __unused,
 					   uint32_t cmd_id,
 					   uint32_t param_types,
@@ -313,6 +331,8 @@ static TEE_Result rproc_pta_invoke_command(void *session __unused,
 		return rproc_pta_da_to_pa(param_types, params);
 	case PTA_RPROC_VERIFY_DIGEST:
 		return rproc_pta_verify_digest(param_types, params);
+	case PTA_REMOTEPROC_RELEASE:
+		return rproc_pta_release_resources(param_types, params);
 	default:
 		return TEE_ERROR_NOT_IMPLEMENTED;
 	}
diff --git a/core/pta/sub.mk b/core/pta/sub.mk
index cf8e86298db49b753bbe141f68474ae8279a41ad..11242686528ee52c56acfbfec069fcd716850ac3 100644
--- a/core/pta/sub.mk
+++ b/core/pta/sub.mk
@@ -1,7 +1,6 @@
 subdirs-$(CFG_TEE_CORE_EMBED_INTERNAL_TESTS) += tests
 
 srcs-$(CFG_ATTESTATION_PTA) += attestation.c
-srcs-$(CFG_TEE_BENCHMARK) += benchmark.c
 srcs-$(CFG_DEVICE_ENUM_PTA) += device.c
 srcs-$(CFG_TA_GPROF_SUPPORT) += gprof.c
 ifeq ($(CFG_WITH_USER_TA),y)
@@ -14,11 +13,13 @@ srcs-$(CFG_APDU_PTA) += apdu.c
 srcs-$(CFG_SCMI_PTA) += scmi.c
 srcs-$(CFG_HWRNG_PTA) += hwrng.c
 srcs-$(CFG_RTC_PTA) += rtc.c
+srcs-$(CFG_WIDEVINE_PTA) += widevine.c
 
 subdirs-y += bcm
 subdirs-y += stm32mp
 subdirs-y += imx
 subdirs-y += k3
+subdirs-y += veraison_attestation
 
 ifeq ($(CFG_REMOTEPROC_PTA),y)
 gensrcs-y += rproc_pub_key
diff --git a/core/pta/system.c b/core/pta/system.c
index 07a2d58cbbe14f7f9af1085bc9c105157869bbaf..3a1c57298d24f94bf32ac1d5fc8fb99c3a4a7e95 100644
--- a/core/pta/system.c
+++ b/core/pta/system.c
@@ -7,28 +7,22 @@
 
 #include <assert.h>
 #include <crypto/crypto.h>
-#include <kernel/handle.h>
 #include <kernel/huk_subkey.h>
 #include <kernel/ldelf_loader.h>
-#include <kernel/misc.h>
 #include <kernel/msg_param.h>
 #include <kernel/pseudo_ta.h>
 #include <kernel/tpm.h>
-#include <kernel/ts_store.h>
 #include <kernel/user_access.h>
 #include <kernel/user_mode_ctx.h>
-#include <ldelf.h>
 #include <mm/file.h>
 #include <mm/fobj.h>
 #include <mm/vm.h>
 #include <pta_system.h>
-#include <stdlib_ext.h>
 #include <stdlib.h>
 #include <string.h>
 #include <tee_api_defines_extensions.h>
 #include <tee_api_defines.h>
 #include <tee/tee_supp_plugin_rpc.h>
-#include <tee/uuid.h>
 #include <util.h>
 
 static unsigned int system_pnum;
diff --git a/core/pta/tests/aes_perf.c b/core/pta/tests/aes_perf.c
index 84a48e8459b63b555bf6c6ef8558ff1201172ed2..535aa79817586f83e6b81a430636de1e938f1e8b 100644
--- a/core/pta/tests/aes_perf.c
+++ b/core/pta/tests/aes_perf.c
@@ -5,7 +5,6 @@
 
 #include <compiler.h>
 #include <crypto/crypto.h>
-#include <kernel/tee_time.h>
 #include <pta_invoke_tests.h>
 #include <tee_api_defines.h>
 #include <tee_api_types.h>
diff --git a/core/pta/tests/dt_driver_test.c b/core/pta/tests/dt_driver_test.c
index 6a5ac857a8ac73e716f2c8e664b3e521d4d9cd62..7048f385f9af0d87f81687a2149eb33ca70d1d97 100644
--- a/core/pta/tests/dt_driver_test.c
+++ b/core/pta/tests/dt_driver_test.c
@@ -15,7 +15,6 @@
 #include <drivers/rstctrl.h>
 #include <initcall.h>
 #include <kernel/dt_driver.h>
-#include <libfdt.h>
 #include <malloc.h>
 #include <sys/queue.h>
 #include <tee_api_defines_extensions.h>
diff --git a/core/pta/veraison_attestation/README.md b/core/pta/veraison_attestation/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6c16bdca58d0e8a16da0ed243b94cb7059931ca2
--- /dev/null
+++ b/core/pta/veraison_attestation/README.md
@@ -0,0 +1,24 @@
+# Veraison Attestation PTA
+
+This is a proof of concept for adding attestation capabilities to S-EL0 TAs and a demonstrator of an end-to-end remote attestation protocol [1] using the Veraison verifier [2].
+
+For convenience, this PTA reuses the PSA token format [3]. However, note that PSA semantics do not fully apply, as many relevant properties required by the PSA SM [4] are not met.
+
+Furthermore, the attestation evidence produced by the PTA attests to the memory contents of the calling TA, but there is no way to establish trust in the PTA in the first place.
+
+For these reasons, the PTA should not be regarded as a best practice example for real-world attestation.
+
+Instead, this PTA aims to demonstrate the integration of various libraries and tools to create a trusted application focused on attestation within the OP-TEE environment and to practically explore an end-to-end remote attestation flow using this approach.
+
+## Known Limitations
+
+1. **PSA Semantics Limitations:** Although this PTA reuses the PSA token format, many of the relevant properties required by the PSA Security Model (SM) are not met. This can impact the effectiveness and security assumptions typically expected from PSA-based attestation.
+
+2. **Lack of Trust in the PTA:** The attestation evidence produced by the PTA attests to the memory contents of the calling TA, but there is no mechanism to establish trust in the PTA itself from a lower-level entity, such as the bootloader. Without such anchoring to a platform Root of Trust (RoT), the PTA lacks foundational trust, which weakens the overall chain of trust.
+
+## References
+
+[1] https://datatracker.ietf.org/doc/rfc9334
+[2] https://github.com/veraison/services
+[3] https://datatracker.ietf.org/doc/draft-tschofenig-rats-psa-token
+[4] https://www.psacertified.org/app/uploads/2021/12/JSADEN014_PSA_Certified_SM_V1.1_BET0.pdf
diff --git a/core/pta/veraison_attestation/cbor.c b/core/pta/veraison_attestation/cbor.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5dfbd9a9431277cda3217780c5c371342218d31
--- /dev/null
+++ b/core/pta/veraison_attestation/cbor.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#include <compiler.h>
+#include <kernel/pseudo_ta.h>
+#include <mempool.h>
+
+#include "cbor.h"
+#include "sign.h"
+
+struct cbor_evidence_args {
+	UsefulBufC ubc_eat_profile;
+	int psa_client_id;
+	int psa_security_lifecycle;
+	UsefulBufC ubc_psa_implementation_id;
+	UsefulBufC ubc_measurement_type;
+	UsefulBufC ubc_signer_id;
+	UsefulBufC ubc_psa_instance_id;
+	UsefulBufC ubc_psa_nonce;
+	UsefulBufC ubc_measurement_value;
+};
+
+struct cose_evidence_args {
+	UsefulBufC ubc_cbor_evidence;
+};
+
+struct tbs_structure_args {
+	UsefulBufC protected_header;
+	UsefulBufC aad;
+	UsefulBufC payload;
+};
+
+static void
+encode_cbor_evidence(QCBOREncodeContext *context, UsefulBufC ubc_eat_profile,
+		     const int psa_client_id, const int psa_security_lifecycle,
+		     UsefulBufC ubc_psa_implementation_id,
+		     UsefulBufC ubc_measurement_type, UsefulBufC ubc_signer_id,
+		     UsefulBufC ubc_psa_instance_id, UsefulBufC ubc_psa_nonce,
+		     UsefulBufC ubc_measurement_value)
+{
+	QCBOREncode_OpenMap(context);
+
+	/* Profile Definition */
+	QCBOREncode_AddTextToMapN(context, PSA_PROFILE_DEFINITION,
+				  ubc_eat_profile);
+
+	/* Client ID */
+	QCBOREncode_AddInt64ToMapN(context, PSA_CLIENT_ID, psa_client_id);
+
+	/* Security Lifecycle */
+	QCBOREncode_AddInt64ToMapN(context, PSA_SECURITY_LIFECYCLE,
+				   psa_security_lifecycle);
+
+	/* Implementation ID */
+	QCBOREncode_AddBytesToMapN(context, PSA_IMPLEMENTATION_ID,
+				   ubc_psa_implementation_id);
+
+	/* Software Components */
+	QCBOREncode_OpenArrayInMapN(context, PSA_SW_COMPONENTS); /* [ */
+	QCBOREncode_OpenMap(context); /* { */
+	QCBOREncode_AddTextToMapN(context, PSA_SW_COMPONENT_MEASUREMENT_TYPE,
+				  ubc_measurement_type);
+	QCBOREncode_AddBytesToMapN(context, PSA_SW_COMPONENT_MEASUREMENT_VALUE,
+				   ubc_measurement_value);
+	QCBOREncode_AddBytesToMapN(context, PSA_SW_COMPONENT_SIGNER_ID,
+				   ubc_signer_id);
+	QCBOREncode_CloseMap(context); /* } */
+	QCBOREncode_CloseArray(context); /* ] */
+
+	/* Nonce */
+	QCBOREncode_AddBytesToMapN(context, PSA_NONCE, ubc_psa_nonce);
+
+	/* Instance ID */
+	QCBOREncode_AddBytesToMapN(context, PSA_INSTANCE_ID,
+				   ubc_psa_instance_id);
+
+	QCBOREncode_CloseMap(context);
+}
+
+/* Generic function for encoding and buffer allocation */
+static UsefulBufC build_encoded_buffer(void (*encode_func)(QCBOREncodeContext *,
+							   void *),
+				       void *encode_args)
+{
+	QCBOREncodeContext context = { };
+	uint8_t *buffer = NULL;
+	size_t required_size = 0;
+	UsefulBufC encoded_data = { NULL, 0 };
+
+	/* First encode: calculate the required length */
+	QCBOREncode_Init(&context, (UsefulBuf){ NULL, INT32_MAX });
+	encode_func(&context, encode_args);
+	if (QCBOREncode_FinishGetSize(&context, &required_size) !=
+	    QCBOR_SUCCESS) {
+		return NULLUsefulBufC;
+	}
+
+	/* Allocate buffer for encoded data */
+	buffer = mempool_alloc(mempool_default, required_size);
+	if (!buffer) {
+		DMSG("Failed to allocate buffer");
+		return NULLUsefulBufC;
+	}
+
+	/* Second encode: encode data */
+	QCBOREncode_Init(&context, (UsefulBuf){ buffer, required_size });
+	encode_func(&context, encode_args);
+	if (QCBOREncode_Finish(&context, &encoded_data) != QCBOR_SUCCESS) {
+		mempool_free(mempool_default, buffer);
+		return NULLUsefulBufC;
+	}
+
+	/* Verify the length of the encoded data */
+	if (encoded_data.len != required_size) {
+		DMSG("Unexpected length of encoded data");
+		mempool_free(mempool_default, buffer);
+		return NULLUsefulBufC;
+	}
+
+	return encoded_data;
+}
+
+static void encode_protected_header(QCBOREncodeContext *context)
+{
+	QCBOREncode_OpenMap(context);
+	QCBOREncode_AddInt64ToMapN(context, COSE_HEADER_PARAM_ALG,
+				   COSE_ALGORITHM_ES256);
+	QCBOREncode_CloseMap(context);
+}
+
+static void encode_protected_header_wrapper(QCBOREncodeContext *context,
+					    void *args __unused)
+{
+	encode_protected_header(context);
+}
+
+/*
+ * Format of to-be-signed bytes. This is defined in COSE (RFC 8152)
+ * section 4.4. It is the input to the hash.
+ *
+ * Sig_structure = [
+ *    context : "Signature1",
+ *    body_protected : empty_or_serialized_map,
+ *    external_aad : bstr,
+ *    payload : bstr
+ * ]
+ *
+ * body_protected refers to the protected parameters from the main
+ * COSE_Sign1 structure.
+ */
+static void encode_tbs_structure(QCBOREncodeContext *context,
+				 UsefulBufC protected_header, UsefulBufC aad,
+				 UsefulBufC payload)
+{
+	QCBOREncode_OpenArray(context);
+	QCBOREncode_AddSZString(context, COSE_SIG_CONTEXT_STRING_SIGNATURE1);
+	QCBOREncode_AddBytes(context, protected_header);
+	QCBOREncode_AddBytes(context, aad);
+	QCBOREncode_AddBytes(context, payload);
+	QCBOREncode_CloseArray(context);
+}
+
+static void encode_tbs_structure_wrapper(QCBOREncodeContext *context,
+					 void *args)
+{
+	struct tbs_structure_args *tbs_args =
+		(struct tbs_structure_args *)args;
+
+	encode_tbs_structure(context, tbs_args->protected_header, tbs_args->aad,
+			     tbs_args->payload);
+}
+
+static UsefulBufC build_protected_header(void)
+{
+	return build_encoded_buffer(encode_protected_header_wrapper, NULL);
+}
+
+static UsefulBufC build_tbs_structure(UsefulBufC protected_header,
+				      UsefulBufC aad, UsefulBufC payload)
+{
+	struct tbs_structure_args args = {
+		.protected_header = protected_header,
+		.aad = aad,
+		.payload = payload,
+	};
+
+	return build_encoded_buffer(encode_tbs_structure_wrapper, &args);
+}
+
+static void encode_cose_evidence(QCBOREncodeContext *context,
+				 UsefulBufC ubc_cbor_evidence)
+{
+	UsefulBufC protected_header = { NULL, 0 };
+	UsefulBufC tbs_payload = { NULL, 0 };
+	uint8_t signature[64] = { };
+	size_t signature_len = 64;
+	UsefulBufC signature_payload = { signature, signature_len };
+
+	/* Add top level array for COSE_Sign1 */
+	QCBOREncode_AddTag(context, CBOR_TAG_COSE_SIGN1);
+	QCBOREncode_OpenArray(context);
+
+	/* Encode protected header */
+	protected_header = build_protected_header();
+	if (UsefulBuf_IsNULLC(protected_header)) {
+		DMSG("Failed to encode protected header payload");
+		return;
+	}
+
+	/* Add protected header */
+	QCBOREncode_AddBytes(context, protected_header);
+
+	/* Add unprotected header (empty map) */
+	QCBOREncode_OpenMap(context);
+	QCBOREncode_CloseMap(context);
+
+	/* Add the payload (evidence CBOR) */
+	QCBOREncode_AddBytes(context, ubc_cbor_evidence);
+
+	/* Encode "To Be Signed" payload */
+	tbs_payload = build_tbs_structure(protected_header, NULLUsefulBufC,
+					  ubc_cbor_evidence);
+	if (UsefulBuf_IsNULLC(tbs_payload)) {
+		DMSG("Failed to encode to-be-signed payload");
+		mempool_free(mempool_default, (void *)protected_header.ptr);
+		return;
+	}
+
+	/* Calculate a signature and add the signature to payload */
+	if (sign_ecdsa_sha256(tbs_payload.ptr, tbs_payload.len, signature,
+			      &signature_len) != TEE_SUCCESS) {
+		DMSG("Failed to sign payload");
+		mempool_free(mempool_default, (void *)protected_header.ptr);
+		mempool_free(mempool_default, (void *)tbs_payload.ptr);
+		return;
+	}
+
+	/* Add the signature */
+	QCBOREncode_AddBytes(context, signature_payload);
+
+	/* Close top level array for COSE_Sign1 */
+	QCBOREncode_CloseArray(context);
+}
+
+static void encode_cbor_evidence_wrapper(QCBOREncodeContext *context,
+					 void *args)
+{
+	struct cbor_evidence_args *evidence_args =
+		(struct cbor_evidence_args *)args;
+
+	encode_cbor_evidence(context, evidence_args->ubc_eat_profile,
+			     evidence_args->psa_client_id,
+			     evidence_args->psa_security_lifecycle,
+			     evidence_args->ubc_psa_implementation_id,
+			     evidence_args->ubc_measurement_type,
+			     evidence_args->ubc_signer_id,
+			     evidence_args->ubc_psa_instance_id,
+			     evidence_args->ubc_psa_nonce,
+			     evidence_args->ubc_measurement_value);
+}
+
+static void encode_cose_evidence_wrapper(QCBOREncodeContext *context,
+					 void *args)
+{
+	struct cose_evidence_args *cose_args =
+		(struct cose_evidence_args *)args;
+
+	encode_cose_evidence(context, cose_args->ubc_cbor_evidence);
+}
+
+static UsefulBufC
+build_cbor_evidence(UsefulBufC ubc_eat_profile, int psa_client_id,
+		    int psa_security_lifecycle,
+		    UsefulBufC ubc_psa_implementation_id,
+		    UsefulBufC ubc_measurement_type, UsefulBufC ubc_signer_id,
+		    UsefulBufC ubc_psa_instance_id, UsefulBufC ubc_psa_nonce,
+		    UsefulBufC ubc_measurement_value)
+{
+	struct cbor_evidence_args args = {
+		.ubc_eat_profile = ubc_eat_profile,
+		.psa_client_id = psa_client_id,
+		.psa_security_lifecycle = psa_security_lifecycle,
+		.ubc_psa_implementation_id = ubc_psa_implementation_id,
+		.ubc_measurement_type = ubc_measurement_type,
+		.ubc_signer_id = ubc_signer_id,
+		.ubc_psa_instance_id = ubc_psa_instance_id,
+		.ubc_psa_nonce = ubc_psa_nonce,
+		.ubc_measurement_value = ubc_measurement_value,
+	};
+
+	return build_encoded_buffer(encode_cbor_evidence_wrapper, &args);
+}
+
+static UsefulBufC build_cose_evidence(UsefulBufC ubc_cbor_evidence)
+{
+	struct cose_evidence_args args = {
+		.ubc_cbor_evidence = ubc_cbor_evidence,
+	};
+
+	return build_encoded_buffer(encode_cose_evidence_wrapper, &args);
+}
+
+UsefulBufC generate_cbor_evidence(const char *eat_profile,
+				  int psa_client_id,
+				  int psa_security_lifecycle,
+				  const uint8_t *psa_implementation_id,
+				  size_t psa_implementation_id_len,
+				  const char *measurement_type,
+				  const uint8_t *signer_id,
+				  size_t signer_id_len,
+				  const uint8_t *psa_instance_id,
+				  size_t psa_instance_id_len,
+				  const uint8_t *psa_nonce,
+				  size_t psa_nonce_len,
+				  const uint8_t *measurement_value,
+				  size_t measurement_value_len)
+{
+	/* prepare usefulbufs because qcbor only accepts them */
+	UsefulBufC ubc_eat_profile = UsefulBuf_FromSZ(eat_profile);
+	UsefulBufC ubc_psa_implementation_id = { psa_implementation_id,
+						 psa_implementation_id_len };
+	UsefulBufC ubc_measurement_type = UsefulBuf_FromSZ(measurement_type);
+	UsefulBufC ubc_signer_id = { signer_id, signer_id_len };
+	UsefulBufC ubc_psa_instance_id = { psa_instance_id,
+					   psa_instance_id_len };
+	UsefulBufC ubc_psa_nonce = { psa_nonce, psa_nonce_len };
+	UsefulBufC ubc_measurement_value = { measurement_value,
+					     measurement_value_len };
+
+	return build_cbor_evidence(ubc_eat_profile,
+				   psa_client_id,
+				   psa_security_lifecycle,
+				   ubc_psa_implementation_id,
+				   ubc_measurement_type,
+				   ubc_signer_id,
+				   ubc_psa_instance_id,
+				   ubc_psa_nonce,
+				   ubc_measurement_value);
+}
+
+UsefulBufC generate_cose_evidence(UsefulBufC ubc_cbor_evidence)
+{
+	return build_cose_evidence(ubc_cbor_evidence);
+}
diff --git a/core/pta/veraison_attestation/cbor.h b/core/pta/veraison_attestation/cbor.h
new file mode 100644
index 0000000000000000000000000000000000000000..3408ff4d9c185c82341aa6405137e0e6318dd25c
--- /dev/null
+++ b/core/pta/veraison_attestation/cbor.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#ifndef PTA_VERAISON_ATTESTATION_CBOR_H
+#define PTA_VERAISON_ATTESTATION_CBOR_H
+
+#include <qcbor.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* PSA claim keys */
+/* https://datatracker.ietf.org/doc/draft-tschofenig-rats-psa-token/13/ */
+#define PSA_NONCE 10
+#define PSA_INSTANCE_ID 256
+#define PSA_PROFILE_DEFINITION 265
+#define PSA_ARM_RANGE_BASE (2393)
+#define PSA_CLIENT_ID (PSA_ARM_RANGE_BASE + 1)
+#define PSA_SECURITY_LIFECYCLE (PSA_ARM_RANGE_BASE + 2)
+#define PSA_IMPLEMENTATION_ID (PSA_ARM_RANGE_BASE + 3)
+#define PSA_BOOT_SEED (PSA_ARM_RANGE_BASE + 4)
+#define PSA_CERTIFICATION_REFERENCE (PSA_ARM_RANGE_BASE + 5)
+#define PSA_SW_COMPONENTS (PSA_ARM_RANGE_BASE + 6)
+#define PSA_VERIFICATION_SERVICE (PSA_ARM_RANGE_BASE + 7)
+
+#define PSA_SW_COMPONENT_MEASUREMENT_TYPE (1)
+#define PSA_SW_COMPONENT_MEASUREMENT_VALUE (2)
+#define PSA_SW_COMPONENT_VERSION (4)
+#define PSA_SW_COMPONENT_SIGNER_ID (5)
+#define PSA_SW_COMPONENT_MEASUREMENT_DESC (6)
+
+#define COSE_HEADER_PARAM_ALG 1
+#define COSE_ALGORITHM_ES256 -7
+#define COSE_SIG_CONTEXT_STRING_SIGNATURE1 "Signature1"
+
+UsefulBufC generate_cbor_evidence(const char *eat_profile,
+				  int psa_client_id,
+				  int psa_security_lifecycle,
+				  const uint8_t *psa_implementation_id,
+				  size_t psa_implementation_id_len,
+				  const char *measurement_type,
+				  const uint8_t *signer_id,
+				  size_t signer_id_len,
+				  const uint8_t *psa_instance_id,
+				  size_t psa_instance_id_len,
+				  const uint8_t *psa_nonce,
+				  size_t psa_nonce_len,
+				  const uint8_t *measurement_value,
+				  size_t measurement_value_len);
+
+UsefulBufC generate_cose_evidence(UsefulBufC ubc_cbor_evidence);
+
+#endif /* PTA_VERAISON_ATTESTATION_CBOR_H */
diff --git a/core/pta/veraison_attestation/hash.c b/core/pta/veraison_attestation/hash.c
new file mode 100644
index 0000000000000000000000000000000000000000..59fc8baeb1335e9cc237293fe9765e6bea5c0e2f
--- /dev/null
+++ b/core/pta/veraison_attestation/hash.c
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#include <crypto/crypto.h>
+#include <kernel/user_mode_ctx.h>
+
+#include "hash.h"
+
+/*
+ * Is region valid for hashing?
+ * Exclude writable regions as well as those that are not specific to the TA
+ * (ldelf, kernel or temporary mappings).
+ */
+static bool is_region_valid(struct vm_region *r)
+{
+	uint32_t dontwant = VM_FLAG_EPHEMERAL | VM_FLAG_PERMANENT |
+			    VM_FLAG_LDELF;
+	uint32_t want = VM_FLAG_READONLY;
+
+	return ((r->flags & want) == want && !(r->flags & dontwant));
+}
+
+/*
+ * With this comparison function, we're hashing the smaller regions first.
+ * Regions of equal size are ordered based on their content (memcmp()).
+ * Identical regions can be in any order since they will yield the same hash
+ * anyways.
+ */
+static int cmp_regions(const void *a, const void *b)
+{
+	const struct vm_region *r1 = *(const struct vm_region **)a;
+	const struct vm_region *r2 = *(const struct vm_region **)b;
+
+	if (r1->size < r2->size)
+		return -1;
+
+	if (r1->size > r2->size)
+		return 1;
+
+	return memcmp((void *)r1->va, (void *)r2->va, r1->size);
+}
+
+static TEE_Result hash_regions(struct vm_info *vm_info,
+			       uint8_t hash[TEE_SHA256_HASH_SIZE])
+{
+	TEE_Result res = TEE_SUCCESS;
+	struct vm_region *r = NULL;
+	struct vm_region **regions = NULL;
+	size_t nregions = 0;
+	void *ctx = NULL;
+	size_t i = 0;
+
+	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
+	if (res)
+		return res;
+
+	res = crypto_hash_init(ctx);
+	if (res)
+		goto out;
+
+	/*
+	 * Make an array of region pointers so we can use qsort() to order it.
+	 */
+
+	TAILQ_FOREACH(r, &vm_info->regions, link)
+		if (is_region_valid(r))
+			nregions++;
+
+	regions = calloc(nregions, sizeof(*regions));
+	if (!regions) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto out;
+	}
+
+	TAILQ_FOREACH(r, &vm_info->regions, link)
+		if (is_region_valid(r))
+			regions[i++] = r;
+
+	/*
+	 * Sort regions so that they are in a consistent order even when TA ASLR
+	 * is enabled.
+	 */
+	qsort(regions, nregions, sizeof(*regions), cmp_regions);
+
+	/* Hash regions in order */
+	for (i = 0; i < nregions; i++) {
+		r = regions[i];
+		DMSG("va %p size %zu", (void *)r->va, r->size);
+		res = crypto_hash_update(ctx, (uint8_t *)r->va, r->size);
+		if (res)
+			goto out;
+	}
+
+	res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE);
+out:
+	free(regions);
+	crypto_hash_free_ctx(ctx);
+	return res;
+}
+
+TEE_Result get_hash_ta_memory(uint8_t out[TEE_SHA256_HASH_SIZE])
+{
+	struct user_mode_ctx *uctx = NULL;
+	TEE_Result res = TEE_SUCCESS;
+	struct ts_session *s = NULL;
+
+	/* Check that we're called from a user TA */
+	s = ts_get_calling_session();
+	if (!s)
+		return TEE_ERROR_ACCESS_DENIED;
+	uctx = to_user_mode_ctx(s->ctx);
+	if (!uctx)
+		return TEE_ERROR_ACCESS_DENIED;
+
+	s = ts_pop_current_session();
+	res = hash_regions(&uctx->vm_info, out);
+	ts_push_current_session(s);
+	return res;
+}
diff --git a/core/pta/veraison_attestation/hash.h b/core/pta/veraison_attestation/hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..2943c1b64419dca9982b441a59451e4ea9daf305
--- /dev/null
+++ b/core/pta/veraison_attestation/hash.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#ifndef PTA_VERAISON_ATTESTATION_HASH_H
+#define PTA_VERAISON_ATTESTATION_HASH_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <tee_api.h>
+
+TEE_Result get_hash_ta_memory(uint8_t out[TEE_SHA256_HASH_SIZE]);
+
+#endif /* PTA_VERAISON_ATTESTATION_HASH_H */
diff --git a/core/pta/veraison_attestation/sign.c b/core/pta/veraison_attestation/sign.c
new file mode 100644
index 0000000000000000000000000000000000000000..c28750ddd7d1c167d565aa123d48bba403b8e990
--- /dev/null
+++ b/core/pta/veraison_attestation/sign.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#include <crypto/crypto.h>
+#include <crypto/crypto_impl.h>
+#include <stdlib_ext.h>
+#include <string.h>
+#include <utee_defines.h>
+
+#include "sign.h"
+
+#define KEY_SIZE 32
+#define KEY_SIZE_BIT (KEY_SIZE * 8)
+
+static struct ecc_keypair *key;
+static struct ecc_public_key *pubkey;
+
+#ifdef CFG_VERAISON_ATTESTATION_PTA_TEST_KEY
+/*
+ * FIXME: Currently, keys are directly embedded within the code. From a security
+ * standpoint these keys should be stored in a secure location and properly
+ * loaded during program execution in a production environment.
+ * The key information has been extracted using the command:
+ *   $ echo "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4=" | base64 -d | xxd -p
+ * (and similar steps for obtaining the x, y, d values).
+ *
+ * {
+ *   "kty": "EC",
+ *   "crv": "P-256",
+ *   "x": "MKBCTNIcKUSDii11ySs3526iDZ8AiTo7Tu6KPAqv7D4",
+ *   "y": "4Etl6SRW2YiLUrN5vfvVHuhp7x8PxltmWWlbbM4IFyM",
+ *   "d": "870MB6gfuTJ4HtUnUvYMyJpr5eUZNP4Bk43bVdj3eAE"
+ * }
+ */
+
+/* clang-format off */
+#define PUBLIC_KEY_X {                                             \
+		0x30, 0xa0, 0x42, 0x4c, 0xd2, 0x1c, 0x29, 0x44,    \
+		0x83, 0x8a, 0x2d, 0x75, 0xc9, 0x2b, 0x37, 0xe7,    \
+		0x6e, 0xa2, 0x0d, 0x9f, 0x00, 0x89, 0x3a, 0x3b,    \
+		0x4e, 0xee, 0x8a, 0x3c, 0x0a, 0xaf, 0xec, 0x3e     \
+	}
+#define PUBLIC_KEY_Y {                                             \
+		0xe0, 0x4b, 0x65, 0xe9, 0x24, 0x56, 0xd9, 0x88,    \
+		0x8b, 0x52, 0xb3, 0x79, 0xbd, 0xfb, 0xd5, 0x1e,    \
+		0xe8, 0x69, 0xef, 0x1f, 0x0f, 0xc6, 0x5b, 0x66,    \
+		0x59, 0x69, 0x5b, 0x6c, 0xce, 0x08, 0x17, 0x23     \
+	}
+#define PRIVATE_KEY {                                              \
+		0xf3, 0xbd, 0x0c, 0x07, 0xa8, 0x1f, 0xb9, 0x32,    \
+		0x78, 0x1e, 0xd5, 0x27, 0x52, 0xf6, 0x0c, 0xc8,    \
+		0x9a, 0x6b, 0xe5, 0xe5, 0x19, 0x34, 0xfe, 0x01,    \
+		0x93, 0x8d, 0xdb, 0x55, 0xd8, 0xf7, 0x78, 0x01     \
+	}
+/* clang-format on */
+#else
+#error "This is experimental code, requires " \
+	"CFG_VERAISON_ATTESTATION_PTA_TEST_KEY=y"
+#endif
+
+static TEE_Result hash_sha256(const uint8_t *msg, size_t msg_len, uint8_t *hash)
+{
+	TEE_Result res = TEE_SUCCESS;
+	void *ctx = NULL;
+
+	res = crypto_hash_alloc_ctx(&ctx, TEE_ALG_SHA256);
+	if (res != TEE_SUCCESS)
+		return res;
+	res = crypto_hash_init(ctx);
+	if (res != TEE_SUCCESS)
+		goto out;
+	res = crypto_hash_update(ctx, msg, msg_len);
+	if (res != TEE_SUCCESS)
+		goto out;
+	res = crypto_hash_final(ctx, hash, TEE_SHA256_HASH_SIZE);
+
+out:
+	crypto_hash_free_ctx(ctx);
+	return res;
+}
+
+static void free_keypair(void)
+{
+	if (!key)
+		return;
+
+	crypto_bignum_free(&key->d);
+	crypto_bignum_free(&key->x);
+	crypto_bignum_free(&key->y);
+
+	free_wipe(key);
+	key = NULL;
+}
+
+static void free_pubkey(void)
+{
+	if (!pubkey)
+		return;
+
+	crypto_bignum_free(&pubkey->x);
+	crypto_bignum_free(&pubkey->y);
+
+	free_wipe(pubkey);
+	pubkey = NULL;
+}
+
+static TEE_Result generate_key(void)
+{
+	TEE_Result res = TEE_SUCCESS;
+	const uint8_t private_key[] = PRIVATE_KEY;
+	const uint8_t public_key_x[] = PUBLIC_KEY_X;
+	const uint8_t public_key_y[] = PUBLIC_KEY_Y;
+
+	/* Allocate a private key storage */
+	assert(!key);
+	key = calloc(1, sizeof(*key));
+	if (!key)
+		return TEE_ERROR_OUT_OF_MEMORY;
+	res = crypto_acipher_alloc_ecc_keypair(key, TEE_TYPE_ECDSA_KEYPAIR,
+					       KEY_SIZE_BIT);
+	if (res != TEE_SUCCESS)
+		goto free_keypair;
+	key->curve = TEE_ECC_CURVE_NIST_P256;
+
+	/* Copy the private key */
+	res = crypto_bignum_bin2bn(private_key, KEY_SIZE, key->d);
+	if (res != TEE_SUCCESS)
+		goto free_keypair;
+
+	/* Allocate a public key storage */
+	assert(!pubkey);
+	pubkey = calloc(1, sizeof(*pubkey));
+	if (!pubkey) {
+		res = TEE_ERROR_OUT_OF_MEMORY;
+		goto free_keypair;
+	}
+	res = crypto_acipher_alloc_ecc_public_key(pubkey,
+						  TEE_TYPE_ECDSA_PUBLIC_KEY,
+						  KEY_SIZE_BIT);
+	if (res != TEE_SUCCESS)
+		goto free_pubkey;
+	pubkey->curve = TEE_ECC_CURVE_NIST_P256;
+
+	/* Copy the public key */
+	res = crypto_bignum_bin2bn(public_key_x, KEY_SIZE, pubkey->x);
+	if (res != TEE_SUCCESS)
+		goto free_pubkey;
+
+	res = crypto_bignum_bin2bn(public_key_y, KEY_SIZE, pubkey->y);
+	if (res != TEE_SUCCESS)
+		goto free_pubkey;
+
+	return TEE_SUCCESS;
+
+free_pubkey:
+	free_pubkey();
+free_keypair:
+	free_keypair();
+
+	return res;
+}
+
+TEE_Result sign_ecdsa_sha256(const uint8_t *msg, size_t msg_len, uint8_t *sig,
+			     size_t *sig_len)
+{
+	TEE_Result res = TEE_SUCCESS;
+	uint8_t hash_msg[TEE_SHA256_HASH_SIZE] = { };
+
+	/* Allocate the key pair*/
+	res = generate_key();
+	if (res != TEE_SUCCESS)
+		return res;
+
+	/* Hash the msg */
+	res = hash_sha256(msg, msg_len, hash_msg);
+	if (res != TEE_SUCCESS)
+		goto free;
+
+	/* Sign the hashed msg by the key pair*/
+	res = crypto_acipher_ecc_sign(TEE_ALG_ECDSA_SHA256, key, hash_msg,
+				      TEE_SHA256_HASH_SIZE, sig, sig_len);
+	if (res != TEE_SUCCESS)
+		goto free;
+
+	/* Verify the signature */
+	res = crypto_acipher_ecc_verify(TEE_ALG_ECDSA_SHA256, pubkey, hash_msg,
+					TEE_SHA256_HASH_SIZE, sig, *sig_len);
+	if (res == TEE_SUCCESS)
+		DMSG("Success to verify");
+	else
+		DMSG("Failed to verify");
+
+free:
+	free_pubkey();
+	assert(!pubkey);
+	free_keypair();
+	assert(!key);
+
+	return res;
+}
diff --git a/core/pta/veraison_attestation/sign.h b/core/pta/veraison_attestation/sign.h
new file mode 100644
index 0000000000000000000000000000000000000000..a64a1142705669b836ba2190ec4376cba5b812f1
--- /dev/null
+++ b/core/pta/veraison_attestation/sign.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#ifndef PTA_VERAISON_ATTESTATION_SIGN_H
+#define PTA_VERAISON_ATTESTATION_SIGN_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <tee_api_types.h>
+
+/**
+ * Sign a message with ECDSA w/ SHA-256
+ * @param msg       The message to sign
+ * @param msg_len   The length of the message to sign
+ * @param sig       [out] Where to store the signature. The signature format
+ *                  follows the specifications in RFC 7518 Section 3.4. This
+ *                  means the signature will be output in a 'plain signature'
+ *                  format, diverging from the traditional ASN.1 DER encoding.
+ *                  In this context, 'plain signature' refers to the direct
+ *                  concatenation of the r and s values of the ECDSA signature,
+ *                  each occupying exactly half of the signature space. When
+ *                  using a 256-bit ECDSA key, r and s are each 32 bytes long.
+ *                  In a plain signature, these values are simply concatenated
+ *                  to produce a total signature of 64 bytes.
+ * @param sig_len   [in/out] The max size and resulting size of the signature.
+ *                  It is important to ensure that the provided buffer is
+ *                  sufficiently large to hold the signature in its specified
+ *                  format. The resulting size will indicate the actual size of
+ *                  the signature in bytes.
+ * @return TEE_SUCCESS if successful
+ */
+TEE_Result sign_ecdsa_sha256(const uint8_t *msg, size_t msg_len, uint8_t *sig,
+			     size_t *sig_len);
+
+#endif /*PTA_VERAISON_ATTESTATION_SIGN_H*/
diff --git a/core/pta/veraison_attestation/sub.mk b/core/pta/veraison_attestation/sub.mk
new file mode 100644
index 0000000000000000000000000000000000000000..b6c2d7f78c144af9250ec974db5608688994ede9
--- /dev/null
+++ b/core/pta/veraison_attestation/sub.mk
@@ -0,0 +1,7 @@
+srcs-$(CFG_VERAISON_ATTESTATION_PTA) += veraison_attestation.c
+srcs-$(CFG_VERAISON_ATTESTATION_PTA) += cbor.c
+srcs-$(CFG_VERAISON_ATTESTATION_PTA) += hash.c
+srcs-$(CFG_VERAISON_ATTESTATION_PTA) += sign.c
+
+cflags-$(CFG_VERAISON_ATTESTATION_PTA) += -Wno-declaration-after-statement
+cflags-$(CFG_VERAISON_ATTESTATION_PTA) += -Wno-redundant-decls
diff --git a/core/pta/veraison_attestation/veraison_attestation.c b/core/pta/veraison_attestation/veraison_attestation.c
new file mode 100644
index 0000000000000000000000000000000000000000..493af70c9c016265ac589b413a7a2413fc5aaff5
--- /dev/null
+++ b/core/pta/veraison_attestation/veraison_attestation.c
@@ -0,0 +1,157 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#include <base64.h>
+#include <kernel/pseudo_ta.h>
+#include <mempool.h>
+#include <pta_veraison_attestation.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "cbor.h"
+#include "hash.h"
+
+#define PTA_NAME "veraison_attestation.pta"
+
+#define MAX_KEY_SIZE 4096
+#define MAX_NONCE_SIZE 64
+#define TEE_SHA256_HASH_SIZE 32
+
+#define EAT_PROFILE "http://arm.com/psa/2.0.0"
+#define CLIENT_ID 1
+#define LIFECYCLE 12288
+#define MEASURMENT_TYPE "PRoT"
+#define SIGNER_ID_LEN 32
+#define INSTANCE_ID_LEN 33
+
+/* clang-format off */
+#define SIGNER_ID {                                                \
+		0xac, 0xbb, 0x11, 0xc7, 0xe4, 0xda, 0x21, 0x72,    \
+		0x05, 0x52, 0x3c, 0xe4, 0xce, 0x1a, 0x24, 0x5a,    \
+		0xe1, 0xa2, 0x39, 0xae, 0x3c, 0x6b, 0xfd, 0x9e,    \
+		0x78, 0x71, 0xf7, 0xe5, 0xd8, 0xba, 0xe8, 0x6b     \
+	}
+#define INSTANCE_ID {                                              \
+		0x01, 0xce, 0xeb, 0xae, 0x7b, 0x89, 0x27, 0xa3,    \
+		0x22, 0x7e, 0x53, 0x03, 0xcf, 0x5e, 0x0f, 0x1f,    \
+		0x7b, 0x34, 0xbb, 0x54, 0x2a, 0xd7, 0x25, 0x0a,    \
+		0xc0, 0x3f, 0xbc, 0xde, 0x36, 0xec, 0x2f, 0x15,    \
+		0x08                                               \
+	}
+/* clang-format on */
+
+static TEE_Result cmd_get_cbor_evidence(uint32_t param_types,
+					TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint8_t *nonce = params[0].memref.buffer;
+	const size_t nonce_sz = params[0].memref.size;
+	uint8_t *output_buffer = params[1].memref.buffer;
+	size_t *output_buffer_len = &params[1].memref.size;
+	const uint8_t *psa_implementation_id = params[2].memref.buffer;
+	const size_t psa_implementation_id_len = params[2].memref.size;
+	TEE_Result status = TEE_SUCCESS;
+
+	const char eat_profile[] = EAT_PROFILE;
+	const int psa_client_id = CLIENT_ID;
+	const int psa_security_lifecycle = LIFECYCLE;
+	const char measurement_type[] = MEASURMENT_TYPE;
+	const uint8_t signer_id[SIGNER_ID_LEN] = SIGNER_ID;
+	const uint8_t psa_instance_id[INSTANCE_ID_LEN] = INSTANCE_ID;
+
+	uint8_t measurement_value[TEE_SHA256_HASH_SIZE] = { 0 };
+	size_t b64_measurement_value_len = TEE_SHA256_HASH_SIZE * 2;
+	char b64_measurement_value[TEE_SHA256_HASH_SIZE * 2] = { 0 };
+
+	UsefulBufC ubc_cbor_evidence = { NULL, 0 };
+	UsefulBufC ubc_cose_evidence = { NULL, 0 };
+
+	if (param_types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INPUT,
+					   TEE_PARAM_TYPE_MEMREF_OUTPUT,
+					   TEE_PARAM_TYPE_MEMREF_INPUT,
+					   TEE_PARAM_TYPE_NONE))
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!nonce || !nonce_sz)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (!output_buffer && *output_buffer_len)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	/* Calculate measurement hash of memory */
+	status = get_hash_ta_memory(measurement_value);
+	if (status != TEE_SUCCESS)
+		return status;
+
+	/* Encode measurement_value to base64 */
+	if (!base64_enc(measurement_value, TEE_SHA256_HASH_SIZE,
+			b64_measurement_value,
+			&b64_measurement_value_len)) {
+		DMSG("Failed to encode measurement_value to base64");
+		return TEE_ERROR_GENERIC;
+	}
+	DMSG("b64_measurement_value: %s", b64_measurement_value);
+
+	/* Encode evidence to CBOR */
+	ubc_cbor_evidence = generate_cbor_evidence(eat_profile,
+						   psa_client_id,
+						   psa_security_lifecycle,
+						   psa_implementation_id,
+						   psa_implementation_id_len,
+						   measurement_type,
+						   signer_id,
+						   SIGNER_ID_LEN,
+						   psa_instance_id,
+						   INSTANCE_ID_LEN,
+						   nonce,
+						   nonce_sz,
+						   measurement_value,
+						   TEE_SHA256_HASH_SIZE);
+	if (UsefulBuf_IsNULLC(ubc_cbor_evidence)) {
+		DMSG("Failed to encode evidence to CBOR");
+		return TEE_ERROR_GENERIC;
+	}
+
+	/* Sign the CBOR and generate a COSE evidence */
+	ubc_cose_evidence = generate_cose_evidence(ubc_cbor_evidence);
+	if (UsefulBuf_IsNULLC(ubc_cose_evidence)) {
+		DMSG("Failed to encode CBOR to COSE");
+		status = TEE_ERROR_GENERIC;
+		goto free_ubc_cbor_evidence;
+	}
+
+	/* Copy COSE evidence for return buffer */
+	if (ubc_cose_evidence.len > *output_buffer_len) {
+		*output_buffer_len = ubc_cose_evidence.len;
+		status = TEE_ERROR_SHORT_BUFFER;
+		goto free_ubc_cose_evidence;
+	}
+	memcpy(output_buffer, ubc_cose_evidence.ptr, ubc_cose_evidence.len);
+	*output_buffer_len = ubc_cose_evidence.len;
+
+	/* Free mempool allocation before returning to the caller */
+free_ubc_cose_evidence:
+	mempool_free(mempool_default, (void *)ubc_cose_evidence.ptr);
+free_ubc_cbor_evidence:
+	mempool_free(mempool_default, (void *)ubc_cbor_evidence.ptr);
+
+	return status;
+}
+
+static TEE_Result invoke_command(void *sess_ctx __unused, uint32_t cmd_id,
+				 uint32_t param_types,
+				 TEE_Param params[TEE_NUM_PARAMS])
+{
+	switch (cmd_id) {
+	case PTA_VERAISON_ATTESTATION_GET_CBOR_EVIDENCE:
+		return cmd_get_cbor_evidence(param_types, params);
+	default:
+		break;
+	}
+	return TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+pseudo_ta_register(.uuid = PTA_VERAISON_ATTESTATION_UUID, .name = PTA_NAME,
+		   .flags = PTA_DEFAULT_FLAGS,
+		   .invoke_command_entry_point = invoke_command);
diff --git a/core/pta/widevine.c b/core/pta/widevine.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f84c9edb9c2f4edc5396b8fcc34817a3a9b505c
--- /dev/null
+++ b/core/pta/widevine.c
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2023, The ChromiumOS Authors
+ */
+
+#include <compiler.h>
+#include <initcall.h>
+#include <kernel/dt.h>
+#include <kernel/pseudo_ta.h>
+#include <kernel/tee_ta_manager.h>
+#include <kernel/ts_manager.h>
+#include <kernel/user_ta.h>
+#include <libfdt.h>
+#include <pta_widevine.h>
+#include <stdint.h>
+#include <string.h>
+#include <tee_api.h>
+#include <util.h>
+
+#define PTA_NAME "widevine.pta"
+
+#define TPM_AUTH_PUB_MAX_SIZE 1024
+#define WIDEVINE_PRIV_MAX_SIZE 32
+
+#define CROS_HWSEC_TA_UUID                                             \
+	{                                                              \
+		0xed800e33, 0x3c58, 0x4cae,                            \
+		{                                                      \
+			0xa7, 0xc0, 0xfd, 0x16, 0x0e, 0x35, 0xe0, 0x0d \
+		}                                                      \
+	}
+#define CROS_HDCP_PROV4_TA_UUID                                        \
+	{                                                              \
+		0x0feb839c, 0xee25, 0x4920,                            \
+		{                                                      \
+			0x8e, 0xe3, 0xac, 0x8d, 0xaa, 0x86, 0x0d, 0x3b \
+		}                                                      \
+	}
+#define TA_OPTEE_OEMCRYPTO_UUID                                        \
+	{                                                              \
+		0xa92d116c, 0xce27, 0x4917,                            \
+		{                                                      \
+			0xb3, 0x0c, 0x4a, 0x41, 0x6e, 0x2d, 0x93, 0x51 \
+		}                                                      \
+	}
+
+static const TEE_UUID allowed_ta_uuids[3] = {
+	CROS_HWSEC_TA_UUID,
+	CROS_HDCP_PROV4_TA_UUID,
+	TA_OPTEE_OEMCRYPTO_UUID,
+};
+
+/*
+ * The TPM auth public key. Used to communicate with the TPM from OP-TEE.
+ * The format of data should be TPM2B_PUBLIC.
+ * For more information, please reference the 12.2.5 section:
+ * https://trustedcomputinggroup.org/wp-content/uploads/TCG_TPM2_r1p59_Part2_Structures_pub.pdf
+ */
+static uint8_t tpm_auth_pub[TPM_AUTH_PUB_MAX_SIZE];
+static uint32_t tpm_auth_pub_size;
+
+/*
+ * The Widevine root of trust secret. Used to sign the widevine
+ * requests in OP-TEE. The value is an ECC NIST P-256 scalar.
+ * For more information, please reference the G.1.2 section:
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-186.pdf
+ */
+static uint8_t widevine_priv[WIDEVINE_PRIV_MAX_SIZE];
+static uint32_t widevine_priv_size;
+
+static TEE_Result init_widevine_dt_data(void)
+{
+	int node = 0;
+	int len = 0;
+	void *fdt = NULL;
+	const void *value = NULL;
+
+	fdt = get_secure_dt();
+	if (!fdt)
+		return TEE_ERROR_NO_DATA;
+
+	node = fdt_path_offset(fdt, "/options/op-tee/widevine");
+	if (node < 0)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	value = fdt_getprop(fdt, node, "tcg,tpm-auth-public-key", &len);
+	if (!value)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (len > TPM_AUTH_PUB_MAX_SIZE)
+		return TEE_ERROR_OVERFLOW;
+
+	memcpy(tpm_auth_pub, value, len);
+	tpm_auth_pub_size = len;
+
+	value = fdt_getprop(fdt, node, "google,widevine-root-of-trust-ecc-p256",
+			    &len);
+	if (!value)
+		return TEE_ERROR_ITEM_NOT_FOUND;
+
+	if (len > WIDEVINE_PRIV_MAX_SIZE)
+		return TEE_ERROR_OVERFLOW;
+
+	memcpy(widevine_priv, value, len);
+	widevine_priv_size = len;
+
+	return TEE_SUCCESS;
+}
+
+service_init(init_widevine_dt_data);
+
+static TEE_Result open_session(uint32_t param_types __unused,
+			       TEE_Param params[TEE_NUM_PARAMS] __unused,
+			       void **sess_ctx __unused)
+{
+	size_t i = 0;
+	struct ts_session *session = ts_get_calling_session();
+
+	/* Make sure we are called from a TA */
+	if (!is_user_ta_ctx(session->ctx))
+		return TEE_ERROR_ACCESS_DENIED;
+
+	/* Make sure we are called from an allowed TA */
+	for (i = 0; i < ARRAY_SIZE(allowed_ta_uuids); i++)
+		if (memcmp(&session->ctx->uuid, &allowed_ta_uuids[i],
+			   sizeof(TEE_UUID)) == 0)
+			return TEE_SUCCESS;
+
+	return TEE_ERROR_ACCESS_DENIED;
+}
+
+static TEE_Result get_dt_data(uint32_t ptypes, TEE_Param params[TEE_NUM_PARAMS],
+			      uint32_t cmd)
+{
+	uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_OUTPUT,
+					  TEE_PARAM_TYPE_NONE,
+					  TEE_PARAM_TYPE_NONE,
+					  TEE_PARAM_TYPE_NONE);
+	uint8_t *data = NULL;
+	uint32_t data_length = 0;
+
+	if (exp_pt != ptypes)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (cmd == PTA_WIDEVINE_GET_TPM_PUBKEY) {
+		data = tpm_auth_pub;
+		data_length = tpm_auth_pub_size;
+	} else if (cmd == PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY) {
+		data = widevine_priv;
+		data_length = widevine_priv_size;
+	} else {
+		return TEE_ERROR_NOT_IMPLEMENTED;
+	}
+
+	if (data_length == 0)
+		return TEE_ERROR_NO_DATA;
+
+	if (data_length > params[0].memref.size) {
+		params[0].memref.size = data_length;
+		return TEE_ERROR_SHORT_BUFFER;
+	}
+
+	params[0].memref.size = data_length;
+	memcpy(params[0].memref.buffer, data, data_length);
+
+	return TEE_SUCCESS;
+}
+
+/*
+ * Trusted Application Entry Points
+ */
+static TEE_Result invoke_command(void *psess __unused, uint32_t cmd,
+				 uint32_t ptypes,
+				 TEE_Param params[TEE_NUM_PARAMS])
+{
+	return get_dt_data(ptypes, params, cmd);
+}
+
+pseudo_ta_register(.uuid = PTA_WIDEVINE_UUID, .name = PTA_NAME,
+		   .flags = PTA_DEFAULT_FLAGS,
+		   .open_session_entry_point = open_session,
+		   .invoke_command_entry_point = invoke_command);
diff --git a/core/tee/entry_std.c b/core/tee/entry_std.c
index d3ae6248624eeebb36d85ce549843e582ae139ae..607ebd4b545f3cc2593876dc7504f538892691fe 100644
--- a/core/tee/entry_std.c
+++ b/core/tee/entry_std.c
@@ -5,7 +5,6 @@
  */
 
 #include <assert.h>
-#include <bench.h>
 #include <compiler.h>
 #include <initcall.h>
 #include <io.h>
@@ -425,8 +424,6 @@ static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params)
 	struct tee_ta_param param = { 0 };
 	uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 };
 
-	bm_timestamp();
-
 	res = copy_in_params(arg->params, num_params, &param, saved_attr);
 	if (res != TEE_SUCCESS)
 		goto out;
@@ -440,8 +437,6 @@ static void entry_invoke_command(struct optee_msg_arg *arg, uint32_t num_params)
 	res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
 				    TEE_TIMEOUT_INFINITE, arg->func, &param);
 
-	bm_timestamp();
-
 	tee_ta_put_session(s);
 
 	copy_out_param(&param, num_params, arg->params, saved_attr);
diff --git a/core/tee/fs_dirfile.c b/core/tee/fs_dirfile.c
index 0cf0fad38c6ad841b80d9a5ce9c4923591cc9dc7..ee623a78e5af32511608c72bcaf6c4a0983fbe62 100644
--- a/core/tee/fs_dirfile.c
+++ b/core/tee/fs_dirfile.c
@@ -369,7 +369,7 @@ TEE_Result tee_fs_dirfile_get_next(struct tee_fs_dirfile_dirh *dirh,
 {
 	TEE_Result res;
 	int i = *idx + 1;
-	struct dirfile_entry dent;
+	struct dirfile_entry dent = { };
 
 	if (i < 0)
 		i = 0;
diff --git a/core/tee/tadb.c b/core/tee/tadb.c
index b5a787de472400834a67cee2012334e00422c25c..fbecd3c4ac58ef755dd7a890d140094b0277a5b6 100644
--- a/core/tee/tadb.c
+++ b/core/tee/tadb.c
@@ -18,7 +18,6 @@
 #include <tee/tee_fs.h>
 #include <tee/tee_fs_rpc.h>
 #include <tee/tee_pobj.h>
-#include <tee/tee_svc_storage.h>
 #include <utee_defines.h>
 
 #define TADB_MAX_BUFFER_SIZE	(64U * 1024)
@@ -335,7 +334,7 @@ static TEE_Result populate_files(struct tee_tadb_dir *db)
 	 * unexpected side effects.
 	 */
 	for (idx = 0;; idx++) {
-		struct tadb_entry entry;
+		struct tadb_entry entry = { };
 
 		res = read_ent(db, idx, &entry);
 		if (res) {
diff --git a/core/tee/tee_cryp_utl.c b/core/tee/tee_cryp_utl.c
index 3220c1677a057b4a2accaf7e54557b72da9db820..cf03a5756fd87298d2fb58e47953f55dafe683c9 100644
--- a/core/tee/tee_cryp_utl.c
+++ b/core/tee/tee_cryp_utl.c
@@ -9,7 +9,6 @@
 #include <kernel/dt_driver.h>
 #include <kernel/panic.h>
 #include <kernel/tee_time.h>
-#include <rng_support.h>
 #include <stdlib.h>
 #include <string_ext.h>
 #include <string.h>
@@ -172,7 +171,7 @@ __weak void plat_prng_add_jitter_entropy(enum crypto_rng_src sid,
 		crypto_rng_add_event(sid, pnum, &current, sizeof(current));
 }
 
-__weak void plat_rng_init(void)
+void __plat_rng_init(void)
 {
 	TEE_Result res = TEE_SUCCESS;
 	TEE_Time t;
@@ -201,6 +200,8 @@ __weak void plat_rng_init(void)
 	}
 }
 
+void plat_rng_init(void) __weak __alias("__plat_rng_init");
+
 static TEE_Result tee_cryp_init(void)
 {
 	TEE_Result res = crypto_init();
@@ -215,4 +216,4 @@ static TEE_Result tee_cryp_init(void)
 
 	return TEE_SUCCESS;
 }
-service_init(tee_cryp_init);
+service_init_crypto(tee_cryp_init);
diff --git a/core/tee/tee_fs_key_manager.c b/core/tee/tee_fs_key_manager.c
index 00bafca2af807eb472c9673fc3b672522e0bd173..392fa4df5887f64a2f01168c514eac5f447fb2c4 100644
--- a/core/tee/tee_fs_key_manager.c
+++ b/core/tee/tee_fs_key_manager.c
@@ -20,7 +20,6 @@
 #include <crypto/crypto.h>
 #include <initcall.h>
 #include <kernel/huk_subkey.h>
-#include <kernel/panic.h>
 #include <kernel/tee_common_otp.h>
 #include <kernel/tee_ta_manager.h>
 #include <stdlib.h>
diff --git a/core/tee/tee_fs_rpc.c b/core/tee/tee_fs_rpc.c
index e0d54e1613721f8ae77904c576b2b27e76c4eb12..8066841e4f938ada2f01d79b53af22e132c2f8f2 100644
--- a/core/tee/tee_fs_rpc.c
+++ b/core/tee/tee_fs_rpc.c
@@ -9,13 +9,9 @@
 #include <mm/core_memprot.h>
 #include <optee_rpc_cmd.h>
 #include <stdlib.h>
-#include <string_ext.h>
-#include <string.h>
 #include <tee/fs_dirfile.h>
 #include <tee/tee_fs.h>
 #include <tee/tee_fs_rpc.h>
-#include <tee/tee_pobj.h>
-#include <tee/tee_svc_storage.h>
 #include <trace.h>
 #include <util.h>
 
diff --git a/core/tee/tee_obj.c b/core/tee/tee_obj.c
index 2d091e461106b8a075740730343b1329bf31846c..afffe025944bdb4ee1884dc01d1703073906ca05 100644
--- a/core/tee/tee_obj.c
+++ b/core/tee/tee_obj.c
@@ -10,7 +10,6 @@
 #include <tee/tee_obj.h>
 #include <tee/tee_pobj.h>
 #include <tee/tee_svc_cryp.h>
-#include <tee/tee_svc_storage.h>
 #include <trace.h>
 
 void tee_obj_add(struct user_ta_ctx *utc, struct tee_obj *o)
diff --git a/core/tee/tee_pobj.c b/core/tee/tee_pobj.c
index cabf49df756d7d5d0f812b60d9e96d8bdc4ad18c..efc75ba868265c13e0475dd364ceaa9c6b15b34f 100644
--- a/core/tee/tee_pobj.c
+++ b/core/tee/tee_pobj.c
@@ -7,7 +7,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <tee/tee_pobj.h>
-#include <trace.h>
 
 static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs =
 		TAILQ_HEAD_INITIALIZER(tee_pobjs);
diff --git a/core/tee/tee_ree_fs.c b/core/tee/tee_ree_fs.c
index 2e44ec48da90dc836a9dc0c03fc601920267c0b4..b18b995ee31f34a5e3e815d7be57ffe60a034092 100644
--- a/core/tee/tee_ree_fs.c
+++ b/core/tee/tee_ree_fs.c
@@ -14,9 +14,7 @@
 #include <mm/core_memprot.h>
 #include <mm/tee_pager.h>
 #include <optee_rpc_cmd.h>
-#include <stdio.h>
 #include <stdlib.h>
-#include <string_ext.h>
 #include <string.h>
 #include <sys/queue.h>
 #include <tee/fs_dirfile.h>
@@ -286,8 +284,8 @@ static TEE_Result ree_fs_ftruncate_internal(struct tee_fs_fd *fdp,
 		size_t sz;
 
 		res = get_offs_size(TEE_FS_HTREE_TYPE_BLOCK,
-				    ROUNDUP(new_file_len, BLOCK_SIZE) /
-					BLOCK_SIZE, 1, &offs, &sz);
+				    ROUNDUP_DIV(new_file_len, BLOCK_SIZE), 1,
+				    &offs, &sz);
 		if (res != TEE_SUCCESS)
 			return res;
 
@@ -512,6 +510,14 @@ static const struct tee_fs_dirfile_operations ree_dirf_ops = {
 	.commit_writes = ree_dirf_commit_writes,
 };
 
+/*
+ * ree_fs_dirh is caching the dirfile handle to avoid frequent opening and
+ * closing of that handle. When ree_fs_dirh_refcount reaches 0, ree_fs_dirh
+ * will be freed. However, ree_fs_dirh_refcount > 0 is not a guarantee that
+ * ree_fs_dirh will not be freed, it may very well be freed earlier in an
+ * error path. get_dirh() must be used to get the ree_fs_dirh pointer each
+ * time it's needed if ree_fs_mutex has been unlocked in between.
+ */
 static struct tee_fs_dirfile_dirh *ree_fs_dirh;
 static size_t ree_fs_dirh_refcount;
 
@@ -1017,7 +1023,8 @@ static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid,
 				     struct tee_fs_dir **dir)
 
 {
-	TEE_Result res;
+	TEE_Result res = TEE_SUCCESS;
+	struct tee_fs_dirfile_dirh *dirh = NULL;
 	struct tee_fs_dir *d = calloc(1, sizeof(*d));
 
 	if (!d)
@@ -1027,14 +1034,14 @@ static TEE_Result ree_fs_opendir_rpc(const TEE_UUID *uuid,
 
 	mutex_lock(&ree_fs_mutex);
 
-	res = get_dirh(&d->dirh);
+	res = get_dirh(&dirh);
 	if (res)
 		goto out;
 
 	/* See that there's at least one file */
 	d->idx = -1;
 	d->d.oidlen = sizeof(d->d.oid);
-	res = tee_fs_dirfile_get_next(d->dirh, d->uuid, &d->idx, d->d.oid,
+	res = tee_fs_dirfile_get_next(dirh, d->uuid, &d->idx, d->d.oid,
 				      &d->d.oidlen);
 	d->idx = -1;
 
@@ -1043,7 +1050,7 @@ out:
 		*dir = d;
 	} else {
 		if (d)
-			put_dirh(d->dirh, false);
+			put_dirh(dirh, false);
 		free(d);
 	}
 	mutex_unlock(&ree_fs_mutex);
@@ -1056,7 +1063,7 @@ static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
 	if (d) {
 		mutex_lock(&ree_fs_mutex);
 
-		put_dirh(d->dirh, false);
+		put_dirh(ree_fs_dirh, false);
 		free(d);
 
 		mutex_unlock(&ree_fs_mutex);
@@ -1066,16 +1073,23 @@ static void ree_fs_closedir_rpc(struct tee_fs_dir *d)
 static TEE_Result ree_fs_readdir_rpc(struct tee_fs_dir *d,
 				     struct tee_fs_dirent **ent)
 {
-	TEE_Result res;
+	struct tee_fs_dirfile_dirh *dirh = NULL;
+	TEE_Result res = TEE_SUCCESS;
 
 	mutex_lock(&ree_fs_mutex);
 
+	res = get_dirh(&dirh);
+	if (res)
+		goto out;
+
 	d->d.oidlen = sizeof(d->d.oid);
-	res = tee_fs_dirfile_get_next(d->dirh, d->uuid, &d->idx, d->d.oid,
+	res = tee_fs_dirfile_get_next(dirh, d->uuid, &d->idx, d->d.oid,
 				      &d->d.oidlen);
 	if (res == TEE_SUCCESS)
 		*ent = &d->d;
 
+	put_dirh(dirh, res);
+out:
 	mutex_unlock(&ree_fs_mutex);
 
 	return res;
diff --git a/core/tee/tee_rpmb_fs.c b/core/tee/tee_rpmb_fs.c
index 0ed30933b3f301c225e70ef805c4a1f1b8744775..b54d92c76b99b64e8994b8fa8676378b6a49fc9e 100644
--- a/core/tee/tee_rpmb_fs.c
+++ b/core/tee/tee_rpmb_fs.c
@@ -255,6 +255,9 @@ struct rpmb_dev_info {
  * @key_derived      Flag indicating if key has been generated.
  * @key_verified     Flag indicating the key generated is verified ok.
  * @dev_info_synced  Flag indicating if dev info has been retrieved from RPMB.
+ * @legacy_operation Flag indicating if the legacy interface is used.
+ * @reinit           Flag indicating if the device needs to be found again
+ * @shm_type         Indicates type of shared memory to allocate
  */
 struct tee_rpmb_ctx {
 	uint8_t key[RPMB_KEY_MAC_SIZE];
@@ -267,6 +270,9 @@ struct tee_rpmb_ctx {
 	bool key_derived;
 	bool key_verified;
 	bool dev_info_synced;
+	bool legacy_operation;
+	bool reinit;
+	enum thread_shm_type shm_type;
 };
 
 static struct tee_rpmb_ctx *rpmb_ctx;
@@ -290,8 +296,7 @@ static const uint8_t rpmb_test_key[RPMB_KEY_MAC_SIZE] = {
 	0xAB, 0x56, 0xE6, 0xC6, 0x1B, 0xB7, 0x01, 0xE4
 };
 
-static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused,
-				   uint8_t *key, uint32_t len)
+static TEE_Result tee_rpmb_key_gen(uint8_t *key, uint32_t len)
 {
 	TEE_Result res = TEE_SUCCESS;
 
@@ -309,8 +314,7 @@ out:
 
 #else /* !CFG_RPMB_TESTKEY */
 
-static TEE_Result tee_rpmb_key_gen(uint16_t dev_id __unused,
-				   uint8_t *key, uint32_t len)
+static TEE_Result tee_rpmb_key_gen(uint8_t *key, uint32_t len)
 {
 	uint8_t message[RPMB_EMMC_CID_SIZE];
 
@@ -406,74 +410,139 @@ func_exit:
 }
 
 struct tee_rpmb_mem {
-	struct mobj *phreq_mobj;
-	struct mobj *phresp_mobj;
+	struct mobj *mobj;
 	size_t req_size;
+	size_t resp_offs;
 	size_t resp_size;
+	struct rpmb_req *req_hdr;
+	struct rpmb_data_frame *req_data;
+	struct rpmb_data_frame *resp_data;
 };
 
-static void tee_rpmb_free(struct tee_rpmb_mem *mem)
+static TEE_Result tee_rpmb_alloc(size_t req_size, size_t resp_size,
+				 struct tee_rpmb_mem *mem)
 {
+	size_t req_s = 0;
+	size_t resp_s = 0;
+	struct mobj *mobj = NULL;
+	void *va = NULL;
+
 	if (!mem)
-		return;
+		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (mem->phreq_mobj) {
-		thread_rpc_free_payload(mem->phreq_mobj);
-		mem->phreq_mobj = NULL;
-	}
-	if (mem->phresp_mobj) {
-		thread_rpc_free_payload(mem->phresp_mobj);
-		mem->phresp_mobj = NULL;
+	if (rpmb_ctx->legacy_operation)
+		req_size += sizeof(struct rpmb_req);
+	req_s = ROUNDUP(req_size, SMALL_PAGE_SIZE);
+	resp_s = ROUNDUP(resp_size, SMALL_PAGE_SIZE);
+	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_RPMB,
+					rpmb_ctx->shm_type, req_s + resp_s,
+					&mobj);
+	if (!va)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	*mem = (struct tee_rpmb_mem){
+		.mobj = mobj,
+		.req_size = req_size,
+		.resp_offs = req_s,
+		.resp_size = resp_size,
+	};
+
+	if (rpmb_ctx->legacy_operation) {
+		mem->req_hdr = mobj_get_va(mem->mobj, 0, req_s);
+		if (!mem->req_hdr)
+			return TEE_ERROR_GENERIC;
+		mem->req_data = (void *)(mem->req_hdr + 1);
+	} else {
+		mem->req_data = mobj_get_va(mem->mobj, 0, req_s);
+		if (!mem->req_data)
+			return TEE_ERROR_GENERIC;
 	}
+	mem->resp_data = mobj_get_va(mem->mobj, req_s, resp_s);
+	if (!mem->resp_data)
+		return TEE_ERROR_GENERIC;
+
+	return TEE_SUCCESS;
 }
 
+static TEE_Result tee_rpmb_invoke(struct tee_rpmb_mem *mem)
+{
+	struct thread_param params[2] = {
+		[0] = THREAD_PARAM_MEMREF(IN, mem->mobj, 0, mem->req_size),
+		[1] = THREAD_PARAM_MEMREF(OUT, mem->mobj, mem->resp_offs,
+					  mem->resp_size),
+	};
+	uint32_t cmd = OPTEE_RPC_CMD_RPMB_FRAMES;
 
-static TEE_Result tee_rpmb_alloc(size_t req_size, size_t resp_size,
-		struct tee_rpmb_mem *mem, void **req, void **resp)
+	if (rpmb_ctx->legacy_operation)
+		cmd = OPTEE_RPC_CMD_RPMB;
+
+	return thread_rpc_cmd(cmd, 2, params);
+}
+
+static TEE_Result rpmb_probe_reset(void)
 {
+	struct thread_param params[1] = {
+		[0] = THREAD_PARAM_VALUE(OUT, 0, 0, 0),
+	};
 	TEE_Result res = TEE_SUCCESS;
-	size_t req_s = ROUNDUP(req_size, sizeof(uint32_t));
-	size_t resp_s = ROUNDUP(resp_size, sizeof(uint32_t));
 
-	if (!mem)
-		return TEE_ERROR_BAD_PARAMETERS;
-
-	memset(mem, 0, sizeof(*mem));
+	res = thread_rpc_cmd(OPTEE_RPC_CMD_RPMB_PROBE_RESET, 1, params);
+	if (res)
+		return res;
 
-	mem->phreq_mobj = thread_rpc_alloc_payload(req_s);
-	mem->phresp_mobj = thread_rpc_alloc_payload(resp_s);
+	rpmb_ctx->legacy_operation = false;
+	rpmb_ctx->dev_id = 0;
 
-	if (!mem->phreq_mobj || !mem->phresp_mobj) {
-		res = TEE_ERROR_OUT_OF_MEMORY;
-		goto out;
+	switch (params[0].u.value.a) {
+	case OPTEE_RPC_SHM_TYPE_APPL:
+		rpmb_ctx->shm_type = THREAD_SHM_TYPE_APPLICATION;
+		return TEE_SUCCESS;
+	case OPTEE_RPC_SHM_TYPE_KERNEL:
+		rpmb_ctx->shm_type = THREAD_SHM_TYPE_KERNEL_PRIVATE;
+		return TEE_SUCCESS;
+	default:
+		return TEE_ERROR_GENERIC;
 	}
+}
 
-	*req = mobj_get_va(mem->phreq_mobj, 0, req_s);
-	*resp = mobj_get_va(mem->phresp_mobj, 0, resp_s);
-	if (!*req || !*resp) {
-		res = TEE_ERROR_GENERIC;
-		goto out;
-	}
+static TEE_Result rpmb_probe_next(struct rpmb_dev_info *dev_info)
+{
+	struct thread_param params[2] = { };
+	TEE_Result res = TEE_SUCCESS;
+	struct mobj *mobj = NULL;
+	void *va = NULL;
 
-	mem->req_size = req_size;
-	mem->resp_size = resp_size;
+	va = thread_rpc_shm_cache_alloc(THREAD_SHM_CACHE_USER_RPMB,
+					THREAD_SHM_TYPE_KERNEL_PRIVATE,
+					sizeof(dev_info->cid), &mobj);
+	if (!va)
+		return TEE_ERROR_OUT_OF_MEMORY;
 
-out:
-	if (res != TEE_SUCCESS)
-		tee_rpmb_free(mem);
-	return res;
-}
+	do {
+		params[0] = THREAD_PARAM_VALUE(OUT, 0, 0, 0);
+		params[1] = THREAD_PARAM_MEMREF(OUT, mobj, 0,
+						sizeof(dev_info->cid));
+		res = thread_rpc_cmd(OPTEE_RPC_CMD_RPMB_PROBE_NEXT, 2, params);
+		/*
+		 * If the ID buffer is too small, perhaps it's a new kind
+		 * of RPMB device that we don't know how to communicate
+		 * with, let's ignore it for now.
+		 */
+	} while (res == TEE_ERROR_SHORT_BUFFER);
+	if (res)
+		return res;
 
-static TEE_Result tee_rpmb_invoke(struct tee_rpmb_mem *mem)
-{
-	struct thread_param params[2] = {
-		[0] = THREAD_PARAM_MEMREF(IN, mem->phreq_mobj, 0,
-					  mem->req_size),
-		[1] = THREAD_PARAM_MEMREF(OUT, mem->phresp_mobj, 0,
-					  mem->resp_size),
+	if (params[0].u.value.a != OPTEE_RPC_RPMB_EMMC)
+		return TEE_ERROR_NOT_SUPPORTED;
+
+	*dev_info = (struct rpmb_dev_info){
+		.rpmb_size_mult = params[0].u.value.b,
+		.rel_wr_sec_c = params[0].u.value.c,
+		.ret_code = RPMB_CMD_GET_DEV_INFO_RET_OK,
 	};
+	memcpy(dev_info->cid, va, sizeof(dev_info->cid));
 
-	return thread_rpc_cmd(OPTEE_RPC_CMD_RPMB, 2, params);
+	return TEE_SUCCESS;
 }
 
 static bool is_zero(const uint8_t *buf, size_t size)
@@ -543,16 +612,17 @@ static TEE_Result decrypt(uint8_t *out, const struct rpmb_data_frame *frm,
 	return res;
 }
 
-static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req,
+static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req_hdr,
+				    struct rpmb_data_frame *req_data,
 				    struct rpmb_raw_data *rawdata,
-				    uint16_t nbr_frms, uint16_t dev_id,
+				    uint16_t nbr_frms,
 				    const uint8_t *fek, const TEE_UUID *uuid)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	int i;
 	struct rpmb_data_frame *datafrm;
 
-	if (!req || !rawdata || !nbr_frms)
+	if (!req_data || !rawdata || !nbr_frms)
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	/*
@@ -566,8 +636,10 @@ static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req,
 		return TEE_ERROR_GENERIC;
 	}
 
-	req->cmd = RPMB_CMD_DATA_REQ;
-	req->dev_id = dev_id;
+	if (req_hdr) {
+		req_hdr->cmd = RPMB_CMD_DATA_REQ;
+		req_hdr->dev_id = rpmb_ctx->dev_id;
+	}
 
 	/* Allocate memory for construct all data packets and calculate MAC. */
 	datafrm = calloc(nbr_frms, RPMB_DATA_FRAME_SIZE);
@@ -630,8 +702,7 @@ static TEE_Result tee_rpmb_req_pack(struct rpmb_req *req,
 		       rawdata->key_mac, RPMB_KEY_MAC_SIZE);
 	}
 
-	memcpy(TEE_RPMB_REQ_DATA(req), datafrm,
-	       nbr_frms * RPMB_DATA_FRAME_SIZE);
+	memcpy(req_data, datafrm, nbr_frms * RPMB_DATA_FRAME_SIZE);
 
 	if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) {
 		for (i = 0; i < nbr_frms; i++) {
@@ -886,84 +957,61 @@ static TEE_Result tee_rpmb_resp_unpack_verify(struct rpmb_data_frame *datafrm,
 	return TEE_SUCCESS;
 }
 
-static TEE_Result tee_rpmb_get_dev_info(uint16_t dev_id,
-					struct rpmb_dev_info *dev_info)
+static TEE_Result tee_rpmb_get_dev_info(struct rpmb_dev_info *dev_info)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	struct tee_rpmb_mem mem;
 	struct rpmb_dev_info *di;
-	struct rpmb_req *req = NULL;
-	uint8_t *resp = NULL;
-	uint32_t req_size;
-	uint32_t resp_size;
 
-	if (!dev_info)
+	if (!dev_info || !rpmb_ctx->legacy_operation)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	req_size = sizeof(struct rpmb_req);
-	resp_size = sizeof(struct rpmb_dev_info);
-	res = tee_rpmb_alloc(req_size, resp_size, &mem,
-			     (void *)&req, (void *)&resp);
+	res = tee_rpmb_alloc(0, sizeof(struct rpmb_dev_info), &mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
-	req->cmd = RPMB_CMD_GET_DEV_INFO;
-	req->dev_id = dev_id;
+	mem.req_hdr->cmd = RPMB_CMD_GET_DEV_INFO;
+	mem.req_hdr->dev_id = rpmb_ctx->dev_id;
 
-	di = (struct rpmb_dev_info *)resp;
+	di = (struct rpmb_dev_info *)mem.resp_data;
 	di->ret_code = RPMB_CMD_GET_DEV_INFO_RET_ERROR;
 
 	res = tee_rpmb_invoke(&mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
-
-	if (di->ret_code != RPMB_CMD_GET_DEV_INFO_RET_OK) {
-		res = TEE_ERROR_GENERIC;
-		goto func_exit;
-	}
+		return res;
 
-	memcpy((uint8_t *)dev_info, resp, sizeof(struct rpmb_dev_info));
+	*dev_info = *di;
+	if (dev_info->ret_code != RPMB_CMD_GET_DEV_INFO_RET_OK)
+		return TEE_ERROR_GENERIC;
 
 	if (IS_ENABLED(CFG_RPMB_FS_DEBUG_DATA)) {
 		DMSG("Dumping dev_info:");
 		DHEXDUMP((uint8_t *)dev_info, sizeof(struct rpmb_dev_info));
 	}
 
-	res = TEE_SUCCESS;
-
-func_exit:
-	tee_rpmb_free(&mem);
-	return res;
+	return TEE_SUCCESS;
 }
 
-static TEE_Result tee_rpmb_init_read_wr_cnt(uint16_t dev_id,
-					    uint32_t *wr_cnt,
-					    uint16_t *op_result)
+static TEE_Result tee_rpmb_init_read_wr_cnt(uint32_t *wr_cnt)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	struct tee_rpmb_mem mem;
 	uint16_t msg_type;
 	uint8_t nonce[RPMB_NONCE_SIZE];
 	uint8_t hmac[RPMB_KEY_MAC_SIZE];
-	struct rpmb_req *req = NULL;
-	struct rpmb_data_frame *resp = NULL;
 	struct rpmb_raw_data rawdata;
-	uint32_t req_size;
-	uint32_t resp_size;
+	uint16_t op_result = 0;
 
 	if (!wr_cnt)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
-	resp_size = RPMB_DATA_FRAME_SIZE;
-	res = tee_rpmb_alloc(req_size, resp_size, &mem,
-			     (void *)&req, (void *)&resp);
+	res = tee_rpmb_alloc(RPMB_DATA_FRAME_SIZE, RPMB_DATA_FRAME_SIZE, &mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	res = crypto_rng_read(nonce, RPMB_NONCE_SIZE);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_REQ_WRITE_COUNTER_VAL_READ;
 
@@ -971,68 +1019,39 @@ static TEE_Result tee_rpmb_init_read_wr_cnt(uint16_t dev_id,
 	rawdata.msg_type = msg_type;
 	rawdata.nonce = nonce;
 
-	res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL);
+	res = tee_rpmb_req_pack(mem.req_hdr, mem.req_data, &rawdata, 1, NULL,
+				NULL);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	res = tee_rpmb_invoke(&mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_RESP_WRITE_COUNTER_VAL_READ;
 
 	memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
 	rawdata.msg_type = msg_type;
-	rawdata.op_result = op_result;
+	rawdata.op_result = &op_result;
 	rawdata.write_counter = wr_cnt;
 	rawdata.nonce = nonce;
 	rawdata.key_mac = hmac;
 
-	res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, NULL);
-	if (res != TEE_SUCCESS)
-		goto func_exit;
-
-	res = TEE_SUCCESS;
-
-func_exit:
-	tee_rpmb_free(&mem);
-	return res;
-}
-
-static TEE_Result tee_rpmb_verify_key_sync_counter(uint16_t dev_id)
-{
-	uint16_t op_result = 0;
-	TEE_Result res = TEE_ERROR_GENERIC;
-
-	res = tee_rpmb_init_read_wr_cnt(dev_id, &rpmb_ctx->wr_cnt,
-					&op_result);
-
-	if (res == TEE_SUCCESS) {
-		rpmb_ctx->key_verified = true;
-		rpmb_ctx->wr_cnt_synced = true;
-	} else
-		EMSG("Verify key returning 0x%x", res);
-	return res;
+	return tee_rpmb_resp_unpack_verify(mem.resp_data, &rawdata, 1, NULL,
+					   NULL);
 }
 
 #ifdef CFG_RPMB_WRITE_KEY
-static TEE_Result tee_rpmb_write_key(uint16_t dev_id)
+static TEE_Result tee_rpmb_write_key(void)
 {
 	TEE_Result res = TEE_ERROR_GENERIC;
 	struct tee_rpmb_mem mem = { 0 };
 	uint16_t msg_type;
-	struct rpmb_req *req = NULL;
-	struct rpmb_data_frame *resp = NULL;
 	struct rpmb_raw_data rawdata;
-	uint32_t req_size;
-	uint32_t resp_size;
 
-	req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
-	resp_size = RPMB_DATA_FRAME_SIZE;
-	res = tee_rpmb_alloc(req_size, resp_size, &mem,
-			     (void *)&req, (void *)&resp);
+	res = tee_rpmb_alloc(RPMB_DATA_FRAME_SIZE, RPMB_DATA_FRAME_SIZE, &mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_REQ_AUTH_KEY_PROGRAM;
 
@@ -1040,31 +1059,25 @@ static TEE_Result tee_rpmb_write_key(uint16_t dev_id)
 	rawdata.msg_type = msg_type;
 	rawdata.key_mac = rpmb_ctx->key;
 
-	res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL);
+	res = tee_rpmb_req_pack(mem.req_hdr, mem.req_data, &rawdata, 1, NULL,
+				NULL);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	res = tee_rpmb_invoke(&mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_RESP_AUTH_KEY_PROGRAM;
 
 	memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
 	rawdata.msg_type = msg_type;
 
-	res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL, NULL);
-	if (res != TEE_SUCCESS)
-		goto func_exit;
-
-	res = TEE_SUCCESS;
-
-func_exit:
-	tee_rpmb_free(&mem);
-	return res;
+	return tee_rpmb_resp_unpack_verify(mem.resp_data, &rawdata, 1, NULL,
+					   NULL);
 }
 
-static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id)
+static TEE_Result tee_rpmb_write_and_verify_key(void)
 {
 	TEE_Result res;
 
@@ -1076,73 +1089,71 @@ static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id)
 	DMSG("RPMB INIT: Writing Key value:");
 	DHEXDUMP(rpmb_ctx->key, RPMB_KEY_MAC_SIZE);
 
-	res = tee_rpmb_write_key(dev_id);
+	res = tee_rpmb_write_key();
 	if (res == TEE_SUCCESS) {
 		DMSG("RPMB INIT: Verifying Key");
-		res = tee_rpmb_verify_key_sync_counter(dev_id);
+		res = tee_rpmb_init_read_wr_cnt(&rpmb_ctx->wr_cnt);
 	}
 	return res;
 }
 #else
-static TEE_Result tee_rpmb_write_and_verify_key(uint16_t dev_id __unused)
+static TEE_Result tee_rpmb_write_and_verify_key(void)
 {
 	DMSG("RPMB INIT: CFG_RPMB_WRITE_KEY is not set");
 	return TEE_ERROR_STORAGE_NOT_AVAILABLE;
 }
 #endif
 
-/* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */
-static TEE_Result tee_rpmb_init(uint16_t dev_id)
+static TEE_Result rpmb_set_dev_info(const struct rpmb_dev_info *dev_info)
 {
-	TEE_Result res = TEE_SUCCESS;
-	struct rpmb_dev_info dev_info = { };
 	uint32_t nblocks = 0;
 
-	if (rpmb_dead)
-		return TEE_ERROR_COMMUNICATION;
+	DMSG("RPMB: Syncing device information");
 
-	if (!rpmb_ctx) {
-		rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx));
-		if (!rpmb_ctx)
-			return TEE_ERROR_OUT_OF_MEMORY;
-	} else if (rpmb_ctx->dev_id != dev_id) {
-		memset(rpmb_ctx, 0x00, sizeof(struct tee_rpmb_ctx));
-	}
+	DMSG("RPMB: RPMB size is %"PRIu8"*128 KB", dev_info->rpmb_size_mult);
+	DMSG("RPMB: Reliable Write Sector Count is %"PRIu8,
+	     dev_info->rel_wr_sec_c);
+	DMSG("RPMB: CID");
+	DHEXDUMP(dev_info->cid, sizeof(dev_info->cid));
 
-	rpmb_ctx->dev_id = dev_id;
+	if (!dev_info->rpmb_size_mult)
+		return TEE_ERROR_GENERIC;
 
-	if (!rpmb_ctx->dev_info_synced) {
-		DMSG("RPMB: Syncing device information");
+	if (MUL_OVERFLOW(dev_info->rpmb_size_mult,
+			 RPMB_SIZE_SINGLE / RPMB_DATA_SIZE, &nblocks) ||
+	    SUB_OVERFLOW(nblocks, 1, &rpmb_ctx->max_blk_idx))
+		return TEE_ERROR_BAD_PARAMETERS;
 
-		dev_info.rpmb_size_mult = 0;
-		dev_info.rel_wr_sec_c = 0;
-		res = tee_rpmb_get_dev_info(dev_id, &dev_info);
-		if (res != TEE_SUCCESS)
-			goto func_exit;
+	memcpy(rpmb_ctx->cid, dev_info->cid, RPMB_EMMC_CID_SIZE);
 
-		DMSG("RPMB: RPMB size is %d*128 KB", dev_info.rpmb_size_mult);
-		DMSG("RPMB: Reliable Write Sector Count is %d",
-		     dev_info.rel_wr_sec_c);
+	if (IS_ENABLED(RPMB_DRIVER_MULTIPLE_WRITE_FIXED))
+		rpmb_ctx->rel_wr_blkcnt = dev_info->rel_wr_sec_c * 2;
+	else
+		rpmb_ctx->rel_wr_blkcnt = 1;
 
-		if (dev_info.rpmb_size_mult == 0) {
-			res = TEE_ERROR_GENERIC;
-			goto func_exit;
-		}
+	return TEE_SUCCESS;
+}
 
-		if (MUL_OVERFLOW(dev_info.rpmb_size_mult,
-				 RPMB_SIZE_SINGLE / RPMB_DATA_SIZE, &nblocks) ||
-		    SUB_OVERFLOW(nblocks, 1, &rpmb_ctx->max_blk_idx)) {
-			res = TEE_ERROR_BAD_PARAMETERS;
-			goto func_exit;
-		}
+static TEE_Result legacy_rpmb_init(void)
+{
+	TEE_Result res = TEE_SUCCESS;
+	struct rpmb_dev_info dev_info = { };
 
-		memcpy(rpmb_ctx->cid, dev_info.cid, RPMB_EMMC_CID_SIZE);
+	DMSG("Trying legacy RPMB init");
+	rpmb_ctx->legacy_operation = true;
+	rpmb_ctx->dev_id = CFG_RPMB_FS_DEV_ID;
+	rpmb_ctx->shm_type = THREAD_SHM_TYPE_APPLICATION;
 
-#ifdef RPMB_DRIVER_MULTIPLE_WRITE_FIXED
-		rpmb_ctx->rel_wr_blkcnt = dev_info.rel_wr_sec_c * 2;
-#else
-		rpmb_ctx->rel_wr_blkcnt = 1;
-#endif
+	if (!rpmb_ctx->dev_info_synced) {
+		dev_info.rpmb_size_mult = 0;
+		dev_info.rel_wr_sec_c = 0;
+		res = tee_rpmb_get_dev_info(&dev_info);
+		if (res != TEE_SUCCESS)
+			return res;
+
+		res = rpmb_set_dev_info(&dev_info);
+		if (res)
+			return res;
 
 		rpmb_ctx->dev_info_synced = true;
 	}
@@ -1150,12 +1161,11 @@ static TEE_Result tee_rpmb_init(uint16_t dev_id)
 	if (!rpmb_ctx->key_derived) {
 		DMSG("RPMB INIT: Deriving key");
 
-		res = tee_rpmb_key_gen(dev_id, rpmb_ctx->key,
-				       RPMB_KEY_MAC_SIZE);
+		res = tee_rpmb_key_gen(rpmb_ctx->key, RPMB_KEY_MAC_SIZE);
 		if (res != TEE_SUCCESS) {
 			EMSG("RPMB INIT: Deriving key failed with error 0x%x",
 				res);
-			goto func_exit;
+			return res;
 		}
 
 		rpmb_ctx->key_derived = true;
@@ -1165,34 +1175,131 @@ static TEE_Result tee_rpmb_init(uint16_t dev_id)
 	if (!rpmb_ctx->wr_cnt_synced || !rpmb_ctx->key_verified) {
 		DMSG("RPMB INIT: Verifying Key");
 
-		res = tee_rpmb_verify_key_sync_counter(dev_id);
-		if (res == TEE_ERROR_ITEM_NOT_FOUND &&
-			!rpmb_ctx->key_verified) {
+		res = tee_rpmb_init_read_wr_cnt(&rpmb_ctx->wr_cnt);
+		if (res == TEE_SUCCESS) {
+			DMSG("Found working RPMB device");
+			rpmb_ctx->key_verified = true;
+			rpmb_ctx->wr_cnt_synced = true;
+		} else if (res == TEE_ERROR_ITEM_NOT_FOUND &&
+			   !rpmb_ctx->key_verified) {
 			/*
 			 * Need to write the key here and verify it.
 			 */
 			DMSG("RPMB INIT: Auth key not yet written");
-			res = tee_rpmb_write_and_verify_key(dev_id);
-		} else if (res != TEE_SUCCESS) {
-			EMSG("Verify key failed!");
+			res = tee_rpmb_write_and_verify_key();
+		} else {
+			EMSG("Verify key failed! %#"PRIx32, res);
 			EMSG("Make sure key here matches device key");
 		}
 	}
 
-func_exit:
 	return res;
 }
 
+/* This function must never return TEE_SUCCESS if rpmb_ctx == NULL */
+static TEE_Result tee_rpmb_init(void)
+{
+	TEE_Result res = TEE_SUCCESS;
+	struct rpmb_dev_info dev_info = { };
+
+	if (rpmb_dead)
+		return TEE_ERROR_COMMUNICATION;
+
+	if (!rpmb_ctx) {
+		rpmb_ctx = calloc(1, sizeof(struct tee_rpmb_ctx));
+		if (!rpmb_ctx)
+			return TEE_ERROR_OUT_OF_MEMORY;
+	}
+
+	if (rpmb_ctx->reinit) {
+		if (!rpmb_ctx->key_verified) {
+			rpmb_ctx->wr_cnt_synced = false;
+			rpmb_ctx->key_derived = false;
+			rpmb_ctx->dev_info_synced = false;
+			rpmb_ctx->reinit = false;
+			goto next;
+		}
+		res = rpmb_probe_reset();
+		if (res) {
+			if (res != TEE_ERROR_NOT_SUPPORTED &&
+			    res != TEE_ERROR_NOT_IMPLEMENTED)
+				return res;
+			return legacy_rpmb_init();
+		}
+		while (true) {
+			res = rpmb_probe_next(&dev_info);
+			if (res) {
+				DMSG("rpmb_probe_next error %#"PRIx32, res);
+				return res;
+			}
+			if (!memcmp(rpmb_ctx->cid, dev_info.cid,
+				    RPMB_EMMC_CID_SIZE)) {
+				rpmb_ctx->reinit = false;
+				return TEE_SUCCESS;
+			}
+		}
+	}
+
+	if (rpmb_ctx->key_verified)
+		return TEE_SUCCESS;
+
+next:
+	if (IS_ENABLED(CFG_RPMB_WRITE_KEY))
+		return legacy_rpmb_init();
+
+	res = rpmb_probe_reset();
+	if (res) {
+		if (res != TEE_ERROR_NOT_SUPPORTED &&
+		    res != TEE_ERROR_NOT_IMPLEMENTED)
+			return res;
+		return legacy_rpmb_init();
+	}
+
+	while (true) {
+		res = rpmb_probe_next(&dev_info);
+		if (res) {
+			DMSG("rpmb_probe_next error %#"PRIx32, res);
+			return res;
+		}
+		res = rpmb_set_dev_info(&dev_info);
+		if (res) {
+			DMSG("Invalid device info, looking for another device");
+			continue;
+		}
+
+		res = tee_rpmb_key_gen(rpmb_ctx->key, RPMB_KEY_MAC_SIZE);
+		if (res)
+			return res;
+
+		res = tee_rpmb_init_read_wr_cnt(&rpmb_ctx->wr_cnt);
+		if (res)
+			continue;
+		break;
+	}
+
+	DMSG("Found working RPMB device");
+	rpmb_ctx->key_verified = true;
+	rpmb_ctx->wr_cnt_synced = true;
+
+	return TEE_SUCCESS;
+}
+
+TEE_Result tee_rpmb_reinit(void)
+{
+	if (rpmb_ctx)
+		rpmb_ctx->reinit = true;
+	return tee_rpmb_init();
+}
+
 /*
  * Read RPMB data in bytes.
  *
- * @dev_id     Device ID of the eMMC device.
  * @addr       Byte address of data.
  * @data       Pointer to the data.
  * @len        Size of data in bytes.
  * @fek        Encrypted File Encryption Key or NULL.
  */
-static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
+static TEE_Result tee_rpmb_read(uint32_t addr, uint8_t *data,
 				uint32_t len, const uint8_t *fek,
 				const TEE_UUID *uuid)
 {
@@ -1201,11 +1308,7 @@ static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
 	uint16_t msg_type;
 	uint8_t nonce[RPMB_NONCE_SIZE];
 	uint8_t hmac[RPMB_KEY_MAC_SIZE];
-	struct rpmb_req *req = NULL;
-	struct rpmb_data_frame *resp = NULL;
 	struct rpmb_raw_data rawdata;
-	uint32_t req_size;
-	uint32_t resp_size;
 	uint16_t blk_idx;
 	uint16_t blkcnt;
 	uint8_t byte_offset;
@@ -1220,40 +1323,39 @@ static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
 		/* Overflow */
 		return TEE_ERROR_BAD_PARAMETERS;
 	}
-	blkcnt =
-	    ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
-	res = tee_rpmb_init(dev_id);
+	blkcnt = ROUNDUP_DIV(len + byte_offset, RPMB_DATA_SIZE);
+	res = tee_rpmb_init();
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
-	req_size = sizeof(struct rpmb_req) + RPMB_DATA_FRAME_SIZE;
-	resp_size = RPMB_DATA_FRAME_SIZE * blkcnt;
-	res = tee_rpmb_alloc(req_size, resp_size, &mem,
-			     (void *)&req, (void *)&resp);
+	res = tee_rpmb_alloc(RPMB_DATA_FRAME_SIZE,
+			     RPMB_DATA_FRAME_SIZE * blkcnt, &mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_READ;
 	res = crypto_rng_read(nonce, RPMB_NONCE_SIZE);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	memset(&rawdata, 0x00, sizeof(struct rpmb_raw_data));
 	rawdata.msg_type = msg_type;
 	rawdata.nonce = nonce;
 	rawdata.blk_idx = &blk_idx;
-	res = tee_rpmb_req_pack(req, &rawdata, 1, dev_id, NULL, NULL);
+	res = tee_rpmb_req_pack(mem.req_hdr, mem.req_data, &rawdata, 1, NULL,
+				NULL);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
-	req->block_count = blkcnt;
+	if (mem.req_hdr)
+		mem.req_hdr->block_count = blkcnt;
 
 	DMSG("Read %u block%s at index %u", blkcnt, ((blkcnt > 1) ? "s" : ""),
 	     blk_idx);
 
 	res = tee_rpmb_invoke(&mem);
 	if (res != TEE_SUCCESS)
-		goto func_exit;
+		return res;
 
 	msg_type = RPMB_MSG_TYPE_RESP_AUTH_DATA_READ;
 
@@ -1268,21 +1370,14 @@ static TEE_Result tee_rpmb_read(uint16_t dev_id, uint32_t addr, uint8_t *data,
 	rawdata.len = len;
 	rawdata.byte_offset = byte_offset;
 
-	res = tee_rpmb_resp_unpack_verify(resp, &rawdata, blkcnt, fek, uuid);
-	if (res != TEE_SUCCESS)
-		goto func_exit;
-
-	res = TEE_SUCCESS;
-
-func_exit:
-	tee_rpmb_free(&mem);
-	return res;
+	return tee_rpmb_resp_unpack_verify(mem.resp_data, &rawdata, blkcnt,
+					   fek, uuid);
 }
 
-static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx,
+static TEE_Result write_req(uint16_t blk_idx,
 			    const void *data_blks, uint16_t blkcnt,
 			    const uint8_t *fek, const TEE_UUID *uuid,
-			    struct tee_rpmb_mem *mem, void  *req, void *resp)
+			    struct tee_rpmb_mem *mem)
 {
 	TEE_Result res = TEE_SUCCESS;
 	uint8_t hmac[RPMB_KEY_MAC_SIZE] = { };
@@ -1290,13 +1385,12 @@ static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx,
 	struct rpmb_raw_data rawdata = { };
 	size_t retry_count = 0;
 
-	assert(mem->req_size <=
-	       sizeof(struct rpmb_req) + blkcnt * RPMB_DATA_FRAME_SIZE);
-	assert(mem->resp_size <= RPMB_DATA_FRAME_SIZE);
-
 	while (true) {
-		memset(req, 0, mem->req_size);
-		memset(resp, 0, mem->resp_size);
+		if (mem->req_hdr)
+			memset(mem->req_hdr, 0, mem->req_size);
+		else
+			memset(mem->req_data, 0, mem->req_size);
+		memset(mem->resp_data, 0, mem->resp_size);
 
 		memset(&rawdata, 0, sizeof(struct rpmb_raw_data));
 		rawdata.msg_type = RPMB_MSG_TYPE_REQ_AUTH_DATA_WRITE;
@@ -1306,8 +1400,8 @@ static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx,
 		rawdata.key_mac = hmac;
 		rawdata.data = (uint8_t *)data_blks;
 
-		res = tee_rpmb_req_pack(req, &rawdata, blkcnt, dev_id, fek,
-					uuid);
+		res = tee_rpmb_req_pack(mem->req_hdr, mem->req_data, &rawdata,
+					blkcnt, fek, uuid);
 		if (res) {
 			/*
 			 * If we haven't tried to send a request yet we can
@@ -1347,8 +1441,8 @@ static TEE_Result write_req(uint16_t dev_id, uint16_t blk_idx,
 		rawdata.write_counter = &wr_cnt;
 		rawdata.key_mac = hmac;
 
-		res = tee_rpmb_resp_unpack_verify(resp, &rawdata, 1, NULL,
-						  NULL);
+		res = tee_rpmb_resp_unpack_verify(mem->resp_data, &rawdata, 1,
+						  NULL, NULL);
 		if (res != TEE_SUCCESS) {
 			retry_count++;
 			if (retry_count >= RPMB_MAX_RETRIES)
@@ -1376,16 +1470,13 @@ out_of_retries:
 	return TEE_ERROR_COMMUNICATION;
 }
 
-static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
+static TEE_Result tee_rpmb_write_blk(uint16_t blk_idx,
 				     const uint8_t *data_blks, uint16_t blkcnt,
 				     const uint8_t *fek, const TEE_UUID *uuid)
 {
 	TEE_Result res;
 	struct tee_rpmb_mem mem;
-	struct rpmb_req *req = NULL;
-	struct rpmb_data_frame *resp = NULL;
 	uint32_t req_size;
-	uint32_t resp_size;
 	uint32_t nbr_writes;
 	uint16_t tmp_blkcnt;
 	uint16_t tmp_blk_idx;
@@ -1397,7 +1488,7 @@ static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
 	if (!data_blks || !blkcnt)
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	res = tee_rpmb_init(dev_id);
+	res = tee_rpmb_init();
 	if (res != TEE_SUCCESS)
 		return res;
 
@@ -1405,16 +1496,8 @@ static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
 	 * We need to split data when block count
 	 * is bigger than reliable block write count.
 	 */
-	if (blkcnt < rpmb_ctx->rel_wr_blkcnt)
-		req_size = sizeof(struct rpmb_req) +
-		    RPMB_DATA_FRAME_SIZE * blkcnt;
-	else
-		req_size = sizeof(struct rpmb_req) +
-		    RPMB_DATA_FRAME_SIZE * rpmb_ctx->rel_wr_blkcnt;
-
-	resp_size = RPMB_DATA_FRAME_SIZE;
-	res = tee_rpmb_alloc(req_size, resp_size, &mem,
-			     (void *)&req, (void *)&resp);
+	req_size = RPMB_DATA_FRAME_SIZE * MIN(blkcnt, rpmb_ctx->rel_wr_blkcnt);
+	res = tee_rpmb_alloc(req_size, RPMB_DATA_FRAME_SIZE, &mem);
 	if (res != TEE_SUCCESS)
 		return res;
 
@@ -1435,26 +1518,22 @@ static TEE_Result tee_rpmb_write_blk(uint16_t dev_id, uint16_t blk_idx,
 			tmp_blkcnt = blkcnt - rpmb_ctx->rel_wr_blkcnt *
 			    (nbr_writes - 1);
 
-		res = write_req(dev_id, tmp_blk_idx, data_blks + offs,
-				tmp_blkcnt, fek, uuid, &mem, req, resp);
+		res = write_req(tmp_blk_idx, data_blks + offs,
+				tmp_blkcnt, fek, uuid, &mem);
 		if (res)
-			goto out;
+			return res;
 
 
 		tmp_blk_idx += tmp_blkcnt;
 	}
 
-out:
-	tee_rpmb_free(&mem);
-	return res;
+	return TEE_SUCCESS;
 }
 
-static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr,
-				     uint32_t len)
+static bool tee_rpmb_write_is_atomic(uint32_t addr, uint32_t len)
 {
 	uint8_t byte_offset = addr % RPMB_DATA_SIZE;
-	uint16_t blkcnt = ROUNDUP(len + byte_offset,
-				  RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
+	uint16_t blkcnt = ROUNDUP_DIV(len + byte_offset, RPMB_DATA_SIZE);
 
 	return (blkcnt <= rpmb_ctx->rel_wr_blkcnt);
 }
@@ -1462,13 +1541,12 @@ static bool tee_rpmb_write_is_atomic(uint16_t dev_id __unused, uint32_t addr,
 /*
  * Write RPMB data in bytes.
  *
- * @dev_id     Device ID of the eMMC device.
  * @addr       Byte address of data.
  * @data       Pointer to the data.
  * @len        Size of data in bytes.
  * @fek        Encrypted File Encryption Key or NULL.
  */
-static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
+static TEE_Result tee_rpmb_write(uint32_t addr,
 				 const uint8_t *data, uint32_t len,
 				 const uint8_t *fek, const TEE_UUID *uuid)
 {
@@ -1481,12 +1559,10 @@ static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
 	blk_idx = addr / RPMB_DATA_SIZE;
 	byte_offset = addr % RPMB_DATA_SIZE;
 
-	blkcnt =
-	    ROUNDUP(len + byte_offset, RPMB_DATA_SIZE) / RPMB_DATA_SIZE;
+	blkcnt = ROUNDUP_DIV(len + byte_offset, RPMB_DATA_SIZE);
 
 	if (byte_offset == 0 && (len % RPMB_DATA_SIZE) == 0) {
-		res = tee_rpmb_write_blk(dev_id, blk_idx, data, blkcnt, fek,
-					 uuid);
+		res = tee_rpmb_write_blk(blk_idx, data, blkcnt, fek, uuid);
 		if (res != TEE_SUCCESS)
 			goto func_exit;
 	} else {
@@ -1497,7 +1573,7 @@ static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
 		}
 
 		/* Read the complete blocks */
-		res = tee_rpmb_read(dev_id, blk_idx * RPMB_DATA_SIZE, data_tmp,
+		res = tee_rpmb_read(blk_idx * RPMB_DATA_SIZE, data_tmp,
 				    blkcnt * RPMB_DATA_SIZE, fek, uuid);
 		if (res != TEE_SUCCESS)
 			goto func_exit;
@@ -1505,8 +1581,7 @@ static TEE_Result tee_rpmb_write(uint16_t dev_id, uint32_t addr,
 		/* Partial update of the data blocks */
 		memcpy(data_tmp + byte_offset, data, len);
 
-		res = tee_rpmb_write_blk(dev_id, blk_idx, data_tmp, blkcnt,
-					 fek, uuid);
+		res = tee_rpmb_write_blk(blk_idx, data_tmp, blkcnt, fek, uuid);
 		if (res != TEE_SUCCESS)
 			goto func_exit;
 	}
@@ -1521,10 +1596,9 @@ func_exit:
 /*
  * Read the RPMB max block.
  *
- * @dev_id     Device ID of the eMMC device.
  * @counter    Pointer to receive the max block.
  */
-static TEE_Result tee_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block)
+static TEE_Result tee_rpmb_get_max_block(uint32_t *max_block)
 {
 	TEE_Result res = TEE_SUCCESS;
 
@@ -1535,7 +1609,7 @@ static TEE_Result tee_rpmb_get_max_block(uint16_t dev_id, uint32_t *max_block)
 		return TEE_ERROR_COMMUNICATION;
 
 	if (!rpmb_ctx || !rpmb_ctx->dev_info_synced) {
-		res = tee_rpmb_init(dev_id);
+		res = tee_rpmb_init();
 		if (res != TEE_SUCCESS)
 			goto func_exit;
 	}
@@ -1613,7 +1687,7 @@ static TEE_Result fat_entry_dir_init(void)
 		goto out;
 	}
 
-	res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, fat_address, (uint8_t *)fe,
+	res = tee_rpmb_read(fat_address, (uint8_t *)fe,
 			    num_elems_read * sizeof(*fe), NULL, NULL);
 	if (res)
 		goto out;
@@ -1758,8 +1832,7 @@ static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry,
 			num_elems_read = CFG_RPMB_FS_RD_ENTRIES;
 			fat_entry_dir->idx_curr = 0;
 
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fat_address_local, (uint8_t *)fe,
+			res = tee_rpmb_read(fat_address_local, (uint8_t *)fe,
 					    num_elems_read * sizeof(*fe), NULL,
 					    NULL);
 			if (res)
@@ -1794,8 +1867,7 @@ static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry,
 			fat_entry_dir->rpmb_fat_entry_buf = fe;
 
 			/* Read in to the next free slot in the buffer/cache. */
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fat_address_local,
+			res = tee_rpmb_read(fat_address_local,
 					    (uint8_t *)(fe +
 					    fat_entry_dir->num_total_read),
 					    num_elems_read * sizeof(*fe),
@@ -1819,8 +1891,7 @@ static TEE_Result fat_entry_dir_get_next(struct rpmb_fat_entry **fat_entry,
 			fat_entry_dir->idx_curr = CFG_RPMB_FS_CACHE_ENTRIES;
 
 			/* Read in elements after the end of the cache. */
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fat_address_local,
+			res = tee_rpmb_read(fat_address_local,
 					    (uint8_t *)(fe +
 					    fat_entry_dir->idx_curr),
 					    num_elems_read * sizeof(*fe),
@@ -1972,8 +2043,7 @@ static TEE_Result write_fat_entry(struct rpmb_file_handle *fh)
 		goto out;
 	}
 
-	res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, fh->rpmb_fat_address,
-			     (uint8_t *)&fh->fat_entry,
+	res = tee_rpmb_write(fh->rpmb_fat_address, (uint8_t *)&fh->fat_entry,
 			     sizeof(struct rpmb_fat_entry), NULL, NULL);
 
 	dump_fat();
@@ -2004,7 +2074,7 @@ static TEE_Result rpmb_fs_setup(void)
 		goto out;
 	}
 
-	res = tee_rpmb_get_max_block(CFG_RPMB_FS_DEV_ID, &max_rpmb_block);
+	res = tee_rpmb_get_max_block(&max_rpmb_block);
 	if (res != TEE_SUCCESS)
 		goto out;
 
@@ -2020,7 +2090,7 @@ static TEE_Result rpmb_fs_setup(void)
 		goto out;
 	}
 
-	res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
+	res = tee_rpmb_read(RPMB_STORAGE_START_ADDRESS,
 			    (uint8_t *)partition_data, RPMB_DATA_SIZE,
 			    NULL, NULL);
 	if (res != TEE_SUCCESS)
@@ -2030,7 +2100,7 @@ static TEE_Result rpmb_fs_setup(void)
 	 * prevents late usage (replay attack) of a previously blocked
 	 * request with a valid write counter value.
 	 */
-	res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
+	res = tee_rpmb_write(RPMB_STORAGE_START_ADDRESS,
 			     (uint8_t *)partition_data, RPMB_DATA_SIZE,
 			     NULL, NULL);
 	if (res != TEE_SUCCESS)
@@ -2041,7 +2111,7 @@ static TEE_Result rpmb_fs_setup(void)
 	 * with the RPMB block since there are no other possible stale
 	 * blocks with valid write counters available.
 	 */
-	res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
+	res = tee_rpmb_read(RPMB_STORAGE_START_ADDRESS,
 			    (uint8_t *)partition_data,
 			    sizeof(struct rpmb_fs_partition), NULL, NULL);
 	if (res != TEE_SUCCESS)
@@ -2081,7 +2151,7 @@ static TEE_Result rpmb_fs_setup(void)
 	if (res != TEE_SUCCESS)
 		goto out;
 
-	res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, RPMB_STORAGE_START_ADDRESS,
+	res = tee_rpmb_write(RPMB_STORAGE_START_ADDRESS,
 			     (uint8_t *)partition_data,
 			     sizeof(struct rpmb_fs_partition), NULL, NULL);
 
@@ -2371,8 +2441,7 @@ static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, size_t pos,
 	size = MIN(size, fh->fat_entry.data_size - pos);
 	if (size) {
 		if (buf_core) {
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fh->fat_entry.start_address + pos,
+			res = tee_rpmb_read(fh->fat_entry.start_address + pos,
 					    buf_core, size, fh->fat_entry.fek,
 					    fh->uuid);
 			if (res != TEE_SUCCESS)
@@ -2384,8 +2453,7 @@ static TEE_Result rpmb_fs_read(struct tee_file_handle *tfh, size_t pos,
 			if (res)
 				goto out;
 			enter_user_access();
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fh->fat_entry.start_address + pos,
+			res = tee_rpmb_read(fh->fat_entry.start_address + pos,
 					    buf_user, size, fh->fat_entry.fek,
 					    fh->uuid);
 			exit_user_access();
@@ -2430,8 +2498,7 @@ static TEE_Result update_write_helper(struct rpmb_file_handle *fh,
 		if (blk_offset < pos && blk_offset < old_size) {
 			rd_size = MIN(blk_size, old_size - blk_offset);
 
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    old_fat + blk_offset, blk_buf,
+			res = tee_rpmb_read(old_fat + blk_offset, blk_buf,
 					    rd_size, fh->fat_entry.fek,
 					    fh->uuid);
 			if (res != TEE_SUCCESS)
@@ -2460,8 +2527,7 @@ static TEE_Result update_write_helper(struct rpmb_file_handle *fh,
 		}
 
 		/* Write temporary buffer to new RPMB destination */
-		res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, new_fat + blk_offset,
-				     blk_buf, blk_size,
+		res = tee_rpmb_write(new_fat + blk_offset, blk_buf, blk_size,
 				     fh->fat_entry.fek, fh->uuid);
 		if (res != TEE_SUCCESS)
 			break;
@@ -2524,10 +2590,10 @@ static TEE_Result rpmb_fs_write_primitive(struct rpmb_file_handle *fh,
 	}
 
 	if (end <= fh->fat_entry.data_size &&
-	    tee_rpmb_write_is_atomic(CFG_RPMB_FS_DEV_ID, start_addr, size)) {
+	    tee_rpmb_write_is_atomic(start_addr, size)) {
 
 		DMSG("Updating data in-place");
-		res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, start_addr, buf,
+		res = tee_rpmb_write(start_addr, buf,
 				     size, fh->fat_entry.fek, fh->uuid);
 	} else {
 		/*
@@ -2751,8 +2817,7 @@ static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length)
 		}
 
 		if (fh->fat_entry.data_size) {
-			res = tee_rpmb_read(CFG_RPMB_FS_DEV_ID,
-					    fh->fat_entry.start_address,
+			res = tee_rpmb_read(fh->fat_entry.start_address,
 					    newbuf, fh->fat_entry.data_size,
 					    fh->fat_entry.fek, fh->uuid);
 			if (res != TEE_SUCCESS)
@@ -2760,7 +2825,7 @@ static TEE_Result rpmb_fs_truncate(struct tee_file_handle *tfh, size_t length)
 		}
 
 		newaddr = tee_mm_get_smem(mm);
-		res = tee_rpmb_write(CFG_RPMB_FS_DEV_ID, newaddr, newbuf,
+		res = tee_rpmb_write(newaddr, newbuf,
 				     newsize, fh->fat_entry.fek, fh->uuid);
 		if (res != TEE_SUCCESS)
 			goto out;
@@ -2873,8 +2938,8 @@ static TEE_Result rpmb_fs_dir_populate(const char *path,
 		res = TEE_ERROR_ITEM_NOT_FOUND; /* No directories were found. */
 
 out:
-	mutex_unlock(&rpmb_mutex);
 	fat_entry_dir_deinit();
+	mutex_unlock(&rpmb_mutex);
 	if (res)
 		rpmb_fs_dir_free(dir);
 
diff --git a/core/tee/tee_svc_cryp.c b/core/tee/tee_svc_cryp.c
index 5a16ee4d65d4f6dd780e4eced860d6d24385e28b..a5773a99f2438e3ae78cc43bc6cad76a7d87c7c2 100644
--- a/core/tee/tee_svc_cryp.c
+++ b/core/tee/tee_svc_cryp.c
@@ -2087,10 +2087,12 @@ static TEE_Result check_pub_rsa_key(struct bignum *e)
 
 	/*
 	 * NIST SP800-56B requires public RSA key to be an odd integer in
-	 * the range 65537 <= e < 2^256.
+	 * the range 65537 <= e < 2^256. AOSP requires implementations to
+	 * support public exponents >= 3, which can be allowed by enabling
+	 * CFG_RSA_PUB_EXPONENT_3.
 	 */
 
-	if (n > sizeof(bin_key) || n < 3)
+	if (n > sizeof(bin_key) || n < 1)
 		return TEE_ERROR_BAD_PARAMETERS;
 
 	crypto_bignum_bn2bin(e, bin_key);
@@ -2098,19 +2100,23 @@ static TEE_Result check_pub_rsa_key(struct bignum *e)
 	if (!(bin_key[n - 1] & 1)) /* key must be odd */
 		return TEE_ERROR_BAD_PARAMETERS;
 
-	if (n == 3) {
+	if (n <= 3) {
+		uint32_t min_key = 65537;
 		uint32_t key = 0;
+		size_t m = 0;
 
-		for (n = 0; n < 3; n++) {
+		if (IS_ENABLED(CFG_RSA_PUB_EXPONENT_3))
+			min_key = 3;
+
+		for (m = 0; m < n; m++) {
 			key <<= 8;
-			key |= bin_key[n];
+			key |= bin_key[m];
 		}
 
-		if (key < 65537)
+		if (key < min_key)
 			return TEE_ERROR_BAD_PARAMETERS;
 	}
 
-	/* key is larger than 65537 */
 	return TEE_SUCCESS;
 }
 
@@ -2133,7 +2139,10 @@ static TEE_Result tee_svc_obj_generate_key_rsa(
 		if (res)
 			return res;
 	} else {
-		crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e), key->e);
+		res = crypto_bignum_bin2bn((const uint8_t *)&e, sizeof(e),
+					   key->e);
+		if (res)
+			return res;
 	}
 	res = crypto_acipher_gen_rsa_key(key, key_size);
 	if (res != TEE_SUCCESS)
@@ -4418,6 +4427,7 @@ TEE_Result syscall_asymm_operate(unsigned long state,
 	int salt_len = 0;
 	TEE_Attribute *params = NULL;
 	size_t alloc_size = 0;
+	uint32_t mgf_algo = 0;
 
 	res = tee_svc_cryp_get_state(sess, uref_to_vaddr(state), &cs);
 	if (res != TEE_SUCCESS)
@@ -4517,41 +4527,33 @@ TEE_Result syscall_asymm_operate(unsigned long state,
 				label_len = params[n].content.ref.length;
 				break;
 			}
-			/*
-			 * If the optional TEE_ATTR_RSA_OAEP_MGF_HASH is
-			 * provided for algorithm
-			 * TEE_ALG_RSAES_PKCS1_OAEP_MGF1_x it must match
-			 * the internal hash x since we don't support using
-			 * a different hash for MGF1 yet.
-			 */
+
 			if (cs->algo != TEE_ALG_RSAES_PKCS1_V1_5 &&
 			    params[n].attributeID ==
 			    TEE_ATTR_RSA_OAEP_MGF_HASH) {
-				uint32_t hash = 0;
 				void *buf = params[n].content.ref.buffer;
 
 				if (params[n].content.ref.length !=
-				    sizeof(hash)) {
+				    sizeof(mgf_algo)) {
 					res = TEE_ERROR_BAD_PARAMETERS;
 					goto out;
 				}
 
-				res = copy_from_user(&hash, buf, sizeof(hash));
+				res = copy_from_user(&mgf_algo, buf,
+						     sizeof(mgf_algo));
 				if (res)
 					goto out;
-
-				if (hash !=
-				    TEE_INTERNAL_HASH_TO_ALGO(cs->algo)) {
-					res = TEE_ERROR_NOT_SUPPORTED;
-					goto out;
-				}
 			}
 		}
 
+		if (!mgf_algo)
+			mgf_algo = TEE_INTERNAL_HASH_TO_ALGO(cs->algo);
+
 		if (cs->mode == TEE_MODE_ENCRYPT) {
 			enter_user_access();
 			res = crypto_acipher_rsaes_encrypt(cs->algo, o->attr,
 							   label, label_len,
+							   mgf_algo,
 							   src_data, src_len,
 							   dst_data, &dlen);
 			exit_user_access();
@@ -4559,6 +4561,7 @@ TEE_Result syscall_asymm_operate(unsigned long state,
 			enter_user_access();
 			res = crypto_acipher_rsaes_decrypt(
 					cs->algo, o->attr, label, label_len,
+					mgf_algo,
 					src_data, src_len, dst_data, &dlen);
 			exit_user_access();
 		} else {
diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c
index 5cf39d567dbe5a53e46b320f0fb07c15b6ecaa39..7274411f5388d50988472a49a7dc54cbfd7a992c 100644
--- a/core/tee/tee_svc_storage.c
+++ b/core/tee/tee_svc_storage.c
@@ -20,7 +20,6 @@
 #include <tee/tee_obj.h>
 #include <tee/tee_pobj.h>
 #include <tee/tee_svc_cryp.h>
-#include <tee/tee_svc.h>
 #include <tee/tee_svc_storage.h>
 #include <trace.h>
 
@@ -136,12 +135,12 @@ static TEE_Result tee_svc_storage_read_head(struct tee_obj *o)
 		bytes = head.attr_size;
 		res = fops->read(o->fh, sizeof(struct tee_svc_storage_head),
 				 attr, NULL, &bytes);
-		if (res == TEE_ERROR_OUT_OF_MEMORY)
+		if (res != TEE_SUCCESS)
 			goto exit;
-		if (res != TEE_SUCCESS || bytes != head.attr_size)
+		if (bytes != head.attr_size) {
 			res = TEE_ERROR_CORRUPT_OBJECT;
-		if (res)
 			goto exit;
+		}
 	}
 
 	res = tee_obj_attr_from_binary(o, attr, head.attr_size);
diff --git a/core/tee/tee_time_generic.c b/core/tee/tee_time_generic.c
index 303b044d4cc5edc17f2bd9394f3294095f118058..8b03a87be08a94dd5b98ccb6933ad15953a96f95 100644
--- a/core/tee/tee_time_generic.c
+++ b/core/tee/tee_time_generic.c
@@ -7,7 +7,6 @@
 #include <kernel/tee_time.h>
 #include <string.h>
 #include <stdlib.h>
-#include <trace.h>
 #include <utee_defines.h>
 
 struct tee_ta_time_offs {
diff --git a/core/tests/notif_test_wd.c b/core/tests/notif_test_wd.c
new file mode 100644
index 0000000000000000000000000000000000000000..7bb0ace2dd74b70b77f79aab0805444a321985f1
--- /dev/null
+++ b/core/tests/notif_test_wd.c
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <initcall.h>
+#include <kernel/callout.h>
+#include <kernel/notif.h>
+#include <kernel/panic.h>
+#include <kernel/tee_time.h>
+#include <kernel/virtualization.h>
+#include <types_ext.h>
+
+#define TEST_WD_TIMER_PERIOD_MS	1000
+
+struct wd_data {
+	bool pending;
+	bool enabled;
+	uint16_t guest_id;
+	unsigned int timeout_count;
+	unsigned int call_count;
+	struct callout callout;
+};
+
+static struct wd_data default_wd_data;
+static unsigned int wd_data_id __nex_bss;
+
+static struct wd_data *get_wd_data(struct guest_partition *prtn)
+{
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		assert(prtn);
+		return virt_get_guest_spec_data(prtn, wd_data_id);
+	}
+	return &default_wd_data;
+}
+
+static bool test_wd_callback(struct callout *co)
+{
+	struct wd_data *wd = container_of(co, struct wd_data, callout);
+
+	if (wd->pending)
+		wd->timeout_count++;
+	wd->call_count++;
+	if (wd->call_count < 10 || !(wd->call_count % 60) || wd->pending) {
+		if (IS_ENABLED(CFG_NS_VIRTUALIZATION))
+			DMSG("WD %"PRIu16" call_count %u, timeout_count %u",
+			     wd->guest_id, wd->call_count, wd->timeout_count);
+		else
+			DMSG("WD call_count %u, timeout_count %u",
+			     wd->call_count, wd->timeout_count);
+	}
+	wd->pending = true;
+	notif_send_async(NOTIF_VALUE_DO_BOTTOM_HALF, wd->guest_id);
+
+	return true;
+}
+
+static void wd_ndrv_atomic_cb(struct notif_driver *ndrv __unused,
+			      enum notif_event ev, uint16_t guest_id)
+{
+	if (ev == NOTIF_EVENT_STARTED) {
+		struct guest_partition *prtn = virt_get_guest(guest_id);
+		struct wd_data *wd = get_wd_data(prtn);
+
+		if (!wd->enabled) {
+			wd->guest_id = guest_id;
+			callout_add(&wd->callout, test_wd_callback,
+				    TEST_WD_TIMER_PERIOD_MS);
+
+			wd->enabled = true;
+		}
+		virt_put_guest(prtn);
+	}
+}
+DECLARE_KEEP_PAGER(wd_ndrv_atomic_cb);
+
+static void wd_ndrv_yielding_cb(struct notif_driver *ndrv __unused,
+				enum notif_event ev)
+{
+	if (ev == NOTIF_EVENT_DO_BOTTOM_HALF) {
+		struct guest_partition *prtn = virt_get_current_guest();
+		struct wd_data *wd = get_wd_data(prtn);
+
+		if (wd->pending && wd->call_count < 10)
+			DMSG("Clearing pending");
+		wd->pending = false;
+		virt_put_guest(prtn);
+	}
+}
+
+struct notif_driver wd_ndrv __nex_data = {
+	.atomic_cb = wd_ndrv_atomic_cb,
+	.yielding_cb = wd_ndrv_yielding_cb,
+};
+
+static void wd_data_destroy(void *data)
+{
+	struct wd_data *wd = data;
+
+	callout_rem(&wd->callout);
+}
+
+static TEE_Result nex_init_test_wd(void)
+{
+	TEE_Result res = TEE_SUCCESS;
+
+	if (IS_ENABLED(CFG_NS_VIRTUALIZATION)) {
+		res = virt_add_guest_spec_data(&wd_data_id,
+					       sizeof(struct wd_data),
+					       wd_data_destroy);
+		if (res)
+			return res;
+	}
+
+	notif_register_driver(&wd_ndrv);
+
+	return TEE_SUCCESS;
+}
+
+nex_early_init(nex_init_test_wd);
+
+struct periodic_data {
+	unsigned int count;
+	struct callout callout;
+};
+
+static bool periodic_callback(struct callout *co)
+{
+	struct periodic_data *d = container_of(co, struct periodic_data,
+					       callout);
+	TEE_Time t = { };
+
+	if (tee_time_get_sys_time(&t))
+		panic();
+	d->count++;
+	DMSG("seconds %"PRIu32" millis %"PRIu32" count %u",
+	     t.seconds, t.millis, d->count);
+
+	if (d->count > 20) {
+		DMSG("Disabling periodic callout");
+		return false;
+	}
+
+	return true;
+}
+DECLARE_KEEP_PAGER(periodic_callback);
+
+static TEE_Result nex_init_periodic_callback(void)
+{
+	struct periodic_data *d = nex_calloc(1, sizeof(*d));
+
+	if (!d)
+		return TEE_ERROR_OUT_OF_MEMORY;
+
+	DMSG("Adding a periodic callout");
+	callout_add(&d->callout, periodic_callback, TEST_WD_TIMER_PERIOD_MS);
+
+	return TEE_SUCCESS;
+}
+
+nex_early_init(nex_init_periodic_callback);
diff --git a/core/tests/sub.mk b/core/tests/sub.mk
index b0833d5e45b4a063916b2729a236d4f4d649103c..093b51ecc31c231a9708217ff699f03cc341f8f7 100644
--- a/core/tests/sub.mk
+++ b/core/tests/sub.mk
@@ -1 +1,2 @@
 srcs-y += ftmn_boot_tests.c
+srcs-$(CFG_NOTIF_TEST_WD) += notif_test_wd.c
diff --git a/debian/changelog b/debian/changelog
index c61219fc7224172729bf3a257c2ce03542861ec6..df95ab14b087d4ae20549cd345842c2cb52f352b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,57 @@
+optee-os (4.5.0-1) unstable; urgency=medium
+
+  * New upstream version 4.5.0
+
+ -- Dylan Aïssi <daissi@debian.org>  Wed, 22 Jan 2025 21:44:58 +0100
+
+optee-os (4.4.0-1) unstable; urgency=medium
+
+  * New upstream version 4.4.0
+  * debian/rules: Export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
+
+ -- Dylan Aïssi <daissi@debian.org>  Fri, 17 Jan 2025 18:16:39 +0100
+
+optee-os (4.3.0-1) unstable; urgency=medium
+
+  [ Dylan Aïssi ]
+  * New upstream version 4.3.0
+
+  [ Loïc Minier ]
+  * Strip -Wl, from LDFLAGS as optee_os calls ld directly. (Closes: #1072948)
+  * Remove -f flags from LDFLAGS as optee_os is built as -pie.
+
+ -- Dylan Aïssi <daissi@debian.org>  Fri, 19 Jul 2024 16:30:57 +0200
+
+optee-os (4.2.0-3) unstable; urgency=medium
+
+  * Upload to unstable
+
+ -- Dylan Aïssi <daissi@debian.org>  Tue, 30 Apr 2024 17:07:30 +0200
+
+optee-os (4.2.0-2) experimental; urgency=medium
+
+  * Build new binary package optee-os-dev installing the SDK of optee-os.
+    These files are required to package optee-test (see #868216) which
+    is the TEE sanity test suite.
+
+ -- Dylan Aïssi <daissi@debian.org>  Tue, 23 Apr 2024 15:24:31 +0200
+
+optee-os (4.2.0-1) unstable; urgency=medium
+
+  * New upstream version 4.2.0
+  * Standards-Version: 4.7.0 (no changes needed)
+
+ -- Dylan Aïssi <daissi@debian.org>  Tue, 23 Apr 2024 14:17:13 +0200
+
+optee-os (4.1.0-2) unstable; urgency=medium
+
+  * Refactor debian/rules
+  * Build optee-os for QEMU
+  * Update debian/copyright
+  * Add debian/upstream/metadata
+
+ -- Dylan Aïssi <daissi@debian.org>  Wed, 28 Feb 2024 17:31:33 +0100
+
 optee-os (4.1.0-1) unstable; urgency=medium
 
   * New upstream version 4.1.0
diff --git a/debian/control b/debian/control
index 918ff56402e9a272624282b61f80a46e53fe34a4..685cfdf3bf94a72b9e0da6c5d79ea6e43191b826 100644
--- a/debian/control
+++ b/debian/control
@@ -2,8 +2,9 @@ Source: optee-os
 Section: devel
 Priority: optional
 Maintainer: Dylan Aïssi <daissi@debian.org>
-Standards-Version: 4.6.2
+Standards-Version: 4.7.0
 Build-Depends: debhelper-compat (= 13),
+               device-tree-compiler,
                python3,
                python3-cryptography,
                python3-pyelftools
@@ -23,3 +24,17 @@ Description: OP-TEE Trusted OS
  exposed to Trusted Applications and the TEE Client API v1.0, which is the API
  describing how to communicate with a TEE. Those APIs are defined in the
  GlobalPlatform API specifications.
+
+Package: optee-os-dev
+Architecture: arm64
+Depends: ${misc:Depends},
+         python3
+Description: SDK of OP-TEE Trusted OS
+ OP-TEE is a Trusted Execution Environment (TEE) designed as companion to a
+ non-secure Linux kernel running on Arm; Cortex-A cores using the TrustZone
+ technology. OP-TEE implements TEE Internal Core API v1.1.x which is the API
+ exposed to Trusted Applications and the TEE Client API v1.0, which is the API
+ describing how to communicate with a TEE. Those APIs are defined in the
+ GlobalPlatform API specifications.
+ .
+ The package includes the SDK which is used for TA development.
diff --git a/debian/copyright b/debian/copyright
index 2f1391b47d207305f85a94a5cbb7eea8513939df..189a3238cf156d9a0644d5af4d3093b00ca2eb4d 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -273,7 +273,7 @@ Copyright: The Mbed TLS Contributors
 License: Apache-2.0
 
 Files: debian/*
-Copyright: 2022-2023, Collabora Ltd.
+Copyright: 2022-2024, Collabora Ltd.
 License: BSD-2-clause
 
 License: BSD-2-Clause
diff --git a/debian/optee-os-dev.install b/debian/optee-os-dev.install
new file mode 100644
index 0000000000000000000000000000000000000000..321ea40435f437e3512ca8270df1237abd040004
--- /dev/null
+++ b/debian/optee-os-dev.install
@@ -0,0 +1,3 @@
+out/arm-plat-k3/export-ta_arm64/*                    usr/lib/optee-os-dev/arm-plat-k3/
+out/arm-plat-vexpress/export-ta_arm64/*              usr/lib/optee-os-dev/vexpress-qemu_armv8a/
+out/arm-plat-vexpress-virtualized/export-ta_arm64/*  usr/lib/optee-os-dev/vexpress-qemu_armv8a-virtualized/
diff --git a/debian/optee-os.install b/debian/optee-os.install
index a0edef7fc4842d1b8467535ca7870c691dc74c03..a9aff77b163ee313942730787722d368df4f6058 100644
--- a/debian/optee-os.install
+++ b/debian/optee-os.install
@@ -1 +1,9 @@
 out/arm-plat-k3/core/tee-raw.bin		usr/lib/optee/k3-am62x
+
+out/arm-plat-vexpress/core/tee-pager_v2.bin     usr/lib/optee/vexpress-qemu_armv8a
+out/arm-plat-vexpress/core/tee-header_v2.bin    usr/lib/optee/vexpress-qemu_armv8a
+out/arm-plat-vexpress/core/tee-pageable_v2.bin  usr/lib/optee/vexpress-qemu_armv8a
+
+out/arm-plat-vexpress-virtualized/core/tee-pager_v2.bin     usr/lib/optee/vexpress-qemu_armv8a-virtualized
+out/arm-plat-vexpress-virtualized/core/tee-header_v2.bin    usr/lib/optee/vexpress-qemu_armv8a-virtualized
+out/arm-plat-vexpress-virtualized/core/tee-pageable_v2.bin  usr/lib/optee/vexpress-qemu_armv8a-virtualized
diff --git a/debian/rules b/debian/rules
index e1c4b663fe46b11deb0b91f8d1354bb9c0974cae..f184cae05d2c3d99bf8cc86e1f4dfbfeba4d8a33 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,13 +1,51 @@
 #!/usr/bin/make -f
 
-# hardening -> relro breaks compilation with error "'-Wl,-z,relro' unknown"
-export DEB_BUILD_MAINT_OPTIONS = hardening=+all,-relro
+include /usr/share/dpkg/architecture.mk
+include /usr/share/dpkg/buildtools.mk
+
+export DEB_BUILD_MAINT_OPTIONS = hardening=+all
+
+export CRYPTOGRAPHY_OPENSSL_NO_LEGACY=1
+
+platforms := k3-am62x vexpress-qemu_armv8a
+
+# k3 platform
+k3-am62x_CFLAGS   = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro dpkg-buildflags --get CFLAGS)
+k3-am62x_CPPFLAGS = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro dpkg-buildflags --get CPPFLAGS)
+k3-am62x_CXXFLAGS = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro dpkg-buildflags --get CXXFLAGS)
+k3-am62x_LDFLAGS  = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro dpkg-buildflags --get LDFLAGS)
+k3-am62x_assigns := O=out/arm-plat-k3 CFG_ARM64_core=y CFG_USER_TA_TARGETS=ta_arm64
+
+# qemu platform
+vexpress-qemu_armv8a_CFLAGS   = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro,-stackprotector,-format dpkg-buildflags --get CFLAGS)
+vexpress-qemu_armv8a_CPPFLAGS = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro,-stackprotector,-format dpkg-buildflags --get CPPFLAGS)
+vexpress-qemu_armv8a_CXXFLAGS = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro,-stackprotector,-format dpkg-buildflags --get CXXFLAGS)
+vexpress-qemu_armv8a_LDFLAGS  = $(shell DEB_BUILD_MAINT_OPTIONS=hardening=+all,-relro,-stackprotector,-format dpkg-buildflags --get LDFLAGS)
+vexpress-qemu_armv8a_subplatforms := vexpress-qemu_armv8a_non-virt vexpress-qemu_armv8a_virt
+vexpress-qemu_armv8a_non-virt_assigns := O=out/arm-plat-vexpress             CFG_TEE_CORE_LOG_LEVEL=3 CFG_TEE_BENCHMARK=n CFG_ARM_GICV3=y CFG_ARM64_core=y CFG_VIRTUALIZATION=n CFG_USER_TA_TARGETS=ta_arm64
+vexpress-qemu_armv8a_virt_assigns     := O=out/arm-plat-vexpress-virtualized CFG_TEE_CORE_LOG_LEVEL=3 CFG_TEE_BENCHMARK=n CFG_ARM_GICV3=y CFG_ARM64_core=y CFG_VIRTUALIZATION=y CFG_USER_TA_TARGETS=ta_arm64
+
+define build_platform
+	$(eval platform := $(1))
+	$(eval debug := $(if $(2), $(2), 0))
+	$(eval subplatforms := $(if $($(platform)_subplatforms), $($(platform)_subplatforms), $(platform)))
+	# LDFLAGS from dpkg-buildflags are prefixed with -Wl, but optee_os
+	# calls ld directly; also, -f flags may not be used without -shared but
+	# optee_os is built as -pie
+	$(foreach subplatform, $(subplatforms), \
+		CROSS_COMPILE=aarch64-linux-gnu-  \
+		CFLAGS='$($(platform)_CFLAGS)' CPPFLAGS='$($(platform)_CPPFLAGS)' \
+		CXXFLAGS='$($(platform)_CXXFLAGS)' LDFLAGS='$(filter-out -f%,$($(platform)_LDFLAGS:-Wl,%=%))' \
+		make PLATFORM=$(platform) $($(subplatform)_assigns) DEBUG=$(debug) V=1; \
+	)
+endef
 
 %:
 	dh $@
 
-override_dh_auto_build:
-	# Build for k3-am62x platform
-	make PLATFORM=k3-am62x \
-	     CFG_ARM64_core=y \
-	     CFG_USER_TA_TARGETS=ta_arm64
+override_dh_auto_build: $(platforms)
+$(platforms):
+	$(call build_platform,$@)
+
+override_dh_auto_clean:
+	rm -rf $(CURDIR)/out
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
new file mode 100644
index 0000000000000000000000000000000000000000..8d696d61114ef76381d345010f6c0f6089faa89e
--- /dev/null
+++ b/debian/upstream/metadata
@@ -0,0 +1,4 @@
+Bug-Database: https://github.com/OP-TEE/optee_os/issues
+Bug-Submit: https://github.com/OP-TEE/optee_os/issues/new
+Repository: https://github.com/OP-TEE/optee_os.git
+Repository-Browse: https://github.com/OP-TEE/optee_os/
diff --git a/ldelf/ta_elf.c b/ldelf/ta_elf.c
index 4e11e00ad75eff9cac28fda7becab707ebe00bd3..1a237e3e5322e93ea173d34ff2ae4d4b520977bb 100644
--- a/ldelf/ta_elf.c
+++ b/ldelf/ta_elf.c
@@ -7,7 +7,6 @@
 #include <assert.h>
 #include <config.h>
 #include <confine_array_index.h>
-#include <ctype.h>
 #include <elf32.h>
 #include <elf64.h>
 #include <elf_common.h>
@@ -963,10 +962,10 @@ static void parse_property_segment(struct ta_elf *elf)
 	    !IS_POWER_OF_TWO(align))
 		return;
 
-	desc_offset = ROUNDUP(sizeof(*note) + sizeof(ELF_NOTE_GNU), align);
+	desc_offset = ROUNDUP2(sizeof(*note) + sizeof(ELF_NOTE_GNU), align);
 
 	if (desc_offset > elf->prop_memsz ||
-	    ROUNDUP(desc_offset + note->n_descsz, align) > elf->prop_memsz)
+	    ROUNDUP2(desc_offset + note->n_descsz, align) > elf->prop_memsz)
 		return;
 
 	desc = (char *)(va + desc_offset);
@@ -993,7 +992,7 @@ static void parse_property_segment(struct ta_elf *elf)
 			}
 		}
 
-		prop_offset += ROUNDUP(sizeof(*prop) + prop->pr_datasz, align);
+		prop_offset += ROUNDUP2(sizeof(*prop) + prop->pr_datasz, align);
 	} while (prop_offset < note->n_descsz);
 }
 
@@ -1069,13 +1068,17 @@ static void add_deps_from_segment(struct ta_elf *elf, unsigned int type,
 	check_range(elf, ".dynstr/STRTAB", str_tab, str_tab_sz);
 
 	for (n = 0; n < num_dyns; n++) {
+		TEE_Result res = TEE_SUCCESS;
+
 		read_dyn(elf, addr, n, &tag, &val);
 		if (tag != DT_NEEDED)
 			continue;
 		if (val >= str_tab_sz)
 			err(TEE_ERROR_BAD_FORMAT,
 			    "Offset into .dynstr/STRTAB out of range");
-		tee_uuid_from_str(&uuid, str_tab + val);
+		res = tee_uuid_from_str(&uuid, str_tab + val);
+		if (res)
+			err(res, "Fail to get UUID from string");
 		queue_elf(&uuid);
 	}
 }
@@ -1473,9 +1476,9 @@ void ta_elf_print_mappings(void *pctx, print_func_t print_func,
 	get_next_in_order(elf_queue, &elf, &seg, &elf_idx);
 	while (true) {
 		vaddr_t va = -1;
+		paddr_t pa = -1;
 		size_t sz = 0;
 		uint32_t flags = DUMP_MAP_SECURE;
-		size_t offs = 0;
 
 		if (seg) {
 			va = rounddown(seg->vaddr + elf->load_addr);
@@ -1488,6 +1491,7 @@ void ta_elf_print_mappings(void *pctx, print_func_t print_func,
 
 			/* If there's a match, it should be the same map */
 			if (maps[map_idx].va == va) {
+				pa = maps[map_idx].pa;
 				/*
 				 * In shared libraries the first page is
 				 * mapped separately with the rest of that
@@ -1526,7 +1530,6 @@ void ta_elf_print_mappings(void *pctx, print_func_t print_func,
 		if (!seg)
 			break;
 
-		offs = rounddown(seg->offset);
 		if (seg->flags & PF_R)
 			flags |= DUMP_MAP_READ;
 		if (seg->flags & PF_W)
@@ -1534,7 +1537,7 @@ void ta_elf_print_mappings(void *pctx, print_func_t print_func,
 		if (seg->flags & PF_X)
 			flags |= DUMP_MAP_EXEC;
 
-		print_seg(pctx, print_func, idx, elf_idx, va, offs, sz, flags);
+		print_seg(pctx, print_func, idx, elf_idx, va, pa, sz, flags);
 		idx++;
 
 		if (!get_next_in_order(elf_queue, &elf, &seg, &elf_idx))
diff --git a/ldelf/ta_elf_rel.c b/ldelf/ta_elf_rel.c
index 5d5b1eba4975b4adc4e0c378d9477e0b250cf23e..39d0c7e259419be380703a9a5bf0c3c497fc29e5 100644
--- a/ldelf/ta_elf_rel.c
+++ b/ldelf/ta_elf_rel.c
@@ -198,6 +198,9 @@ static TEE_Result resolve_sym_helper(const char *name, vaddr_t *val,
 		uint32_t *bucket = &hashtab[2];
 		uint32_t *chain = &bucket[nbuckets];
 
+		if (!nbuckets)
+			return TEE_ERROR_ITEM_NOT_FOUND;
+
 		hash = elf_hash(name);
 
 		for (n = bucket[hash % nbuckets]; n; n = chain[n]) {
@@ -282,7 +285,7 @@ static void resolve_sym(const char *name, vaddr_t *val, struct ta_elf **mod,
 	if (res) {
 		if (err_if_not_found)
 			err(res, "Symbol %s not found", name);
-		else
+		else if (val)
 			*val = 0;
 	}
 }
@@ -644,7 +647,7 @@ static void e64_relocate(struct ta_elf *elf, unsigned int rel_sidx)
 	rela_end = rela + shdr[rel_sidx].sh_size / sizeof(Elf64_Rela);
 	for (; rela < rela_end; rela++) {
 		Elf64_Addr *where = NULL;
-		size_t sym_idx = 0;
+		size_t sym_idx __maybe_unused = 0;
 
 		/* Check the address is inside TA memory */
 		if (rela->r_offset >= (elf->max_addr - elf->load_addr))
diff --git a/lib/libmbedtls/core/hash.c b/lib/libmbedtls/core/hash.c
index 651a9bf4ee24bbfd7832ef131e580d27009671b1..d342c247182acf12dfbed361173d42945f71b934 100644
--- a/lib/libmbedtls/core/hash.c
+++ b/lib/libmbedtls/core/hash.c
@@ -202,11 +202,6 @@ TEE_Result hash_sha256_check(const uint8_t *hash, const uint8_t *data,
 int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx,
 				  const unsigned char data[64])
 {
-	MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL,
-				      MBEDTLS_ERR_SHA1_BAD_INPUT_DATA);
-	MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL,
-				      MBEDTLS_ERR_SHA1_BAD_INPUT_DATA);
-
 	crypto_accel_sha1_compress(ctx->state, data, 1);
 
 	return 0;
@@ -217,11 +212,6 @@ int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx,
 int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
 				    const unsigned char data[64])
 {
-	MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL,
-				      MBEDTLS_ERR_SHA256_BAD_INPUT_DATA);
-	MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL,
-				      MBEDTLS_ERR_SHA256_BAD_INPUT_DATA);
-
 	crypto_accel_sha256_compress(ctx->state, data, 1);
 
 	return 0;
@@ -232,11 +222,6 @@ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
 int mbedtls_internal_sha512_process(mbedtls_sha512_context *ctx,
 				    const unsigned char data[64])
 {
-	MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL,
-				      MBEDTLS_ERR_SHA512_BAD_INPUT_DATA);
-	MBEDTLS_INTERNAL_VALIDATE_RET((const unsigned char *)data != NULL,
-				      MBEDTLS_ERR_SHA512_BAD_INPUT_DATA);
-
 	crypto_accel_sha512_compress(ctx->state, data, 1);
 
 	return 0;
diff --git a/lib/libmbedtls/core/rsa.c b/lib/libmbedtls/core/rsa.c
index 89ebb0dc668fd3ff353163eb97e7e5152321ab7e..60742a797d8d87aa734a4ae2c3bea5e925dfe676 100644
--- a/lib/libmbedtls/core/rsa.c
+++ b/lib/libmbedtls/core/rsa.c
@@ -97,13 +97,11 @@ static uint32_t tee_algo_to_mbedtls_hash_algo(uint32_t algo)
 	}
 }
 
-static TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa,
+static TEE_Result rsa_complete_from_key_pair(mbedtls_rsa_context *rsa,
 						      struct rsa_keypair *key)
 {
 	int lmd_res = 0;
 
-	mbedtls_rsa_init(rsa);
-
 	rsa->E = *(mbedtls_mpi *)key->e;
 	rsa->N = *(mbedtls_mpi *)key->n;
 	rsa->D = *(mbedtls_mpi *)key->d;
@@ -150,6 +148,14 @@ err:
 	return get_tee_result(lmd_res);
 }
 
+static TEE_Result rsa_init_and_complete_from_key_pair(mbedtls_rsa_context *rsa,
+						      struct rsa_keypair *key)
+{
+	mbedtls_rsa_init(rsa);
+
+	return rsa_complete_from_key_pair(rsa, key);
+}
+
 static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key)
 {
 	/*
@@ -171,6 +177,18 @@ static void mbd_rsa_free(mbedtls_rsa_context *rsa, struct rsa_keypair *key)
 	mbedtls_rsa_free(rsa);
 }
 
+static void mbd_pk_free(mbedtls_pk_context *ctx, struct rsa_keypair *key)
+{
+	mbedtls_rsa_context *rsa = ctx->pk_ctx;
+
+	/*
+	 * Executing mbedtls_rsa_free twice is fine, as it does nothing if its
+	 * argument is NULL.
+	 */
+	mbd_rsa_free(rsa, key);
+	mbedtls_pk_free(ctx);
+}
+
 TEE_Result crypto_acipher_alloc_rsa_keypair(struct rsa_keypair *s,
 					    size_t key_size_bits)
 __weak __alias("sw_crypto_acipher_alloc_rsa_keypair");
@@ -437,6 +455,7 @@ TEE_Result crypto_acipher_rsaes_decrypt(uint32_t algo,
 					struct rsa_keypair *key,
 					const uint8_t *label __unused,
 					size_t label_len __unused,
+					uint32_t mgf_algo,
 					const uint8_t *src, size_t src_len,
 					uint8_t *dst, size_t *dst_len)
 __weak __alias("sw_crypto_acipher_rsaes_decrypt");
@@ -445,6 +464,7 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 					   struct rsa_keypair *key,
 					   const uint8_t *label __unused,
 					   size_t label_len __unused,
+					   uint32_t mgf_algo,
 					   const uint8_t *src, size_t src_len,
 					   uint8_t *dst, size_t *dst_len)
 {
@@ -454,11 +474,24 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 	size_t blen = 0;
 	size_t mod_size = 0;
 	void *buf = NULL;
-	mbedtls_rsa_context rsa = { };
+	mbedtls_pk_context ctx = { };
+	mbedtls_rsa_context *rsa = NULL;
 	const mbedtls_pk_info_t *pk_info = NULL;
 	uint32_t md_algo = MBEDTLS_MD_NONE;
 
-	res = rsa_init_and_complete_from_key_pair(&rsa, key);
+	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+	if (!pk_info) {
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	mbedtls_pk_init(&ctx);
+	res = mbedtls_pk_setup(&ctx, pk_info);
+	if (res != 0) {
+		goto out;
+	}
+
+	rsa = ctx.pk_ctx;
+	res = rsa_complete_from_key_pair(rsa, key);
 	if (res)
 		return res;
 
@@ -483,12 +516,6 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 		goto out;
 	}
 
-	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
-	if (!pk_info) {
-		res = TEE_ERROR_NOT_SUPPORTED;
-		goto out;
-	}
-
 	/*
 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
 	 * not be used in rsa, so skip it here.
@@ -499,11 +526,16 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 			res = TEE_ERROR_NOT_SUPPORTED;
 			goto out;
 		}
+		if (md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
+			DMSG("Using a different MGF1 algorithm is not supported");
+			res = TEE_ERROR_NOT_SUPPORTED;
+			goto out;
+		}
 	}
 
-	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
+	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
 
-	lmd_res = pk_info->decrypt_func(&rsa, src, src_len, buf, &blen,
+	lmd_res = pk_info->decrypt_func(&ctx, src, src_len, buf, &blen,
 					blen, mbd_rand, NULL);
 	if (lmd_res != 0) {
 		FMSG("decrypt_func() returned 0x%x", -lmd_res);
@@ -523,7 +555,7 @@ TEE_Result sw_crypto_acipher_rsaes_decrypt(uint32_t algo,
 out:
 	if (buf)
 		free(buf);
-	mbd_rsa_free(&rsa, key);
+	mbd_pk_free(&ctx, key);
 	return res;
 }
 
@@ -531,6 +563,7 @@ TEE_Result crypto_acipher_rsaes_encrypt(uint32_t algo,
 					struct rsa_public_key *key,
 					const uint8_t *label __unused,
 					size_t label_len __unused,
+					uint32_t mgf_algo,
 					const uint8_t *src, size_t src_len,
 					uint8_t *dst, size_t *dst_len)
 __weak __alias("sw_crypto_acipher_rsaes_encrypt");
@@ -539,6 +572,7 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 					   struct rsa_public_key *key,
 					   const uint8_t *label __unused,
 					   size_t label_len __unused,
+					   uint32_t mgf_algo,
 					   const uint8_t *src, size_t src_len,
 					   uint8_t *dst, size_t *dst_len)
 {
@@ -546,15 +580,28 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 	int lmd_res = 0;
 	int lmd_padding = 0;
 	size_t mod_size = 0;
-	mbedtls_rsa_context rsa;
+	mbedtls_pk_context ctx = { };
+	mbedtls_rsa_context *rsa = NULL;
 	const mbedtls_pk_info_t *pk_info = NULL;
 	uint32_t md_algo = MBEDTLS_MD_NONE;
 
-	memset(&rsa, 0, sizeof(rsa));
-	mbedtls_rsa_init(&rsa);
+	memset(&ctx, 0, sizeof(ctx));
 
-	rsa.E = *(mbedtls_mpi *)key->e;
-	rsa.N = *(mbedtls_mpi *)key->n;
+	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+	if (!pk_info) {
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	mbedtls_pk_init(&ctx);
+	res = mbedtls_pk_setup(&ctx, pk_info);
+	if (res != 0) {
+		goto out;
+	}
+
+	rsa = ctx.pk_ctx;
+
+	rsa->E = *(mbedtls_mpi *)key->e;
+	rsa->N = *(mbedtls_mpi *)key->n;
 
 	mod_size = crypto_bignum_num_bytes(key->n);
 	if (*dst_len < mod_size) {
@@ -563,34 +610,30 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 		goto out;
 	}
 	*dst_len = mod_size;
-	rsa.len = mod_size;
+	rsa->len = mod_size;
 
 	if (algo == TEE_ALG_RSAES_PKCS1_V1_5)
 		lmd_padding = MBEDTLS_RSA_PKCS_V15;
 	else
 		lmd_padding = MBEDTLS_RSA_PKCS_V21;
 
-	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
-	if (!pk_info) {
-		res = TEE_ERROR_NOT_SUPPORTED;
-		goto out;
-	}
-
 	/*
 	 * TEE_ALG_RSAES_PKCS1_V1_5 is invalid in hash. But its hash algo will
 	 * not be used in rsa, so skip it here.
 	 */
 	if (algo != TEE_ALG_RSAES_PKCS1_V1_5) {
 		md_algo = tee_algo_to_mbedtls_hash_algo(algo);
-		if (md_algo == MBEDTLS_MD_NONE) {
+		/* Using a different MGF1 algorithm is not supported. */
+		if (md_algo == MBEDTLS_MD_NONE ||
+		    md_algo != tee_algo_to_mbedtls_hash_algo(mgf_algo)) {
 			res = TEE_ERROR_NOT_SUPPORTED;
 			goto out;
 		}
 	}
 
-	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
+	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
 
-	lmd_res = pk_info->encrypt_func(&rsa, src, src_len, dst, dst_len,
+	lmd_res = pk_info->encrypt_func(&ctx, src, src_len, dst, dst_len,
 					*dst_len, mbd_rand, NULL);
 	if (lmd_res != 0) {
 		FMSG("encrypt_func() returned 0x%x", -lmd_res);
@@ -600,9 +643,9 @@ TEE_Result sw_crypto_acipher_rsaes_encrypt(uint32_t algo,
 	res = TEE_SUCCESS;
 out:
 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
-	mbedtls_mpi_init(&rsa.E);
-	mbedtls_mpi_init(&rsa.N);
-	mbedtls_rsa_free(&rsa);
+	mbedtls_mpi_init(&rsa->E);
+	mbedtls_mpi_init(&rsa->N);
+	mbedtls_pk_free(&ctx);
 	return res;
 }
 
@@ -622,11 +665,26 @@ TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
 	int lmd_padding = 0;
 	size_t mod_size = 0;
 	size_t hash_size = 0;
-	mbedtls_rsa_context rsa = { };
+	mbedtls_pk_context ctx = { };
+	mbedtls_rsa_context *rsa = NULL;
 	const mbedtls_pk_info_t *pk_info = NULL;
 	uint32_t md_algo = 0;
 
-	res = rsa_init_and_complete_from_key_pair(&rsa, key);
+	memset(&ctx, 0, sizeof(ctx));
+	
+	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+	if (!pk_info) {
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	mbedtls_pk_init(&ctx);
+	res = mbedtls_pk_setup(&ctx, pk_info);
+	if (res != 0) {
+		goto err;
+	}
+
+	rsa = ctx.pk_ctx;
+	res = rsa_complete_from_key_pair(rsa, key);
 	if (res)
 		return res;
 
@@ -668,7 +726,7 @@ TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
 		res = TEE_ERROR_SHORT_BUFFER;
 		goto err;
 	}
-	rsa.len = mod_size;
+	rsa->len = mod_size;
 
 	md_algo = tee_algo_to_mbedtls_hash_algo(algo);
 	if (md_algo == MBEDTLS_MD_NONE) {
@@ -676,15 +734,10 @@ TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
 		goto err;
 	}
 
-	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
-	if (!pk_info) {
-		res = TEE_ERROR_NOT_SUPPORTED;
-		goto err;
-	}
 
-	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
+	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
 
-	lmd_res = pk_info->sign_func(&rsa, md_algo, msg, msg_len, sig,
+	lmd_res = pk_info->sign_func(&ctx, md_algo, msg, msg_len, sig,
 				     *sig_len, sig_len, mbd_rand, NULL);
 	if (lmd_res != 0) {
 		FMSG("sign_func failed, returned 0x%x", -lmd_res);
@@ -693,7 +746,7 @@ TEE_Result sw_crypto_acipher_rsassa_sign(uint32_t algo, struct rsa_keypair *key,
 	}
 	res = TEE_SUCCESS;
 err:
-	mbd_rsa_free(&rsa, key);
+	mbd_pk_free(&ctx, key);
 	return res;
 }
 
@@ -717,7 +770,8 @@ TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
 	int lmd_padding = 0;
 	size_t hash_size = 0;
 	size_t bigint_size = 0;
-	mbedtls_rsa_context rsa;
+	mbedtls_pk_context ctx = { };
+	mbedtls_rsa_context *rsa = NULL;
 	const mbedtls_pk_info_t *pk_info = NULL;
 	uint32_t md_algo = 0;
 	struct ftmn ftmn = { };
@@ -729,11 +783,23 @@ TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
 	 */
 	FTMN_CALLEE_SWAP_HASH(FTMN_FUNC_HASH("crypto_acipher_rsassa_verify"));
 
-	memset(&rsa, 0, sizeof(rsa));
-	mbedtls_rsa_init(&rsa);
+	memset(&ctx, 0, sizeof(ctx));
 
-	rsa.E = *(mbedtls_mpi *)key->e;
-	rsa.N = *(mbedtls_mpi *)key->n;
+	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
+	if (!pk_info) {
+		return TEE_ERROR_NOT_SUPPORTED;
+	}
+
+	mbedtls_pk_init(&ctx);
+	res = mbedtls_pk_setup(&ctx, pk_info);
+	if (res != 0) {
+		goto err;
+	}
+
+	rsa = ctx.pk_ctx;
+
+	rsa->E = *(mbedtls_mpi *)key->e;
+	rsa->N = *(mbedtls_mpi *)key->n;
 
 	res = tee_alg_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(algo),
 				      &hash_size);
@@ -751,7 +817,7 @@ TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
 		goto err;
 	}
 
-	rsa.len = bigint_size;
+	rsa->len = bigint_size;
 
 	switch (algo) {
 	case TEE_ALG_RSASSA_PKCS1_V1_5_MD5:
@@ -783,17 +849,11 @@ TEE_Result sw_crypto_acipher_rsassa_verify(uint32_t algo,
 		goto err;
 	}
 
-	pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
-	if (!pk_info) {
-		res = TEE_ERROR_NOT_SUPPORTED;
-		goto err;
-	}
-
-	mbedtls_rsa_set_padding(&rsa, lmd_padding, md_algo);
+	mbedtls_rsa_set_padding(rsa, lmd_padding, md_algo);
 
 	FTMN_PUSH_LINKED_CALL(&ftmn, arg_hash);
-	lmd_res = pk_info->verify_func(&rsa, md_algo, msg, msg_len,
-				       sig, sig_len);
+	lmd_res = pk_info->verify_func(&ctx, md_algo, msg, msg_len,
+	                               sig, sig_len);
 	if (!lmd_res)
 		FTMN_SET_CHECK_RES_FROM_CALL(&ftmn, FTMN_INCR0, lmd_res);
 	FTMN_POP_LINKED_CALL(&ftmn);
@@ -810,8 +870,8 @@ err:
 out:
 	FTMN_CALLEE_DONE_CHECK(&ftmn, FTMN_INCR0, FTMN_STEP_COUNT(1), res);
 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
-	mbedtls_mpi_init(&rsa.E);
-	mbedtls_mpi_init(&rsa.N);
-	mbedtls_rsa_free(&rsa);
+	mbedtls_mpi_init(&rsa->E);
+	mbedtls_mpi_init(&rsa->N);
+	mbedtls_pk_free(&ctx);
 	return res;
 }
diff --git a/lib/libmbedtls/include/mbedtls_config_kernel.h b/lib/libmbedtls/include/mbedtls_config_kernel.h
index c3924f46980d3e787f71a9d7a833fda9a1d6fb6e..9bc961f35a24231dc95748c719f548dcff00ca34 100644
--- a/lib/libmbedtls/include/mbedtls_config_kernel.h
+++ b/lib/libmbedtls/include/mbedtls_config_kernel.h
@@ -95,6 +95,7 @@
 
 #if defined(CFG_CRYPTO_RSA)
 #define MBEDTLS_RSA_C
+#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 128
 #endif
 
 #if defined(CFG_CRYPTO_RSA) || defined(CFG_CRYPTO_ECC)
@@ -131,6 +132,4 @@
 
 #endif /*CFG_CRYPTOLIB_NAME_mbedtls*/
 
-#include <mbedtls/check_config.h>
-
 #endif /* __MBEDTLS_CONFIG_KERNEL_H */
diff --git a/lib/libmbedtls/include/mbedtls_config_uta.h b/lib/libmbedtls/include/mbedtls_config_uta.h
index 83b454e88446989d6fa298ffb28dcdc57d0e5526..a21301210223780f3fad976294aa52091291129f 100644
--- a/lib/libmbedtls/include/mbedtls_config_uta.h
+++ b/lib/libmbedtls/include/mbedtls_config_uta.h
@@ -22,6 +22,8 @@
 
 #define MBEDTLS_SHA1_C
 #define MBEDTLS_SHA256_C
+#define MBEDTLS_SHA384_C
+#define MBEDTLS_SHA512_C
 #define MBEDTLS_MD_C
 #define MBEDTLS_MD5_C
 
@@ -65,6 +67,4 @@
 #define MBEDTLS_PEM_PARSE_C
 #define MBEDTLS_PEM_WRITE_C
 
-#include <mbedtls/check_config.h>
-
 #endif /* __MBEDTLS_CONFIG_UTA_H */
diff --git a/lib/libmbedtls/mbedtls/.uncrustify.cfg b/lib/libmbedtls/mbedtls/.uncrustify.cfg
index 92b8ce9cd233509eea7aac93e23efdc1fb3665da..8dc9db0497de46ea6144f194d1be1f42baa27acc 100644
--- a/lib/libmbedtls/mbedtls/.uncrustify.cfg
+++ b/lib/libmbedtls/mbedtls/.uncrustify.cfg
@@ -4,19 +4,7 @@
 # to Mbed TLS.
 #
 # Copyright The Mbed TLS Contributors
-# SPDX-License-Identifier: Apache-2.0
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
 
 
 # Wrap lines at 100 characters
diff --git a/lib/libmbedtls/mbedtls/BUGS.md b/lib/libmbedtls/mbedtls/BUGS.md
index 47bde07a239c050b095205a8391371ef4ea8480c..a65c606de93ecf0d9b59a251433e9e2ffb7b90e8 100644
--- a/lib/libmbedtls/mbedtls/BUGS.md
+++ b/lib/libmbedtls/mbedtls/BUGS.md
@@ -7,7 +7,7 @@ Known issues in Mbed TLS are [tracked on GitHub](https://github.com/Mbed-TLS/mbe
 If you think you've found a bug in Mbed TLS, please follow these steps:
 
 1. Make sure you're using the latest version of a
-   [maintained branch](BRANCHES.md): `master`, `development`,
+   [maintained branch](BRANCHES.md): `main`, `development`,
    or a long-time support branch.
 2. Check [GitHub](https://github.com/Mbed-TLS/mbedtls/issues) to see if
    your issue has already been reported. If not, …
diff --git a/lib/libmbedtls/mbedtls/CONTRIBUTING.md b/lib/libmbedtls/mbedtls/CONTRIBUTING.md
index a7bf198dabf80337c676afc1e78986aad1f15adf..d793434ceddbd1dbe8f7d89109872c61cfbe5717 100644
--- a/lib/libmbedtls/mbedtls/CONTRIBUTING.md
+++ b/lib/libmbedtls/mbedtls/CONTRIBUTING.md
@@ -24,7 +24,7 @@ Making a Contribution
 1. [Check for open issues](https://github.com/Mbed-TLS/mbedtls/issues) or [start a discussion](https://lists.trustedfirmware.org/mailman3/lists/mbed-tls.lists.trustedfirmware.org) around a feature idea or a bug.
 1. Fork the [Mbed TLS repository on GitHub](https://github.com/Mbed-TLS/mbedtls) to start making your changes. As a general rule, you should use the ["development" branch](https://github.com/Mbed-TLS/mbedtls/tree/development) as a basis.
 1. Write a test which shows that the bug was fixed or that the feature works as expected.
-1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. We will include your name in the ChangeLog :)
+1. Send a pull request (PR) and work with us until it gets merged and published. Contributions may need some modifications, so a few rounds of review and fixing may be necessary. See our [review process guidelines](https://mbed-tls.readthedocs.io/en/latest/reviews/review-for-contributors/).
 1. For quick merging, the contribution should be short, and concentrated on a single feature or topic. The larger the contribution is, the longer it would take to review it and merge it.
 
 Backwards Compatibility
@@ -84,8 +84,14 @@ Mbed TLS is well documented, but if you think documentation is needed, speak out
 License and Copyright
 ---------------------
 
-All new files should include the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) standard license header where possible. For licensing details, please see the [License section of the README](README.md#License).
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses. This means that users may choose which of these licenses they take the code under.
+
+Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses.
+
+All new files should include the standard SPDX license identifier where possible, i.e. "SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later".
 
 The copyright on contributions is retained by the original authors of the code. Where possible for new files, this should be noted in a comment at the top of the file in the form: "Copyright The Mbed TLS Contributors".
 
-When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and be subject to the same Apache 2.0 license. This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.
+When contributing code to us, the committer and all authors are required to make the submission under the terms of the [Developer Certificate of Origin](dco.txt), confirming that the code submitted can (legally) become part of the project, and is submitted under both the Apache-2.0 AND GPL-2.0-or-later licenses.
+
+This is done by including the standard Git `Signed-off-by:` line in every commit message. If more than one person contributed to the commit, they should also add their own `Signed-off-by:` line.
diff --git a/lib/libmbedtls/mbedtls/ChangeLog b/lib/libmbedtls/mbedtls/ChangeLog
index 9b30aff0086a1c88d6ceab16cfbeafe2306515d8..a88c9c5694b0f65a6ec2f4117493bbb2cfe62857 100644
--- a/lib/libmbedtls/mbedtls/ChangeLog
+++ b/lib/libmbedtls/mbedtls/ChangeLog
@@ -1,5 +1,781 @@
 Mbed TLS ChangeLog (Sorted per branch, date)
 
+= Mbed TLS 3.6.2 branch released 2024-10-14
+
+Security
+   * Fix a buffer underrun in mbedtls_pk_write_key_der() when
+     called on an opaque key, MBEDTLS_USE_PSA_CRYPTO is enabled,
+     and the output buffer is smaller than the actual output.
+     Fix a related buffer underrun in mbedtls_pk_write_key_pem()
+     when called on an opaque RSA key, MBEDTLS_USE_PSA_CRYPTO is enabled
+     and MBEDTLS_MPI_MAX_SIZE is smaller than needed for a 4096-bit RSA key.
+     CVE-2024-49195
+
+= Mbed TLS 3.6.1 branch released 2024-08-30
+
+API changes
+   * The experimental functions psa_generate_key_ext() and
+     psa_key_derivation_output_key_ext() are no longer declared when compiling
+     in C++. This resolves a build failure under C++ compilers that do not
+     support flexible array members (a C99 feature not adopted by C++).
+     Fixes #9020.
+
+Default behavior changes
+   * In a PSA-client-only build (i.e. MBEDTLS_PSA_CRYPTO_CLIENT &&
+     !MBEDTLS_PSA_CRYPTO_C), do not automatically enable local crypto when the
+     corresponding PSA mechanism is enabled, since the server provides the
+     crypto. Fixes #9126.
+   * A TLS handshake may now call psa_crypto_init() if TLS 1.3 is enabled.
+     This can happen even if TLS 1.3 is offered but eventually not selected
+     in the protocol version negotiation.
+   * By default, the handling of TLS 1.3 tickets by the Mbed TLS client is now
+     disabled at runtime. Applications that were using TLS 1.3 tickets
+     signalled by MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET return values now
+     need to enable the handling of TLS 1.3 tickets through the new
+     mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets() API.
+
+New deprecations
+   * The experimental functions psa_generate_key_ext() and
+     psa_key_derivation_output_key_ext() are deprecated in favor of
+     psa_generate_key_custom() and psa_key_derivation_output_key_custom().
+     They have almost exactly the same interface, but the variable-length
+     data is passed in a separate parameter instead of a flexible array
+     member.
+   * The following cryptographic mechanisms are planned to be removed
+     in Mbed TLS 4.0:
+     - DES (including 3DES).
+     - PKCS#1v1.5 encryption/decryption (RSAES-PKCS1-v1_5).
+       (OAEP, PSS, and PKCS#1v1.5 signature are staying.)
+     - Finite-field Diffie-Hellman with custom groups.
+       (RFC 7919 groups remain supported.)
+     - Elliptic curves of size 225 bits or less.
+   * The following cipher suites are planned to be removed from (D)TLS 1.2
+     in Mbed TLS 4.0:
+     - TLS_RSA_* (including TLS_RSA_PSK_*), i.e. cipher suites using
+       RSA decryption.
+       (RSA signatures, i.e. TLS_ECDHE_RSA_*, are staying.)
+     - TLS_ECDH_*, i.e. cipher suites using static ECDH.
+       (Ephemeral ECDH, i.e. TLS_ECDHE_*, is staying.)
+     - TLS_DHE_*, i.e. cipher suites using finite-field Diffie-Hellman.
+       (Ephemeral ECDH, i.e. TLS_ECDHE_*, is staying.)
+     - TLS_*CBC*, i.e. all cipher suites using CBC.
+   * The following low-level application interfaces are planned to be removed
+     from the public API in Mbed TLS 4.0:
+     - Hashes: hkdf.h, md5.h, ripemd160.h, sha1.h, sha3.h, sha256.h, sha512.h;
+     - Random generation: ctr_drbg.h, hmac_drbg.h, entropy.h;
+     - Ciphers and modes: aes.h, aria.h, camellia.h, chacha20.h, chachapoly.h,
+       cipher.h, cmac.h, gcm.h, poly1305.h;
+     - Private key encryption mechanisms: pkcs5.h, pkcs12.h.
+     - Asymmetric cryptography: bignum.h, dhm.h, ecdh.h, ecdsa.h, ecjpake.h,
+       ecp.h, rsa.h.
+     The cryptographic mechanisms remain present, but they will only be
+     accessible via the PSA API (psa_xxx functions introduced gradually
+     starting with Mbed TLS 2.17) and, where relevant, `pk.h`.
+     For guidance on migrating application code to the PSA API, please consult
+     the PSA transition guide (docs/psa-transition.md).
+   * The following integration interfaces are planned to be removed
+     in Mbed TLS 4.0:
+     - MBEDTLS_xxx_ALT replacement of cryptographic modules and functions.
+       Use PSA transparent drivers instead.
+     - MBEDTLS_PK_RSA_ALT and MBEDTLS_PSA_CRYPTO_SE_C.
+       Use PSA opaque drivers instead.
+
+Features
+   * When the new compilation option MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,
+     the number of volatile PSA keys is virtually unlimited, at the expense
+     of increased code size. This option is off by default, but enabled in
+     the default mbedtls_config.h. Fixes #9216.
+
+Security
+   * Unlike previously documented, enabling MBEDTLS_PSA_HMAC_DRBG_MD_TYPE does
+     not cause the PSA subsystem to use HMAC_DRBG: it uses HMAC_DRBG only when
+     MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG and MBEDTLS_CTR_DRBG_C are disabled.
+     CVE-2024-45157
+   * Fix a stack buffer overflow in mbedtls_ecdsa_der_to_raw() and
+     mbedtls_ecdsa_raw_to_der() when the bits parameter is larger than the
+     largest supported curve. In some configurations with PSA disabled,
+     all values of bits are affected. This never happens in internal library
+     calls, but can affect applications that call these functions directly.
+     CVE-2024-45158
+   * With TLS 1.3, when a server enables optional authentication of the
+     client, if the client-provided certificate does not have appropriate values
+     in keyUsage or extKeyUsage extensions, then the return value of
+     mbedtls_ssl_get_verify_result() would incorrectly have the
+     MBEDTLS_X509_BADCERT_KEY_USAGE and MBEDTLS_X509_BADCERT_EXT_KEY_USAGE bits
+     clear. As a result, an attacker that had a certificate valid for uses other
+     than TLS client authentication could be able to use it for TLS client
+     authentication anyway. Only TLS 1.3 servers were affected, and only with
+     optional authentication (required would abort the handshake with a fatal
+     alert).
+     CVE-2024-45159
+
+Bugfix
+   * Fix TLS 1.3 client build and runtime when support for session tickets is
+     disabled (MBEDTLS_SSL_SESSION_TICKETS configuration option). Fixes #6395.
+   * Fix compilation error when memcpy() is a function-like macros. Fixes #8994.
+   * MBEDTLS_ASN1_PARSE_C and MBEDTLS_ASN1_WRITE_C are now automatically enabled
+     as soon as MBEDTLS_RSA_C is enabled. Fixes #9041.
+   * Fix undefined behaviour (incrementing a NULL pointer by zero length) when
+     passing in zero length additional data to multipart AEAD.
+   * Fix rare concurrent access bug where attempting to operate on a
+     non-existent key while concurrently creating a new key could potentially
+     corrupt the key store.
+   * Fix error handling when creating a key in a dynamic secure element
+     (feature enabled by MBEDTLS_PSA_CRYPTO_SE_C). In a low memory condition,
+     the creation could return PSA_SUCCESS but using or destroying the key
+     would not work. Fixes #8537.
+   * Fix issue of redefinition warning messages for _GNU_SOURCE in
+     entropy_poll.c and sha_256.c. There was a build warning during
+     building for linux platform.
+     Resolves #9026
+   * Fix a compilation warning in pk.c when PSA is enabled and RSA is disabled.
+   * Fix the build when MBEDTLS_PSA_CRYPTO_CONFIG is enabled and the built-in
+     CMAC is enabled, but no built-in unauthenticated cipher is enabled.
+     Fixes #9209.
+   * Fix redefinition warnings when SECP192R1 and/or SECP192K1 are disabled.
+     Fixes #9029.
+   * Fix psa_cipher_decrypt() with CCM* rejecting messages less than 3 bytes
+     long. Credit to Cryptofuzz. Fixes #9314.
+   * Fix interference between PSA volatile keys and built-in keys
+     when MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS is enabled and
+     MBEDTLS_PSA_KEY_SLOT_COUNT is more than 4096.
+   * Document and enforce the limitation of mbedtls_psa_register_se_key()
+     to persistent keys. Resolves #9253.
+   * Fix Clang compilation error when MBEDTLS_USE_PSA_CRYPTO is enabled
+     but MBEDTLS_DHM_C is disabled. Reported by Michael Schuster in #9188.
+   * Fix server mode only build when MBEDTLS_SSL_SRV_C is enabled but
+     MBEDTLS_SSL_CLI_C is disabled. Reported by M-Bab on GitHub in #9186.
+   * When MBEDTLS_PSA_CRYPTO_C was disabled and MBEDTLS_ECDSA_C enabled,
+     some code was defining 0-size arrays, resulting in compilation errors.
+     Fixed by disabling the offending code in configurations without PSA
+     Crypto, where it never worked. Fixes #9311.
+   * Fix unintended performance regression when using short RSA public keys.
+     Fixes #9232.
+   * Fixes an issue where some TLS 1.2 clients could not connect to an
+     Mbed TLS 3.6.0 server, due to incorrect handling of
+     legacy_compression_methods in the ClientHello.
+     Fixes #8995, #9243.
+   * Fix TLS connections failing when the handshake selects TLS 1.3
+     in an application that does not call psa_crypto_init().
+     Fixes #9072.
+   * Fix TLS connection failure in applications using an Mbed TLS client in
+     the default configuration connecting to a TLS 1.3 server sending tickets.
+     See the documentation of
+     mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets() for more
+     information.
+     Fixes #8749.
+   * Fix a memory leak that could occur when failing to process an RSA
+     key through some PSA functions due to low memory conditions.
+   * Fixed a regression introduced in 3.6.0 where the CA callback set with
+     mbedtls_ssl_conf_ca_cb() would stop working when connections were
+     upgraded to TLS 1.3. Fixed by adding support for the CA callback with TLS
+     1.3.
+   * Fixed a regression introduced in 3.6.0 where clients that relied on
+     optional/none authentication mode, by calling mbedtls_ssl_conf_authmode()
+     with MBEDTLS_SSL_VERIFY_OPTIONAL or MBEDTLS_SSL_VERIFY_NONE, would stop
+     working when connections were upgraded to TLS 1.3. Fixed by adding
+     support for optional/none with TLS 1.3 as well. Note that the TLS 1.3
+     standard makes server authentication mandatory; users are advised not to
+     use authmode none, and to carefully check the results when using optional
+     mode.
+   * Fixed a regression introduced in 3.6.0 where context-specific certificate
+     verify callbacks, set with mbedtls_ssl_set_verify() as opposed to
+     mbedtls_ssl_conf_verify(), would stop working when connections were
+     upgraded to TLS 1.3. Fixed by adding support for context-specific verify
+     callback in TLS 1.3.
+
+Changes
+   * Warn if mbedtls/check_config.h is included manually, as this can
+     lead to spurious errors. Error if a *adjust*.h header is included
+     manually, as this can lead to silently inconsistent configurations,
+     potentially resulting in buffer overflows.
+     When migrating from Mbed TLS 2.x, if you had a custom config.h that
+     included check_config.h, remove this inclusion from the Mbed TLS 3.x
+     configuration file (renamed to mbedtls_config.h). This change was made
+     in Mbed TLS 3.0, but was not announced in a changelog entry at the time.
+
+= Mbed TLS 3.6.0 branch released 2024-03-28
+
+API changes
+   * Remove `tls13_` in mbedtls_ssl_tls13_conf_early_data() and
+     mbedtls_ssl_tls13_conf_max_early_data_size() API names. Early data
+     feature may not be TLS 1.3 specific in the future. Fixes #6909.
+
+Default behavior changes
+   * psa_import_key() now only accepts RSA keys in the PSA standard formats.
+     The undocumented ability to import other formats (PKCS#8, SubjectPublicKey,
+     PEM) accepted by the pkparse module has been removed. Applications that
+     need these formats can call mbedtls_pk_parse_{public,}key() followed by
+     mbedtls_pk_import_into_psa().
+
+Requirement changes
+   * Drop support for Visual Studio 2013 and 2015, and Arm Compiler 5.
+
+New deprecations
+   * Rename the MBEDTLS_SHA256_USE_A64_CRYPTO_xxx config options to
+     MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_xxx. The old names may still
+     be used, but are deprecated.
+   * In the PSA API, domain parameters are no longer used for anything.
+     They are deprecated and will be removed in a future version of the
+     library.
+   * mbedtls_ecp_write_key() is deprecated in favor of
+     mbedtls_ecp_write_key_ext().
+
+Removals
+   * In the PSA API, the experimental way to encode the public exponent of
+     an RSA key as a domain parameter is no longer supported. Use
+     psa_generate_key_ext() instead.
+   * Temporary function mbedtls_pk_wrap_as_opaque() is removed. To mimic the
+     same behavior mbedtls_pk_get_psa_attributes() and
+     mbedtls_pk_import_into_psa() can be used to import a PK key into PSA,
+     while mbedtls_pk_setup_opaque() can be used to wrap a PSA key into a opaque
+     PK context.
+
+Features
+   * Added an example program showing how to hash with the PSA API.
+   * Support Armv8-A Crypto Extension acceleration for SHA-256
+     when compiling for Thumb (T32) or 32-bit Arm (A32).
+   * AES-NI is now supported in Windows builds with clang and clang-cl.
+     Resolves #8372.
+   * Add new mbedtls_x509_csr_parse_der_with_ext_cb() routine which allows
+     parsing unsupported certificate extensions via user provided callback.
+   * Enable the new option MBEDTLS_BLOCK_CIPHER_NO_DECRYPT to omit
+     the decryption direction of block ciphers (AES, ARIA, Camellia).
+     This affects both the low-level modules and the high-level APIs
+     (the cipher and PSA interfaces). This option is incompatible with modes
+     that use the decryption direction (ECB in PSA, CBC, XTS, KW) and with DES.
+   * Support use of Armv8-A Cryptographic Extensions for hardware acclerated
+     AES when compiling for Thumb (T32) or 32-bit Arm (A32).
+   * If a cipher or AEAD mechanism has a PSA driver, you can now build the
+     library without the corresponding built-in implementation. Generally
+     speaking that requires both the key type and algorithm to be accelerated
+     or they'll both be built in. However, for CCM and GCM the built-in
+     implementation is able to take advantage of a driver that only
+     accelerates the key type (that is, the block cipher primitive). See
+     docs/driver-only-builds.md for full details and current limitations.
+   * The CTR_DRBG module will now use AES from a PSA driver if MBEDTLS_AES_C is
+     disabled. This requires PSA_WANT_ALG_ECB_NO_PADDING in addition to
+     MBEDTLS_PSA_CRYPTO_C and PSA_WANT_KEY_TYPE_AES.
+   * Fewer modules depend on MBEDTLS_CIPHER_C, making it possible to save code
+     size by disabling it in more circumstances. In particular, the CCM and
+     GCM modules no longer depend on MBEDTLS_CIPHER_C. Also,
+     MBEDTLS_PSA_CRYPTO can now be enabled without MBEDTLS_CIPHER_C if all
+     unauthenticated (non-AEAD) ciphers are disabled, or if they're all
+     fully provided by drivers. See docs/driver-only-builds.md for full
+     details and current limitations; in particular, NIST_KW and PKCS5/PKCS12
+     decryption still unconditionally depend on MBEDTLS_CIPHER_C.
+   * Add support for record size limit extension as defined by RFC 8449
+     and configured with MBEDTLS_SSL_RECORD_SIZE_LIMIT.
+     Application data sent and received will be fragmented according to
+     Record size limits negotiated during handshake.
+   * Improve performance of AES-GCM, AES-CTR and CTR-DRBG when
+     hardware accelerated AES is not present (around 13-23% on 64-bit Arm).
+   * Add functions mbedtls_ecc_group_to_psa() and mbedtls_ecc_group_from_psa()
+     to convert between Mbed TLS and PSA curve identifiers.
+   * Add utility functions to manipulate mbedtls_ecp_keypair objects, filling
+     gaps made by making its fields private: mbedtls_ecp_set_public_key(),
+     mbedtls_ecp_write_public_key(), mbedtls_ecp_keypair_calc_public(),
+     mbedtls_ecp_keypair_get_group_id(). Fixes #5017, #5441, #8367, #8652.
+   * Add functions mbedtls_md_psa_alg_from_type() and
+     mbedtls_md_type_from_psa_alg() to convert between mbedtls_md_type_t and
+     psa_algorithm_t.
+   * Add partial platform support for z/OS.
+   * Improve performance for gcc (versions older than 9.3.0) and IAR.
+   * Add functions mbedtls_ecdsa_raw_to_der() and mbedtls_ecdsa_der_to_raw() to
+     convert ECDSA signatures between raw and DER (ASN.1) formats.
+   * Add support for using AES-CBC 128, 192, and 256 bit schemes
+     with PKCS#5 PBES2. Keys encrypted this way can now be parsed by PK parse.
+   * The new function mbedtls_rsa_get_bitlen() returns the length of the modulus
+     in bits, i.e. the key size for an RSA key.
+   * Add pc files for pkg-config, e.g.:
+     pkg-config --cflags --libs (mbedtls|mbedcrypto|mbedx509)
+   * Add getter (mbedtls_ssl_session_get_ticket_creation_time()) to access
+     `mbedtls_ssl_session.ticket_creation_time`.
+   * The new functions mbedtls_pk_get_psa_attributes() and
+     mbedtls_pk_import_into_psa() provide a uniform way to create a PSA
+     key from a PK key.
+   * The benchmark program now reports times for both ephemeral and static
+     ECDH in all ECDH configurations.
+   * Add support for 8-bit GCM tables for Shoup's algorithm to speedup GCM
+     operations when hardware accelerated AES is not present. Improves
+     performance by around 30% on 64-bit Intel; 125% on Armv7-M.
+   * The new function psa_generate_key_ext() allows generating an RSA
+     key pair with a custom public exponent.
+   * The new function mbedtls_ecp_write_key_ext() is similar to
+     mbedtls_ecp_write_key(), but can be used without separately calculating
+     the output length.
+   * Add new accessor to expose the private group id member of
+     `mbedtls_ecdh_context` structure.
+   * Add new accessor to expose the `MBEDTLS_PRIVATE(ca_istrue)` member of
+     `mbedtls_x509_crt` structure. This requires setting
+     the MBEDTLS_X509_EXT_BASIC_CONSTRAINTS bit in the certificate's
+     ext_types field.
+   * mbedtls_psa_get_random() is always available as soon as
+     MBEDTLS_PSA_CRYPTO_CLIENT is enabled at build time and psa_crypto_init() is
+     called at runtime. This together with MBEDTLS_PSA_RANDOM_STATE can be
+     used as random number generator function (f_rng) and context (p_rng) in
+     legacy functions.
+   * The new functions mbedtls_pk_copy_from_psa() and
+     mbedtls_pk_copy_public_from_psa() provide ways to set up a PK context
+     with the same content as a PSA key.
+   * Add new accessors to expose the private session-id,
+     session-id length, and ciphersuite-id members of
+     `mbedtls_ssl_session` structure.
+     Add new accessor to expose the ciphersuite-id of
+     `mbedtls_ssl_ciphersuite_t` structure.Design ref: #8529
+   * Mbed TLS now supports the writing and reading of TLS 1.3 early data (see
+     docs/tls13-early-data.md). The support enablement is controlled at build
+     time by the MBEDTLS_SSL_EARLY_DATA configuration option and at runtime by
+     the mbedtls_ssl_conf_early_data() API (by default disabled in both cases).
+   * Add protection for multithreaded access to the PSA keystore and protection
+     for multithreaded access to the the PSA global state, including
+     concurrently calling psa_crypto_init() when MBEDTLS_THREADING_C and
+     MBEDTLS_THREADING_PTHREAD are defined. See
+     docs/architecture/psa-thread-safety/psa-thread-safety.md for more details.
+     Resolves issues #3263 and #7945.
+
+Security
+   * Fix a stack buffer overread (less than 256 bytes) when parsing a TLS 1.3
+     ClientHello in a TLS 1.3 server supporting some PSK key exchange mode. A
+     malicious client could cause information disclosure or a denial of service.
+     Fixes CVE-2024-30166.
+   * Passing buffers that are stored in untrusted memory as arguments
+     to PSA functions is now secure by default.
+     The PSA core now protects against modification of inputs or exposure
+     of intermediate outputs during operations. This is currently implemented
+     by copying buffers.
+     This feature increases code size and memory usage. If buffers passed to
+     PSA functions are owned exclusively by the PSA core for the duration of
+     the function call (i.e. no buffer parameters are in shared memory),
+     copying may be disabled by setting MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS.
+     Note that setting this option will cause input-output buffer overlap to
+     be only partially supported (#3266).
+     Fixes CVE-2024-28960.
+   * Restore the maximum TLS version to be negotiated to the configured one
+     when an SSL context is reset with the mbedtls_ssl_session_reset() API.
+     An attacker was able to prevent an Mbed TLS server from establishing any
+     TLS 1.3 connection potentially resulting in a Denial of Service or forced
+     version downgrade from TLS 1.3 to TLS 1.2. Fixes #8654 reported by hey3e.
+     Fixes CVE-2024-28755.
+   * When negotiating TLS version on server side, do not fall back to the
+     TLS 1.2 implementation of the protocol if it is disabled.
+     - If the TLS 1.2 implementation was disabled at build time, a TLS 1.2
+       client could put the TLS 1.3-only server in an infinite loop processing
+       a TLS 1.2 ClientHello, resulting in a denial of service. Reported by
+       Matthias Mucha and Thomas Blattmann, SICK AG.
+     - If the TLS 1.2 implementation was disabled at runtime, a TLS 1.2 client
+       was able to successfully establish a TLS 1.2 connection with the server.
+       Reported by alluettiv on GitHub.
+    Fixes CVE-2024-28836.
+
+Bugfix
+   * Fix the build with CMake when Everest or P256-m is enabled through
+     a user configuration file or the compiler command line. Fixes #8165.
+   * Fix compilation error in C++ programs when MBEDTLS_ASN1_PARSE_C is
+     disabled.
+   * Fix possible NULL dereference issue in X509 cert_req program if an entry
+     in the san parameter is not separated by a colon.
+   * Fix possible NULL dereference issue in X509 cert_write program if an entry
+     in the san parameter is not separated by a colon.
+   * Fix an inconsistency between implementations and usages of `__cpuid`,
+     which mainly causes failures when building Windows target using
+     mingw or clang. Fixes #8334 & #8332.
+   * Fix build failure in conda-forge.  Fixes #8422.
+   * Fix parsing of CSRs with critical extensions.
+   * Switch to milliseconds as the unit for ticket creation and reception time
+     instead of seconds. That avoids rounding errors when computing the age of
+     tickets compared to peer using a millisecond clock (observed with GnuTLS).
+     Fixes #6623.
+   * Fix TLS server accepting TLS 1.2 handshake while TLS 1.2
+     is disabled at runtime. Fixes #8593.
+   * Remove accidental introduction of RSA signature algorithms
+     in TLS Suite B Profile. Fixes #8221.
+   * Fix unsupported PSA asymmetric encryption and decryption
+     (psa_asymmetric_[en|de]crypt) with opaque keys.
+     Resolves #8461.
+   * On Linux on ARMv8, fix a build error with SHA-256 and SHA-512
+     acceleration detection when the libc headers do not define the
+     corresponding constant. Reported by valord577.
+   * Correct initial capacities for key derivation algorithms:TLS12_PRF,
+     TLS12_PSK_TO_MS, PBKDF2-HMAC, PBKDF2-CMAC
+   * Fix mbedtls_pk_get_bitlen() for RSA keys whose size is not a
+     multiple of 8. Fixes #868.
+   * Avoid segmentation fault caused by releasing not initialized
+     entropy resource in gen_key example. Fixes #8809.
+   * mbedtls_pem_read_buffer() now performs a check on the padding data of
+     decrypted keys and it rejects invalid ones.
+   * Fix mbedtls_pk_sign(), mbedtls_pk_verify(), mbedtls_pk_decrypt() and
+     mbedtls_pk_encrypt() on non-opaque RSA keys to honor the padding mode in
+     the RSA context. Before, if MBEDTLS_USE_PSA_CRYPTO was enabled and the
+     RSA context was configured for PKCS#1 v2.1 (PSS/OAEP), the sign/verify
+     functions performed a PKCS#1 v1.5 signature instead and the
+     encrypt/decrypt functions returned an error. Fixes #8824.
+   * Fix missing bitflags in SSL session serialization headers. Their absence
+     allowed SSL sessions saved in one configuration to be loaded in a
+     different, incompatible configuration.
+   * In TLS 1.3 clients, fix an interoperability problem due to the client
+     generating a new random after a HelloRetryRequest. Fixes #8669.
+   * Fix the restoration of the ALPN when loading serialized connection with
+     the mbedtls_ssl_context_load() API.
+   * Fix NULL pointer dereference in mbedtls_pk_verify_ext() when called using
+     an opaque RSA context and specifying MBEDTLS_PK_RSASSA_PSS as key type.
+   * Fix RSA opaque keys always using PKCS1 v1.5 algorithms instead of the
+     primary algorithm of the wrapped PSA key.
+   * Fully support arbitrary overlap between inputs and outputs of PSA
+     functions. Note that overlap is still only partially supported when
+     MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS is set (#3266).
+
+Changes
+   * Use heap memory to allocate DER encoded public/private key.
+     This reduces stack usage significantly for writing a public/private
+     key to a PEM string.
+   * PSA_WANT_ALG_CCM and PSA_WANT_ALG_CCM_STAR_NO_TAG are no more synonyms and
+     they are now treated separately. This means that they should be
+     individually enabled in order to enable respective support; also the
+     corresponding MBEDTLS_PSA_ACCEL symbol should be defined in case
+     acceleration is required.
+   * Moved declaration of functions mbedtls_ecc_group_to_psa and
+     mbedtls_ecc_group_of_psa from psa/crypto_extra.h to mbedtls/psa_util.h
+   * mbedtls_pk_sign_ext() is now always available, not just when
+     PSA (MBEDTLS_PSA_CRYPTO_C) is enabled.
+   * Extended PSA Crypto configurations options for FFDH by making it possible
+     to select only some of the parameters / groups, with the macros
+     PSA_WANT_DH_RFC7919_XXXX. You now need to defined the corresponding macro
+     for each size you want to support. Also, if you have an FFDH accelerator,
+     you'll need to define the appropriate MBEDTLS_PSA_ACCEL macros to signal
+     support for these domain parameters.
+   * RSA support in PSA no longer auto-enables the pkparse and pkwrite modules,
+     saving code size when those are not otherwise enabled.
+   * mbedtls_mpi_exp_mod and code that uses it, notably RSA and DHM operations,
+     have changed their speed/memory compromise as part of a proactive security
+     improvement. The new default value of MBEDTLS_MPI_WINDOW_SIZE roughly
+     preserves the current speed, at the expense of increasing memory
+     consumption.
+   * Rename directory containing Visual Studio files from visualc/VS2013 to
+     visualc/VS2017.
+   * The TLS 1.3 protocol is now enabled in the default configuration.
+
+= Mbed TLS 3.5.2 branch released 2024-01-26
+
+Security
+   * Fix a timing side channel in private key RSA operations. This side channel
+     could be sufficient for an attacker to recover the plaintext. A local
+     attacker or a remote attacker who is close to the victim on the network
+     might have precise enough timing measurements to exploit this. It requires
+     the attacker to send a large number of messages for decryption. For
+     details, see "Everlasting ROBOT: the Marvin Attack", Hubert Kario. Reported
+     by Hubert Kario, Red Hat.
+   * Fix a failure to validate input when writing x509 extensions lengths which
+     could result in an integer overflow, causing a zero-length buffer to be
+     allocated to hold the extension. The extension would then be copied into
+     the buffer, causing a heap buffer overflow.
+
+= Mbed TLS 3.5.1 branch released 2023-11-06
+
+Changes
+   *  Mbed TLS is now released under a dual Apache-2.0 OR GPL-2.0-or-later
+      license. Users may choose which license they take the code under.
+
+Bugfix
+   * Fix accidental omission of MBEDTLS_TARGET_PREFIX in 3rdparty modules
+     in CMake.
+
+= Mbed TLS 3.5.0 branch released 2023-10-05
+
+API changes
+   * Mbed TLS 3.4 introduced support for omitting the built-in implementation
+     of ECDSA and/or EC J-PAKE when those are provided by a driver. However,
+     there was a flaw in the logic checking if the built-in implementation, in
+     that it failed to check if all the relevant curves were supported by the
+     accelerator. As a result, it was possible to declare no curves as
+     accelerated and still have the built-in implementation compiled out.
+     Starting with this release, it is necessary to declare which curves are
+     accelerated (using MBEDTLS_PSA_ACCEL_ECC_xxx macros), or they will be
+     considered not accelerated, and the built-in implementation of the curves
+     and any algorithm possible using them will be included in the build.
+   * Add new millisecond time type `mbedtls_ms_time_t` and `mbedtls_ms_time()`
+     function, needed for TLS 1.3 ticket lifetimes. Alternative implementations
+     can be created using an ALT interface.
+
+Requirement changes
+   * Officially require Python 3.8 now that earlier versions are out of support.
+   * Minimum required Windows version is now Windows Vista, or
+     Windows Server 2008.
+
+New deprecations
+   * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and
+     MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR, where xxx is either ECC or RSA,
+     are now being deprecated in favor of PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and
+     MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy. Here yyy can be: BASIC,
+     IMPORT, EXPORT, GENERATE, DERIVE. The goal is to have a finer detail about
+     the capabilities of the PSA side for either key.
+   * MBEDTLS_CIPHER_BLKSIZE_MAX is deprecated in favor of
+     MBEDTLS_MAX_BLOCK_LENGTH (if you intended what the name suggests:
+     maximum size of any supported block cipher) or the new name
+     MBEDTLS_CMAC_MAX_BLOCK_SIZE (if you intended the actual semantics:
+     maximum size of a block cipher supported by the CMAC module).
+   * mbedtls_pkcs5_pbes2() and mbedtls_pkcs12_pbe() functions are now
+     deprecated in favor of mbedtls_pkcs5_pbes2_ext() and
+     mbedtls_pkcs12_pbe_ext() as they offer more security by checking
+     for overflow of the output buffer and reporting the actual length
+     of the output.
+
+Features
+   * All modules that use hashes or HMAC can now take advantage of PSA Crypto
+     drivers when MBEDTLS_PSA_CRYPTO_C is enabled and psa_crypto_init() has
+     been called. Previously (in 3.3), this was restricted to a few modules,
+     and only in builds where MBEDTLS_MD_C was disabled; in particular the
+     entropy module was not covered which meant an external RNG had to be
+     provided - these limitations are lifted in this version. A new set of
+     feature macros, MBEDTLS_MD_CAN_xxx, has been introduced that can be used
+     to check for availability of hash algorithms, regardless of whether
+     they're provided by a built-in implementation, a driver or both. See
+     docs/driver-only-builds.md.
+   * When a PSA driver for ECDH is present, it is now possible to disable
+     MBEDTLS_ECDH_C in the build in order to save code size. For TLS 1.2
+     key exchanges based on ECDH(E) to work, this requires
+     MBEDTLS_USE_PSA_CRYPTO. Restartable/interruptible ECDHE operations in
+     TLS 1.2 (ECDHE-ECDSA key exchange) are not supported in those builds yet,
+     as PSA does not have an API for restartable ECDH yet.
+   * When all of ECDH, ECDSA and EC J-PAKE are either disabled or provided by
+     a driver, it is possible to disable MBEDTLS_ECP_C (and MBEDTLS_BIGNUM_C
+     if not required by another module) and still get support for ECC keys and
+     algorithms in PSA, with some limitations. See docs/driver-only-builds.txt
+     for details.
+   * Add parsing of directoryName subtype for subjectAltName extension in
+     x509 certificates.
+   * Add support for server-side TLS version negotiation. If both TLS 1.2 and
+     TLS 1.3 protocols are enabled, the TLS server now selects TLS 1.2 or
+     TLS 1.3 depending on the capabilities and preferences of TLS clients.
+     Fixes #6867.
+   * X.509 hostname verification now supports IPAddress Subject Alternate Names.
+   * Add support for reading and writing X25519 and X448
+     public and private keys in RFC 8410 format using the existing PK APIs.
+   * When parsing X.509 certificates, support the extensions
+     SignatureKeyIdentifier and AuthorityKeyIdentifier.
+   * Don't include the PSA dispatch functions for PAKEs (psa_pake_setup() etc)
+     if no PAKE algorithms are requested
+   * Add support for the FFDH algorithm and DH key types in PSA, with
+     parameters from RFC 7919. This includes a built-in implementation based
+     on MBEDTLS_BIGNUM_C, and a driver dispatch layer enabling alternative
+     implementations of FFDH through the driver entry points.
+   * It is now possible to generate certificates with SubjectAltNames.
+     Currently supported subtypes: DnsName, UniformResourceIdentifier,
+     IP address, OtherName, and DirectoryName, as defined in RFC 5280.
+     See mbedtls_x509write_crt_set_subject_alternative_name for
+     more information.
+   * X.509 hostname verification now partially supports URI Subject Alternate
+     Names. Only exact matching, without any normalization procedures
+     described in 7.4 of RFC5280, will result in a positive URI verification.
+   * Add function mbedtls_oid_from_numeric_string() to parse an OID from a
+     string to a DER-encoded mbedtls_asn1_buf.
+   * Add SHA-3 family hash functions.
+   * Add support to restrict AES to 128-bit keys in order to save code size.
+     A new configuration option, MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH, can be
+     used to enable this feature.
+   * AES performance improvements. Uplift varies by platform,
+     toolchain, optimisation flags and mode.
+     Aarch64, gcc -Os and CCM, GCM and XTS benefit the most.
+     On Aarch64, uplift is typically around 20 - 110%.
+     When compiling with gcc -Os on Aarch64, AES-XTS improves
+     by 4.5x.
+   * Add support for PBKDF2-HMAC through the PSA API.
+   * New symbols PSA_WANT_KEY_TYPE_xxx_KEY_PAIR_yyy and
+     MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR_yyy (where xxx is either ECC, RSA
+     or DH) were introduced in order to have finer accuracy in defining the
+     PSA capabilities for each key. These capabilities, named yyy above, can be
+     any of: BASIC, IMPORT, EXPORT, GENERATE, DERIVE.
+     - DERIVE is only available for ECC keys, not for RSA or DH ones.
+     - implementations are free to enable more than what it was strictly
+       requested. For example BASIC internally enables IMPORT and EXPORT
+       (useful for testing purposes), but this might change in the future.
+   * Add support for FFDH key exchange in TLS 1.3.
+     This is automatically enabled as soon as PSA_WANT_ALG_FFDH
+     and the ephemeral or psk-ephemeral key exchange mode are enabled.
+     By default, all groups are offered; the list of groups can be
+     configured using the existing API function mbedtls_ssl_conf_groups().
+   * Improve mbedtls_x509_time performance and reduce memory use.
+   * Reduce syscalls to time() during certificate verification.
+   * Allow MBEDTLS_CONFIG_FILE and MBEDTLS_USER_CONFIG_FILE to be set by
+     setting the CMake variable of the same name at configuration time.
+   * Add getter (mbedtls_ssl_cache_get_timeout()) to access
+     `mbedtls_ssl_cache_context.timeout`.
+   * Add getter (mbedtls_ssl_get_hostname()) to access
+     `mbedtls_ssl_context.hostname`.
+   * Add getter (mbedtls_ssl_conf_get_endpoint()) to access
+     `mbedtls_ssl_config.endpoint`.
+   * Support for "opaque" (PSA-held) ECC keys in the PK module has been
+     extended: it is now possible to use mbedtls_pk_write_key_der(),
+     mbedtls_pk_write_key_pem(), mbedtls_pk_check_pair(), and
+     mbedtls_pk_verify() with opaque ECC keys (provided the PSA attributes
+     allow it).
+   * The documentation of mbedtls_ecp_group now describes the optimized
+     representation of A for some curves. Fixes #8045.
+   * Add a possibility to generate CSR's with RCF822 and directoryName subtype
+     of subjectAltName extension in x509 certificates.
+   * Add support for PBKDF2-CMAC through the PSA API.
+   * New configuration option MBEDTLS_AES_USE_HARDWARE_ONLY introduced. When
+     using CPU-accelerated AES (e.g., Arm Crypto Extensions), this option
+     disables the plain C implementation and the run-time detection for the
+     CPU feature, which reduces code size and avoids the vulnerability of the
+     plain C implementation.
+   * Accept arbitrary AttributeType and AttributeValue in certificate
+     Distinguished Names using RFC 4514 syntax.
+   * Applications using ECC over secp256r1 through the PSA API can use a
+     new implementation with a much smaller footprint, but some minor
+     usage restrictions. See the documentation of the new configuration
+     option MBEDTLS_PSA_P256M_DRIVER_ENABLED for details.
+
+Security
+   * Fix a case where potentially sensitive information held in memory would not
+     be completely zeroized during TLS 1.2 handshake, in both server and client
+     configurations.
+   * In configurations with ARIA or Camellia but not AES, the value of
+     MBEDTLS_CIPHER_BLKSIZE_MAX was 8, rather than 16 as the name might
+     suggest. This did not affect any library code, because this macro was
+     only used in relation with CMAC which does not support these ciphers.
+     This may affect application code that uses this macro.
+   * Developers using mbedtls_pkcs5_pbes2() or mbedtls_pkcs12_pbe() should
+     review the size of the output buffer passed to this function, and note
+     that the output after decryption may include CBC padding. Consider moving
+     to the new functions mbedtls_pkcs5_pbes2_ext() or mbedtls_pkcs12_pbe_ext()
+     which checks for overflow of the output buffer and reports the actual
+     length of the output.
+   * Improve padding calculations in CBC decryption, NIST key unwrapping and
+     RSA OAEP decryption. With the previous implementation, some compilers
+     (notably recent versions of Clang and IAR) could produce non-constant
+     time code, which could allow a padding oracle attack if the attacker
+     has access to precise timing measurements.
+   * Updates to constant-time C code so that compilers are less likely to use
+     conditional instructions, which can have an observable difference in
+     timing. (Clang has been seen to do this.) Also introduce assembly
+     implementations for 32- and 64-bit Arm and for x86 and x86-64, which are
+     guaranteed not to use conditional instructions.
+   * Fix definition of MBEDTLS_MD_MAX_BLOCK_SIZE, which was too
+     small when MBEDTLS_SHA384_C was defined and MBEDTLS_SHA512_C was
+     undefined. Mbed TLS itself was unaffected by this, but user code
+     which used MBEDTLS_MD_MAX_BLOCK_SIZE could be affected. The only
+     release containing this bug was Mbed TLS 3.4.0.
+   * Fix a buffer overread when parsing short TLS application data records in
+     null-cipher cipher suites. Credit to OSS-Fuzz.
+   * Fix a remotely exploitable heap buffer overflow in TLS handshake parsing.
+     In TLS 1.3, all configurations are affected except PSK-only ones, and
+     both clients and servers are affected.
+     In TLS 1.2, the affected configurations are those with
+     MBEDTLS_USE_PSA_CRYPTO and ECDH enabled but DHM and RSA disabled,
+     and only servers are affected, not clients.
+     Credit to OSS-Fuzz.
+
+Bugfix
+   * Fix proper sizing for PSA_EXPORT_[KEY_PAIR/PUBLIC_KEY]_MAX_SIZE and
+     PSA_SIGNATURE_MAX_SIZE buffers when at least one accelerated EC is bigger
+     than all built-in ones and RSA is disabled.
+     Resolves #6622.
+   * Add missing md.h includes to some of the external programs from
+     the programs directory. Without this, even though the configuration
+     was sufficient for a particular program to work, it would only print
+     a message that one of the required defines is missing.
+   * Fix declaration of mbedtls_ecdsa_sign_det_restartable() function
+     in the ecdsa.h header file. There was a build warning when the
+     configuration macro MBEDTLS_ECDSA_SIGN_ALT was defined.
+     Resolves #7407.
+   * Fix an error when MBEDTLS_ECDSA_SIGN_ALT is defined but not
+     MBEDTLS_ECDSA_VERIFY_ALT, causing ecdsa verify to fail. Fixes #7498.
+   * Fix missing PSA initialization in sample programs when
+     MBEDTLS_USE_PSA_CRYPTO is enabled.
+   * Fix the J-PAKE driver interface for user and peer to accept any values
+     (previously accepted values were limited to "client" or "server").
+   * Fix clang and armclang compilation error when targeting certain Arm
+     M-class CPUs (Cortex-M0, Cortex-M0+, Cortex-M1, Cortex-M23,
+     SecurCore SC000). Fixes #1077.
+   * Fix "unterminated '#pragma clang attribute push'" in sha256/sha512.c when
+     built with MBEDTLS_SHAxxx_USE_A64_CRYPTO_IF_PRESENT but don't have a
+     way to detect the crypto extensions required. A warning is still issued.
+   * Fixed an issue that caused compile errors when using CMake and the IAR
+     toolchain.
+   * Fix very high stack usage in SSL debug code. Reported by Maximilian
+     Gerhardt in #7804.
+   * Fix a compilation failure in the constant_time module when
+     building for arm64_32 (e.g., for watchos). Reported by Paulo
+     Coutinho in #7787.
+   * Fix crypt_and_hash decryption fail when used with a stream cipher
+     mode of operation due to the input not being multiple of block size.
+     Resolves #7417.
+   * Fix a bug in which mbedtls_x509_string_to_names() would return success
+     when given a invalid name string if it did not contain '=' or ','.
+   * Fix compilation warnings in aes.c, which prevented the
+     example TF-M configuration in configs/ from building cleanly:
+     tfm_mbedcrypto_config_profile_medium.h with
+     crypto_config_profile_medium.h.
+   * In TLS 1.3, fix handshake failure when a client in its ClientHello
+     proposes an handshake based on PSK only key exchange mode or at least
+     one of the key exchange modes using ephemeral keys to a server that
+     supports only the PSK key exchange mode.
+   * Fix CCM* with no tag being not supported in a build with CCM as the only
+     symmetric encryption algorithm and the PSA configuration enabled.
+   * Fix the build with MBEDTLS_PSA_INJECT_ENTROPY. Fixes #7516.
+   * Fix a compilation error on some platforms when including mbedtls/ssl.h
+     with all TLS support disabled. Fixes #6628.
+   * Fix x509 certificate generation to conform to RFC 5480 / RFC 5758 when
+     using ECC key. The certificate was rejected by some crypto frameworks.
+     Fixes #2924.
+   * Fix a potential corruption of the passed-in IV when mbedtls_aes_crypt_cbc()
+     is called with zero length and padlock is not enabled.
+   * Fix compile failure due to empty enum in cipher_wrap.c, when building
+     with a very minimal configuration. Fixes #7625.
+   * Fix some cases where mbedtls_mpi_mod_exp, RSA key construction or ECDSA
+     signature can silently return an incorrect result in low memory conditions.
+   * Don't try to include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE when
+     MBEDTLS_PSA_CRYPTO_CONFIG is disabled.
+   * Fix IAR compiler warnings.
+   * Fix an issue when parsing an otherName subject alternative name into a
+     mbedtls_x509_san_other_name struct. The type-id of the otherName was not
+     copied to the struct. This meant that the struct had incomplete
+     information about the otherName SAN and contained uninitialized memory.
+   * Fix the detection of HardwareModuleName otherName SANs. These were being
+     detected by comparing the wrong field and the check was erroneously
+     inverted.
+   * Fix a build error in some configurations with MBEDTLS_PSA_CRYPTO_CONFIG
+     enabled, where some low-level modules required by requested PSA crypto
+     features were not getting automatically enabled. Fixes #7420.
+   * Fix undefined symbols in some builds using TLS 1.3 with a custom
+     configuration file.
+   * Fix log level for the got supported group message. Fixes #6765
+   * Functions in the ssl_cache module now return a negative MBEDTLS_ERR_xxx
+     error code on failure. Before, they returned 1 to indicate failure in
+     some cases involving a missing entry or a full cache.
+   * mbedtls_pk_parse_key() now rejects trailing garbage in encrypted keys.
+   * Fix the build with CMake when Everest or P256-m is enabled through
+     a user configuration file or the compiler command line. Fixes #8165.
+
+Changes
+   * Enable Arm / Thumb bignum assembly for most Arm platforms when
+     compiling with gcc, clang or armclang and -O0.
+   * Enforce minimum RSA key size when generating a key
+     to avoid accidental misuse.
+   * Use heap memory to allocate DER encoded RSA private key.
+     This reduces stack usage significantly for RSA signature
+     operations when MBEDTLS_PSA_CRYPTO_C is defined.
+   * Update Windows code to use BCryptGenRandom and wcslen, and
+     ensure that conversions between size_t, ULONG, and int are
+     always done safely.  Original contribution by Kevin Kane #635, #730
+     followed by Simon Butcher #1453.
+   * Users integrating their own PSA drivers should be aware that
+     the file library/psa_crypto_driver_wrappers.c has been renamed
+     to psa_crypto_driver_wrappers_no_static.c.
+   * When using CBC with the cipher module, the requirement to call
+     mbedtls_cipher_set_padding_mode() is now enforced. Previously, omitting
+     this call accidentally applied a default padding mode chosen at compile
+     time.
+
+= Mbed TLS 3.4.1 branch released 2023-08-04
+
+Bugfix
+   * Fix builds on Windows with clang
+
+Changes
+   * Update test data to avoid failures of unit tests after 2023-08-07.
+
 = Mbed TLS 3.4.0 branch released 2023-03-28
 
 Default behavior changes
diff --git a/lib/libmbedtls/mbedtls/LICENSE b/lib/libmbedtls/mbedtls/LICENSE
index d645695673349e3947e8e5ae42332d0ac3164cd7..776ac77eaf5a0da545f95ad7386b9954378fa8ae 100644
--- a/lib/libmbedtls/mbedtls/LICENSE
+++ b/lib/libmbedtls/mbedtls/LICENSE
@@ -1,3 +1,10 @@
+Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)
+OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license.
+This means that users may choose which of these licenses they take the code
+under.
+
+The full text of each of these licenses is given below.
+
 
                                  Apache License
                            Version 2.0, January 2004
@@ -200,3 +207,347 @@
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
+
+
+===============================================================================
+
+
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program 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 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/lib/libmbedtls/mbedtls/README.md b/lib/libmbedtls/mbedtls/README.md
index 288e692baf69a9b77a0d2ac63cdeb59dcb506a85..b70c67e030d02432813754a8a1b6ca8a8e831f0e 100644
--- a/lib/libmbedtls/mbedtls/README.md
+++ b/lib/libmbedtls/mbedtls/README.md
@@ -47,13 +47,17 @@ The Make and CMake build systems create three libraries: libmbedcrypto, libmbedx
 You need the following tools to build the library with the provided makefiles:
 
 * GNU Make 3.82 or a build tool that CMake supports.
-* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, IAR 8 and Visual Studio 2013. More recent versions should work. Slightly older versions may work.
-* Python 3.6 to generate the test code, and to generate sample programs in the development branch.
+* A C99 toolchain (compiler, linker, archiver). We actively test with GCC 5.4, Clang 3.8, Arm Compiler 6, IAR 8 and Visual Studio 2017. More recent versions should work. Slightly older versions may work.
+* Python 3.8 to generate the test code. Python is also needed to integrate PSA drivers and to build the development branch (see next section).
 * Perl to run the tests, and to generate some source files in the development branch.
 * CMake 3.10.2 or later (if using CMake).
-* Microsoft Visual Studio 2013 or later (if using Visual Studio).
+* Microsoft Visual Studio 2017 or later (if using Visual Studio).
 * Doxygen 1.8.11 or later (if building the documentation; slightly older versions should work).
 
+### Git usage
+
+The `development` branch and the `mbedtls-3.6` long-term support branch of Mbed TLS use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules#_cloning_submodules) ([framework](https://github.com/Mbed-TLS/mbedtls-framework)). This is not needed to merely compile the library at a release tag. This is not needed to consume a release archive (zip or tar).
+
 ### Generated source files in the development branch
 
 The source code of Mbed TLS includes some files that are automatically generated by scripts and whose content depends only on the Mbed TLS source, not on the platform or on the library configuration. These files are not included in the development branch of Mbed TLS, but the generated files are included in official releases. This section explains how to generate the missing files in the development branch.
@@ -61,7 +65,7 @@ The source code of Mbed TLS includes some files that are automatically generated
 The following tools are required:
 
 * Perl, for some library source files and for Visual Studio build files.
-* Python 3 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:
+* Python 3.8 and some Python packages, for some library source files, sample programs and test data. To install the necessary packages, run:
     ```
     python3 -m pip install --user -r scripts/basic.requirements.txt
     ```
@@ -221,7 +225,7 @@ subproject.
 
 ### Microsoft Visual Studio
 
-The build files for Microsoft Visual Studio are generated for Visual Studio 2013.
+The build files for Microsoft Visual Studio are generated for Visual Studio 2017.
 
 The solution file `mbedTLS.sln` contains all the basic projects needed to build the library and all the programs. The files in tests are not generated and compiled, as these need Python and perl environments as well. However, the selftest program in `programs/test/` is still available.
 
@@ -246,7 +250,7 @@ For machines with a Unix shell and OpenSSL (and optionally GnuTLS) installed, ad
 -   `tests/scripts/depends.py` test builds in configurations with a single curve, key exchange, hash, cipher, or pkalg on.
 -   `tests/scripts/all.sh` runs a combination of the above tests, plus some more, with various build options (such as ASan, full `mbedtls_config.h`, etc).
 
-Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/master/README.md#quick-start).
+Instead of manually installing the required versions of all tools required for testing, it is possible to use the Docker images from our CI systems, as explained in [our testing infrastructure repository](https://github.com/Mbed-TLS/mbedtls-test/blob/main/README.md#quick-start).
 
 Porting Mbed TLS
 ----------------
@@ -293,19 +297,28 @@ However, it does not aim to implement the whole specification; in particular it
 
 The X.509 and TLS code can use PSA cryptography for most operations. To enable this support, activate the compilation option `MBEDTLS_USE_PSA_CRYPTO` in `mbedtls_config.h`. Note that TLS 1.3 uses PSA cryptography for most operations regardless of this option. See `docs/use-psa-crypto.md` for details.
 
-### Upcoming features
+### PSA drivers
+
+Mbed TLS supports drivers for cryptographic accelerators, secure elements and random generators. This is work in progress. Please note that the driver interfaces are not fully stable yet and may change without notice. We intend to preserve backward compatibility for application code (using the PSA Crypto API), but the code of the drivers may have to change in future minor releases of Mbed TLS.
+
+Please see the [PSA driver example and guide](docs/psa-driver-example-and-guide.md) for information on writing a driver.
 
-Future releases of this library will include:
+When using drivers, you will generally want to enable two compilation options (see the reference manual for more information):
 
-* A driver programming interface, which makes it possible to use hardware accelerators instead of the default software implementation for chosen algorithms.
-* Support for external keys to be stored and manipulated exclusively in a separate cryptoprocessor.
-* A configuration mechanism to compile only the algorithms you need for your application.
-* A wider set of cryptographic algorithms.
+* `MBEDTLS_USE_PSA_CRYPTO` is necessary so that the X.509 and TLS code calls the PSA drivers rather than the built-in software implementation.
+* `MBEDTLS_PSA_CRYPTO_CONFIG` allows you to enable PSA cryptographic mechanisms without including the code of the corresponding software implementation. This is not yet supported for all mechanisms.
 
 License
 -------
 
-Unless specifically indicated otherwise in a file, Mbed TLS files are provided under the [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) license. See the [LICENSE](LICENSE) file for the full text of this license. Contributors must accept that their contributions are made under both the Apache-2.0 AND [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) licenses. This enables LTS (Long Term Support) branches of the software to be provided under either the Apache-2.0 OR GPL-2.0-or-later licenses.
+Unless specifically indicated otherwise in a file, Mbed TLS files are provided under a dual [Apache-2.0](https://spdx.org/licenses/Apache-2.0.html) OR [GPL-2.0-or-later](https://spdx.org/licenses/GPL-2.0-or-later.html) license. See the [LICENSE](LICENSE) file for the full text of these licenses, and [the 'License and Copyright' section in the contributing guidelines](CONTRIBUTING.md#License-and-Copyright) for more information.
+
+### Third-party code included in Mbed TLS
+
+This project contains code from other projects. This code is located within the `3rdparty/` directory. The original license text is included within project subdirectories, where it differs from the normal Mbed TLS license, and/or in source files. The projects are listed below:
+
+* `3rdparty/everest/`: Files stem from [Project Everest](https://project-everest.github.io/) and are distributed under the Apache 2.0 license.
+* `3rdparty/p256-m/p256-m/`: Files have been taken from the [p256-m](https://github.com/mpg/p256-m) repository. The code in the original repository is distributed under the Apache 2.0 license. It is distributed in Mbed TLS under a dual Apache-2.0 OR GPL-2.0-or-later license with permission from the author.
 
 Contributing
 ------------
diff --git a/lib/libmbedtls/mbedtls/SECURITY.md b/lib/libmbedtls/mbedtls/SECURITY.md
index 61e39361af9f2f5b0565a6d285a13919d07df19d..7ed72de921a28206420938be7b2535a61460fb54 100644
--- a/lib/libmbedtls/mbedtls/SECURITY.md
+++ b/lib/libmbedtls/mbedtls/SECURITY.md
@@ -135,3 +135,12 @@ Guide](docs/architecture/alternative-implementations.md) for more information.
 - Use cryptographic mechanisms that are not based on block ciphers. In
   particular, for authenticated encryption, use ChaCha20/Poly1305 instead of
   block cipher modes. For random generation, use HMAC\_DRBG instead of CTR\_DRBG.
+
+#### Everest
+
+The HACL* implementation of X25519 taken from the Everest project only protects
+against remote timing attacks. (See their [Security
+Policy](https://github.com/hacl-star/hacl-star/blob/main/SECURITY.md).)
+
+The Everest variant is only used when `MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED`
+configuration option is defined. This option is off by default.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/aes.h b/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
index 42e1fe85509e962a7a2ae22b52e77ca4a19a4a16..d5eb1fd5c2c141dceea437c56a08e909eabdfa06 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/aes.h
@@ -22,19 +22,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_AES_H
@@ -76,6 +64,10 @@ typedef struct mbedtls_aes_context {
     int MBEDTLS_PRIVATE(nr);                     /*!< The number of rounds. */
     size_t MBEDTLS_PRIVATE(rk_offset);           /*!< The offset in array elements to AES
                                                     round keys in the buffer. */
+#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C)
+    uint32_t MBEDTLS_PRIVATE(buf)[44];           /*!< Aligned data buffer to hold
+                                                    10 round keys for 128-bit case. */
+#else
     uint32_t MBEDTLS_PRIVATE(buf)[68];           /*!< Unaligned data buffer. This buffer can
                                                     hold 32 extra Bytes, which can be used for
                                                     one of the following purposes:
@@ -84,6 +76,7 @@ typedef struct mbedtls_aes_context {
                                                     <li>Simplifying key expansion in the 256-bit
                                                     case by generating an extra round key.
                                                     </li></ul> */
+#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH && !MBEDTLS_PADLOCK_C */
 }
 mbedtls_aes_context;
 
@@ -162,6 +155,7 @@ MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief          This function sets the decryption key.
  *
@@ -180,6 +174,7 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
 MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
 /**
@@ -599,6 +594,7 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
                                  const unsigned char input[16],
                                  unsigned char output[16]);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief           Internal AES block decryption function. This is only
  *                  exposed to allow overriding it using see
@@ -614,6 +610,7 @@ MBEDTLS_CHECK_RETURN_TYPICAL
 int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
                                  const unsigned char input[16],
                                  unsigned char output[16]);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 #if defined(MBEDTLS_SELF_TEST)
 /**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/aria.h b/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
index 587cbf8bd67c0910a8cf2bfab2f9330153c68d61..c685fc314127b05d1bf2fafa4c1518966e0a4564 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/aria.h
@@ -11,19 +11,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_ARIA_H
@@ -110,6 +98,7 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
                             const unsigned char *key,
                             unsigned int keybits);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief          This function sets the decryption key.
  *
@@ -128,6 +117,7 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
 int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,
                             const unsigned char *key,
                             unsigned int keybits);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /**
  * \brief          This function performs an ARIA single-block encryption or
@@ -259,10 +249,6 @@ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,
  * \brief      This function performs an ARIA-CTR encryption or decryption
  *             operation.
  *
- *             This function performs the operation defined in the \p mode
- *             parameter (encrypt/decrypt), on the input data buffer
- *             defined in the \p input parameter.
- *
  *             Due to the nature of CTR, you must use the same key schedule
  *             for both encryption and decryption operations. Therefore, you
  *             must use the context initialized with mbedtls_aria_setkey_enc()
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h b/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
index e15aeb3f896e68fdd56746c096a8d5f086cf1f43..ff019f432a3feb9e04a6540aead6ecbcde94d796 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/asn1.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ASN1_H
 #define MBEDTLS_ASN1_H
@@ -96,15 +84,14 @@
 
 /* Slightly smaller way to check if tag is a string tag
  * compared to canonical implementation. */
-#define MBEDTLS_ASN1_IS_STRING_TAG(tag)                                     \
-    ((tag) < 32u && (                                                      \
+#define MBEDTLS_ASN1_IS_STRING_TAG(tag)                                \
+    ((unsigned int) (tag) < 32u && (                                   \
          ((1u << (tag)) & ((1u << MBEDTLS_ASN1_BMP_STRING)       |     \
                            (1u << MBEDTLS_ASN1_UTF8_STRING)      |     \
                            (1u << MBEDTLS_ASN1_T61_STRING)       |     \
                            (1u << MBEDTLS_ASN1_IA5_STRING)       |     \
                            (1u << MBEDTLS_ASN1_UNIVERSAL_STRING) |     \
-                           (1u << MBEDTLS_ASN1_PRINTABLE_STRING) |     \
-                           (1u << MBEDTLS_ASN1_BIT_STRING))) != 0))
+                           (1u << MBEDTLS_ASN1_PRINTABLE_STRING))) != 0))
 
 /*
  * Bit masks for each of the components of an ASN.1 tag as specified in
@@ -210,6 +197,8 @@ typedef struct mbedtls_asn1_named_data {
 }
 mbedtls_asn1_named_data;
 
+#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
+    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 /**
  * \brief       Get the length of an ASN.1 element.
  *              Updates the pointer to immediately behind the length.
@@ -256,7 +245,9 @@ int mbedtls_asn1_get_len(unsigned char **p,
 int mbedtls_asn1_get_tag(unsigned char **p,
                          const unsigned char *end,
                          size_t *len, int tag);
+#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
 
+#if defined(MBEDTLS_ASN1_PARSE_C)
 /**
  * \brief       Retrieve a boolean ASN.1 tag and its value.
  *              Updates the pointer to immediately behind the full tag.
@@ -474,7 +465,7 @@ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq);
  *                       on a successful invocation.
  * \param end            The end of the ASN.1 SEQUENCE container.
  * \param tag_must_mask  A mask to be applied to the ASN.1 tags found within
- *                       the SEQUENCE before comparing to \p tag_must_value.
+ *                       the SEQUENCE before comparing to \p tag_must_val.
  * \param tag_must_val   The required value of each ASN.1 tag found in the
  *                       SEQUENCE, after masking with \p tag_must_mask.
  *                       Mismatching tags lead to an error.
@@ -483,7 +474,7 @@ void mbedtls_asn1_sequence_free(mbedtls_asn1_sequence *seq);
  *                       while a value of \c 0xFF for \p tag_must_mask means
  *                       that \p tag_must_val is the only allowed tag.
  * \param tag_may_mask   A mask to be applied to the ASN.1 tags found within
- *                       the SEQUENCE before comparing to \p tag_may_value.
+ *                       the SEQUENCE before comparing to \p tag_may_val.
  * \param tag_may_val    The desired value of each ASN.1 tag found in the
  *                       SEQUENCE, after masking with \p tag_may_mask.
  *                       Mismatching tags will be silently ignored.
@@ -642,6 +633,8 @@ void mbedtls_asn1_free_named_data_list_shallow(mbedtls_asn1_named_data *name);
 /** \} name Functions to parse ASN.1 data structures */
 /** \} addtogroup asn1_module */
 
+#endif /* MBEDTLS_ASN1_PARSE_C */
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h b/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
index da7375962cf7a5c81d1cbca4b1efb9e1d2a6bf2d..0c5a85ac27f99137b5820ef1a28901a7276ef3cb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/asn1write.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ASN1_WRITE_H
 #define MBEDTLS_ASN1_WRITE_H
@@ -48,6 +36,8 @@
 extern "C" {
 #endif
 
+#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
+    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 /**
  * \brief           Write a length field in ASN.1 format.
  *
@@ -76,7 +66,9 @@ int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start,
  */
 int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start,
                            unsigned char tag);
+#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/
 
+#if defined(MBEDTLS_ASN1_WRITE_C)
 /**
  * \brief           Write raw buffer data.
  *
@@ -163,6 +155,27 @@ int mbedtls_asn1_write_algorithm_identifier(unsigned char **p,
                                             const char *oid, size_t oid_len,
                                             size_t par_len);
 
+/**
+ * \brief           Write an AlgorithmIdentifier sequence in ASN.1 format.
+ *
+ * \note            This function works backwards in data buffer.
+ *
+ * \param p         The reference to the current position pointer.
+ * \param start     The start of the buffer, for bounds-checking.
+ * \param oid       The OID of the algorithm to write.
+ * \param oid_len   The length of the algorithm's OID.
+ * \param par_len   The length of the parameters, which must be already written.
+ * \param has_par   If there are any parameters. If 0, par_len must be 0. If 1
+ *                  and \p par_len is 0, NULL parameters are added.
+ *
+ * \return          The number of bytes written to \p p on success.
+ * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
+ */
+int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p,
+                                                const unsigned char *start,
+                                                const char *oid, size_t oid_len,
+                                                size_t par_len, int has_par);
+
 /**
  * \brief           Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
  *                  in ASN.1 format.
@@ -372,4 +385,6 @@ mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data *
 }
 #endif
 
+#endif /* MBEDTLS_ASN1_WRITE_C */
+
 #endif /* MBEDTLS_ASN1_WRITE_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/base64.h b/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
index 635be713d85804669aadc7f687bb5c9a36243c23..8f459b74c5764347d6305aecde44d55f52e8f1da 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/base64.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_BASE64_H
 #define MBEDTLS_BASE64_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h b/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
index 56c289aaf599de3b75d56e28d5d025d0b8b5a9c3..52205236e2b1370a66596bd777001e294c70fc4c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/bignum.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_BIGNUM_H
 #define MBEDTLS_BIGNUM_H
@@ -63,15 +51,15 @@
 
 #if !defined(MBEDTLS_MPI_WINDOW_SIZE)
 /*
- * Maximum window size used for modular exponentiation. Default: 2
+ * Maximum window size used for modular exponentiation. Default: 3
  * Minimum value: 1. Maximum value: 6.
  *
  * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used
- * for the sliding window calculation. (So 64 by default)
+ * for the sliding window calculation. (So 8 by default)
  *
  * Reduction in size, reduces speed.
  */
-#define MBEDTLS_MPI_WINDOW_SIZE                           2        /**< Maximum window size used. */
+#define MBEDTLS_MPI_WINDOW_SIZE                           3        /**< Maximum window size used. */
 #endif /* !MBEDTLS_MPI_WINDOW_SIZE */
 
 #if !defined(MBEDTLS_MPI_MAX_SIZE)
@@ -129,6 +117,7 @@
         #endif /* !MBEDTLS_HAVE_INT64 */
 typedef  int64_t mbedtls_mpi_sint;
 typedef uint64_t mbedtls_mpi_uint;
+#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX
     #elif defined(__GNUC__) && (                         \
     defined(__amd64__) || defined(__x86_64__)     || \
     defined(__ppc64__) || defined(__powerpc64__)  || \
@@ -141,6 +130,7 @@ typedef uint64_t mbedtls_mpi_uint;
         #endif /* MBEDTLS_HAVE_INT64 */
 typedef  int64_t mbedtls_mpi_sint;
 typedef uint64_t mbedtls_mpi_uint;
+#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX
         #if !defined(MBEDTLS_NO_UDBL_DIVISION)
 /* mbedtls_t_udbl defined as 128-bit unsigned int */
 typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
@@ -156,6 +146,7 @@ typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI)));
         #endif /* !MBEDTLS_HAVE_INT64 */
 typedef  int64_t mbedtls_mpi_sint;
 typedef uint64_t mbedtls_mpi_uint;
+#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX
         #if !defined(MBEDTLS_NO_UDBL_DIVISION)
 /* mbedtls_t_udbl defined as 128-bit unsigned int */
 typedef __uint128_t mbedtls_t_udbl;
@@ -165,6 +156,7 @@ typedef __uint128_t mbedtls_t_udbl;
 /* Force 64-bit integers with unknown compiler */
 typedef  int64_t mbedtls_mpi_sint;
 typedef uint64_t mbedtls_mpi_uint;
+#define MBEDTLS_MPI_UINT_MAX                UINT64_MAX
     #endif
 #endif /* !MBEDTLS_HAVE_INT32 */
 
@@ -175,12 +167,22 @@ typedef uint64_t mbedtls_mpi_uint;
     #endif /* !MBEDTLS_HAVE_INT32 */
 typedef  int32_t mbedtls_mpi_sint;
 typedef uint32_t mbedtls_mpi_uint;
+#define MBEDTLS_MPI_UINT_MAX                UINT32_MAX
     #if !defined(MBEDTLS_NO_UDBL_DIVISION)
 typedef uint64_t mbedtls_t_udbl;
         #define MBEDTLS_HAVE_UDBL
     #endif /* !MBEDTLS_NO_UDBL_DIVISION */
 #endif /* !MBEDTLS_HAVE_INT64 */
 
+/*
+ * Sanity check that exactly one of MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 is defined,
+ * so that code elsewhere doesn't have to check.
+ */
+#if (!(defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64))) || \
+    (defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64))
+#error "Only 32-bit or 64-bit limbs are supported in bignum"
+#endif
+
 /** \typedef mbedtls_mpi_uint
  * \brief The type of machine digits in a bignum, called _limbs_.
  *
@@ -203,6 +205,12 @@ extern "C" {
  * \brief          MPI structure
  */
 typedef struct mbedtls_mpi {
+    /** Pointer to limbs.
+     *
+     * This may be \c NULL if \c n is 0.
+     */
+    mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);
+
     /** Sign: -1 if the mpi is negative, 1 otherwise.
      *
      * The number 0 must be represented with `s = +1`. Although many library
@@ -214,18 +222,22 @@ typedef struct mbedtls_mpi {
      * Note that this implies that calloc() or `... = {0}` does not create
      * a valid MPI representation. You must call mbedtls_mpi_init().
      */
-    int MBEDTLS_PRIVATE(s);
+    signed short MBEDTLS_PRIVATE(s);
 
     /** Total number of limbs in \c p.  */
-    size_t MBEDTLS_PRIVATE(n);
-
-    /** Pointer to limbs.
-     *
-     * This may be \c NULL if \c n is 0.
+    unsigned short MBEDTLS_PRIVATE(n);
+    /* Make sure that MBEDTLS_MPI_MAX_LIMBS fits in n.
+     * Use the same limit value on all platforms so that we don't have to
+     * think about different behavior on the rare platforms where
+     * unsigned short can store values larger than the minimum required by
+     * the C language, which is 65535.
      */
-    mbedtls_mpi_uint *MBEDTLS_PRIVATE(p);
+#if MBEDTLS_MPI_MAX_LIMBS > 65535
+#error "MBEDTLS_MPI_MAX_LIMBS > 65535 is not supported"
+#endif
 
     short use_mempool;
+
 }
 mbedtls_mpi;
 
@@ -535,7 +547,7 @@ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X,
  * \param X        The destination MPI. This must point to an initialized MPI.
  * \param buf      The input buffer. This must be a readable buffer of length
  *                 \p buflen Bytes.
- * \param buflen   The length of the input buffer \p p in Bytes.
+ * \param buflen   The length of the input buffer \p buf in Bytes.
  *
  * \return         \c 0 if successful.
  * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
@@ -550,7 +562,7 @@ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf,
  * \param X        The destination MPI. This must point to an initialized MPI.
  * \param buf      The input buffer. This must be a readable buffer of length
  *                 \p buflen Bytes.
- * \param buflen   The length of the input buffer \p p in Bytes.
+ * \param buflen   The length of the input buffer \p buf in Bytes.
  *
  * \return         \c 0 if successful.
  * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed.
@@ -599,6 +611,8 @@ int mbedtls_mpi_write_binary_le(const mbedtls_mpi *X,
  * \brief          Perform a left-shift on an MPI: X <<= count
  *
  * \param X        The MPI to shift. This must point to an initialized MPI.
+ *                 The MPI pointed by \p X may be resized to fit
+ *                 the resulting number.
  * \param count    The number of bits to shift by.
  *
  * \return         \c 0 if successful.
@@ -872,7 +886,7 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A,
                         mbedtls_mpi_sint b);
 
 /**
- * \brief          Perform a sliding-window exponentiation: X = A^E mod N
+ * \brief          Perform a modular exponentiation: X = A^E mod N
  *
  * \param X        The destination MPI. This must point to an initialized MPI.
  *                 This must not alias E or N.
@@ -988,8 +1002,8 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A,
  * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
  * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than
  *                 or equal to one.
- * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse
- *                 with respect to \p N.
+ * \return         #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p A has no modular
+ *                 inverse with respect to \p N.
  */
 int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
                         const mbedtls_mpi *N);
@@ -1010,7 +1024,7 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
  *                 This must point to an initialized MPI.
  * \param rounds   The number of bases to perform the Miller-Rabin primality
  *                 test for. The probability of returning 0 on a composite is
- *                 at most 2<sup>-2*\p rounds</sup>.
+ *                 at most 2<sup>-2*\p rounds </sup>.
  * \param f_rng    The RNG function to use. This must not be \c NULL.
  * \param p_rng    The RNG parameter to be passed to \p f_rng.
  *                 This may be \c NULL if \p f_rng doesn't use
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/block_cipher.h b/lib/libmbedtls/mbedtls/include/mbedtls/block_cipher.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f60f6f7dd4168e59e6b8d79d42687bf96465d1b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/block_cipher.h
@@ -0,0 +1,76 @@
+/**
+ * \file block_cipher.h
+ *
+ * \brief Internal abstraction layer.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_BLOCK_CIPHER_H
+#define MBEDTLS_BLOCK_CIPHER_H
+
+#include "mbedtls/private_access.h"
+
+#include "mbedtls/build_info.h"
+
+#if defined(MBEDTLS_AES_C)
+#include "mbedtls/aes.h"
+#endif
+#if defined(MBEDTLS_ARIA_C)
+#include "mbedtls/aria.h"
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+#include "mbedtls/camellia.h"
+#endif
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+#include "psa/crypto_types.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    MBEDTLS_BLOCK_CIPHER_ID_NONE = 0,  /**< Unset. */
+    MBEDTLS_BLOCK_CIPHER_ID_AES,       /**< The AES cipher. */
+    MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA,  /**< The Camellia cipher. */
+    MBEDTLS_BLOCK_CIPHER_ID_ARIA,      /**< The Aria cipher. */
+} mbedtls_block_cipher_id_t;
+
+/**
+ * Used internally to indicate whether a context uses legacy or PSA.
+ *
+ * Internal use only.
+ */
+typedef enum {
+    MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY = 0,
+    MBEDTLS_BLOCK_CIPHER_ENGINE_PSA,
+} mbedtls_block_cipher_engine_t;
+
+typedef struct {
+    mbedtls_block_cipher_id_t MBEDTLS_PRIVATE(id);
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+    mbedtls_block_cipher_engine_t MBEDTLS_PRIVATE(engine);
+    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(psa_key_id);
+#endif
+    union {
+        unsigned dummy; /* Make the union non-empty even with no supported algorithms. */
+#if defined(MBEDTLS_AES_C)
+        mbedtls_aes_context MBEDTLS_PRIVATE(aes);
+#endif
+#if defined(MBEDTLS_ARIA_C)
+        mbedtls_aria_context MBEDTLS_PRIVATE(aria);
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+        mbedtls_camellia_context MBEDTLS_PRIVATE(camellia);
+#endif
+    } MBEDTLS_PRIVATE(ctx);
+} mbedtls_block_cipher_context_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_BLOCK_CIPHER_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h b/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h
index 1b3d59fabce5f2718ed0912c5b56497e4cef3656..d91d2964b6aeba95ac46ef98090b21ea14ea6cca 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/build_info.h
@@ -1,5 +1,5 @@
 /**
- * \file build_info.h
+ * \file mbedtls/build_info.h
  *
  * \brief Build-time configuration info
  *
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_BUILD_INFO_H
@@ -37,17 +25,71 @@
  * Major, Minor, Patchlevel
  */
 #define MBEDTLS_VERSION_MAJOR  3
-#define MBEDTLS_VERSION_MINOR  4
-#define MBEDTLS_VERSION_PATCH  0
+#define MBEDTLS_VERSION_MINOR  6
+#define MBEDTLS_VERSION_PATCH  2
 
 /**
  * The single version number has the following structure:
  *    MMNNPP00
  *    Major version | Minor version | Patch version
  */
-#define MBEDTLS_VERSION_NUMBER         0x03040000
-#define MBEDTLS_VERSION_STRING         "3.4.0"
-#define MBEDTLS_VERSION_STRING_FULL    "mbed TLS 3.4.0"
+#define MBEDTLS_VERSION_NUMBER         0x03060200
+#define MBEDTLS_VERSION_STRING         "3.6.2"
+#define MBEDTLS_VERSION_STRING_FULL    "Mbed TLS 3.6.2"
+
+/* Macros for build-time platform detection */
+
+#if !defined(MBEDTLS_ARCH_IS_ARM64) && \
+    (defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC))
+#define MBEDTLS_ARCH_IS_ARM64
+#endif
+
+#if !defined(MBEDTLS_ARCH_IS_ARM32) && \
+    (defined(__arm__) || defined(_M_ARM) || \
+    defined(_M_ARMT) || defined(__thumb__) || defined(__thumb2__))
+#define MBEDTLS_ARCH_IS_ARM32
+#endif
+
+#if !defined(MBEDTLS_ARCH_IS_X64) && \
+    (defined(__amd64__) || defined(__x86_64__) || \
+    ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC)))
+#define MBEDTLS_ARCH_IS_X64
+#endif
+
+#if !defined(MBEDTLS_ARCH_IS_X86) && \
+    (defined(__i386__) || defined(_X86_) || \
+    (defined(_M_IX86) && !defined(_M_I86)))
+#define MBEDTLS_ARCH_IS_X86
+#endif
+
+#if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
+    (defined(_M_ARM64) || defined(_M_ARM64EC))
+#define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64
+#endif
+
+/* This is defined if the architecture is Armv8-A, or higher */
+#if !defined(MBEDTLS_ARCH_IS_ARMV8_A)
+#if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE)
+#if (__ARM_ARCH >= 8) && (__ARM_ARCH_PROFILE == 'A')
+/* GCC, clang, armclang and IAR */
+#define MBEDTLS_ARCH_IS_ARMV8_A
+#endif
+#elif defined(__ARM_ARCH_8A)
+/* Alternative defined by clang */
+#define MBEDTLS_ARCH_IS_ARMV8_A
+#elif defined(_M_ARM64) || defined(_M_ARM64EC)
+/* MSVC ARM64 is at least Armv8.0-A */
+#define MBEDTLS_ARCH_IS_ARMV8_A
+#endif
+#endif
+
+#if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \
+    && !defined(__llvm__) && !defined(__INTEL_COMPILER)
+/* Defined if the compiler really is gcc and not clang, etc */
+#define MBEDTLS_COMPILER_IS_GCC
+#define MBEDTLS_GCC_VERSION \
+    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
 
 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE)
 #define _CRT_SECURE_NO_DEPRECATE 1
@@ -59,6 +101,14 @@
 #define inline __inline
 #endif
 
+#if defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Something went wrong: MBEDTLS_CONFIG_FILES_READ defined before reading the config files!"
+#endif
+#if defined(MBEDTLS_CONFIG_IS_FINALIZED)
+#error "Something went wrong: MBEDTLS_CONFIG_IS_FINALIZED defined before reading the config files!"
+#endif
+
+/* X.509, TLS and non-PSA crypto configuration */
 #if !defined(MBEDTLS_CONFIG_FILE)
 #include "mbedtls/mbedtls_config.h"
 #else
@@ -80,73 +130,64 @@
 #include MBEDTLS_USER_CONFIG_FILE
 #endif
 
-/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C.
- * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C.
- */
-#if defined(MBEDTLS_MD_C)
-#define MBEDTLS_MD_LIGHT
+/* PSA crypto configuration */
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE)
+#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE
+#else
+#include "psa/crypto_config.h"
 #endif
-
-/* Auto-enable MBEDTLS_MD_LIGHT if some module needs it.
- */
-#if defined(MBEDTLS_PEM_PARSE_C) || \
-    defined(MBEDTLS_RSA_C)
-#define MBEDTLS_MD_LIGHT
+#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE)
+#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
 #endif
+#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
 
-/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
- * is defined as well to include all PSA code.
+/* Indicate that all configuration files have been read.
+ * It is now time to adjust the configuration (follow through on dependencies,
+ * make PSA and legacy crypto consistent, etc.).
  */
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#define MBEDTLS_PSA_CRYPTO_CLIENT
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#define MBEDTLS_CONFIG_FILES_READ
 
-/* The PK wrappers need pk_write functions to format RSA key objects
- * when they are dispatching to the PSA API. This happens under USE_PSA_CRYPTO,
- * and also even without USE_PSA_CRYPTO for mbedtls_pk_sign_ext(). */
-#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(MBEDTLS_RSA_C)
-#define MBEDTLS_PK_C
-#define MBEDTLS_PK_WRITE_C
-#define MBEDTLS_PK_PARSE_C
+/* Auto-enable MBEDTLS_CTR_DRBG_USE_128_BIT_KEY if
+ * MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH and MBEDTLS_CTR_DRBG_C defined
+ * to ensure a 128-bit key size in CTR_DRBG.
+ */
+#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && defined(MBEDTLS_CTR_DRBG_C)
+#define MBEDTLS_CTR_DRBG_USE_128_BIT_KEY
 #endif
 
-#if !defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
-#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+/* Auto-enable MBEDTLS_MD_C if needed by a module that didn't require it
+ * in a previous release, to ensure backwards compatibility.
+ */
+#if defined(MBEDTLS_PKCS5_C)
+#define MBEDTLS_MD_C
 #endif
 
-#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
-#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
-#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
-#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
-#undef MBEDTLS_SSL_EARLY_DATA
+/* PSA crypto specific configuration options
+ * - If config_psa.h reads a configuration option in preprocessor directive,
+ *   this symbol should be set before its inclusion. (e.g. MBEDTLS_MD_C)
+ * - If config_psa.h writes a configuration option in conditional directive,
+ *   this symbol should be consulted after its inclusion.
+ *   (e.g. MBEDTLS_MD_LIGHT)
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \
+    defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */ || \
+    defined(MBEDTLS_PSA_CRYPTO_CLIENT) /* The same as the previous, but with separation only */
+#include "mbedtls/config_psa.h"
 #endif
 
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \
-    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED
-#endif
+#include "mbedtls/config_adjust_legacy_crypto.h"
 
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \
-    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED
-#endif
+#include "mbedtls/config_adjust_x509.h"
 
-/* Make sure all configuration symbols are set before including check_config.h,
- * even the ones that are calculated programmatically. */
-#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) /* PSA_WANT_xxx influences MBEDTLS_xxx */ || \
-    defined(MBEDTLS_PSA_CRYPTO_C) /* MBEDTLS_xxx influences PSA_WANT_xxx */
-#include "mbedtls/config_psa.h"
-#endif
+#include "mbedtls/config_adjust_ssl.h"
+
+/* Indicate that all configuration symbols are set,
+ * even the ones that are calculated programmatically.
+ * It is now safe to query the configuration (to check it, to size buffers,
+ * etc.).
+ */
+#define MBEDTLS_CONFIG_IS_FINALIZED
 
 #include "mbedtls/check_config.h"
 
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h b/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
index f4aa00299d6d250444de0b2df996b9c089feaa7e..557f4725310228eaa716f59b22c8829b956babdf 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/camellia.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_CAMELLIA_H
 #define MBEDTLS_CAMELLIA_H
@@ -93,6 +81,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief          Perform a CAMELLIA key schedule operation for decryption.
  *
@@ -108,6 +97,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,
 int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /**
  * \brief          Perform a CAMELLIA-ECB block encryption/decryption operation.
@@ -220,7 +210,7 @@ int mbedtls_camellia_crypt_cfb128(mbedtls_camellia_context *ctx,
  * *note       Due to the nature of CTR mode, you should use the same
  *             key for both encryption and decryption. In particular, calls
  *             to this function should be preceded by a key-schedule via
- *             mbedtls_camellia_setkey_enc() regardless of whether \p mode
+ *             mbedtls_camellia_setkey_enc() regardless of whether the mode
  *             is #MBEDTLS_CAMELLIA_ENCRYPT or #MBEDTLS_CAMELLIA_DECRYPT.
  *
  * \warning    You must never reuse a nonce value with the same key. Doing so
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h b/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
index 6c2255281c254a03ae067b0f6cd51933a6262da8..1da57c921bf71996d26da7f44c0168e06e7a08ae 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ccm.h
@@ -29,19 +29,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CCM_H
@@ -52,6 +40,10 @@
 
 #include "mbedtls/cipher.h"
 
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+#include "mbedtls/block_cipher.h"
+#endif
+
 #define MBEDTLS_CCM_DECRYPT       0
 #define MBEDTLS_CCM_ENCRYPT       1
 #define MBEDTLS_CCM_STAR_DECRYPT  2
@@ -77,7 +69,6 @@ extern "C" {
 typedef struct mbedtls_ccm_context {
     unsigned char MBEDTLS_PRIVATE(y)[16];    /*!< The Y working buffer */
     unsigned char MBEDTLS_PRIVATE(ctr)[16];  /*!< The counter buffer */
-    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */
     size_t MBEDTLS_PRIVATE(plaintext_len);   /*!< Total plaintext length */
     size_t MBEDTLS_PRIVATE(add_len);         /*!< Total authentication data length */
     size_t MBEDTLS_PRIVATE(tag_len);         /*!< Total tag length */
@@ -87,15 +78,19 @@ typedef struct mbedtls_ccm_context {
                                                   and plaintext/ciphertext.
                                                   This variable is set to zero after
                                                   auth data input is finished. */
-    unsigned char MBEDTLS_PRIVATE(q);        /*!< The Q working value */
-    unsigned char MBEDTLS_PRIVATE(mode);     /*!< The operation to perform:
+    unsigned int MBEDTLS_PRIVATE(q);         /*!< The Q working value */
+    unsigned int MBEDTLS_PRIVATE(mode);      /*!< The operation to perform:
                                               #MBEDTLS_CCM_ENCRYPT or
                                               #MBEDTLS_CCM_DECRYPT or
                                               #MBEDTLS_CCM_STAR_ENCRYPT or
                                               #MBEDTLS_CCM_STAR_DECRYPT. */
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx);    /*!< The cipher context used. */
+#else
+    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */
+#endif
     int MBEDTLS_PRIVATE(state);              /*!< Working value holding context's
-                                                  state. Used for chunked data
-                                                  input */
+                                                  state. Used for chunked data input */
 }
 mbedtls_ccm_context;
 
@@ -514,7 +509,7 @@ int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
 int mbedtls_ccm_finish(mbedtls_ccm_context *ctx,
                        unsigned char *tag, size_t tag_len);
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
 /**
  * \brief          The CCM checkup routine.
  *
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h b/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
index e24e56b98eb8796ae6fd5fba26052644ed270f77..680fe360461e688ce10169939199b7e0042547ee 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/chacha20.h
@@ -14,19 +14,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CHACHA20_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h b/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
index 19baadefd23e0534a242ea683f1141823835cb3e..3dc21e380b00718b06f7d176bdd3b82d3aac9bf4 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/chachapoly.h
@@ -14,19 +14,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CHACHAPOLY_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h b/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
index bd683ddd1d54e1bc9ae8784b11c7d7820879f993..67a05f83b8b4fff3c1075fb482045fdc41df5699 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/check_config.h
@@ -2,56 +2,48 @@
  * \file check_config.h
  *
  * \brief Consistency checks for configuration options
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * This header is included automatically by all public Mbed TLS headers
+ * (via mbedtls/build_info.h). Do not include it directly in a configuration
+ * file such as mbedtls/mbedtls_config.h or #MBEDTLS_USER_CONFIG_FILE!
+ * It would run at the wrong time due to missing derived symbols.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CHECK_CONFIG_H
 #define MBEDTLS_CHECK_CONFIG_H
 
 /* *INDENT-OFF* */
+
+#if !defined(MBEDTLS_CONFIG_IS_FINALIZED)
+#warning "Do not include mbedtls/check_config.h manually! " \
+         "This may cause spurious errors. " \
+         "It is included automatically at the right point since Mbed TLS 3.0."
+#endif /* !MBEDTLS_CONFIG_IS_FINALIZED */
+
 /*
  * We assume CHAR_BIT is 8 in many places. In practice, this is true on our
  * target platforms, so not an issue, but let's just be extra sure.
  */
 #include <limits.h>
 #if CHAR_BIT != 8
-#error "mbed TLS requires a platform with 8-bit chars"
+#error "Mbed TLS requires a platform with 8-bit chars"
 #endif
 
 #include <stdint.h>
 
-#if defined(_WIN32)
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)
 #if !defined(MBEDTLS_PLATFORM_C)
 #error "MBEDTLS_PLATFORM_C is required on Windows"
 #endif
-
-/* Fix the config here. Not convenient to put an #ifdef _WIN32 in mbedtls_config.h as
- * it would confuse config.py. */
-#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
-    !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
-#define MBEDTLS_PLATFORM_SNPRINTF_ALT
-#endif
-
-#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \
-    !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
-#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
-#endif
-#endif /* _WIN32 */
+/* See auto-enabling SNPRINTF_ALT and VSNPRINTF_ALT
+ * in * config_adjust_legacy_crypto.h */
+#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */
 
 #if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C)
 #error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS"
@@ -66,14 +58,49 @@
 #error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense"
 #endif
 
-#if defined(__aarch64__) && defined(__GNUC__)
-/* We don't do anything with MBEDTLS_AESCE_C on systems without ^ these two */
-#if defined(MBEDTLS_AESCE_C) && !defined(MBEDTLS_HAVE_ASM)
-#error "MBEDTLS_AESCE_C defined, but not all prerequisites"
-#endif
-#endif
-
-#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C)
+/* Limitations on ECC key types acceleration: if we have any of `PUBLIC_KEY`,
+ * `KEY_PAIR_BASIC`, `KEY_PAIR_IMPORT`, `KEY_PAIR_EXPORT` then we must have
+ * all 4 of them.
+ */
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)
+#error "Unsupported partial support for ECC key type acceleration, see docs/driver-only-builds.md"
+#endif /* not all of public, basic, import, export */
+#endif /* one of public, basic, import, export */
+
+/* Limitations on ECC curves acceleration: partial curve acceleration is only
+ * supported with crypto excluding PK, X.509 or TLS.
+ * Note: no need to check X.509 as it depends on PK. */
+#if defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \
+    defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)
+#if defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)
+#if defined(MBEDTLS_PK_C) || \
+    defined(MBEDTLS_SSL_TLS_C)
+#error "Unsupported partial support for ECC curves acceleration, see docs/driver-only-builds.md"
+#endif /* modules beyond what's supported */
+#endif /* not all curves accelerated */
+#endif /* some curve accelerated */
+
+#if defined(MBEDTLS_CTR_DRBG_C) && !(defined(MBEDTLS_AES_C) || \
+    (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_KEY_TYPE_AES) && \
+    defined(PSA_WANT_ALG_ECB_NO_PADDING)))
 #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites"
 #endif
 
@@ -91,6 +118,36 @@
 #error "MBEDTLS_NIST_KW_C defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT) && defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#if defined(PSA_WANT_ALG_CBC_NO_PADDING)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_NO_PADDING cannot be defined simultaneously"
+#endif
+#if defined(PSA_WANT_ALG_CBC_PKCS7)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_CBC_PKCS7 cannot be defined simultaneously"
+#endif
+#if defined(PSA_WANT_ALG_ECB_NO_PADDING)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_ALG_ECB_NO_PADDING cannot be defined simultaneously"
+#endif
+#if defined(PSA_WANT_KEY_TYPE_DES)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and PSA_WANT_KEY_TYPE_DES cannot be defined simultaneously"
+#endif
+#endif
+
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_CBC cannot be defined simultaneously"
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_CIPHER_MODE_XTS cannot be defined simultaneously"
+#endif
+#if defined(MBEDTLS_DES_C)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_DES_C cannot be defined simultaneously"
+#endif
+#if defined(MBEDTLS_NIST_KW_C)
+#error "MBEDTLS_BLOCK_CIPHER_NO_DECRYPT and MBEDTLS_NIST_KW_C cannot be defined simultaneously"
+#endif
+#endif
+
 #if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C)
 #error "MBEDTLS_ECDH_C defined, but not all prerequisites"
 #endif
@@ -113,9 +170,17 @@
 #error "MBEDTLS_ECDSA_C defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_ECJPAKE_C) &&           \
-    ( !defined(MBEDTLS_ECP_C) ||            \
-      !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) ) )
+#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_ASN1_WRITE_C)
+#error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_WRITE_C for ECDSA signature"
+#endif
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) && !defined(MBEDTLS_ASN1_PARSE_C)
+#error "MBEDTLS_PK_C with MBEDTLS_USE_PSA_CRYPTO needs MBEDTLS_ASN1_PARSE_C for ECDSA verification"
+#endif
+#endif /* MBEDTLS_PK_C && MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_ECJPAKE_C) && \
+    !defined(MBEDTLS_ECP_C)
 #error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites"
 #endif
 
@@ -139,7 +204,7 @@
 #error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || (    \
+#if defined(MBEDTLS_ECP_LIGHT) && ( !defined(MBEDTLS_BIGNUM_C) || (    \
     !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) &&                  \
@@ -153,76 +218,46 @@
     !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) &&                  \
     !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) &&                 \
     !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) )
-#error "MBEDTLS_ECP_C defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C)
-#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_PKCS12_C) && !defined(MBEDTLS_CIPHER_C)
-#error "MBEDTLS_PKCS12_C defined, but not all prerequisites"
+#error "MBEDTLS_ECP_C defined (or a subset enabled), but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PKCS5_C) && \
-    ( !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) ) || \
-        !defined(MBEDTLS_CIPHER_C) )
-#error "MBEDTLS_PKCS5_C defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_PKCS12_C) && \
-    !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) )
-#error "MBEDTLS_PKCS12_C defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_PKCS1_V21) && \
-    !( defined(MBEDTLS_MD_C) || defined(MBEDTLS_PSA_CRYPTO_C) )
-#error "MBEDTLS_PKCS1_V21 defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) &&      \
-                                    !defined(MBEDTLS_SHA256_C))
+#if defined(MBEDTLS_ENTROPY_C) && \
+    !(defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA256))
 #error "MBEDTLS_ENTROPY_C defined, but not all prerequisites"
 #endif
-#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) &&         \
+#if defined(MBEDTLS_ENTROPY_C) && \
     defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64)
 #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
 #endif
 #if defined(MBEDTLS_ENTROPY_C) &&                                            \
-    ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \
+    (defined(MBEDTLS_ENTROPY_FORCE_SHA256) || !defined(MBEDTLS_MD_CAN_SHA512)) \
     && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32)
 #error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high"
 #endif
 #if defined(MBEDTLS_ENTROPY_C) && \
-    defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C)
+    defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_MD_CAN_SHA256)
 #error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites"
 #endif
 
 #if defined(__has_feature)
 #if __has_feature(memory_sanitizer)
-#define MBEDTLS_HAS_MEMSAN
+#define MBEDTLS_HAS_MEMSAN // #undef at the end of this paragraph
 #endif
 #endif
 #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) &&  !defined(MBEDTLS_HAS_MEMSAN)
 #error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer"
 #endif
-#undef MBEDTLS_HAS_MEMSAN
-
-#if defined(MBEDTLS_CCM_C) && (                                        \
-    !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
-#error "MBEDTLS_CCM_C defined, but not all prerequisites"
-#endif
+#undef MBEDTLS_HAS_MEMSAN // temporary macro defined above
 
-#if defined(MBEDTLS_CCM_C) && !defined(MBEDTLS_CIPHER_C)
+#if defined(MBEDTLS_CCM_C) && \
+    !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \
+    defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA))
 #error "MBEDTLS_CCM_C defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_GCM_C) && (                                        \
-    !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) )
-#error "MBEDTLS_GCM_C defined, but not all prerequisites"
-#endif
-
-#if defined(MBEDTLS_GCM_C) && !defined(MBEDTLS_CIPHER_C)
+#if defined(MBEDTLS_GCM_C) && \
+    !(defined(MBEDTLS_CCM_GCM_CAN_AES) || defined(MBEDTLS_CCM_GCM_CAN_ARIA) || \
+    defined(MBEDTLS_CCM_GCM_CAN_CAMELLIA))
 #error "MBEDTLS_GCM_C defined, but not all prerequisites"
 #endif
 
@@ -278,37 +313,15 @@
 #error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites"
 #endif
 
-/* Helper for ECDSA dependencies, will be undefined at the end of the file */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#if defined(PSA_HAVE_FULL_ECDSA)
-#define MBEDTLS_PK_HAVE_ECDSA
-#endif
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-#if defined(MBEDTLS_ECDSA_C)
-#define MBEDTLS_PK_HAVE_ECDSA
-#endif
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-/* Helper for JPAKE dependencies, will be undefined at the end of the file */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#if defined(PSA_HAVE_FULL_JPAKE)
-#define MBEDTLS_PK_HAVE_JPAKE
-#endif
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-#if defined(MBEDTLS_ECJPAKE_C)
-#define MBEDTLS_PK_HAVE_JPAKE
-#endif
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) &&                 \
-    ( !defined(MBEDTLS_ECDH_C) ||                                       \
-      !defined(MBEDTLS_PK_HAVE_ECDSA) ||                                \
+    ( !defined(MBEDTLS_CAN_ECDH) ||                                       \
+      !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) ||                                \
       !defined(MBEDTLS_X509_CRT_PARSE_C) )
 #error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) &&                 \
-    ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) ||          \
+    ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) ||          \
       !defined(MBEDTLS_X509_CRT_PARSE_C) )
 #error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites"
 #endif
@@ -318,7 +331,7 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) &&                     \
-    !defined(MBEDTLS_ECDH_C)
+    !defined(MBEDTLS_CAN_ECDH)
 #error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites"
 #endif
 
@@ -329,14 +342,14 @@
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) &&                 \
-    ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) ||          \
+    ( !defined(MBEDTLS_CAN_ECDH) || !defined(MBEDTLS_RSA_C) ||          \
       !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) )
 #error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) &&                \
-    ( !defined(MBEDTLS_ECDH_C) ||                                       \
-      !defined(MBEDTLS_PK_HAVE_ECDSA) ||                                \
+    ( !defined(MBEDTLS_CAN_ECDH) ||                                       \
+      !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) ||                                \
       !defined(MBEDTLS_X509_CRT_PARSE_C) )
 #error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites"
 #endif
@@ -353,42 +366,52 @@
 #error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&                    \
-    ( !defined(MBEDTLS_PK_HAVE_JPAKE) ||                                    \
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&    \
+    ( !defined(PSA_WANT_ALG_JPAKE) ||                   \
+      !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+      !defined(PSA_WANT_ECC_SECP_R1_256) )
+#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
+#endif
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&    \
+    ( !defined(MBEDTLS_ECJPAKE_C) ||                    \
       !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) )
 #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
 #endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-/* Use of EC J-PAKE in TLS requires SHA-256.
- * This will be taken from MD if it is present, or from PSA if MD is absent.
- * Note: MBEDTLS_ECJPAKE_C depends on MBEDTLS_MD_C || MBEDTLS_PSA_CRYPTO_C. */
+/* Use of EC J-PAKE in TLS requires SHA-256. */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) &&                    \
-    !( defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C) ) &&          \
-    !( !defined(MBEDTLS_MD_C) && defined(PSA_WANT_ALG_SHA_256) )
+    !defined(MBEDTLS_MD_CAN_SHA256)
 #error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
 #endif
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) &&        \
-    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) &&              \
-    ( !defined(MBEDTLS_SHA256_C) &&                             \
-      !defined(MBEDTLS_SHA512_C) &&                             \
-      !defined(MBEDTLS_SHA1_C) )
-#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C"
-#endif
-
-#if defined(MBEDTLS_MD_C) && !( \
-    defined(MBEDTLS_MD5_C) || \
-    defined(MBEDTLS_RIPEMD160_C) || \
-    defined(MBEDTLS_SHA1_C) || \
-    defined(MBEDTLS_SHA224_C) || \
-    defined(MBEDTLS_SHA256_C) || \
-    defined(MBEDTLS_SHA384_C) || \
-    defined(MBEDTLS_SHA512_C) )
-#error "MBEDTLS_MD_C defined, but not all prerequisites"
+    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) &&            \
+    !defined(MBEDTLS_MD_CAN_SHA256) &&                        \
+    !defined(MBEDTLS_MD_CAN_SHA512) &&                        \
+    !defined(MBEDTLS_MD_CAN_SHA1)
+#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires SHA-512, SHA-256 or SHA-1".
+#endif
+
+#if defined(MBEDTLS_MD_C) && \
+    !defined(MBEDTLS_MD_CAN_MD5) && \
+    !defined(MBEDTLS_MD_CAN_RIPEMD160) && \
+    !defined(MBEDTLS_MD_CAN_SHA1) && \
+    !defined(MBEDTLS_MD_CAN_SHA224) && \
+    !defined(MBEDTLS_MD_CAN_SHA256) && \
+    !defined(MBEDTLS_MD_CAN_SHA384) && \
+    !defined(MBEDTLS_MD_CAN_SHA512) && \
+    !defined(MBEDTLS_MD_CAN_SHA3_224) && \
+    !defined(MBEDTLS_MD_CAN_SHA3_256) && \
+    !defined(MBEDTLS_MD_CAN_SHA3_384) && \
+    !defined(MBEDTLS_MD_CAN_SHA3_512)
+#error "MBEDTLS_MD_C defined, but no hash algorithm"
 #endif
 
 #if defined(MBEDTLS_LMS_C) &&                                          \
-    ! ( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256) )
+    ! ( defined(MBEDTLS_PSA_CRYPTO_CLIENT) && defined(PSA_WANT_ALG_SHA_256) )
 #error "MBEDTLS_LMS_C requires MBEDTLS_PSA_CRYPTO_C and PSA_WANT_ALG_SHA_256"
 #endif
 
@@ -410,10 +433,6 @@
 #error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
-#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
-#endif
-
 #if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
 #error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
 #endif
@@ -423,15 +442,21 @@
 #endif
 
 #if defined(MBEDTLS_PK_C) && \
-    !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C)
+    !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 #error "MBEDTLS_PK_C defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C)
+#if defined(MBEDTLS_PK_PARSE_C) && \
+    (!defined(MBEDTLS_ASN1_PARSE_C) || \
+     !defined(MBEDTLS_OID_C)        || \
+     !defined(MBEDTLS_PK_C))
 #error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C)
+#if defined(MBEDTLS_PK_WRITE_C) && \
+    (!defined(MBEDTLS_ASN1_WRITE_C) || \
+     !defined(MBEDTLS_OID_C)        || \
+     !defined(MBEDTLS_PK_C))
 #error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites"
 #endif
 
@@ -475,6 +500,16 @@
 #error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites"
 #endif
 
+#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO) &&\
+    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) )
+#error "MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT)   && \
+    ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_HAVE_TIME) )
+#error "MBEDTLS_PLATFORM_MS_TIME_ALT defined, but not all prerequisites"
+#endif
+
 #if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\
     ( !defined(MBEDTLS_PLATFORM_C) ||\
         !defined(MBEDTLS_HAVE_TIME) )
@@ -659,7 +694,8 @@
 #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)"
 #endif
 
-#if defined(MBEDTLS_PSA_CRYPTO_C) && !defined(MBEDTLS_CIPHER_C )
+#if defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_HAVE_SOFT_BLOCK_MODE) && \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER) && !defined(MBEDTLS_CIPHER_C)
 #error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites"
 #endif
 
@@ -742,64 +778,50 @@
 #error "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system"
 #endif
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \
-    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
-#error "Must only define one of MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) && \
+    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
+#error "Must only define one of MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
 #endif
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
-    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 #if !defined(MBEDTLS_SHA256_C)
-#error "MBEDTLS_SHA256_USE_A64_CRYPTO_* defined without MBEDTLS_SHA256_C"
+#error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_* defined without MBEDTLS_SHA256_C"
 #endif
 #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA256_PROCESS_ALT)
-#error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_A64_CRYPTO_*"
-#endif
-
+#error "MBEDTLS_SHA256_*ALT can't be used with MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
 #endif
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && \
-    !defined(__aarch64__) && !defined(_M_ARM64)
-#error "MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY defined on non-Aarch64 system"
 #endif
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    !( defined(MBEDTLS_SHA1_C) || defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) )
-#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites"
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) && !defined(MBEDTLS_ARCH_IS_ARMV8_A)
+#error "MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY defined on non-Armv8-A system"
 #endif
 
-/* TLS 1.3 requires separate HKDF parts from PSA */
+/* TLS 1.3 requires separate HKDF parts from PSA,
+ * and at least one ciphersuite, so at least SHA-256 or SHA-384
+ * from PSA to use with HKDF.
+ *
+ * Note: for dependencies common with TLS 1.2 (running handshake hash),
+ * see MBEDTLS_SSL_TLS_C. */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
-        !( defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_HKDF_EXTRACT) && defined(PSA_WANT_ALG_HKDF_EXPAND) )
+    !(defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
+      defined(PSA_WANT_ALG_HKDF_EXTRACT) && \
+      defined(PSA_WANT_ALG_HKDF_EXPAND) && \
+      (defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384)))
 #error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
 #endif
 
-/* TLS 1.3 requires at least one ciphersuite, so at least SHA-256 or SHA-384 */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-/* We always need at least one of the hashes via PSA (for use with HKDF) */
-#if !( defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384) )
-#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
-#endif /* !(PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384) */
-#if !defined(MBEDTLS_USE_PSA_CRYPTO)
-/* When USE_PSA_CRYPTO is not defined, we also need SHA-256 or SHA-384 via the
- * legacy interface, including via the MD layer, for the parts of the code
- * that are shared with TLS 1.2 (running handshake hash). */
-#if !defined(MBEDTLS_MD_C) || \
-    !( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA384_C) )
-#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites"
-#endif /* !MBEDTLS_MD_C || !(MBEDTLS_SHA256_C || MBEDTLS_SHA384_C) */
-#endif /* !MBEDTLS_USE_PSA_CRYPTO */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
-#if !( defined(MBEDTLS_ECDH_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
-       ( defined(MBEDTLS_PK_HAVE_ECDSA) || defined(MBEDTLS_PKCS1_V21) ) )
+#if !( (defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)) && \
+       defined(MBEDTLS_X509_CRT_PARSE_C) && \
+       ( defined(MBEDTLS_PK_CAN_ECDSA_SIGN) || defined(MBEDTLS_PKCS1_V21) ) )
 #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED defined, but not all prerequisites"
 #endif
 #endif
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-#if !( defined(MBEDTLS_ECDH_C) )
+#if !( defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH) )
 #error "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED defined, but not all prerequisites"
 #endif
 #endif
@@ -835,10 +857,10 @@
 #endif
 
 #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C) && \
-    ( !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)     || \
-      ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0 )       || \
-      ( MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX ) )
-#error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE MUST be defined and in range(0..UINT32_MAX)"
+    defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE) &&                      \
+        ((MBEDTLS_SSL_MAX_EARLY_DATA_SIZE < 0) ||                    \
+         (MBEDTLS_SSL_MAX_EARLY_DATA_SIZE > UINT32_MAX))
+#error "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE must be in the range(0..UINT32_MAX)"
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)     && \
@@ -854,11 +876,25 @@
 #error "MBEDTLS_SSL_ASYNC_PRIVATE defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) ||     \
-    ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
+#if defined(MBEDTLS_SSL_TLS_C) && !(defined(MBEDTLS_CIPHER_C) || \
+    defined(MBEDTLS_USE_PSA_CRYPTO))
 #error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
 #endif
 
+/* TLS 1.2 and 1.3 require SHA-256 or SHA-384 (running handshake hash) */
+#if defined(MBEDTLS_SSL_TLS_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if !(defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA_384))
+#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
+#endif
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#if !defined(MBEDTLS_MD_C) || \
+    !(defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA384))
+#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites"
+#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_SSL_TLS_C */
+
 #if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C)
 #error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites"
 #endif
@@ -933,7 +969,8 @@
 #endif
 
 #if defined(MBEDTLS_SSL_TICKET_C) && \
-    !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
+    !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \
+    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) )
 #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
 #endif
 
@@ -951,22 +988,20 @@
 #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
 #error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites"
 #endif
-#define MBEDTLS_THREADING_IMPL
+#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph
 #endif
-
 #if defined(MBEDTLS_THREADING_ALT)
 #if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL)
 #error "MBEDTLS_THREADING_ALT defined, but not all prerequisites"
 #endif
-#define MBEDTLS_THREADING_IMPL
+#define MBEDTLS_THREADING_IMPL // undef at the end of this paragraph
 #endif
-
 #if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL)
 #error "MBEDTLS_THREADING_C defined, single threading implementation required"
 #endif
-#undef MBEDTLS_THREADING_IMPL
+#undef MBEDTLS_THREADING_IMPL // temporary macro defined above
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites"
 #endif
 
@@ -974,15 +1009,15 @@
 #error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) ||  \
-    !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) ||    \
+#if defined(MBEDTLS_X509_USE_C) && \
+    (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) ||   \
     !defined(MBEDTLS_PK_PARSE_C) ||                                 \
     ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
 #error "MBEDTLS_X509_USE_C defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) ||  \
-    !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) ||       \
+#if defined(MBEDTLS_X509_CREATE_C) && \
+    (!defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) ||      \
     !defined(MBEDTLS_PK_PARSE_C) ||                                    \
     ( !defined(MBEDTLS_MD_C) && !defined(MBEDTLS_USE_PSA_CRYPTO) ) )
 #error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites"
@@ -1034,7 +1069,9 @@
 #error "MBEDTLS_SSL_RECORD_SIZE_LIMIT defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && !( defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) )
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION) && \
+    !( defined(MBEDTLS_SSL_HAVE_CCM) || defined(MBEDTLS_SSL_HAVE_GCM) || \
+    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) )
 #error "MBEDTLS_SSL_CONTEXT_SERIALIZATION defined, but not all prerequisites"
 #endif
 
@@ -1087,16 +1124,12 @@
 
 #if defined(MBEDTLS_PKCS7_C) && ( ( !defined(MBEDTLS_ASN1_PARSE_C) ) || \
     ( !defined(MBEDTLS_OID_C) ) || ( !defined(MBEDTLS_PK_PARSE_C) ) || \
-    ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) ||\
-    ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || ( !defined(MBEDTLS_BIGNUM_C) ) || \
+    ( !defined(MBEDTLS_X509_CRT_PARSE_C) ) || \
+    ( !defined(MBEDTLS_X509_CRL_PARSE_C) ) || \
     ( !defined(MBEDTLS_MD_C) ) )
 #error  "MBEDTLS_PKCS7_C is defined, but not all prerequisites"
 #endif
 
-/* Undefine helper symbols */
-#undef MBEDTLS_PK_HAVE_ECDSA
-#undef MBEDTLS_PK_HAVE_JPAKE
-
 /*
  * Avoid warning from -pedantic. This is a convenient place for this
  * workaround since this is included by every single file before the
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h b/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
index 0a5319b5a7bf2dcec39da9da638e6fd0205d7c7e..5d5fc0c5ecbe86c89688336fd1fff23edaecf6c5 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/cipher.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CIPHER_H
@@ -270,45 +258,58 @@ typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t;
  *              mbedtls_cipher_info_from_type(),
  *              mbedtls_cipher_info_from_values(),
  *              mbedtls_cipher_info_from_psa().
+ *
+ * \note        Some fields store a value that has been right-shifted to save
+ *              code-size, so should not be used directly. The accessor
+ *              functions adjust for this and return the "natural" value.
  */
 typedef struct mbedtls_cipher_info_t {
-    /** Full cipher identifier. For example,
-     * MBEDTLS_CIPHER_AES_256_CBC.
-     */
-    mbedtls_cipher_type_t MBEDTLS_PRIVATE(type);
+    /** Name of the cipher. */
+    const char *MBEDTLS_PRIVATE(name);
 
-    /** The cipher mode. For example, MBEDTLS_MODE_CBC. */
-    mbedtls_cipher_mode_t MBEDTLS_PRIVATE(mode);
+    /** The block size, in bytes. */
+    unsigned int MBEDTLS_PRIVATE(block_size) : 5;
 
-    /** The cipher key length, in bits. This is the
-     * default length for variable sized ciphers.
+    /** IV or nonce size, in bytes (right shifted by #MBEDTLS_IV_SIZE_SHIFT).
+     * For ciphers that accept variable IV sizes,
+     * this is the recommended size.
+     */
+    unsigned int MBEDTLS_PRIVATE(iv_size) : 3;
+
+    /** The cipher key length, in bits (right shifted by #MBEDTLS_KEY_BITLEN_SHIFT).
+     * This is the default length for variable sized ciphers.
      * Includes parity bits for ciphers like DES.
      */
-    unsigned int MBEDTLS_PRIVATE(key_bitlen);
+    unsigned int MBEDTLS_PRIVATE(key_bitlen) : 4;
 
-    /** Name of the cipher. */
-    const char *MBEDTLS_PRIVATE(name);
+    /** The cipher mode (as per mbedtls_cipher_mode_t).
+     * For example, MBEDTLS_MODE_CBC.
+     */
+    unsigned int MBEDTLS_PRIVATE(mode) : 4;
 
-    /** IV or nonce size, in Bytes.
-     * For ciphers that accept variable IV sizes,
-     * this is the recommended size.
+    /** Full cipher identifier (as per mbedtls_cipher_type_t).
+     * For example, MBEDTLS_CIPHER_AES_256_CBC.
+     *
+     * This could be 7 bits, but 8 bits retains byte alignment for the
+     * next field, which reduces code size to access that field.
      */
-    unsigned int MBEDTLS_PRIVATE(iv_size);
+    unsigned int MBEDTLS_PRIVATE(type) : 8;
 
     /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and
      *  MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the
      *  cipher supports variable IV or variable key sizes, respectively.
      */
-    int MBEDTLS_PRIVATE(flags);
-
-    /** The block size, in Bytes. */
-    unsigned int MBEDTLS_PRIVATE(block_size);
+    unsigned int MBEDTLS_PRIVATE(flags) : 2;
 
-    /** Struct for base cipher information and functions. */
-    const mbedtls_cipher_base_t *MBEDTLS_PRIVATE(base);
+    /** Index to LUT for base cipher information and functions. */
+    unsigned int MBEDTLS_PRIVATE(base_idx) : 5;
 
 } mbedtls_cipher_info_t;
 
+/* For internal use only.
+ * These are used to more compactly represent the fields above. */
+#define MBEDTLS_KEY_BITLEN_SHIFT  6
+#define MBEDTLS_IV_SIZE_SHIFT     2
 /**
  * Generic cipher context.
  */
@@ -353,7 +354,7 @@ typedef struct mbedtls_cipher_context_t {
     mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx);
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     /** Indicates whether the cipher operations should be performed
      *  by Mbed TLS' own crypto library or an external implementation
      *  of the PSA Crypto API.
@@ -362,7 +363,7 @@ typedef struct mbedtls_cipher_context_t {
      *  mbedtls_cipher_setup_psa().
      */
     unsigned char MBEDTLS_PRIVATE(psa_enabled);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 } mbedtls_cipher_context_t;
 
@@ -439,7 +440,7 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type(
     if (info == NULL) {
         return MBEDTLS_CIPHER_NONE;
     } else {
-        return info->MBEDTLS_PRIVATE(type);
+        return (mbedtls_cipher_type_t) info->MBEDTLS_PRIVATE(type);
     }
 }
 
@@ -458,7 +459,7 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode(
     if (info == NULL) {
         return MBEDTLS_MODE_NONE;
     } else {
-        return info->MBEDTLS_PRIVATE(mode);
+        return (mbedtls_cipher_mode_t) info->MBEDTLS_PRIVATE(mode);
     }
 }
 
@@ -479,7 +480,7 @@ static inline size_t mbedtls_cipher_info_get_key_bitlen(
     if (info == NULL) {
         return 0;
     } else {
-        return info->MBEDTLS_PRIVATE(key_bitlen);
+        return ((size_t) info->MBEDTLS_PRIVATE(key_bitlen)) << MBEDTLS_KEY_BITLEN_SHIFT;
     }
 }
 
@@ -492,7 +493,7 @@ static inline size_t mbedtls_cipher_info_get_key_bitlen(
  *
  * \return              The cipher name, which is a human readable string,
  *                      with static storage duration.
- * \return              \c NULL if \c info is \p NULL.
+ * \return              \c NULL if \p info is \c NULL.
  */
 static inline const char *mbedtls_cipher_info_get_name(
     const mbedtls_cipher_info_t *info)
@@ -521,7 +522,7 @@ static inline size_t mbedtls_cipher_info_get_iv_size(
         return 0;
     }
 
-    return (size_t) info->MBEDTLS_PRIVATE(iv_size);
+    return ((size_t) info->MBEDTLS_PRIVATE(iv_size)) << MBEDTLS_IV_SIZE_SHIFT;
 }
 
 /**
@@ -541,7 +542,7 @@ static inline size_t mbedtls_cipher_info_get_block_size(
         return 0;
     }
 
-    return (size_t) info->MBEDTLS_PRIVATE(block_size);
+    return (size_t) (info->MBEDTLS_PRIVATE(block_size));
 }
 
 /**
@@ -583,7 +584,7 @@ static inline int mbedtls_cipher_info_has_variable_iv_size(
 }
 
 /**
- * \brief               This function initializes a \p cipher_context as NONE.
+ * \brief               This function initializes a \p ctx as NONE.
  *
  * \param ctx           The context to be initialized. This must not be \c NULL.
  */
@@ -703,12 +704,11 @@ int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx,
 static inline unsigned int mbedtls_cipher_get_block_size(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return 0;
     }
 
-    return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);
+    return (unsigned int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size);
 }
 
 /**
@@ -723,12 +723,11 @@ static inline unsigned int mbedtls_cipher_get_block_size(
 static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, MBEDTLS_MODE_NONE);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return MBEDTLS_MODE_NONE;
     }
 
-    return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode);
+    return (mbedtls_cipher_mode_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode);
 }
 
 /**
@@ -744,7 +743,6 @@ static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode(
 static inline int mbedtls_cipher_get_iv_size(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return 0;
     }
@@ -753,7 +751,8 @@ static inline int mbedtls_cipher_get_iv_size(
         return (int) ctx->MBEDTLS_PRIVATE(iv_size);
     }
 
-    return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size);
+    return (int) (((int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size)) <<
+                  MBEDTLS_IV_SIZE_SHIFT);
 }
 
 /**
@@ -767,13 +766,11 @@ static inline int mbedtls_cipher_get_iv_size(
 static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(
-        ctx != NULL, MBEDTLS_CIPHER_NONE);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return MBEDTLS_CIPHER_NONE;
     }
 
-    return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type);
+    return (mbedtls_cipher_type_t) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type);
 }
 
 /**
@@ -788,7 +785,6 @@ static inline mbedtls_cipher_type_t mbedtls_cipher_get_type(
 static inline const char *mbedtls_cipher_get_name(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(ctx != NULL, 0);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return 0;
     }
@@ -802,19 +798,18 @@ static inline const char *mbedtls_cipher_get_name(
  * \param ctx           The context of the cipher. This must be initialized.
  *
  * \return              The key length of the cipher in bits.
- * \return              #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been
+ * \return              #MBEDTLS_KEY_LENGTH_NONE if \p ctx has not been
  *                      initialized.
  */
 static inline int mbedtls_cipher_get_key_bitlen(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(
-        ctx != NULL, MBEDTLS_KEY_LENGTH_NONE);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return MBEDTLS_KEY_LENGTH_NONE;
     }
 
-    return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen);
+    return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen) <<
+           MBEDTLS_KEY_BITLEN_SHIFT;
 }
 
 /**
@@ -828,8 +823,6 @@ static inline int mbedtls_cipher_get_key_bitlen(
 static inline mbedtls_operation_t mbedtls_cipher_get_operation(
     const mbedtls_cipher_context_t *ctx)
 {
-    MBEDTLS_INTERNAL_VALIDATE_RET(
-        ctx != NULL, MBEDTLS_OPERATION_NONE);
     if (ctx->MBEDTLS_PRIVATE(cipher_info) == NULL) {
         return MBEDTLS_OPERATION_NONE;
     }
@@ -863,7 +856,6 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
  * \brief               This function sets the padding mode, for cipher modes
  *                      that use padding.
  *
- *                      The default passing mode is PKCS7 padding.
  *
  * \param ctx           The generic cipher context. This must be initialized and
  *                      bound to a cipher information structure.
@@ -1001,7 +993,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx,
  * \param ctx           The generic cipher context. This must be initialized and
  *                      bound to a key.
  * \param output        The buffer to write data to. This needs to be a writable
- *                      buffer of at least \p block_size Bytes.
+ *                      buffer of at least block_size Bytes.
  * \param olen          The length of the data written to the \p output buffer.
  *                      This may not be \c NULL.
  *
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h b/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
index 1bc857c952a83f6efff7f1b88b704cfca20c69c9..16421ba3d389feae0ea83ae55f8639563fef2513 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/cmac.h
@@ -5,22 +5,11 @@
  *
  * The Cipher-based Message Authentication Code (CMAC) Mode for
  * Authentication is defined in <em>RFC-4493: The AES-CMAC Algorithm</em>.
+ * It is supported with AES and DES.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CMAC_H
@@ -38,12 +27,30 @@ extern "C" {
 #define MBEDTLS_AES_BLOCK_SIZE          16
 #define MBEDTLS_DES3_BLOCK_SIZE         8
 
+/* We don't support Camellia or ARIA in this module */
 #if defined(MBEDTLS_AES_C)
-#define MBEDTLS_CIPHER_BLKSIZE_MAX      16  /**< The longest block used by CMAC is that of AES. */
+#define MBEDTLS_CMAC_MAX_BLOCK_SIZE      16  /**< The longest block used by CMAC is that of AES. */
 #else
-#define MBEDTLS_CIPHER_BLKSIZE_MAX      8   /**< The longest block used by CMAC is that of 3DES. */
+#define MBEDTLS_CMAC_MAX_BLOCK_SIZE      8   /**< The longest block used by CMAC is that of 3DES. */
 #endif
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/** The longest block supported by the cipher module.
+ *
+ * \deprecated
+ * For the maximum block size of a cipher supported by the CMAC module,
+ * use #MBEDTLS_CMAC_MAX_BLOCK_SIZE.
+ * For the maximum block size of a cipher supported by the cipher module,
+ * use #MBEDTLS_MAX_BLOCK_LENGTH.
+ */
+/* Before Mbed TLS 3.5, this was the maximum block size supported by the CMAC
+ * module, so it didn't take Camellia or ARIA into account. Since the name
+ * of the macro doesn't even convey "CMAC", this was misleading. Now the size
+ * is sufficient for any cipher, but the name is defined in cmac.h for
+ * backward compatibility. */
+#define MBEDTLS_CIPHER_BLKSIZE_MAX MBEDTLS_MAX_BLOCK_LENGTH
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
 #if !defined(MBEDTLS_CMAC_ALT)
 
 /**
@@ -51,11 +58,11 @@ extern "C" {
  */
 struct mbedtls_cmac_context_t {
     /** The internal state of the CMAC algorithm.  */
-    unsigned char       MBEDTLS_PRIVATE(state)[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char       MBEDTLS_PRIVATE(state)[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
 
     /** Unprocessed data - either data that was not block aligned and is still
      *  pending processing, or the final block. */
-    unsigned char       MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char       MBEDTLS_PRIVATE(unprocessed_block)[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
 
     /** The length of data pending processing. */
     size_t              MBEDTLS_PRIVATE(unprocessed_len);
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h b/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h
index cdf81dcbb8ece5a833ce11ffaefe9ea34222d2cd..096341ba76cdd3fa434a8449109c50217e262b6b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/compat-2.x.h
@@ -7,19 +7,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #if defined(MBEDTLS_DEPRECATED_WARNING)
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ba987ebb2eb33f585e35d6085f604963168b048
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h
@@ -0,0 +1,476 @@
+/**
+ * \file mbedtls/config_adjust_legacy_crypto.h
+ * \brief Adjust legacy configuration configuration
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * Automatically enable certain dependencies. Generally, MBEDTLS_xxx
+ * configurations need to be explicitly enabled by the user: enabling
+ * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
+ * compilation error. However, we do automatically enable certain options
+ * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option
+ * used to identify parts of a module that are used by other module, and we
+ * don't want to make the symbol MBEDTLS_xxx_B part of the public API.
+ * Another case is if A didn't depend on B in earlier versions, and we
+ * want to use B in A but we need to preserve backward compatibility with
+ * configurations that explicitly activate MBEDTLS_xxx_A but not
+ * MBEDTLS_xxx_B.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
+#define MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/* Ideally, we'd set those as defaults in mbedtls_config.h, but
+ * putting an #ifdef _WIN32 in mbedtls_config.h would confuse config.py.
+ *
+ * So, adjust it here.
+ * Not related to crypto, but this is the bottom of the stack. */
+#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900)
+#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \
+    !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
+#define MBEDTLS_PLATFORM_SNPRINTF_ALT
+#endif
+#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \
+    !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
+#define MBEDTLS_PLATFORM_VSNPRINTF_ALT
+#endif
+#endif /* _MINGW32__ || (_MSC_VER && (_MSC_VER <= 1900)) */
+
+/* Auto-enable CIPHER_C when any of the unauthenticated ciphers is builtin
+ * in PSA. */
+#if defined(MBEDTLS_PSA_CRYPTO_C) && \
+    (defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CTR) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CFB) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC))
+#define MBEDTLS_CIPHER_C
+#endif
+
+/* Auto-enable MBEDTLS_MD_LIGHT based on MBEDTLS_MD_C.
+ * This allows checking for MD_LIGHT rather than MD_LIGHT || MD_C.
+ */
+#if defined(MBEDTLS_MD_C)
+#define MBEDTLS_MD_LIGHT
+#endif
+
+/* Auto-enable MBEDTLS_MD_LIGHT if needed by a module that didn't require it
+ * in a previous release, to ensure backwards compatibility.
+ */
+#if defined(MBEDTLS_ECJPAKE_C) || \
+    defined(MBEDTLS_PEM_PARSE_C) || \
+    defined(MBEDTLS_ENTROPY_C) || \
+    defined(MBEDTLS_PK_C) || \
+    defined(MBEDTLS_PKCS12_C) || \
+    defined(MBEDTLS_RSA_C) || \
+    defined(MBEDTLS_SSL_TLS_C) || \
+    defined(MBEDTLS_X509_USE_C) || \
+    defined(MBEDTLS_X509_CREATE_C)
+#define MBEDTLS_MD_LIGHT
+#endif
+
+#if defined(MBEDTLS_MD_LIGHT)
+/*
+ * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx.
+ * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA
+ *   (see below).
+ * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed
+ *   via PSA (see below).
+ * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed
+ *   via a direct legacy call (see below).
+ *
+ * The md module performs an algorithm via PSA if there is a PSA hash
+ * accelerator and the PSA driver subsytem is initialized at the time the
+ * operation is started, and makes a direct legacy call otherwise.
+ */
+
+/* PSA accelerated implementations */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
+#define MBEDTLS_MD_CAN_MD5
+#define MBEDTLS_MD_MD5_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
+#define MBEDTLS_MD_CAN_SHA1
+#define MBEDTLS_MD_SHA1_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
+#define MBEDTLS_MD_CAN_SHA224
+#define MBEDTLS_MD_SHA224_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
+#define MBEDTLS_MD_CAN_SHA256
+#define MBEDTLS_MD_SHA256_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
+#define MBEDTLS_MD_CAN_SHA384
+#define MBEDTLS_MD_SHA384_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
+#define MBEDTLS_MD_CAN_SHA512
+#define MBEDTLS_MD_SHA512_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
+#define MBEDTLS_MD_CAN_RIPEMD160
+#define MBEDTLS_MD_RIPEMD160_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224)
+#define MBEDTLS_MD_CAN_SHA3_224
+#define MBEDTLS_MD_SHA3_224_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256)
+#define MBEDTLS_MD_CAN_SHA3_256
+#define MBEDTLS_MD_SHA3_256_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384)
+#define MBEDTLS_MD_CAN_SHA3_384
+#define MBEDTLS_MD_SHA3_384_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512)
+#define MBEDTLS_MD_CAN_SHA3_512
+#define MBEDTLS_MD_SHA3_512_VIA_PSA
+#define MBEDTLS_MD_SOME_PSA
+#endif
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/* Built-in implementations */
+#if defined(MBEDTLS_MD5_C)
+#define MBEDTLS_MD_CAN_MD5
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA1_C)
+#define MBEDTLS_MD_CAN_SHA1
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA224_C)
+#define MBEDTLS_MD_CAN_SHA224
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_MD_CAN_SHA256
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA384_C)
+#define MBEDTLS_MD_CAN_SHA384
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_MD_CAN_SHA512
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_SHA3_C)
+#define MBEDTLS_MD_CAN_SHA3_224
+#define MBEDTLS_MD_CAN_SHA3_256
+#define MBEDTLS_MD_CAN_SHA3_384
+#define MBEDTLS_MD_CAN_SHA3_512
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+#if defined(MBEDTLS_RIPEMD160_C)
+#define MBEDTLS_MD_CAN_RIPEMD160
+#define MBEDTLS_MD_SOME_LEGACY
+#endif
+
+#endif /* MBEDTLS_MD_LIGHT */
+
+/* BLOCK_CIPHER module can dispatch to PSA when:
+ * - PSA is enabled and drivers have been initialized
+ * - desired key type is supported on the PSA side
+ * If the above conditions are not met, but the legacy support is enabled, then
+ * BLOCK_CIPHER will dynamically fallback to it.
+ *
+ * In case BLOCK_CIPHER is defined (see below) the following symbols/helpers
+ * can be used to define its capabilities:
+ * - MBEDTLS_BLOCK_CIPHER_SOME_PSA: there is at least 1 key type between AES,
+ *   ARIA and Camellia which is supported through a driver;
+ * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_PSA: xxx key type is supported through a
+ *   driver;
+ * - MBEDTLS_BLOCK_CIPHER_xxx_VIA_LEGACY: xxx key type is supported through
+ *   a legacy module (i.e. MBEDTLS_xxx_C)
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
+#define MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA
+#define MBEDTLS_BLOCK_CIPHER_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)
+#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA
+#define MBEDTLS_BLOCK_CIPHER_SOME_PSA
+#endif
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
+#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA
+#define MBEDTLS_BLOCK_CIPHER_SOME_PSA
+#endif
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+#if defined(MBEDTLS_AES_C)
+#define MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY
+#endif
+#if defined(MBEDTLS_ARIA_C)
+#define MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+#define MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY
+#endif
+
+/* Helpers to state that BLOCK_CIPHER module supports AES, ARIA and/or Camellia
+ * block ciphers via either PSA or legacy. */
+#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA) || \
+    defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_LEGACY)
+#define MBEDTLS_BLOCK_CIPHER_CAN_AES
+#endif
+#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA) || \
+    defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_LEGACY)
+#define MBEDTLS_BLOCK_CIPHER_CAN_ARIA
+#endif
+#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA) || \
+    defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_LEGACY)
+#define MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA
+#endif
+
+/* GCM_C and CCM_C can either depend on (in order of preference) BLOCK_CIPHER_C
+ * or CIPHER_C. The former is auto-enabled when:
+ * - CIPHER_C is not defined, which is also the legacy solution;
+ * - BLOCK_CIPHER_SOME_PSA because in this case BLOCK_CIPHER can take advantage
+ *   of the driver's acceleration.
+ */
+#if (defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C)) && \
+    (!defined(MBEDTLS_CIPHER_C) || defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA))
+#define MBEDTLS_BLOCK_CIPHER_C
+#endif
+
+/* Helpers for GCM/CCM capabilities */
+#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_AES_C)) || \
+    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_AES))
+#define MBEDTLS_CCM_GCM_CAN_AES
+#endif
+
+#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_ARIA_C)) || \
+    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_ARIA))
+#define MBEDTLS_CCM_GCM_CAN_ARIA
+#endif
+
+#if (defined(MBEDTLS_CIPHER_C) && defined(MBEDTLS_CAMELLIA_C)) || \
+    (defined(MBEDTLS_BLOCK_CIPHER_C) && defined(MBEDTLS_BLOCK_CIPHER_CAN_CAMELLIA))
+#define MBEDTLS_CCM_GCM_CAN_CAMELLIA
+#endif
+
+/* MBEDTLS_ECP_LIGHT is auto-enabled by the following symbols:
+ * - MBEDTLS_ECP_C because now it consists of MBEDTLS_ECP_LIGHT plus functions
+ *   for curve arithmetic. As a consequence if MBEDTLS_ECP_C is required for
+ *   some reason, then MBEDTLS_ECP_LIGHT should be enabled as well.
+ * - MBEDTLS_PK_PARSE_EC_EXTENDED and MBEDTLS_PK_PARSE_EC_COMPRESSED because
+ *   these features are not supported in PSA so the only way to have them is
+ *   to enable the built-in solution.
+ *   Both of them are temporary dependencies:
+ *   - PK_PARSE_EC_EXTENDED will be removed after #7779 and #7789
+ *   - support for compressed points should also be added to PSA, but in this
+ *     case there is no associated issue to track it yet.
+ * - PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE because Weierstrass key derivation
+ *   still depends on ECP_LIGHT.
+ * - PK_C + USE_PSA + PSA_WANT_ALG_ECDSA is a temporary dependency which will
+ *   be fixed by #7453.
+ */
+#if defined(MBEDTLS_ECP_C) || \
+    defined(MBEDTLS_PK_PARSE_EC_EXTENDED) || \
+    defined(MBEDTLS_PK_PARSE_EC_COMPRESSED) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#define MBEDTLS_ECP_LIGHT
+#endif
+
+/* Backward compatibility: after #8740 the RSA module offers functions to parse
+ * and write RSA private/public keys without relying on the PK one. Of course
+ * this needs ASN1 support to do so, so we enable it here. */
+#if defined(MBEDTLS_RSA_C)
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#endif
+
+/* MBEDTLS_PK_PARSE_EC_COMPRESSED is introduced in Mbed TLS version 3.5, while
+ * in previous version compressed points were automatically supported as long
+ * as PK_PARSE_C and ECP_C were enabled. As a consequence, for backward
+ * compatibility, we auto-enable PK_PARSE_EC_COMPRESSED when these conditions
+ * are met. */
+#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_ECP_C)
+#define MBEDTLS_PK_PARSE_EC_COMPRESSED
+#endif
+
+/* Helper symbol to state that there is support for ECDH, either through
+ * library implementation (ECDH_C) or through PSA. */
+#if (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_ECDH)) || \
+    (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C))
+#define MBEDTLS_CAN_ECDH
+#endif
+
+/* PK module can achieve ECDSA functionalities by means of either software
+ * implementations (ECDSA_C) or through a PSA driver. The following defines
+ * are meant to list these capabilities in a general way which abstracts how
+ * they are implemented under the hood. */
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_ECDSA_C)
+#define MBEDTLS_PK_CAN_ECDSA_SIGN
+#define MBEDTLS_PK_CAN_ECDSA_VERIFY
+#endif /* MBEDTLS_ECDSA_C */
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(PSA_WANT_ALG_ECDSA)
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#define MBEDTLS_PK_CAN_ECDSA_SIGN
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#define MBEDTLS_PK_CAN_ECDSA_VERIFY
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+#endif /* PSA_WANT_ALG_ECDSA */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+#define MBEDTLS_PK_CAN_ECDSA_SOME
+#endif
+
+/* If MBEDTLS_PSA_CRYPTO_C is defined, make sure MBEDTLS_PSA_CRYPTO_CLIENT
+ * is defined as well to include all PSA code.
+ */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+#define MBEDTLS_PSA_CRYPTO_CLIENT
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+
+/* Helpers to state that each key is supported either on the builtin or PSA side. */
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521)
+#define MBEDTLS_ECP_HAVE_SECP521R1
+#endif
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+#define MBEDTLS_ECP_HAVE_BP512R1
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448)
+#define MBEDTLS_ECP_HAVE_CURVE448
+#endif
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+#define MBEDTLS_ECP_HAVE_BP384R1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384)
+#define MBEDTLS_ECP_HAVE_SECP384R1
+#endif
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+#define MBEDTLS_ECP_HAVE_BP256R1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256)
+#define MBEDTLS_ECP_HAVE_SECP256K1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256)
+#define MBEDTLS_ECP_HAVE_SECP256R1
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255)
+#define MBEDTLS_ECP_HAVE_CURVE25519
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224)
+#define MBEDTLS_ECP_HAVE_SECP224K1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224)
+#define MBEDTLS_ECP_HAVE_SECP224R1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192)
+#define MBEDTLS_ECP_HAVE_SECP192K1
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192)
+#define MBEDTLS_ECP_HAVE_SECP192R1
+#endif
+
+/* Helper symbol to state that the PK module has support for EC keys. This
+ * can either be provided through the legacy ECP solution or through the
+ * PSA friendly MBEDTLS_PK_USE_PSA_EC_DATA (see pk.h for its description). */
+#if defined(MBEDTLS_ECP_C) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
+#define MBEDTLS_PK_HAVE_ECC_KEYS
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_ECP_C */
+
+/* Historically pkparse did not check the CBC padding when decrypting
+ * a key. This was a bug, which is now fixed. As a consequence, pkparse
+ * now needs PKCS7 padding support, but existing configurations might not
+ * enable it, so we enable it here. */
+#if defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_MODE_CBC)
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#endif
+
+/* Backwards compatibility for some macros which were renamed to reflect that
+ * they are related to Armv8, not aarch64. */
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) && \
+    !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
+#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
+#endif
+#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY) && !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
+#define MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY
+#endif
+
+/* psa_util file features some ECDSA conversion functions, to convert between
+ * legacy's ASN.1 DER format and PSA's raw one. */
+#if (defined(MBEDTLS_PSA_CRYPTO_CLIENT) && \
+    (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)))
+#define MBEDTLS_PSA_UTIL_HAVE_ECDSA
+#endif
+
+/* Some internal helpers to determine which keys are available. */
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_AES_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_AES))
+#define MBEDTLS_SSL_HAVE_AES
+#endif
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ARIA_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ARIA))
+#define MBEDTLS_SSL_HAVE_ARIA
+#endif
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CAMELLIA_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_CAMELLIA))
+#define MBEDTLS_SSL_HAVE_CAMELLIA
+#endif
+
+/* Some internal helpers to determine which operation modes are available. */
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CIPHER_MODE_CBC)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CBC_NO_PADDING))
+#define MBEDTLS_SSL_HAVE_CBC
+#endif
+
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_GCM_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))
+#define MBEDTLS_SSL_HAVE_GCM
+#endif
+
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CCM_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM))
+#define MBEDTLS_SSL_HAVE_CCM
+#endif
+
+#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_CHACHAPOLY_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305))
+#define MBEDTLS_SSL_HAVE_CHACHAPOLY
+#endif
+
+#if defined(MBEDTLS_SSL_HAVE_GCM) || defined(MBEDTLS_SSL_HAVE_CCM) || \
+    defined(MBEDTLS_SSL_HAVE_CHACHAPOLY)
+#define MBEDTLS_SSL_HAVE_AEAD
+#endif
+
+#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_CRYPTO_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h
new file mode 100644
index 0000000000000000000000000000000000000000..04bdae61bb3dec512ccb23b07e4465ae4f98f7e2
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h
@@ -0,0 +1,892 @@
+/**
+ * \file mbedtls/config_adjust_legacy_from_psa.h
+ * \brief Adjust PSA configuration: activate legacy implementations
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * When MBEDTLS_PSA_CRYPTO_CONFIG is enabled, activate legacy implementations
+ * of cryptographic mechanisms as needed to fulfill the needs of the PSA
+ * configuration. Generally speaking, we activate a legacy mechanism if
+ * it's needed for a requested PSA mechanism and there is no PSA driver
+ * for it.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
+#define MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/* Define appropriate ACCEL macros for the p256-m driver.
+ * In the future, those should be generated from the drivers JSON description.
+ */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE
+#endif
+
+/*
+ * ECC: support for a feature is controlled by a triplet or a pair:
+ * (curve, key_type public/basic, alg) or (curve, key_type_<action>).
+ *
+ * A triplet/pair is accelerated if all of is components are accelerated;
+ * otherwise each component needs to be built in.
+ *
+ * We proceed in two passes:
+ * 1. Check if acceleration is complete for curves, key types, algs.
+ * 2. Then enable built-ins for each thing that's either not accelerated of
+ * doesn't have complete acceleration of the other triplet/pair components.
+ *
+ * Note: this needs psa/crypto_adjust_keypair_types.h to have been included
+ * already, so that we know the full set of key types that are requested.
+ */
+
+/* ECC: curves: is acceleration complete? */
+#if (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256) && \
+    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)) || \
+    (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384) && \
+    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)) || \
+    (defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512) && \
+    !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)) || \
+    (defined(PSA_WANT_ECC_SECP_R1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)) || \
+    (defined(PSA_WANT_ECC_SECP_R1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)) || \
+    (defined(PSA_WANT_ECC_SECP_R1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)) || \
+    (defined(PSA_WANT_ECC_SECP_R1_384) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)) || \
+    (defined(PSA_WANT_ECC_SECP_R1_521) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)) || \
+    (defined(PSA_WANT_ECC_SECP_K1_192) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)) || \
+    (defined(PSA_WANT_ECC_SECP_K1_224) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224)) || \
+    (defined(PSA_WANT_ECC_SECP_K1_256) && !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256))
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES
+#endif
+
+#if (defined(PSA_WANT_ECC_MONTGOMERY_255) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)) || \
+    (defined(PSA_WANT_ECC_MONTGOMERY_448) && !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448))
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES
+#endif
+
+/* ECC: algs: is acceleration complete? */
+#if (defined(PSA_WANT_ALG_ECDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)) || \
+    (defined(PSA_WANT_ALG_ECDSA) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)) || \
+    (defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)) || \
+    (defined(PSA_WANT_ALG_JPAKE) && !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE))
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS
+#endif
+
+/* ECC: key types: is acceleration complete? */
+#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC))
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC
+#endif
+
+/* Special case: we don't support cooked key derivation in drivers yet */
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#undef MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE
+#endif
+
+/* Note: the condition about key derivation is always true as DERIVE can't be
+ * accelerated yet */
+#if (defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)) || \
+    (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE))
+#define MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES
+#endif
+
+/* ECC: curves: enable built-ins as needed.
+ *
+ * We need the curve built-in:
+ * - if it's not accelerated, or
+ * - if there's a key type with missing acceleration, or
+ * - if there's a alg with missing acceleration.
+ */
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
+#define MBEDTLS_ECP_DP_BP256R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */
+
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1
+#define MBEDTLS_ECP_DP_BP384R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */
+
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1
+#define MBEDTLS_ECP_DP_BP512R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */
+
+#if defined(PSA_WANT_ECC_MONTGOMERY_255)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1
+#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_MONTGOMERY_255 */
+
+#if defined(PSA_WANT_ECC_MONTGOMERY_448)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
+#define MBEDTLS_ECP_DP_CURVE448_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_MONTGOMERY_448 */
+
+#if defined(PSA_WANT_ECC_SECP_R1_192)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1
+#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_R1_192 */
+
+#if defined(PSA_WANT_ECC_SECP_R1_224)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1
+#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_R1_224 */
+
+#if defined(PSA_WANT_ECC_SECP_R1_256)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_R1_256 */
+
+#if defined(PSA_WANT_ECC_SECP_R1_384)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1
+#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_R1_384 */
+
+#if defined(PSA_WANT_ECC_SECP_R1_521)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1
+#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_R1_521 */
+
+#if defined(PSA_WANT_ECC_SECP_K1_192)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1
+#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_K1_192 */
+
+#if defined(PSA_WANT_ECC_SECP_K1_224)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1
+#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
+/* https://github.com/Mbed-TLS/mbedtls/issues/3541 */
+#error "SECP224K1 is buggy via the PSA API in Mbed TLS."
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_K1_224 */
+
+#if defined(PSA_WANT_ECC_SECP_K1_256)
+#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1
+#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
+#endif /* missing accel */
+#endif /* PSA_WANT_ECC_SECP_K1_256 */
+
+/* ECC: algs: enable built-ins as needed.
+ *
+ * We need the alg built-in:
+ * - if it's not accelerated, or
+ * - if there's a relevant curve (see below) with missing acceleration, or
+ * - if there's a key type among (public, basic) with missing acceleration.
+ *
+ * Relevant curves are:
+ * - all curves for ECDH
+ * - Weierstrass curves for (deterministic) ECDSA
+ * - secp256r1 for EC J-PAKE
+ */
+#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)
+#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_MD_C
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#endif /* missing accel */
+#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */
+
+#if defined(PSA_WANT_ALG_ECDH)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#endif /* missing accel */
+#endif /* PSA_WANT_ALG_ECDH */
+
+#if defined(PSA_WANT_ALG_ECDSA)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_WEIERSTRASS_CURVES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#endif /* missing accel */
+#endif /* PSA_WANT_ALG_ECDSA */
+
+#if defined(PSA_WANT_ALG_JPAKE)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE) || \
+    !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_KEY_TYPES_BASIC)
+#define MBEDTLS_PSA_BUILTIN_PAKE 1
+#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECJPAKE_C
+#endif /* missing accel */
+#endif /* PSA_WANT_ALG_JPAKE */
+
+/* ECC: key types: enable built-ins as needed.
+ *
+ * We need the key type built-in:
+ * - if it's not accelerated, or
+ * - if there's a curve with missing acceleration, or
+ * - only for public/basic: if there's an alg with missing acceleration.
+ */
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
+#endif /* missing accel */
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
+#endif /* missing accel */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
+#endif /* missing accel */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
+#endif /* missing accel */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+#endif /* missing accel */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+
+/* Note: the condition is always true as DERIVE can't be accelerated yet */
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \
+    defined(MBEDTLS_PSA_ECC_ACCEL_INCOMPLETE_CURVES)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
+#endif /* missing accel */
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#define MBEDTLS_ECP_LIGHT
+#define MBEDTLS_BIGNUM_C
+#endif
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+#define MBEDTLS_ECP_C
+#define MBEDTLS_BIGNUM_C
+#endif
+
+/* End of ECC section */
+
+/*
+ * DH key types follow the same pattern used above for EC keys. They are defined
+ * by a triplet (group, key_type, alg). A triplet is accelerated if all its
+ * component are accelerated, otherwise each component needs to be builtin.
+ */
+
+/* DH: groups: is acceleration complete? */
+#if (defined(PSA_WANT_DH_RFC7919_2048) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048)) || \
+    (defined(PSA_WANT_DH_RFC7919_3072) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072)) || \
+    (defined(PSA_WANT_DH_RFC7919_4096) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096)) || \
+    (defined(PSA_WANT_DH_RFC7919_6144) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144)) || \
+    (defined(PSA_WANT_DH_RFC7919_8192) && !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192))
+#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS
+#endif
+
+/* DH: algs: is acceleration complete? */
+#if defined(PSA_WANT_ALG_FFDH) && !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH)
+#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS
+#endif
+
+/* DH: key types: is acceleration complete? */
+#if (defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY)) || \
+    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC)) || \
+    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT)) || \
+    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT)) || \
+    (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) && \
+    !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE))
+#define MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES
+#endif
+
+#if defined(PSA_WANT_DH_RFC7919_2048)
+#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_2048) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1
+#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
+#endif /* PSA_WANT_DH_RFC7919_2048 */
+
+#if defined(PSA_WANT_DH_RFC7919_3072)
+#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_3072) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1
+#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
+#endif /* PSA_WANT_DH_RFC7919_3072 */
+
+#if defined(PSA_WANT_DH_RFC7919_4096)
+#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_4096) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1
+#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
+#endif /* PSA_WANT_DH_RFC7919_4096 */
+
+#if defined(PSA_WANT_DH_RFC7919_6144)
+#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_6144) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1
+#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
+#endif /* PSA_WANT_DH_RFC7919_6144 */
+
+#if defined(PSA_WANT_DH_RFC7919_8192)
+#if !defined(MBEDTLS_PSA_ACCEL_DH_RFC7919_8192) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1
+#endif /* !MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
+#endif /* PSA_WANT_DH_RFC7919_8192 */
+
+#if defined(PSA_WANT_ALG_FFDH)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_FFDH) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_KEY_TYPES)
+#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1
+#define MBEDTLS_BIGNUM_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_FFDH */
+#endif /* PSA_WANT_ALG_FFDH */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_IMPORT */
+#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_EXPORT */
+#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_GENERATE */
+#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_KEY_PAIR_BASIC */
+#endif /* PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_GROUPS) || \
+    defined(MBEDTLS_PSA_DH_ACCEL_INCOMPLETE_ALGS)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1
+#define MBEDTLS_BIGNUM_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DH_PUBLIC_KEY */
+#endif /* PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY */
+
+/* End of DH section */
+
+#if defined(PSA_WANT_ALG_HKDF)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)
+/*
+ * The PSA implementation has its own implementation of HKDF, separate from
+ * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
+ */
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
+#endif /* PSA_WANT_ALG_HKDF */
+
+#if defined(PSA_WANT_ALG_HKDF_EXTRACT)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)
+/*
+ * The PSA implementation has its own implementation of HKDF, separate from
+ * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
+ */
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */
+#endif /* PSA_WANT_ALG_HKDF_EXTRACT */
+
+#if defined(PSA_WANT_ALG_HKDF_EXPAND)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)
+/*
+ * The PSA implementation has its own implementation of HKDF, separate from
+ * hkdf.c. No need to enable MBEDTLS_HKDF_C here.
+ */
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */
+#endif /* PSA_WANT_ALG_HKDF_EXPAND */
+
+#if defined(PSA_WANT_ALG_HMAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
+#endif /* PSA_WANT_ALG_HMAC */
+
+#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
+#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
+#define MBEDTLS_MD5_C
+#endif
+
+#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
+#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
+#define MBEDTLS_RIPEMD160_C
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_OAEP)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V21
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */
+#endif /* PSA_WANT_ALG_RSA_OAEP */
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V15
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */
+#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V15
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */
+#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
+
+#if defined(PSA_WANT_ALG_RSA_PSS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_PKCS1_V21
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */
+#endif /* PSA_WANT_ALG_RSA_PSS */
+
+#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
+#define MBEDTLS_SHA1_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
+#define MBEDTLS_SHA224_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
+#define MBEDTLS_SHA256_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
+#define MBEDTLS_SHA384_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
+#define MBEDTLS_SHA512_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA3_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_224)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1
+#define MBEDTLS_SHA3_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA3_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_256)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1
+#define MBEDTLS_SHA3_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA3_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_384)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1
+#define MBEDTLS_SHA3_C
+#endif
+
+#if defined(PSA_WANT_ALG_SHA3_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA3_512)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1
+#define MBEDTLS_SHA3_C
+#endif
+
+#if defined(PSA_WANT_ALG_PBKDF2_HMAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC)
+#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC 1
+#define PSA_HAVE_SOFT_PBKDF2_HMAC 1
+#endif /* !MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
+#endif /* PSA_WANT_ALG_PBKDF2_HMAC */
+
+#if defined(PSA_WANT_ALG_TLS12_PRF)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */
+#endif /* PSA_WANT_ALG_TLS12_PRF */
+
+#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */
+#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */
+
+#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */
+#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
+#define MBEDTLS_GENPRIME
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
+#define MBEDTLS_RSA_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_OID_C
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */
+#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
+
+/* If any of the block modes are requested that don't have an
+ * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking
+ * in the block cipher key types. */
+#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \
+    (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \
+    (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \
+    (defined(PSA_WANT_ALG_ECB_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)) || \
+    (defined(PSA_WANT_ALG_CBC_NO_PADDING) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \
+    (defined(PSA_WANT_ALG_CBC_PKCS7) && !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \
+    (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC))
+#define PSA_HAVE_SOFT_BLOCK_MODE 1
+#endif
+
+#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128)
+#define MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 1
+#define PSA_HAVE_SOFT_PBKDF2_CMAC 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128 */
+#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */
+
+#if defined(PSA_WANT_KEY_TYPE_AES)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
+#define PSA_HAVE_SOFT_KEY_TYPE_AES 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_BLOCK_MODE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
+#define MBEDTLS_AES_C
+#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */
+#endif /* PSA_WANT_KEY_TYPE_AES */
+
+#if defined(PSA_WANT_KEY_TYPE_ARIA)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)
+#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_BLOCK_MODE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
+#define MBEDTLS_ARIA_C
+#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */
+#endif /* PSA_WANT_KEY_TYPE_ARIA */
+
+#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
+#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \
+    defined(PSA_HAVE_SOFT_BLOCK_MODE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
+#define MBEDTLS_CAMELLIA_C
+#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */
+#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */
+
+#if defined(PSA_WANT_KEY_TYPE_DES)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES)
+#define PSA_HAVE_SOFT_KEY_TYPE_DES 1
+#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
+    defined(PSA_HAVE_SOFT_BLOCK_MODE)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
+#define MBEDTLS_DES_C
+#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */
+#endif /* PSA_WANT_KEY_TYPE_DES */
+
+#if defined(PSA_WANT_ALG_STREAM_CIPHER)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
+#endif /* MBEDTLS_PSA_ACCEL_ALG_STREAM_CIPHER */
+#endif /* PSA_WANT_ALG_STREAM_CIPHER */
+
+#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
+#define MBEDTLS_CHACHA20_C
+#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */
+#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
+
+/* If any of the software block ciphers are selected, define
+ * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these
+ * situations. */
+#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
+#define PSA_HAVE_SOFT_BLOCK_CIPHER 1
+#endif
+
+#if defined(PSA_WANT_ALG_CBC_MAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC)
+#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS."
+#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */
+#endif /* PSA_WANT_ALG_CBC_MAC */
+
+#if defined(PSA_WANT_ALG_CMAC)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1
+#define MBEDTLS_CMAC_C
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */
+#endif /* PSA_WANT_ALG_CMAC */
+
+#if defined(PSA_HAVE_SOFT_PBKDF2_HMAC) || \
+    defined(PSA_HAVE_SOFT_PBKDF2_CMAC)
+#define PSA_HAVE_SOFT_PBKDF2 1
+#endif /* PSA_HAVE_SOFT_PBKDF2_HMAC || PSA_HAVE_SOFT_PBKDF2_CMAC */
+
+#if defined(PSA_WANT_ALG_CTR)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
+#define MBEDTLS_CIPHER_MODE_CTR
+#endif
+#endif /* PSA_WANT_ALG_CTR */
+
+#if defined(PSA_WANT_ALG_CFB)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
+#define MBEDTLS_CIPHER_MODE_CFB
+#endif
+#endif /* PSA_WANT_ALG_CFB */
+
+#if defined(PSA_WANT_ALG_OFB)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
+#define MBEDTLS_CIPHER_MODE_OFB
+#endif
+#endif /* PSA_WANT_ALG_OFB */
+
+#if defined(PSA_WANT_ALG_ECB_NO_PADDING) &&     \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
+#endif
+
+#if defined(PSA_WANT_ALG_CBC_NO_PADDING)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
+#endif
+#endif /* PSA_WANT_ALG_CBC_NO_PADDING */
+
+#if defined(PSA_WANT_ALG_CBC_PKCS7)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \
+    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
+#define MBEDTLS_CIPHER_MODE_CBC
+#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
+#define MBEDTLS_CIPHER_PADDING_PKCS7
+#endif
+#endif /* PSA_WANT_ALG_CBC_PKCS7 */
+
+#if defined(PSA_WANT_ALG_CCM)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
+#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
+#define MBEDTLS_CCM_C
+#endif
+#endif /* PSA_WANT_ALG_CCM */
+
+#if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM_STAR_NO_TAG) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
+#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1
+#define MBEDTLS_CCM_C
+#endif
+#endif /* PSA_WANT_ALG_CCM_STAR_NO_TAG */
+
+#if defined(PSA_WANT_ALG_GCM)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
+    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
+#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1
+#define MBEDTLS_GCM_C
+#endif
+#endif /* PSA_WANT_ALG_GCM */
+
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305)
+#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
+#define MBEDTLS_CHACHAPOLY_C
+#define MBEDTLS_CHACHA20_C
+#define MBEDTLS_POLY1305_C
+#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
+#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
+#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+
+#endif /* MBEDTLS_CONFIG_ADJUST_LEGACY_FROM_PSA_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h
new file mode 100644
index 0000000000000000000000000000000000000000..14ca14696f7dd43380de9d9eed497d6118eb079d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h
@@ -0,0 +1,359 @@
+/**
+ * \file mbedtls/config_adjust_psa_from_legacy.h
+ * \brief Adjust PSA configuration: construct PSA configuration from legacy
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * When MBEDTLS_PSA_CRYPTO_CONFIG is disabled, we automatically enable
+ * cryptographic mechanisms through the PSA interface when the corresponding
+ * legacy mechanism is enabled. In many cases, this just enables the PSA
+ * wrapper code around the legacy implementation, but we also do this for
+ * some mechanisms where PSA has its own independent implementation so
+ * that high-level modules that can use either cryptographic API have the
+ * same feature set in both cases.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
+#define MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/*
+ * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
+ * is not defined
+ */
+
+#if defined(MBEDTLS_CCM_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
+#define PSA_WANT_ALG_CCM 1
+#if defined(MBEDTLS_CIPHER_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1
+#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1
+#endif /* MBEDTLS_CIPHER_C */
+#endif /* MBEDTLS_CCM_C */
+
+#if defined(MBEDTLS_CMAC_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1
+#define PSA_WANT_ALG_CMAC 1
+#endif /* MBEDTLS_CMAC_C */
+
+#if defined(MBEDTLS_ECDH_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
+#define PSA_WANT_ALG_ECDH 1
+#endif /* MBEDTLS_ECDH_C */
+
+#if defined(MBEDTLS_ECDSA_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
+#define PSA_WANT_ALG_ECDSA 1
+#define PSA_WANT_ALG_ECDSA_ANY 1
+
+// Only add in DETERMINISTIC support if ECDSA is also enabled
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
+#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
+#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
+
+#endif /* MBEDTLS_ECDSA_C */
+
+#if defined(MBEDTLS_ECP_C)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+/* Normally we wouldn't enable this because it's not implemented in ecp.c,
+ * but since it used to be available any time ECP_C was enabled, let's enable
+ * it anyway for the sake of backwards compatibility */
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+/* See comment for PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE above. */
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
+#endif /* MBEDTLS_ECP_C */
+
+#if defined(MBEDTLS_DHM_C)
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1
+#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1
+#define PSA_WANT_ALG_FFDH 1
+#define PSA_WANT_DH_RFC7919_2048 1
+#define PSA_WANT_DH_RFC7919_3072 1
+#define PSA_WANT_DH_RFC7919_4096 1
+#define PSA_WANT_DH_RFC7919_6144 1
+#define PSA_WANT_DH_RFC7919_8192 1
+#define MBEDTLS_PSA_BUILTIN_ALG_FFDH 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_BASIC 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY 1
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 1
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 1
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 1
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 1
+#define MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 1
+#endif /* MBEDTLS_DHM_C */
+
+#if defined(MBEDTLS_GCM_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1
+#define PSA_WANT_ALG_GCM 1
+#endif /* MBEDTLS_GCM_C */
+
+/* Enable PSA HKDF algorithm if mbedtls HKDF is supported.
+ * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when
+ * PSA HKDF is enabled, so enable both algorithms together
+ * with PSA HKDF. */
+#if defined(MBEDTLS_HKDF_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+#define PSA_WANT_ALG_HMAC 1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
+#define PSA_WANT_ALG_HKDF 1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
+#define PSA_WANT_ALG_HKDF_EXTRACT 1
+#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
+#define PSA_WANT_ALG_HKDF_EXPAND 1
+#endif /* MBEDTLS_HKDF_C */
+
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+#define PSA_WANT_ALG_HMAC 1
+#define PSA_WANT_KEY_TYPE_HMAC 1
+
+#if defined(MBEDTLS_MD_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
+#define PSA_WANT_ALG_TLS12_PRF 1
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
+#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
+#endif /* MBEDTLS_MD_C */
+
+#if defined(MBEDTLS_MD5_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
+#define PSA_WANT_ALG_MD5 1
+#endif
+
+#if defined(MBEDTLS_ECJPAKE_C)
+#define MBEDTLS_PSA_BUILTIN_PAKE 1
+#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
+#define PSA_WANT_ALG_JPAKE 1
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
+#define PSA_WANT_ALG_RIPEMD160 1
+#endif
+
+#if defined(MBEDTLS_RSA_C)
+#if defined(MBEDTLS_PKCS1_V15)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
+#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
+#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
+#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1
+#endif /* MBEDTLS_PKCS1_V15 */
+#if defined(MBEDTLS_PKCS1_V21)
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
+#define PSA_WANT_ALG_RSA_OAEP 1
+#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
+#define PSA_WANT_ALG_RSA_PSS 1
+#endif /* MBEDTLS_PKCS1_V21 */
+#if defined(MBEDTLS_GENPRIME)
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
+#endif /* MBEDTLS_GENPRIME */
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
+#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_SHA1_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
+#define PSA_WANT_ALG_SHA_1 1
+#endif
+
+#if defined(MBEDTLS_SHA224_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
+#define PSA_WANT_ALG_SHA_224 1
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
+#define PSA_WANT_ALG_SHA_256 1
+#endif
+
+#if defined(MBEDTLS_SHA384_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
+#define PSA_WANT_ALG_SHA_384 1
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
+#define PSA_WANT_ALG_SHA_512 1
+#endif
+
+#if defined(MBEDTLS_SHA3_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_224 1
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_256 1
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_384 1
+#define MBEDTLS_PSA_BUILTIN_ALG_SHA3_512 1
+#define PSA_WANT_ALG_SHA3_224 1
+#define PSA_WANT_ALG_SHA3_256 1
+#define PSA_WANT_ALG_SHA3_384 1
+#define PSA_WANT_ALG_SHA3_512 1
+#endif
+
+#if defined(MBEDTLS_AES_C)
+#define PSA_WANT_KEY_TYPE_AES 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
+#endif
+
+#if defined(MBEDTLS_ARIA_C)
+#define PSA_WANT_KEY_TYPE_ARIA 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
+#endif
+
+#if defined(MBEDTLS_CAMELLIA_C)
+#define PSA_WANT_KEY_TYPE_CAMELLIA 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
+#endif
+
+#if defined(MBEDTLS_DES_C)
+#define PSA_WANT_KEY_TYPE_DES 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
+#endif
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
+#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+#define PSA_WANT_KEY_TYPE_CHACHA20 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
+/* ALG_STREAM_CIPHER requires CIPHER_C in order to be supported in PSA */
+#if defined(MBEDTLS_CIPHER_C)
+#define PSA_WANT_ALG_STREAM_CIPHER 1
+#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
+#endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+#define PSA_WANT_ALG_CHACHA20_POLY1305 1
+#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
+#endif
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
+#define PSA_WANT_ALG_CBC_NO_PADDING 1
+#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
+#define PSA_WANT_ALG_CBC_PKCS7 1
+#endif
+#endif
+
+#if (defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \
+    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)) && \
+    defined(MBEDTLS_CIPHER_C)
+#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
+#define PSA_WANT_ALG_ECB_NO_PADDING 1
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CFB)
+#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
+#define PSA_WANT_ALG_CFB 1
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_CTR)
+#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
+#define PSA_WANT_ALG_CTR 1
+#endif
+
+#if defined(MBEDTLS_CIPHER_MODE_OFB)
+#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
+#define PSA_WANT_ALG_OFB 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1
+#define PSA_WANT_ECC_MONTGOMERY_255 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
+#define PSA_WANT_ECC_MONTGOMERY_448 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1
+#define PSA_WANT_ECC_SECP_R1_192 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1
+#define PSA_WANT_ECC_SECP_R1_224 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
+#define PSA_WANT_ECC_SECP_R1_256 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1
+#define PSA_WANT_ECC_SECP_R1_384 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1
+#define PSA_WANT_ECC_SECP_R1_521 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1
+#define PSA_WANT_ECC_SECP_K1_192 1
+#endif
+
+/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */
+#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1
+#define PSA_WANT_ECC_SECP_K1_224 1
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1
+#define PSA_WANT_ECC_SECP_K1_256 1
+#endif
+
+#endif /* MBEDTLS_CONFIG_ADJUST_PSA_FROM_LEGACY_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef65cce0d9aef1f2d42b9f6ff783c4cd7245f360
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h
@@ -0,0 +1,152 @@
+/**
+ * \file mbedtls/config_adjust_psa_superset_legacy.h
+ * \brief Adjust PSA configuration: automatic enablement from legacy
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * To simplify some edge cases, we automatically enable certain cryptographic
+ * mechanisms in the PSA API if they are enabled in the legacy API. The general
+ * idea is that if legacy module M uses mechanism A internally, and A has
+ * both a legacy and a PSA implementation, we enable A through PSA whenever
+ * it's enabled through legacy. This facilitates the transition to PSA
+ * implementations of A for users of M.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
+#define MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/****************************************************************/
+/* Hashes that are built in are also enabled in PSA.
+ * This simplifies dependency declarations especially
+ * for modules that obey MBEDTLS_USE_PSA_CRYPTO. */
+/****************************************************************/
+
+#if defined(MBEDTLS_MD5_C)
+#define PSA_WANT_ALG_MD5 1
+#endif
+
+#if defined(MBEDTLS_RIPEMD160_C)
+#define PSA_WANT_ALG_RIPEMD160 1
+#endif
+
+#if defined(MBEDTLS_SHA1_C)
+#define PSA_WANT_ALG_SHA_1 1
+#endif
+
+#if defined(MBEDTLS_SHA224_C)
+#define PSA_WANT_ALG_SHA_224 1
+#endif
+
+#if defined(MBEDTLS_SHA256_C)
+#define PSA_WANT_ALG_SHA_256 1
+#endif
+
+#if defined(MBEDTLS_SHA384_C)
+#define PSA_WANT_ALG_SHA_384 1
+#endif
+
+#if defined(MBEDTLS_SHA512_C)
+#define PSA_WANT_ALG_SHA_512 1
+#endif
+
+#if defined(MBEDTLS_SHA3_C)
+#define PSA_WANT_ALG_SHA3_224 1
+#define PSA_WANT_ALG_SHA3_256 1
+#define PSA_WANT_ALG_SHA3_384 1
+#define PSA_WANT_ALG_SHA3_512 1
+#endif
+
+/* Ensure that the PSA's supported curves (PSA_WANT_ECC_xxx) are always a
+ * superset of the builtin ones (MBEDTLS_ECP_DP_xxx). */
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */
+#endif /*MBEDTLS_ECP_DP_BP384R1_ENABLED  */
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#if !defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1
+#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+#if !defined(PSA_WANT_ECC_MONTGOMERY_255)
+#define PSA_WANT_ECC_MONTGOMERY_255 1
+#endif /* PSA_WANT_ECC_MONTGOMERY_255 */
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#if !defined(PSA_WANT_ECC_MONTGOMERY_448)
+#define PSA_WANT_ECC_MONTGOMERY_448 1
+#endif /* PSA_WANT_ECC_MONTGOMERY_448 */
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_R1_192)
+#define PSA_WANT_ECC_SECP_R1_192 1
+#endif /* PSA_WANT_ECC_SECP_R1_192 */
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_R1_224)
+#define PSA_WANT_ECC_SECP_R1_224 1
+#endif /* PSA_WANT_ECC_SECP_R1_224 */
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_R1_256)
+#define PSA_WANT_ECC_SECP_R1_256 1
+#endif /* PSA_WANT_ECC_SECP_R1_256 */
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_R1_384)
+#define PSA_WANT_ECC_SECP_R1_384 1
+#endif /* PSA_WANT_ECC_SECP_R1_384 */
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_R1_521)
+#define PSA_WANT_ECC_SECP_R1_521 1
+#endif /* PSA_WANT_ECC_SECP_R1_521 */
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_K1_192)
+#define PSA_WANT_ECC_SECP_K1_192 1
+#endif /* PSA_WANT_ECC_SECP_K1_192 */
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */
+#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_K1_224)
+#define PSA_WANT_ECC_SECP_K1_224 1
+#endif /* PSA_WANT_ECC_SECP_K1_224 */
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#if !defined(PSA_WANT_ECC_SECP_K1_256)
+#define PSA_WANT_ECC_SECP_K1_256 1
+#endif /* PSA_WANT_ECC_SECP_K1_256 */
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+#endif /* MBEDTLS_CONFIG_ADJUST_PSA_SUPERSET_LEGACY_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_ssl.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_ssl.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f82d9c006c0fb3b46c8a649c619e34ebe78ab8e
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_ssl.h
@@ -0,0 +1,91 @@
+/**
+ * \file mbedtls/config_adjust_ssl.h
+ * \brief Adjust TLS configuration
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * Automatically enable certain dependencies. Generally, MBEDTLS_xxx
+ * configurations need to be explicitly enabled by the user: enabling
+ * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
+ * compilation error. However, we do automatically enable certain options
+ * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option
+ * used to identify parts of a module that are used by other module, and we
+ * don't want to make the symbol MBEDTLS_xxx_B part of the public API.
+ * Another case is if A didn't depend on B in earlier versions, and we
+ * want to use B in A but we need to preserve backward compatibility with
+ * configurations that explicitly activate MBEDTLS_xxx_A but not
+ * MBEDTLS_xxx_B.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_SSL_H
+#define MBEDTLS_CONFIG_ADJUST_SSL_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/* The following blocks make it easier to disable all of TLS,
+ * or of TLS 1.2 or 1.3 or DTLS, without having to manually disable all
+ * key exchanges, options and extensions related to them. */
+
+#if !defined(MBEDTLS_SSL_TLS_C)
+#undef MBEDTLS_SSL_CLI_C
+#undef MBEDTLS_SSL_SRV_C
+#undef MBEDTLS_SSL_PROTO_TLS1_3
+#undef MBEDTLS_SSL_PROTO_TLS1_2
+#undef MBEDTLS_SSL_PROTO_DTLS
+#endif
+
+#if !(defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS))
+#undef MBEDTLS_SSL_TICKET_C
+#endif
+
+#if !defined(MBEDTLS_SSL_PROTO_DTLS)
+#undef MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#undef MBEDTLS_SSL_DTLS_CONNECTION_ID
+#undef MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT
+#undef MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#undef MBEDTLS_SSL_DTLS_SRTP
+#undef MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE
+#endif
+
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_2)
+#undef MBEDTLS_SSL_ENCRYPT_THEN_MAC
+#undef MBEDTLS_SSL_EXTENDED_MASTER_SECRET
+#undef MBEDTLS_SSL_RENEGOTIATION
+#undef MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED
+#undef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+#endif
+
+#if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
+#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED
+#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED
+#undef MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED
+#undef MBEDTLS_SSL_EARLY_DATA
+#undef MBEDTLS_SSL_RECORD_SIZE_LIMIT
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))
+#define MBEDTLS_SSL_TLS1_2_SOME_ECC
+#endif
+
+#endif /* MBEDTLS_CONFIG_ADJUST_SSL_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_x509.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_x509.h
new file mode 100644
index 0000000000000000000000000000000000000000..cfb2d889164efc752f1951aeb0f32428db38650c
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_adjust_x509.h
@@ -0,0 +1,35 @@
+/**
+ * \file mbedtls/config_adjust_x509.h
+ * \brief Adjust X.509 configuration
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * Automatically enable certain dependencies. Generally, MBEDTLS_xxx
+ * configurations need to be explicitly enabled by the user: enabling
+ * MBEDTLS_xxx_A but not MBEDTLS_xxx_B when A requires B results in a
+ * compilation error. However, we do automatically enable certain options
+ * in some circumstances. One case is if MBEDTLS_xxx_B is an internal option
+ * used to identify parts of a module that are used by other module, and we
+ * don't want to make the symbol MBEDTLS_xxx_B part of the public API.
+ * Another case is if A didn't depend on B in earlier versions, and we
+ * want to use B in A but we need to preserve backward compatibility with
+ * configurations that explicitly activate MBEDTLS_xxx_A but not
+ * MBEDTLS_xxx_B.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONFIG_ADJUST_X509_H
+#define MBEDTLS_CONFIG_ADJUST_X509_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include mbedtls/config_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+#endif /* MBEDTLS_CONFIG_ADJUST_X509_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h b/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h
index cedce1e7f87964f33884481c4e4bb86a8bd128b1..5f3d0f3d5d7f692afd02abda83f5057e4602f6b5 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/config_psa.h
@@ -12,855 +12,50 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CONFIG_PSA_H
 #define MBEDTLS_CONFIG_PSA_H
 
-#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
-#if defined(MBEDTLS_PSA_CRYPTO_CONFIG_FILE)
-#include MBEDTLS_PSA_CRYPTO_CONFIG_FILE
-#else
-#include "psa/crypto_config.h"
-#endif
-#endif /* defined(MBEDTLS_PSA_CRYPTO_CONFIG) */
-
-#if defined(MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE)
-#include MBEDTLS_PSA_CRYPTO_USER_CONFIG_FILE
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-
-/****************************************************************/
-/* De facto synonyms */
-/****************************************************************/
-
-#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA)
-#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY
-#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA)
-#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA
-#endif
-
-#if defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && !defined(PSA_WANT_ALG_CCM)
-#define PSA_WANT_ALG_CCM PSA_WANT_ALG_CCM_STAR_NO_TAG
-#elif !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && defined(PSA_WANT_ALG_CCM)
-#define PSA_WANT_ALG_CCM_STAR_NO_TAG PSA_WANT_ALG_CCM
-#endif
-
-#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
-#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW
-#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
-#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN
-#endif
-
-#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS)
-#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT
-#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS)
-#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS
-#endif
+#include "psa/crypto_legacy.h"
 
+#include "psa/crypto_adjust_config_synonyms.h"
 
+#include "psa/crypto_adjust_config_dependencies.h"
 
-/****************************************************************/
-/* Require built-in implementations based on PSA requirements */
-/****************************************************************/
+#include "mbedtls/config_adjust_psa_superset_legacy.h"
 
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
 
-#if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA)
-#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
-#define MBEDTLS_ECDSA_DETERMINISTIC
-#define MBEDTLS_ECDSA_C
-#define MBEDTLS_HMAC_DRBG_C
-#define MBEDTLS_MD_C
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_DETERMINISTIC_ECDSA */
-#endif /* PSA_WANT_ALG_DETERMINISTIC_ECDSA */
-
-#if defined(PSA_WANT_ALG_ECDH)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDH)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
-#define MBEDTLS_ECDH_C
-#define MBEDTLS_ECP_C
-#define MBEDTLS_BIGNUM_C
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDH */
-#endif /* PSA_WANT_ALG_ECDH */
-
-#if defined(PSA_WANT_ALG_ECDSA)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_ECDSA)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
-#define MBEDTLS_ECDSA_C
-#define MBEDTLS_ECP_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_ASN1_WRITE_C
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_ECDSA */
-#endif /* PSA_WANT_ALG_ECDSA */
-
-#if defined(PSA_WANT_ALG_HKDF)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF */
-#endif /* PSA_WANT_ALG_HKDF */
-
-#if defined(PSA_WANT_ALG_HKDF_EXTRACT)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT */
-#endif /* PSA_WANT_ALG_HKDF_EXTRACT */
-
-#if defined(PSA_WANT_ALG_HKDF_EXPAND)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND */
-#endif /* PSA_WANT_ALG_HKDF_EXPAND */
-
-#if defined(PSA_WANT_ALG_HMAC)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_HMAC)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_HMAC */
-#endif /* PSA_WANT_ALG_HMAC */
-
-#if defined(PSA_WANT_ALG_MD5) && !defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
-#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
-#define MBEDTLS_MD5_C
-#endif
-
-#if defined(PSA_WANT_ALG_JPAKE)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_JPAKE)
-#define MBEDTLS_PSA_BUILTIN_PAKE 1
-#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_ECP_C
-#define MBEDTLS_ECJPAKE_C
-#endif /* MBEDTLS_PSA_ACCEL_ALG_JPAKE */
-#endif /* PSA_WANT_ALG_JPAKE */
-
-#if defined(PSA_WANT_ALG_RIPEMD160) && !defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
-#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
-#define MBEDTLS_RIPEMD160_C
-#endif
-
-#if defined(PSA_WANT_ALG_RSA_OAEP)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS1_V21
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_OAEP */
-#endif /* PSA_WANT_ALG_RSA_OAEP */
-
-#if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS1_V15
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_CRYPT */
-#endif /* PSA_WANT_ALG_RSA_PKCS1V15_CRYPT */
-
-#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS1_V15
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PKCS1V15_SIGN */
-#endif /* PSA_WANT_ALG_RSA_PKCS1V15_SIGN */
-
-#if defined(PSA_WANT_ALG_RSA_PSS)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_RSA_PSS)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PKCS1_V21
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_RSA_PSS */
-#endif /* PSA_WANT_ALG_RSA_PSS */
-
-#if defined(PSA_WANT_ALG_SHA_1) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
-#define MBEDTLS_SHA1_C
-#endif
-
-#if defined(PSA_WANT_ALG_SHA_224) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
-#define MBEDTLS_SHA224_C
-#endif
-
-#if defined(PSA_WANT_ALG_SHA_256) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
-#define MBEDTLS_SHA256_C
-#endif
-
-#if defined(PSA_WANT_ALG_SHA_384) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
-#define MBEDTLS_SHA384_C
-#endif
-
-#if defined(PSA_WANT_ALG_SHA_512) && !defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
-#define MBEDTLS_SHA512_C
-#endif
-
-#if defined(PSA_WANT_ALG_TLS12_PRF)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF */
-#endif /* PSA_WANT_ALG_TLS12_PRF */
-
-#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS */
-#endif /* PSA_WANT_ALG_TLS12_PSK_TO_MS */
-
-#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS)
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_TLS12_ECJPAKE_TO_PMS */
-#endif /* PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS */
-
-#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
-#define MBEDTLS_ECP_C
-#define MBEDTLS_BIGNUM_C
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR */
-#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */
-
-#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
-#define MBEDTLS_ECP_C
-#define MBEDTLS_BIGNUM_C
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY */
-#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
-
-#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_GENPRIME
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_PK_WRITE_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_ASN1_WRITE_C
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR */
-#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
-
-#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
-#define MBEDTLS_RSA_C
-#define MBEDTLS_BIGNUM_C
-#define MBEDTLS_OID_C
-#define MBEDTLS_PK_PARSE_C
-#define MBEDTLS_PK_WRITE_C
-#define MBEDTLS_PK_C
-#define MBEDTLS_ASN1_PARSE_C
-#define MBEDTLS_ASN1_WRITE_C
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_PUBLIC_KEY */
-#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
-
-/* If any of the block modes are requested that don't have an
- * associated HW assist, define PSA_HAVE_SOFT_BLOCK_MODE for checking
- * in the block cipher key types. */
-#if (defined(PSA_WANT_ALG_CTR) && !defined(MBEDTLS_PSA_ACCEL_ALG_CTR)) || \
-    (defined(PSA_WANT_ALG_CFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_CFB)) || \
-    (defined(PSA_WANT_ALG_OFB) && !defined(MBEDTLS_PSA_ACCEL_ALG_OFB)) || \
-    defined(PSA_WANT_ALG_ECB_NO_PADDING) || \
-    (defined(PSA_WANT_ALG_CBC_NO_PADDING) && \
-    !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING)) || \
-    (defined(PSA_WANT_ALG_CBC_PKCS7) && \
-    !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7)) || \
-    (defined(PSA_WANT_ALG_CMAC) && !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC))
-#define PSA_HAVE_SOFT_BLOCK_MODE 1
-#endif
-
-#if (defined(PSA_WANT_ALG_GCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_GCM)) || \
-    (defined(PSA_WANT_ALG_CCM) && !defined(MBEDTLS_PSA_ACCEL_ALG_CCM))
-#define PSA_HAVE_SOFT_BLOCK_AEAD 1
-#endif
-
-#if defined(PSA_WANT_KEY_TYPE_AES)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_AES)
-#define PSA_HAVE_SOFT_KEY_TYPE_AES 1
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_AES */
-#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
-    defined(PSA_HAVE_SOFT_BLOCK_MODE) || \
-    defined(PSA_HAVE_SOFT_BLOCK_AEAD)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
-#define MBEDTLS_AES_C
-#endif /* PSA_HAVE_SOFT_KEY_TYPE_AES || PSA_HAVE_SOFT_BLOCK_MODE */
-#endif /* PSA_WANT_KEY_TYPE_AES */
-
-#if defined(PSA_WANT_KEY_TYPE_ARIA)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA)
-#define PSA_HAVE_SOFT_KEY_TYPE_ARIA 1
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_ARIA */
-#if defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
-    defined(PSA_HAVE_SOFT_BLOCK_MODE) || \
-    defined(PSA_HAVE_SOFT_BLOCK_AEAD)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
-#define MBEDTLS_ARIA_C
-#endif /* PSA_HAVE_SOFT_KEY_TYPE_ARIA || PSA_HAVE_SOFT_BLOCK_MODE */
-#endif /* PSA_WANT_KEY_TYPE_ARIA */
-
-#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA)
-#define PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA 1
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_CAMELLIA */
-#if defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA) || \
-    defined(PSA_HAVE_SOFT_BLOCK_MODE) || \
-    defined(PSA_HAVE_SOFT_BLOCK_AEAD)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
-#define MBEDTLS_CAMELLIA_C
-#endif /* PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA || PSA_HAVE_SOFT_BLOCK_MODE */
-#endif /* PSA_WANT_KEY_TYPE_CAMELLIA */
-
-#if defined(PSA_WANT_KEY_TYPE_DES)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_DES)
-#define PSA_HAVE_SOFT_KEY_TYPE_DES 1
-#endif /* !MBEDTLS_PSA_ACCEL_KEY_TYPE_DES */
-#if defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
-    defined(PSA_HAVE_SOFT_BLOCK_MODE)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
-#define MBEDTLS_DES_C
-#endif /*PSA_HAVE_SOFT_KEY_TYPE_DES || PSA_HAVE_SOFT_BLOCK_MODE */
-#endif /* PSA_WANT_KEY_TYPE_DES */
-
-#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
-#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
-#define MBEDTLS_CHACHA20_C
-#endif /*!MBEDTLS_PSA_ACCEL_KEY_TYPE_CHACHA20 */
-#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
-
-/* If any of the software block ciphers are selected, define
- * PSA_HAVE_SOFT_BLOCK_CIPHER, which can be used in any of these
- * situations. */
-#if defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_DES) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
-#define PSA_HAVE_SOFT_BLOCK_CIPHER 1
-#endif
-
-#if defined(PSA_WANT_ALG_STREAM_CIPHER)
-#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
-#endif /* PSA_WANT_ALG_STREAM_CIPHER */
-
-#if defined(PSA_WANT_ALG_CBC_MAC)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_MAC)
-#error "CBC-MAC is not yet supported via the PSA API in Mbed TLS."
-#define MBEDTLS_PSA_BUILTIN_ALG_CBC_MAC 1
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_CBC_MAC */
-#endif /* PSA_WANT_ALG_CBC_MAC */
-
-#if defined(PSA_WANT_ALG_CMAC)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CMAC) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1
-#define MBEDTLS_CMAC_C
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_CMAC */
-#endif /* PSA_WANT_ALG_CMAC */
-
-#if defined(PSA_WANT_ALG_CTR)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CTR) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
-#define MBEDTLS_CIPHER_MODE_CTR
-#endif
-#endif /* PSA_WANT_ALG_CTR */
-
-#if defined(PSA_WANT_ALG_CFB)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CFB) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
-#define MBEDTLS_CIPHER_MODE_CFB
-#endif
-#endif /* PSA_WANT_ALG_CFB */
-
-#if defined(PSA_WANT_ALG_OFB)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_OFB) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
-#define MBEDTLS_CIPHER_MODE_OFB
-#endif
-#endif /* PSA_WANT_ALG_OFB */
-
-#if defined(PSA_WANT_ALG_ECB_NO_PADDING) &&     \
-    !defined(MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
-#endif
-
-#if defined(PSA_WANT_ALG_CBC_NO_PADDING)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
-#endif
-#endif /* PSA_WANT_ALG_CBC_NO_PADDING */
-
-#if defined(PSA_WANT_ALG_CBC_PKCS7)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7) || \
-    defined(PSA_HAVE_SOFT_BLOCK_CIPHER)
-#define MBEDTLS_CIPHER_MODE_CBC
-#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
-#define MBEDTLS_CIPHER_PADDING_PKCS7
-#endif
-#endif /* PSA_WANT_ALG_CBC_PKCS7 */
+/* Require built-in implementations based on PSA requirements */
 
-#if defined(PSA_WANT_ALG_CCM)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CCM) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
-#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
-#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1
-#define MBEDTLS_CCM_C
-#endif
-#endif /* PSA_WANT_ALG_CCM */
+/* We need this to have a complete list of requirements
+ * before we deduce what built-ins are required. */
+#include "psa/crypto_adjust_config_key_pair_types.h"
 
-#if defined(PSA_WANT_ALG_GCM)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_GCM) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_AES) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_ARIA) || \
-    defined(PSA_HAVE_SOFT_KEY_TYPE_CAMELLIA)
-#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1
-#define MBEDTLS_GCM_C
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/* If we are implementing PSA crypto ourselves, then we want to enable the
+ * required built-ins. Otherwise, PSA features will be provided by the server. */
+#include "mbedtls/config_adjust_legacy_from_psa.h"
 #endif
-#endif /* PSA_WANT_ALG_GCM */
-
-#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
-#if !defined(MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305)
-#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
-#define MBEDTLS_CHACHAPOLY_C
-#define MBEDTLS_CHACHA20_C
-#define MBEDTLS_POLY1305_C
-#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
-#endif /* PSA_WANT_KEY_TYPE_CHACHA20 */
-#endif /* !MBEDTLS_PSA_ACCEL_ALG_CHACHA20_POLY1305 */
-#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
-
-#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256)
-#define MBEDTLS_ECP_DP_BP256R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_256 */
-#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_256 */
-
-#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384)
-#define MBEDTLS_ECP_DP_BP384R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_384 */
-#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_384 */
-
-#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512)
-#define MBEDTLS_ECP_DP_BP512R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_BRAINPOOL_P_R1_512 */
-#endif /* PSA_WANT_ECC_BRAINPOOL_P_R1_512 */
-
-#if defined(PSA_WANT_ECC_MONTGOMERY_255)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255)
-#define MBEDTLS_ECP_DP_CURVE25519_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_255 */
-#endif /* PSA_WANT_ECC_MONTGOMERY_255 */
-
-#if defined(PSA_WANT_ECC_MONTGOMERY_448)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448)
-#define MBEDTLS_ECP_DP_CURVE448_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_MONTGOMERY_448 */
-#endif /* PSA_WANT_ECC_MONTGOMERY_448 */
-
-#if defined(PSA_WANT_ECC_SECP_R1_192)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192)
-#define MBEDTLS_ECP_DP_SECP192R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_192 */
-#endif /* PSA_WANT_ECC_SECP_R1_192 */
-
-#if defined(PSA_WANT_ECC_SECP_R1_224)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224)
-#define MBEDTLS_ECP_DP_SECP224R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_224 */
-#endif /* PSA_WANT_ECC_SECP_R1_224 */
-
-#if defined(PSA_WANT_ECC_SECP_R1_256)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256)
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256 */
-#endif /* PSA_WANT_ECC_SECP_R1_256 */
-
-#if defined(PSA_WANT_ECC_SECP_R1_384)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384)
-#define MBEDTLS_ECP_DP_SECP384R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_384 */
-#endif /* PSA_WANT_ECC_SECP_R1_384 */
-
-#if defined(PSA_WANT_ECC_SECP_R1_521)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521)
-#define MBEDTLS_ECP_DP_SECP521R1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_R1_521 */
-#endif /* PSA_WANT_ECC_SECP_R1_521 */
-
-#if defined(PSA_WANT_ECC_SECP_K1_192)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192)
-#define MBEDTLS_ECP_DP_SECP192K1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_192 */
-#endif /* PSA_WANT_ECC_SECP_K1_192 */
-
-#if defined(PSA_WANT_ECC_SECP_K1_224)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224)
-/*
- * SECP224K1 is buggy via the PSA API in Mbed TLS
- * (https://github.com/Mbed-TLS/mbedtls/issues/3541).
- */
-#error "SECP224K1 is buggy via the PSA API in Mbed TLS."
-#define MBEDTLS_ECP_DP_SECP224K1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_224 */
-#endif /* PSA_WANT_ECC_SECP_K1_224 */
-
-#if defined(PSA_WANT_ECC_SECP_K1_256)
-#if !defined(MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256)
-#define MBEDTLS_ECP_DP_SECP256K1_ENABLED
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1
-#endif /* !MBEDTLS_PSA_ACCEL_ECC_SECP_K1_256 */
-#endif /* PSA_WANT_ECC_SECP_K1_256 */
-
-
-
-/****************************************************************/
-/* Infer PSA requirements from Mbed TLS capabilities */
-/****************************************************************/
 
 #else /* MBEDTLS_PSA_CRYPTO_CONFIG */
 
-/*
- * Ensure PSA_WANT_* defines are setup properly if MBEDTLS_PSA_CRYPTO_CONFIG
- * is not defined
- */
-
-#if defined(MBEDTLS_CCM_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_CCM 1
-#define MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG 1
-#define PSA_WANT_ALG_CCM 1
-#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1
-#endif /* MBEDTLS_CCM_C */
-
-#if defined(MBEDTLS_CMAC_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_CMAC 1
-#define PSA_WANT_ALG_CMAC 1
-#endif /* MBEDTLS_CMAC_C */
-
-#if defined(MBEDTLS_ECDH_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
-#define PSA_WANT_ALG_ECDH 1
-#endif /* MBEDTLS_ECDH_C */
-
-#if defined(MBEDTLS_ECDSA_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
-#define PSA_WANT_ALG_ECDSA 1
-#define PSA_WANT_ALG_ECDSA_ANY 1
-
-// Only add in DETERMINISTIC support if ECDSA is also enabled
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-#define MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA 1
-#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1
-#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
-
-#endif /* MBEDTLS_ECDSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
-#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
-#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
-#endif /* MBEDTLS_ECP_C */
-
-#if defined(MBEDTLS_GCM_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_GCM 1
-#define PSA_WANT_ALG_GCM 1
-#endif /* MBEDTLS_GCM_C */
-
-/* Enable PSA HKDF algorithm if mbedtls HKDF is supported.
- * PSA HKDF EXTRACT and PSA HKDF EXPAND have minimal cost when
- * PSA HKDF is enabled, so enable both algorithms together
- * with PSA HKDF. */
-#if defined(MBEDTLS_HKDF_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#define PSA_WANT_ALG_HMAC 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF 1
-#define PSA_WANT_ALG_HKDF 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT 1
-#define PSA_WANT_ALG_HKDF_EXTRACT 1
-#define MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND 1
-#define PSA_WANT_ALG_HKDF_EXPAND 1
-#endif /* MBEDTLS_HKDF_C */
-
-#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
-#define PSA_WANT_ALG_HMAC 1
-#define PSA_WANT_KEY_TYPE_HMAC
-
-#if defined(MBEDTLS_MD_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF 1
-#define PSA_WANT_ALG_TLS12_PRF 1
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS 1
-#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1
-#endif /* MBEDTLS_MD_C */
-
-#if defined(MBEDTLS_MD5_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_MD5 1
-#define PSA_WANT_ALG_MD5 1
-#endif
-
-#if defined(MBEDTLS_ECJPAKE_C)
-#define MBEDTLS_PSA_BUILTIN_PAKE 1
-#define MBEDTLS_PSA_BUILTIN_ALG_JPAKE 1
-#define PSA_WANT_ALG_JPAKE 1
-#endif
-
-#if defined(MBEDTLS_RIPEMD160_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160 1
-#define PSA_WANT_ALG_RIPEMD160 1
-#endif
-
-#if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_PKCS1_V15)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT 1
-#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN 1
-#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1
-#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW 1
-#endif /* MBEDTLS_PKCS1_V15 */
-#if defined(MBEDTLS_PKCS1_V21)
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP 1
-#define PSA_WANT_ALG_RSA_OAEP 1
-#define MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS 1
-#define PSA_WANT_ALG_RSA_PSS 1
-#endif /* MBEDTLS_PKCS1_V21 */
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR 1
-#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY 1
-#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_SHA1_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_1 1
-#define PSA_WANT_ALG_SHA_1 1
-#endif
-
-#if defined(MBEDTLS_SHA224_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_224 1
-#define PSA_WANT_ALG_SHA_224 1
-#endif
-
-#if defined(MBEDTLS_SHA256_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_256 1
-#define PSA_WANT_ALG_SHA_256 1
-#endif
-
-#if defined(MBEDTLS_SHA384_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_384 1
-#define PSA_WANT_ALG_SHA_384 1
-#endif
-
-#if defined(MBEDTLS_SHA512_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_SHA_512 1
-#define PSA_WANT_ALG_SHA_512 1
-#endif
-
-#if defined(MBEDTLS_AES_C)
-#define PSA_WANT_KEY_TYPE_AES 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES 1
-#endif
-
-#if defined(MBEDTLS_ARIA_C)
-#define PSA_WANT_KEY_TYPE_ARIA 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA 1
-#endif
-
-#if defined(MBEDTLS_CAMELLIA_C)
-#define PSA_WANT_KEY_TYPE_CAMELLIA 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA 1
-#endif
-
-#if defined(MBEDTLS_DES_C)
-#define PSA_WANT_KEY_TYPE_DES 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES 1
-#endif
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
-#define MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS 1
-#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1
-#endif
-
-#if defined(MBEDTLS_CHACHA20_C)
-#define PSA_WANT_KEY_TYPE_CHACHA20 1
-#define PSA_WANT_ALG_STREAM_CIPHER 1
-#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20 1
-#define MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER 1
-#if defined(MBEDTLS_CHACHAPOLY_C)
-#define PSA_WANT_ALG_CHACHA20_POLY1305 1
-#define MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 1
-#endif
-#endif
-
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#define MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING 1
-#define PSA_WANT_ALG_CBC_NO_PADDING 1
-#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
-#define MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 1
-#define PSA_WANT_ALG_CBC_PKCS7 1
-#endif
-#endif
-
-#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) || \
-    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C)
-#define MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING 1
-#define PSA_WANT_ALG_ECB_NO_PADDING 1
-#endif
-
-#if defined(MBEDTLS_CIPHER_MODE_CFB)
-#define MBEDTLS_PSA_BUILTIN_ALG_CFB 1
-#define PSA_WANT_ALG_CFB 1
-#endif
-
-#if defined(MBEDTLS_CIPHER_MODE_CTR)
-#define MBEDTLS_PSA_BUILTIN_ALG_CTR 1
-#define PSA_WANT_ALG_CTR 1
-#endif
-
-#if defined(MBEDTLS_CIPHER_MODE_OFB)
-#define MBEDTLS_PSA_BUILTIN_ALG_OFB 1
-#define PSA_WANT_ALG_OFB 1
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_256 1
-#define PSA_WANT_ECC_BRAINPOOL_P_R1_256
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_384 1
-#define PSA_WANT_ECC_BRAINPOOL_P_R1_384
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_BRAINPOOL_P_R1_512 1
-#define PSA_WANT_ECC_BRAINPOOL_P_R1_512
-#endif
-
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_255 1
-#define PSA_WANT_ECC_MONTGOMERY_255
-#endif
-
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_MONTGOMERY_448 1
-#define PSA_WANT_ECC_MONTGOMERY_448
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_192 1
-#define PSA_WANT_ECC_SECP_R1_192
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_224 1
-#define PSA_WANT_ECC_SECP_R1_224
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
-#define PSA_WANT_ECC_SECP_R1_256
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_384 1
-#define PSA_WANT_ECC_SECP_R1_384
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_521 1
-#define PSA_WANT_ECC_SECP_R1_521
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_192 1
-#define PSA_WANT_ECC_SECP_K1_192
-#endif
+/* Infer PSA requirements from Mbed TLS capabilities */
 
-/* SECP224K1 is buggy via the PSA API (https://github.com/Mbed-TLS/mbedtls/issues/3541) */
-#if 0 && defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_224 1
-#define PSA_WANT_ECC_SECP_K1_224
-#endif
+#include "mbedtls/config_adjust_psa_from_legacy.h"
 
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-#define MBEDTLS_PSA_BUILTIN_ECC_SECP_K1_256 1
-#define PSA_WANT_ECC_SECP_K1_256
-#endif
+/* Hopefully the file above will have enabled keypair symbols in a consistent
+ * way, but including this here fixes them if that wasn't the case. */
+#include "psa/crypto_adjust_config_key_pair_types.h"
 
 #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
 
-#if defined(PSA_WANT_ALG_ECDSA) && defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \
-    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#define PSA_HAVE_FULL_ECDSA 1
-#endif
-
-#if defined(PSA_WANT_ALG_JPAKE) && defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \
-    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#define PSA_HAVE_FULL_JPAKE 1
+#if defined(PSA_WANT_ALG_JPAKE)
+#define PSA_WANT_ALG_SOME_PAKE 1
 #endif
 
-/* These features are always enabled. */
-#define PSA_WANT_KEY_TYPE_DERIVE 1
-#define PSA_WANT_KEY_TYPE_PASSWORD 1
-#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
-#define PSA_WANT_KEY_TYPE_RAW_DATA 1
-
-#ifdef __cplusplus
-}
-#endif
+#include "psa/crypto_adjust_auto_enabled.h"
 
 #endif /* MBEDTLS_CONFIG_PSA_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h b/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h
index 91a9e7fc3346d3472d70ff75bca9b967dddd34ca..d31bff677e9dd444ce01dec8d526b6bae94592fb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/constant_time.h
@@ -3,19 +3,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CONSTANT_TIME_H
@@ -23,20 +11,22 @@
 
 #include <stddef.h>
 
-
 /** Constant-time buffer comparison without branches.
  *
  * This is equivalent to the standard memcmp function, but is likely to be
- * compiled to code using bitwise operation rather than a branch.
+ * compiled to code using bitwise operations rather than a branch, such that
+ * the time taken is constant w.r.t. the data pointed to by \p a and \p b,
+ * and w.r.t. whether \p a and \p b are equal or not. It is not constant-time
+ * w.r.t. \p n .
  *
  * This function can be used to write constant-time code by replacing branches
  * with bit operations using masks.
  *
- * \param a     Pointer to the first buffer.
- * \param b     Pointer to the second buffer.
- * \param n     The number of bytes to compare in the buffer.
+ * \param a     Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
+ * \param b     Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
+ * \param n     The number of bytes to compare.
  *
- * \return      Zero if the content of the two buffer is the same,
+ * \return      Zero if the contents of the two buffers are the same,
  *              otherwise non-zero.
  */
 int mbedtls_ct_memcmp(const void *a,
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h b/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
index 8d28150d74eef613c5405afa08e9d4f4b3d53893..0b7cce1923428600527efbc35c2b0df59ac30566 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ctr_drbg.h
@@ -23,19 +23,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CTR_DRBG_H
@@ -44,7 +32,30 @@
 
 #include "mbedtls/build_info.h"
 
+/* The CTR_DRBG implementation can either directly call the low-level AES
+ * module (gated by MBEDTLS_AES_C) or call the PSA API to perform AES
+ * operations. Calling the AES module directly is the default, both for
+ * maximum backward compatibility and because it's a bit more efficient
+ * (less glue code).
+ *
+ * When MBEDTLS_AES_C is disabled, the CTR_DRBG module calls PSA crypto and
+ * thus benefits from the PSA AES accelerator driver.
+ * It is technically possible to enable MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO
+ * to use PSA even when MBEDTLS_AES_C is enabled, but there is very little
+ * reason to do so other than testing purposes and this is not officially
+ * supported.
+ */
+#if !defined(MBEDTLS_AES_C)
+#define MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO
+#endif
+
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#else
 #include "mbedtls/aes.h"
+#endif
+
+#include "entropy.h"
 
 #if defined(MBEDTLS_THREADING_C)
 #include "mbedtls/threading.h"
@@ -94,17 +105,14 @@
  * \brief The amount of entropy used per seed by default, in bytes.
  */
 #if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN)
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
-/** This is 48 bytes because the entropy module uses SHA-512
- * (\c MBEDTLS_ENTROPY_FORCE_SHA256 is disabled).
+#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
+/** This is 48 bytes because the entropy module uses SHA-512.
  */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        48
 
-#else /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
 
-/** This is 32 bytes because the entropy module uses SHA-256
- * (the SHA512 module is disabled or
- * \c MBEDTLS_ENTROPY_FORCE_SHA256 is enabled).
+/** This is 32 bytes because the entropy module uses SHA-256.
  */
 #if !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
 /** \warning To achieve a 256-bit security strength, you must pass a nonce
@@ -112,7 +120,7 @@
  */
 #endif /* !defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY) */
 #define MBEDTLS_CTR_DRBG_ENTROPY_LEN        32
-#endif /* defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) */
+#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
 #endif /* !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) */
 
 #if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL)
@@ -164,6 +172,13 @@ extern "C" {
 #define MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN (MBEDTLS_CTR_DRBG_ENTROPY_LEN + 1) / 2
 #endif
 
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+typedef struct mbedtls_ctr_drbg_psa_context {
+    mbedtls_svc_key_id_t key_id;
+    psa_cipher_operation_t operation;
+} mbedtls_ctr_drbg_psa_context;
+#endif
+
 /**
  * \brief          The CTR_DRBG context structure.
  */
@@ -189,7 +204,11 @@ typedef struct mbedtls_ctr_drbg_context {
                                                   * This is the maximum number of requests
                                                   * that can be made between reseedings. */
 
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    mbedtls_ctr_drbg_psa_context MBEDTLS_PRIVATE(psa_ctx); /*!< The PSA context. */
+#else
     mbedtls_aes_context MBEDTLS_PRIVATE(aes_ctx);        /*!< The AES context. */
+#endif
 
     /*
      * Callbacks (Entropy)
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/debug.h b/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
index 2b0d00e4c40c78dd93f59fd753a6274709c434c0..424ed4b3fd985d3bceb7bb6edeba3829483e1dd2 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/debug.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_DEBUG_H
 #define MBEDTLS_DEBUG_H
@@ -131,6 +119,15 @@
 #endif \
     /* (defined(__MINGW32__)  && __USE_MINGW_ANSI_STDIO == 0) || (defined(_MSC_VER) && _MSC_VER < 1800) */
 
+#if !defined(MBEDTLS_PRINTF_MS_TIME)
+#include <inttypes.h>
+#if !defined(PRId64)
+#define MBEDTLS_PRINTF_MS_TIME MBEDTLS_PRINTF_LONGLONG
+#else
+#define MBEDTLS_PRINTF_MS_TIME PRId64
+#endif
+#endif /* MBEDTLS_PRINTF_MS_TIME */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -152,161 +149,8 @@ extern "C" {
  */
 void mbedtls_debug_set_threshold(int threshold);
 
-/**
- * \brief    Print a message to the debug output. This function is always used
- *          through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl
- *          context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the message has occurred in
- * \param line      line number the message has occurred at
- * \param format    format specifier, in printf format
- * \param ...       variables used by the format specifier
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line,
-                             const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6);
-
-/**
- * \brief   Print the return value of a function to the debug output. This
- *          function is always used through the MBEDTLS_SSL_DEBUG_RET() macro,
- *          which supplies the ssl context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param text      the name of the function that returned the error
- * \param ret       the return code value
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line,
-                             const char *text, int ret);
-
-/**
- * \brief   Output a buffer of size len bytes to the debug output. This function
- *          is always used through the MBEDTLS_SSL_DEBUG_BUF() macro,
- *          which supplies the ssl context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param text      a name or label for the buffer being dumped. Normally the
- *                  variable or buffer name
- * \param buf       the buffer to be outputted
- * \param len       length of the buffer
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line, const char *text,
-                             const unsigned char *buf, size_t len);
-
-#if defined(MBEDTLS_BIGNUM_C)
-/**
- * \brief   Print a MPI variable to the debug output. This function is always
- *          used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the
- *          ssl context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param text      a name or label for the MPI being output. Normally the
- *                  variable name
- * \param X         the MPI variable
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line,
-                             const char *text, const mbedtls_mpi *X);
-#endif
-
-#if defined(MBEDTLS_ECP_C)
-/**
- * \brief   Print an ECP point to the debug output. This function is always
- *          used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the
- *          ssl context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param text      a name or label for the ECP point being output. Normally the
- *                  variable name
- * \param X         the ECP point
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line,
-                             const char *text, const mbedtls_ecp_point *X);
-#endif
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
-/**
- * \brief   Print a X.509 certificate structure to the debug output. This
- *          function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro,
- *          which supplies the ssl context, file and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param text      a name or label for the certificate being output
- * \param crt       X.509 certificate structure
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
-                             const char *file, int line,
-                             const char *text, const mbedtls_x509_crt *crt);
-#endif
-
-#if defined(MBEDTLS_ECDH_C)
-typedef enum {
-    MBEDTLS_DEBUG_ECDH_Q,
-    MBEDTLS_DEBUG_ECDH_QP,
-    MBEDTLS_DEBUG_ECDH_Z,
-} mbedtls_debug_ecdh_attr;
-
-/**
- * \brief   Print a field of the ECDH structure in the SSL context to the debug
- *          output. This function is always used through the
- *          MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file
- *          and line number parameters.
- *
- * \param ssl       SSL context
- * \param level     error level of the debug message
- * \param file      file the error has occurred in
- * \param line      line number the error has occurred in
- * \param ecdh      the ECDH context
- * \param attr      the identifier of the attribute being output
- *
- * \attention       This function is intended for INTERNAL usage within the
- *                  library only.
- */
-void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
-                               const char *file, int line,
-                               const mbedtls_ecdh_context *ecdh,
-                               mbedtls_debug_ecdh_attr attr);
-#endif
-
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* debug.h */
+#endif /* MBEDTLS_DEBUG_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/des.h b/lib/libmbedtls/mbedtls/include/mbedtls/des.h
index f445102d9d4c598e56a7ebe6ca0b28f893e88933..2b097a13dd248c16d3384a98d41a5cf20f536248 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/des.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/des.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  *
  */
 #ifndef MBEDTLS_DES_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h b/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
index 6ffe681cabef4e791dfb336e8e8b1c875383ae85..fcba3d2af0cf4f7a50ccbbb38624617039121ae8 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/dhm.h
@@ -45,19 +45,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_DHM_H
@@ -325,7 +313,7 @@ size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx);
  *                 initialized.
  *
  * \return         \c 0 on success.
- * \return         #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p field is invalid.
+ * \return         #MBEDTLS_ERR_DHM_BAD_INPUT_DATA if \p param is invalid.
  * \return         An \c MBEDTLS_ERR_MPI_XXX error code if the copy fails.
  */
 int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
index 67c94f0fae5d2f15a780e1e4b179efb64d26e4fa..a6a5069337503fba735fd520f44df2fa057e93b7 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecdh.h
@@ -14,19 +14,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_ECDH_H
@@ -153,6 +141,19 @@ typedef struct mbedtls_ecdh_context {
 }
 mbedtls_ecdh_context;
 
+/**
+ * \brief          Return the ECP group for provided context.
+ *
+ * \note           To access group specific fields, users should use
+ *                 `mbedtls_ecp_curve_info_from_grp_id` or
+ *                 `mbedtls_ecp_group_load` on the extracted `group_id`.
+ *
+ * \param ctx      The ECDH context to parse. This must not be \c NULL.
+ *
+ * \return         The \c mbedtls_ecp_group_id of the context.
+ */
+mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx);
+
 /**
  * \brief          Check whether a given group can be used for ECDH.
  *
@@ -324,7 +325,7 @@ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
  * \brief           This function sets up an ECDH context from an EC key.
  *
  *                  It is used by clients and servers in place of the
- *                  ServerKeyEchange for static ECDH, and imports ECDH
+ *                  ServerKeyExchange for static ECDH, and imports ECDH
  *                  parameters from the EC key information of a certificate.
  *
  * \see             ecp.h
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
index c5d9701f6ea0dbbb87fcf55a40ae882914358eb9..2ecf349115ed25f509aeb94173ff94bac73dac8b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecdsa.h
@@ -12,19 +12,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_ECDSA_H
@@ -207,8 +195,9 @@ int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
  * \param md_alg        The hash algorithm used to hash the original data.
  * \param f_rng_blind   The RNG function used for blinding. This must not be
  *                      \c NULL.
- * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
- *                      \c NULL if \p f_rng doesn't need a context parameter.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng_blind. This
+ *                      may be \c NULL if \p f_rng_blind doesn't need a context
+ *                      parameter.
  *
  * \return          \c 0 on success.
  * \return          An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX
@@ -288,6 +277,8 @@ int mbedtls_ecdsa_sign_restartable(
     void *p_rng_blind,
     mbedtls_ecdsa_restart_ctx *rs_ctx);
 
+#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
+
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
 
 /**
@@ -321,10 +312,11 @@ int mbedtls_ecdsa_sign_restartable(
  *                      buffer of length \p blen Bytes. It may be \c NULL if
  *                      \p blen is zero.
  * \param blen          The length of \p buf in Bytes.
+ * \param md_alg        The hash algorithm used to hash the original data.
  * \param f_rng_blind   The RNG function used for blinding. This must not be
  *                      \c NULL.
- * \param p_rng_blind   The RNG context to be passed to \p f_rng. This may be
- *                      \c NULL if \p f_rng doesn't need a context parameter.
+ * \param p_rng_blind   The RNG context to be passed to \p f_rng_blind. This may be
+ *                      \c NULL if \p f_rng_blind doesn't need a context parameter.
  * \param rs_ctx        The restart context to use. This may be \c NULL
  *                      to disable restarting. If it is not \c NULL, it
  *                      must point to an initialized restart context.
@@ -348,8 +340,6 @@ int mbedtls_ecdsa_sign_det_restartable(
 
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 
-#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
-
 /**
  * \brief           This function verifies the ECDSA signature of a
  *                  previously-hashed message.
@@ -458,7 +448,7 @@ int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
  *                  via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
  * \param md_alg    The message digest that was used to hash the message.
  * \param hash      The message hash to be signed. This must be a readable
- *                  buffer of length \p blen Bytes.
+ *                  buffer of length \p hlen Bytes.
  * \param hlen      The length of the hash \p hash in Bytes.
  * \param sig       The buffer to which to write the signature. This must be a
  *                  writable buffer of length at least twice as large as the
@@ -501,7 +491,7 @@ int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
  *                  via mbedtls_ecdsa_genkey() or mbedtls_ecdsa_from_keypair().
  * \param md_alg    The message digest that was used to hash the message.
  * \param hash      The message hash to be signed. This must be a readable
- *                  buffer of length \p blen Bytes.
+ *                  buffer of length \p hlen Bytes.
  * \param hlen      The length of the hash \p hash in Bytes.
  * \param sig       The buffer to which to write the signature. This must be a
  *                  writable buffer of length at least twice as large as the
@@ -548,7 +538,7 @@ int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
  * \param ctx       The ECDSA context to use. This must be initialized
  *                  and have a group and public key bound to it.
  * \param hash      The message hash that was signed. This must be a readable
- *                  buffer of length \p size Bytes.
+ *                  buffer of length \p hlen Bytes.
  * \param hlen      The size of the hash \p hash.
  * \param sig       The signature to read and verify. This must be a readable
  *                  buffer of length \p slen Bytes.
@@ -578,7 +568,7 @@ int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
  * \param ctx       The ECDSA context to use. This must be initialized
  *                  and have a group and public key bound to it.
  * \param hash      The message hash that was signed. This must be a readable
- *                  buffer of length \p size Bytes.
+ *                  buffer of length \p hlen Bytes.
  * \param hlen      The size of the hash \p hash.
  * \param sig       The signature to read and verify. This must be a readable
  *                  buffer of length \p slen Bytes.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
index a63bb32f38728ce1c970f663a679deeee95888d6..c2148a2bd191b58f8b01ddb4d3ccfce426607484 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecjpake.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ECJPAKE_H
 #define MBEDTLS_ECJPAKE_H
@@ -54,6 +42,7 @@ extern "C" {
 typedef enum {
     MBEDTLS_ECJPAKE_CLIENT = 0,         /**< Client                         */
     MBEDTLS_ECJPAKE_SERVER,             /**< Server                         */
+    MBEDTLS_ECJPAKE_NONE,               /**< Undefined                      */
 } mbedtls_ecjpake_role;
 
 #if !defined(MBEDTLS_ECJPAKE_ALT)
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h b/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
index 08a5f04988558a9af86f4046fbd490f32dfc4b14..e40ab61dafa3da03d7505dec2855be3d2f87c755 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ecp.h
@@ -16,19 +16,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_ECP_H
@@ -36,6 +24,7 @@
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include "mbedtls/bignum.h"
 
@@ -143,15 +132,6 @@ typedef enum {
     MBEDTLS_ECP_TYPE_MONTGOMERY,           /* y^2 = x^3 + a x^2 + x    */
 } mbedtls_ecp_curve_type;
 
-/*
- * Curve modulus types
- */
-typedef enum {
-    MBEDTLS_ECP_MOD_NONE = 0,
-    MBEDTLS_ECP_MOD_COORDINATE,
-    MBEDTLS_ECP_MOD_SCALAR
-} mbedtls_ecp_modulus_type;
-
 /**
  * Curve information, for use by other modules.
  *
@@ -186,7 +166,7 @@ mbedtls_ecp_point;
 
 #if !defined(MBEDTLS_ECP_ALT)
 /*
- * default mbed TLS elliptic curve arithmetic implementation
+ * default Mbed TLS elliptic curve arithmetic implementation
  *
  * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an
  * alternative implementation for the whole module and it will replace this
@@ -208,6 +188,27 @@ mbedtls_ecp_point;
  * odd prime as mbedtls_ecp_mul() requires an odd number, and
  * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes.
  *
+ * The default implementation only initializes \p A without setting it to the
+ * authentic value for curves with <code>A = -3</code>(SECP256R1, etc), in which
+ * case you need to load \p A by yourself when using domain parameters directly,
+ * for example:
+ * \code
+ * mbedtls_mpi_init(&A);
+ * mbedtls_ecp_group_init(&grp);
+ * CHECK_RETURN(mbedtls_ecp_group_load(&grp, grp_id));
+ * if (mbedtls_ecp_group_a_is_minus_3(&grp)) {
+ *     CHECK_RETURN(mbedtls_mpi_sub_int(&A, &grp.P, 3));
+ * } else {
+ *     CHECK_RETURN(mbedtls_mpi_copy(&A, &grp.A));
+ * }
+ *
+ * do_something_with_a(&A);
+ *
+ * cleanup:
+ * mbedtls_mpi_free(&A);
+ * mbedtls_ecp_group_free(&grp);
+ * \endcode
+ *
  * For Montgomery curves, we do not store \p A, but <code>(A + 2) / 4</code>,
  * which is the quantity used in the formulas. Additionally, \p nbits is
  * not the size of \p N but the required size for private keys.
@@ -217,7 +218,7 @@ mbedtls_ecp_point;
  * range of <code>0..2^(2*pbits)-1</code>, and transforms it in-place to an integer
  * which is congruent mod \p P to the given MPI, and is close enough to \p pbits
  * in size, so that it may be efficiently brought in the 0..P-1 range by a few
- * additions or subtractions. Therefore, it is only an approximative modular
+ * additions or subtractions. Therefore, it is only an approximate modular
  * reduction. It must return 0 on success and non-zero on failure.
  *
  * \note        Alternative implementations of the ECP module must obey the
@@ -234,8 +235,11 @@ mbedtls_ecp_point;
 typedef struct mbedtls_ecp_group {
     mbedtls_ecp_group_id id;    /*!< An internal group identifier. */
     mbedtls_mpi P;              /*!< The prime modulus of the base field. */
-    mbedtls_mpi A;              /*!< For Short Weierstrass: \p A in the equation. For
-                                     Montgomery curves: <code>(A + 2) / 4</code>. */
+    mbedtls_mpi A;              /*!< For Short Weierstrass: \p A in the equation. Note that
+                                     \p A is not set to the authentic value in some cases.
+                                     Refer to detailed description of ::mbedtls_ecp_group if
+                                     using domain parameters in the structure.
+                                     For Montgomery curves: <code>(A + 2) / 4</code>. */
     mbedtls_mpi B;              /*!< For Short Weierstrass: \p B in the equation.
                                      For Montgomery curves: unused. */
     mbedtls_ecp_point G;        /*!< The generator of the subgroup used. */
@@ -314,7 +318,7 @@ mbedtls_ecp_group;
 /**
  * The maximum size of the groups, that is, of \c N and \c P.
  */
-#if !defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_ECP_LIGHT)
 /* Dummy definition to help code that has optional ECP support and
  * defines an MBEDTLS_ECP_MAX_BYTES-sized array unconditionally. */
 #define MBEDTLS_ECP_MAX_BITS 1
@@ -345,9 +349,9 @@ mbedtls_ecp_group;
 #define MBEDTLS_ECP_MAX_BITS 192
 #elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
 #define MBEDTLS_ECP_MAX_BITS 192
-#else
+#else /* !MBEDTLS_ECP_LIGHT */
 #error "Missing definition of MBEDTLS_ECP_MAX_BITS"
-#endif
+#endif /* !MBEDTLS_ECP_LIGHT */
 
 #define MBEDTLS_ECP_MAX_BYTES    ((MBEDTLS_ECP_MAX_BITS + 7) / 8)
 #define MBEDTLS_ECP_MAX_PT_LEN   (2 * MBEDTLS_ECP_MAX_BYTES + 1)
@@ -1002,6 +1006,26 @@ int mbedtls_ecp_mul_restartable(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
                                 mbedtls_ecp_restart_ctx *rs_ctx);
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+/**
+ * \brief           This function checks if domain parameter A of the curve is
+ *                  \c -3.
+ *
+ * \note            This function is only defined for short Weierstrass curves.
+ *                  It may not be included in builds without any short
+ *                  Weierstrass curve.
+ *
+ * \param grp       The ECP group to use.
+ *                  This must be initialized and have group parameters
+ *                  set, for example through mbedtls_ecp_group_load().
+ *
+ * \return          \c 1 if <code>A = -3</code>.
+ * \return          \c 0 Otherwise.
+ */
+static inline int mbedtls_ecp_group_a_is_minus_3(const mbedtls_ecp_group *grp)
+{
+    return grp->A.MBEDTLS_PRIVATE(p) == NULL;
+}
+
 /**
  * \brief           This function performs multiplication and addition of two
  *                  points by integers: \p R = \p m * \p P + \p n * \p Q
@@ -1094,7 +1118,7 @@ int mbedtls_ecp_muladd_restartable(
  *
  *                  It only checks that the point is non-zero, has
  *                  valid coordinates and lies on the curve. It does not verify
- *                  that it is indeed a multiple of \p G. This additional
+ *                  that it is indeed a multiple of \c G. This additional
  *                  check is computationally more expensive, is not required
  *                  by standards, and should not be necessary if the group
  *                  used has a small cofactor. In particular, it is useless for
@@ -1119,7 +1143,7 @@ int mbedtls_ecp_check_pubkey(const mbedtls_ecp_group *grp,
                              const mbedtls_ecp_point *pt);
 
 /**
- * \brief           This function checks that an \p mbedtls_mpi is a
+ * \brief           This function checks that an \c mbedtls_mpi is a
  *                  valid private key for this curve.
  *
  * \note            This function uses bare components rather than an
@@ -1238,9 +1262,56 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng);
 
+/** \brief          Set the public key in a key pair object.
+ *
+ * \note            This function does not check that the point actually
+ *                  belongs to the given group. Call mbedtls_ecp_check_pubkey()
+ *                  on \p Q before calling this function to check that.
+ *
+ * \note            This function does not check that the public key matches
+ *                  the private key that is already in \p key, if any.
+ *                  To check the consistency of the resulting key pair object,
+ *                  call mbedtls_ecp_check_pub_priv() after setting both
+ *                  the public key and the private key.
+ *
+ * \param grp_id    The ECP group identifier.
+ * \param key       The key pair object. It must be initialized.
+ *                  If its group has already been set, it must match \p grp_id.
+ *                  If its group has not been set, it will be set to \p grp_id.
+ *                  If the public key has already been set, it is overwritten.
+ * \param Q         The public key to copy. This must be a point on the
+ *                  curve indicated by \p grp_id.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p key does not
+ *                  match \p grp_id.
+ * \return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
+ *                  the group is not implemented.
+ * \return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
+ * \return          Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,
+                               mbedtls_ecp_keypair *key,
+                               const mbedtls_ecp_point *Q);
+
 /**
  * \brief           This function reads an elliptic curve private key.
  *
+ * \note            This function does not set the public key in the
+ *                  key pair object. Without a public key, the key pair object
+ *                  cannot be used with operations that require the public key.
+ *                  Call mbedtls_ecp_keypair_calc_public() to set the public
+ *                  key from the private key. Alternatively, you can call
+ *                  mbedtls_ecp_set_public_key() to set the public key part,
+ *                  and then optionally mbedtls_ecp_check_pub_priv() to check
+ *                  that the private and public parts are consistent.
+ *
+ * \note            If a public key has already been set in the key pair
+ *                  object, this function does not check that it is consistent
+ *                  with the private key. Call mbedtls_ecp_check_pub_priv()
+ *                  after setting both the public key and the private key
+ *                  to make that check.
+ *
  * \param grp_id    The ECP group identifier.
  * \param key       The destination key.
  * \param buf       The buffer containing the binary representation of the
@@ -1259,24 +1330,106 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
 int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
                          const unsigned char *buf, size_t buflen);
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief           This function exports an elliptic curve private key.
  *
+ * \deprecated      Note that although this function accepts an output
+ *                  buffer that is smaller or larger than the key, most key
+ *                  import interfaces require the output to have exactly
+ *                  key's nominal length. It is generally simplest to
+ *                  pass the key's nominal length as \c buflen, after
+ *                  checking that the output buffer is large enough.
+ *                  See the description of the \p buflen parameter for
+ *                  how to calculate the nominal length.
+ *                  To avoid this difficulty, use mbedtls_ecp_write_key_ext()
+ *                  instead.
+ *                  mbedtls_ecp_write_key() is deprecated and will be
+ *                  removed in a future version of the library.
+ *
+ * \note            If the private key was not set in \p key,
+ *                  the output is unspecified. Future versions
+ *                  may return an error in that case.
+ *
  * \param key       The private key.
  * \param buf       The output buffer for containing the binary representation
- *                  of the key. (Big endian integer for Weierstrass curves, byte
- *                  string for Montgomery curves.)
+ *                  of the key.
+ *                  For Weierstrass curves, this is the big-endian
+ *                  representation, padded with null bytes at the beginning
+ *                  to reach \p buflen bytes.
+ *                  For Montgomery curves, this is the standard byte string
+ *                  representation (which is little-endian), padded with
+ *                  null bytes at the end to reach \p buflen bytes.
  * \param buflen    The total length of the buffer in bytes.
+ *                  The length of the output is
+ *                  (`grp->nbits` + 7) / 8 bytes
+ *                  where `grp->nbits` is the private key size in bits.
+ *                  For Weierstrass keys, if the output buffer is smaller,
+ *                  leading zeros are trimmed to fit if possible. For
+ *                  Montgomery keys, the output buffer must always be large
+ *                  enough for the nominal length.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL or
+ *                  #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the \p key
+ *                  representation is larger than the available space in \p buf.
+ * \return          Another negative error code on different kinds of failure.
+ */
+int MBEDTLS_DEPRECATED mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
+                                             unsigned char *buf, size_t buflen);
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/**
+ * \brief           This function exports an elliptic curve private key.
+ *
+ * \param key       The private key.
+ * \param olen      On success, the length of the private key.
+ *                  This is always (`grp->nbits` + 7) / 8 bytes
+ *                  where `grp->nbits` is the private key size in bits.
+ * \param buf       The output buffer for containing the binary representation
+ *                  of the key.
+ * \param buflen    The total length of the buffer in bytes.
+ *                  #MBEDTLS_ECP_MAX_BYTES is always sufficient.
  *
  * \return          \c 0 on success.
  * \return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the \p key
-                    representation is larger than the available space in \p buf.
- * \return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the operation for
- *                  the group is not implemented.
+ *                  representation is larger than the available space in \p buf.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if no private key is
+ *                  set in \p key.
  * \return          Another negative error code on different kinds of failure.
  */
-int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
-                          unsigned char *buf, size_t buflen);
+int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key,
+                              size_t *olen, unsigned char *buf, size_t buflen);
+
+/**
+ * \brief           This function exports an elliptic curve public key.
+ *
+ * \note            If the public key was not set in \p key,
+ *                  the output is unspecified. Future versions
+ *                  may return an error in that case.
+ *
+ * \param key       The public key.
+ * \param format    The point format. This must be either
+ *                  #MBEDTLS_ECP_PF_COMPRESSED or #MBEDTLS_ECP_PF_UNCOMPRESSED.
+ *                  (For groups without these formats, this parameter is
+ *                  ignored. But it still has to be either of the above
+ *                  values.)
+ * \param olen      The address at which to store the length of
+ *                  the output in Bytes. This must not be \c NULL.
+ * \param buf       The output buffer. This must be a writable buffer
+ *                  of length \p buflen Bytes.
+ * \param buflen    The length of the output buffer \p buf in Bytes.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL if the output buffer
+ *                  is too small to hold the point.
+ * \return          #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format
+ *                  or the export for the given group is not implemented.
+ * \return          Another negative error code on other kinds of failure.
+ */
+int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key,
+                                 int format, size_t *olen,
+                                 unsigned char *buf, size_t buflen);
 
 /**
  * \brief           This function checks that the keypair objects
@@ -1302,16 +1455,52 @@ int mbedtls_ecp_check_pub_priv(
     const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv,
     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
 
+/** \brief          Calculate the public key from a private key in a key pair.
+ *
+ * \param key       A keypair structure. It must have a private key set.
+ *                  If the public key is set, it will be overwritten.
+ * \param f_rng     The RNG function. This must not be \c NULL.
+ * \param p_rng     The RNG context to be passed to \p f_rng. This may be \c
+ *                  NULL if \p f_rng doesn't need a context.
+ *
+ * \return          \c 0 on success. The key pair object can be used for
+ *                  operations that require the public key.
+ * \return          An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX
+ *                  error code on calculation failure.
+ */
+int mbedtls_ecp_keypair_calc_public(
+    mbedtls_ecp_keypair *key,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
+
+/** \brief          Query the group that a key pair belongs to.
+ *
+ * \param key       The key pair to query.
+ *
+ * \return          The group ID for the group registered in the key pair
+ *                  object.
+ *                  This is \c MBEDTLS_ECP_DP_NONE if no group has been set
+ *                  in the key pair object.
+ */
+mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id(
+    const mbedtls_ecp_keypair *key);
+
 /**
  * \brief           This function exports generic key-pair parameters.
  *
+ *                  Each of the output parameters can be a null pointer
+ *                  if you do not need that parameter.
+ *
+ * \note            If the private key or the public key was not set in \p key,
+ *                  the corresponding output is unspecified. Future versions
+ *                  may return an error in that case.
+ *
  * \param key       The key pair to export from.
  * \param grp       Slot for exported ECP group.
- *                  It must point to an initialized ECP group.
+ *                  It must either be null or point to an initialized ECP group.
  * \param d         Slot for the exported secret value.
- *                  It must point to an initialized mpi.
+ *                  It must either be null or point to an initialized mpi.
  * \param Q         Slot for the exported public value.
- *                  It must point to an initialized ECP point.
+ *                  It must either be null or point to an initialized ECP point.
  *
  * \return          \c 0 on success,
  * \return          #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h b/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
index 2c8b75031327a59e301ecd2eba6ca9200e711242..20fd6872b89b8e563d10a0fe09d64ef19c03f5a1 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/entropy.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ENTROPY_H
 #define MBEDTLS_ENTROPY_H
@@ -27,13 +15,17 @@
 
 #include <stddef.h>
 
-#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
-#include "mbedtls/sha512.h"
+#include "md.h"
+
+#if defined(MBEDTLS_MD_CAN_SHA512) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256)
 #define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR
+#define MBEDTLS_ENTROPY_MD  MBEDTLS_MD_SHA512
+#define MBEDTLS_ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
 #else
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR
-#include "mbedtls/sha256.h"
+#define MBEDTLS_ENTROPY_MD  MBEDTLS_MD_SHA256
+#define MBEDTLS_ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
 #endif
 #endif
 
@@ -71,12 +63,6 @@
 
 /** \} name SECTION: Module settings */
 
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-#define MBEDTLS_ENTROPY_BLOCK_SIZE      64      /**< Block size of entropy accumulator (SHA-512) */
-#else
-#define MBEDTLS_ENTROPY_BLOCK_SIZE      32      /**< Block size of entropy accumulator (SHA-256) */
-#endif
-
 #define MBEDTLS_ENTROPY_MAX_SEED_SIZE   1024    /**< Maximum size of seed we read from seed file */
 #define MBEDTLS_ENTROPY_SOURCE_MANUAL   MBEDTLS_ENTROPY_MAX_SOURCES
 
@@ -117,14 +103,10 @@ mbedtls_entropy_source_state;
  * \brief           Entropy context structure
  */
 typedef struct mbedtls_entropy_context {
+    mbedtls_md_context_t  MBEDTLS_PRIVATE(accumulator);
     int MBEDTLS_PRIVATE(accumulator_started); /* 0 after init.
                                                * 1 after the first update.
                                                * -1 after free. */
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    mbedtls_sha512_context  MBEDTLS_PRIVATE(accumulator);
-#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR)
-    mbedtls_sha256_context  MBEDTLS_PRIVATE(accumulator);
-#endif
     int             MBEDTLS_PRIVATE(source_count); /* Number of entries used in source. */
     mbedtls_entropy_source_state    MBEDTLS_PRIVATE(source)[MBEDTLS_ENTROPY_MAX_SOURCES];
 #if defined(MBEDTLS_THREADING_C)
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/error.h b/lib/libmbedtls/mbedtls/include/mbedtls/error.h
index 23a83f2c84d73b7462392eb7793ce3d4a9b41bcd..186589ac5bc5da6b1507fe0aee779dd377bc3a6e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/error.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/error.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ERROR_H
 #define MBEDTLS_ERROR_H
@@ -73,6 +61,7 @@
  * SHA1      1                  0x0035-0x0035 0x0073-0x0073
  * SHA256    1                  0x0037-0x0037 0x0074-0x0074
  * SHA512    1                  0x0039-0x0039 0x0075-0x0075
+ * SHA-3     1                  0x0076-0x0076
  * CHACHA20  3                  0x0051-0x0055
  * POLY1305  3                  0x0057-0x005B
  * CHACHAPOLY 2 0x0054-0x0056
@@ -165,9 +154,9 @@ static inline int mbedtls_error_add(int high, int low,
 }
 
 /**
- * \brief Translate a mbed TLS error code into a string representation,
- *        Result is truncated if necessary and always includes a terminating
- *        null byte.
+ * \brief Translate an Mbed TLS error code into a string representation.
+ *        The result is truncated if necessary and always includes a
+ *        terminating null byte.
  *
  * \param errnum    error code
  * \param buffer    buffer to place representation in
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h b/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
index c3343e6aa3f25c533bfd7a6509752cdf6fab1b6c..98faa436126d9510cced43ec3fba44bb997c91fa 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/gcm.h
@@ -13,19 +13,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_GCM_H
@@ -36,6 +24,10 @@
 
 #include "mbedtls/cipher.h"
 
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+#include "mbedtls/block_cipher.h"
+#endif
+
 #include <stdint.h>
 
 #define MBEDTLS_GCM_ENCRYPT     1
@@ -54,21 +46,31 @@ extern "C" {
 
 #if !defined(MBEDTLS_GCM_ALT)
 
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+#define MBEDTLS_GCM_HTABLE_SIZE 256
+#else
+#define MBEDTLS_GCM_HTABLE_SIZE 16
+#endif
+
 /**
  * \brief          The GCM context structure.
  */
 typedef struct mbedtls_gcm_context {
-    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);  /*!< The cipher context used. */
-    uint64_t MBEDTLS_PRIVATE(HL)[16];                      /*!< Precalculated HTable low. */
-    uint64_t MBEDTLS_PRIVATE(HH)[16];                      /*!< Precalculated HTable high. */
-    uint64_t MBEDTLS_PRIVATE(len);                         /*!< The total length of the encrypted data. */
-    uint64_t MBEDTLS_PRIVATE(add_len);                     /*!< The total length of the additional data. */
-    unsigned char MBEDTLS_PRIVATE(base_ectr)[16];          /*!< The first ECTR for tag. */
-    unsigned char MBEDTLS_PRIVATE(y)[16];                  /*!< The Y working value. */
-    unsigned char MBEDTLS_PRIVATE(buf)[16];                /*!< The buf working value. */
-    int MBEDTLS_PRIVATE(mode);                             /*!< The operation to perform:
-                                                            #MBEDTLS_GCM_ENCRYPT or
-                                                            #MBEDTLS_GCM_DECRYPT. */
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_context_t MBEDTLS_PRIVATE(block_cipher_ctx);  /*!< The cipher context used. */
+#else
+    mbedtls_cipher_context_t MBEDTLS_PRIVATE(cipher_ctx);    /*!< The cipher context used. */
+#endif
+    uint64_t MBEDTLS_PRIVATE(H)[MBEDTLS_GCM_HTABLE_SIZE][2]; /*!< Precalculated HTable. */
+    uint64_t MBEDTLS_PRIVATE(len);                           /*!< The total length of the encrypted data. */
+    uint64_t MBEDTLS_PRIVATE(add_len);                       /*!< The total length of the additional data. */
+    unsigned char MBEDTLS_PRIVATE(base_ectr)[16];            /*!< The first ECTR for tag. */
+    unsigned char MBEDTLS_PRIVATE(y)[16];                    /*!< The Y working value. */
+    unsigned char MBEDTLS_PRIVATE(buf)[16];                  /*!< The buf working value. */
+    unsigned char MBEDTLS_PRIVATE(mode);                     /*!< The operation to perform:
+                                                              #MBEDTLS_GCM_ENCRYPT or
+                                                              #MBEDTLS_GCM_DECRYPT. */
+    unsigned char MBEDTLS_PRIVATE(acceleration);             /*!< The acceleration to use. */
 }
 mbedtls_gcm_context;
 
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h b/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
index 699c6d9e9c7360ad72a3345ef84af7a6b3e69d30..930e93f3251517a58f388c3c5ec89419b22147a1 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/hkdf.h
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_HKDF_H
 #define MBEDTLS_HKDF_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h b/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
index 4ca6b0823ed3daccb706b475ab88ce0d5481dc5d..18b1b75a69f2234a54cec12cce4ee51b3553ca01 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/hmac_drbg.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_HMAC_DRBG_H
 #define MBEDTLS_HMAC_DRBG_H
@@ -183,8 +171,8 @@ void mbedtls_hmac_drbg_init(mbedtls_hmac_drbg_context *ctx);
  * \param len           The length of the personalization string.
  *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
  *                      and also at most
- *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len * 3 / 2
- *                      where \p entropy_len is the entropy length
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len * 3 / 2
+ *                      where \c entropy_len is the entropy length
  *                      described above.
  *
  * \return              \c 0 if successful.
@@ -313,8 +301,8 @@ int mbedtls_hmac_drbg_update(mbedtls_hmac_drbg_context *ctx,
  * \param len           The length of the additional data.
  *                      This must be at most #MBEDTLS_HMAC_DRBG_MAX_INPUT
  *                      and also at most
- *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \p entropy_len
- *                      where \p entropy_len is the entropy length
+ *                      #MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT - \c entropy_len
+ *                      where \c entropy_len is the entropy length
  *                      (see mbedtls_hmac_drbg_set_entropy_len()).
  *
  * \return              \c 0 if successful.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h b/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h
deleted file mode 100644
index e9bdb77833c687436cbe173be26759d995e1a965..0000000000000000000000000000000000000000
--- a/lib/libmbedtls/mbedtls/include/mbedtls/legacy_or_psa.h
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- *  Macros to express dependencies for code and tests that may use either the
- *  legacy API or PSA in various builds. This whole header file is currently
- *  for internal use only and both the header file and the macros it defines
- *  may change or be removed without notice.
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-/*
- * Note: applications that are targeting a specific configuration do not need
- * to use these macros; instead they should directly use the functions they
- * know are available in their configuration.
- *
- * Note: code that is purely based on PSA Crypto (psa_xxx() functions)
- * does not need to use these macros; instead it should use the relevant
- * PSA_WANT_xxx macros.
- *
- * Note: code that is purely based on the legacy crypto APIs (mbedtls_xxx())
- * does not need to use these macros; instead it should use the relevant
- * MBEDTLS_xxx macros.
- *
- * These macros are for code that wants to use <crypto feature> and will do so
- * using <legacy API> or PSA depending on <condition>, where:
- * - <crypto feature> will generally be an algorithm (SHA-256, ECDH) but may
- *   also be a key type (AES, RSA, EC) or domain parameters (elliptic curve);
- * - <legacy API> will be either:
- *      - low-level module API (aes.h, sha256.h), or
- *      - an abstraction layer (md.h, cipher.h);
- * - <condition> will be either:
- *      - depending on what's available in the build:
- *          legacy API used if available, PSA otherwise
- *          (this is done to ensure backwards compatibility); or
- *      - depending on whether MBEDTLS_USE_PSA_CRYPTO is defined.
- *
- * Examples:
- * - TLS 1.2 will compute hashes using either mbedtls_md_xxx() (and
- *   mbedtls_sha256_xxx()) or psa_aead_xxx() depending on whether
- *   MBEDTLS_USE_PSA_CRYPTO is defined;
- * - RSA PKCS#1 v2.1 will compute hashes (for padding) using either
- *   `mbedtls_md()` if it's available, or `psa_hash_compute()` otherwise;
- * - PEM decoding of PEM-encrypted keys will compute MD5 hashes using either
- *   `mbedtls_md5_xxx()` if it's available, or `psa_hash_xxx()` otherwise.
- *
- * Note: the macros are essential to express test dependencies. Inside code,
- * we could instead just use the equivalent pre-processor condition, but
- * that's not possible in test dependencies where we need a single macro.
- * Hopefully, using these macros in code will also help with consistency.
- *
- * The naming scheme for these macros is:
- *      MBEDTLS_HAS_feature_VIA_legacy_OR_PSA(_condition)
- * where:
- * - feature is expressed the same way as in PSA_WANT_xxx macros, for example:
- *   KEY_TYPE_AES, ALG_SHA_256, ECC_SECP_R1_256;
- * - legacy is either LOWLEVEL or the name of the layer: MD, CIPHER;
- * - condition is omitted if it's based on availability, else it's
- *   BASED_ON_USE_PSA.
- *
- * Coming back to the examples above:
- * - TLS 1.2 will determine if it can use SHA-256 using
- *      MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
- *   for the purposes of negotiation, and in test dependencies;
- * - RSA PKCS#1 v2.1 tests that used SHA-256 will depend on
- *      MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
- * - PEM decoding code and its associated tests will depend on
- *      MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA
- *
- * Note: every time it's possible to use, say SHA-256, via the MD API, then
- * it's also possible to use it via the low-level API. So, code that wants to
- * use SHA-256 via both APIs only needs to depend on the MD macro. Also, it
- * just so happens that all the code choosing which API to use based on
- * MBEDTLS_USE_PSA_CRYPTO (X.509, TLS 1.2/shared), always uses the abstraction
- * layer (sometimes in addition to the low-level API), so we don't need the
- * MBEDTLS_HAS_feature_VIA_LOWLEVEL_OR_PSA_BASED_ON_USE_PSA macros.
- * (PK, while obeying MBEDTLS_USE_PSA_CRYPTO, doesn't compute hashes itself,
- * even less makes use of ciphers.)
- *
- * Note: the macros MBEDTLS_HAS_feature_VIA_LOWLEVEL_OR_PSA are the minimal
- * condition for being able to use <feature> at all. As such, they should be
- * used for guarding data about <feature>, such as OIDs or size. For example,
- * OID values related to SHA-256 are only useful when SHA-256 can be used at
- * least in some way.
- */
-
-#ifndef MBEDTLS_OR_PSA_HELPERS_H
-#define MBEDTLS_OR_PSA_HELPERS_H
-
-#include "mbedtls/build_info.h"
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#include "psa/crypto.h"
-#endif /* MBEDTLS_PSA_CRYPTO_C */
-
-/*
- * Hashes
- */
-
-/* Hashes using low-level or PSA based on availability */
-#if defined(MBEDTLS_MD5_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_MD5))
-#define MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_RIPEMD160_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_RIPEMD160))
-#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_SHA1_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_1))
-#define MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_SHA224_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_224))
-#define MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_SHA256_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256))
-#define MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_SHA384_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_384))
-#define MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA
-#endif
-#if defined(MBEDTLS_SHA512_C) || \
-    (defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_512))
-#define MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA
-#endif
-
-/* Hashes using MD or PSA based on availability */
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_MD5_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_MD5))
-#define MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_RIPEMD160_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_RIPEMD160))
-#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_1))
-#define MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA224_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_224))
-#define MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_256))
-#define MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA384_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_384))
-#define MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA
-#endif
-#if (defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C)) || \
-    (!defined(MBEDTLS_MD_C) && \
-    defined(MBEDTLS_PSA_CRYPTO_C) && defined(PSA_WANT_ALG_SHA_512))
-#define MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA
-#endif
-
-/* Hashes using MD or PSA based on MBEDTLS_USE_PSA_CRYPTO */
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_MD5_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_MD5))
-#define MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_RIPEMD160_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_RIPEMD160))
-#define MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA1_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_1))
-#define MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA224_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_224))
-#define MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA256_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_256))
-#define MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA384_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_384))
-#define MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-#if (!defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(MBEDTLS_MD_C) && defined(MBEDTLS_SHA512_C)) || \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_SHA_512))
-#define MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA
-#endif
-
-#endif /* MBEDTLS_OR_PSA_HELPERS_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/lms.h b/lib/libmbedtls/mbedtls/include/mbedtls/lms.h
index 5c8df42f83864670979e86abe150d709fe23aabb..95fce21337e32dc24bc7477d9df3adc0318aa41a 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/lms.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/lms.h
@@ -10,19 +10,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_LMS_H
 #define MBEDTLS_LMS_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md.h b/lib/libmbedtls/mbedtls/include/mbedtls/md.h
index 7bad24dc9b1c71675c9d411e6893acd4fec94667..478e9f7667010fcea4f3b77a78b06af269c34b45 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md.h
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_MD_H
@@ -32,93 +20,6 @@
 #include "mbedtls/build_info.h"
 #include "mbedtls/platform_util.h"
 
-#if defined(MBEDTLS_MD_LIGHT)
-
-/*
- * - MBEDTLS_MD_CAN_xxx is defined if the md module can perform xxx.
- * - MBEDTLS_MD_xxx_VIA_PSA is defined if the md module may perform xxx via PSA
- *   (see below).
- * - MBEDTLS_MD_SOME_PSA is defined if at least one algorithm may be performed
- *   via PSA (see below).
- * - MBEDTLS_MD_SOME_LEGACY is defined if at least one algorithm may be performed
- *   via a direct legacy call (see below).
- *
- * The md module performs an algorithm via PSA if there is a PSA hash
- * accelerator and the PSA driver subsytem is initialized at the time the
- * operation is started, and makes a direct legacy call otherwise.
- */
-
-/* PSA accelerated implementations */
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#if defined(MBEDTLS_PSA_ACCEL_ALG_MD5)
-#define MBEDTLS_MD_CAN_MD5
-#define MBEDTLS_MD_MD5_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_1)
-#define MBEDTLS_MD_CAN_SHA1
-#define MBEDTLS_MD_SHA1_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_224)
-#define MBEDTLS_MD_CAN_SHA224
-#define MBEDTLS_MD_SHA224_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_256)
-#define MBEDTLS_MD_CAN_SHA256
-#define MBEDTLS_MD_SHA256_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_384)
-#define MBEDTLS_MD_CAN_SHA384
-#define MBEDTLS_MD_SHA384_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_SHA_512)
-#define MBEDTLS_MD_CAN_SHA512
-#define MBEDTLS_MD_SHA512_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#if defined(MBEDTLS_PSA_ACCEL_ALG_RIPEMD160)
-#define MBEDTLS_MD_CAN_RIPEMD160
-#define MBEDTLS_MD_RIPEMD160_VIA_PSA
-#define MBEDTLS_MD_SOME_PSA
-#endif
-#endif /* MBEDTLS_PSA_CRYPTO_C */
-
-/* Built-in implementations */
-#if defined(MBEDTLS_MD5_C)
-#define MBEDTLS_MD_CAN_MD5
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_SHA1_C)
-#define MBEDTLS_MD_CAN_SHA1
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_SHA224_C)
-#define MBEDTLS_MD_CAN_SHA224
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_SHA256_C)
-#define MBEDTLS_MD_CAN_SHA256
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_SHA384_C)
-#define MBEDTLS_MD_CAN_SHA384
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_SHA512_C)
-#define MBEDTLS_MD_CAN_SHA512
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-#define MBEDTLS_MD_CAN_RIPEMD160
-#define MBEDTLS_MD_SOME_LEGACY
-#endif
-
-#endif /* MBEDTLS_MD_LIGHT */
-
 /** The selected feature is not available. */
 #define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE                -0x5080
 /** Bad input parameters to function. */
@@ -140,32 +41,55 @@ extern "C" {
  *            stronger message digests instead.
  *
  */
+/* Note: these are aligned with the definitions of PSA_ALG_ macros for hashes,
+ * in order to enable an efficient implementation of conversion functions.
+ * This is tested by md_to_from_psa() in test_suite_md. */
 typedef enum {
     MBEDTLS_MD_NONE=0,    /**< None. */
-    MBEDTLS_MD_MD5,       /**< The MD5 message digest. */
-    MBEDTLS_MD_SHA1,      /**< The SHA-1 message digest. */
-    MBEDTLS_MD_SHA224,    /**< The SHA-224 message digest. */
-    MBEDTLS_MD_SHA256,    /**< The SHA-256 message digest. */
-    MBEDTLS_MD_SHA384,    /**< The SHA-384 message digest. */
-    MBEDTLS_MD_SHA512,    /**< The SHA-512 message digest. */
-    MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
+    MBEDTLS_MD_MD5=0x03,       /**< The MD5 message digest. */
+    MBEDTLS_MD_RIPEMD160=0x04, /**< The RIPEMD-160 message digest. */
+    MBEDTLS_MD_SHA1=0x05,      /**< The SHA-1 message digest. */
+    MBEDTLS_MD_SHA224=0x08,    /**< The SHA-224 message digest. */
+    MBEDTLS_MD_SHA256=0x09,    /**< The SHA-256 message digest. */
+    MBEDTLS_MD_SHA384=0x0a,    /**< The SHA-384 message digest. */
+    MBEDTLS_MD_SHA512=0x0b,    /**< The SHA-512 message digest. */
+    MBEDTLS_MD_SHA3_224=0x10,  /**< The SHA3-224 message digest. */
+    MBEDTLS_MD_SHA3_256=0x11,  /**< The SHA3-256 message digest. */
+    MBEDTLS_MD_SHA3_384=0x12,  /**< The SHA3-384 message digest. */
+    MBEDTLS_MD_SHA3_512=0x13,  /**< The SHA3-512 message digest. */
 } mbedtls_md_type_t;
 
-#if defined(MBEDTLS_MD_CAN_SHA512)
+/* Note: this should always be >= PSA_HASH_MAX_SIZE
+ * in all builds with both CRYPTO_C and MD_LIGHT.
+ *
+ * This is to make things easier for modules such as TLS that may define a
+ * buffer size using MD_MAX_SIZE in a part of the code that's common to PSA
+ * and legacy, then assume the buffer's size is PSA_HASH_MAX_SIZE in another
+ * part of the code based on PSA.
+ */
+#if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA3_512)
 #define MBEDTLS_MD_MAX_SIZE         64  /* longest known is SHA512 */
-#elif defined(MBEDTLS_MD_CAN_SHA384)
+#elif defined(MBEDTLS_MD_CAN_SHA384) || defined(MBEDTLS_MD_CAN_SHA3_384)
 #define MBEDTLS_MD_MAX_SIZE         48  /* longest known is SHA384 */
-#elif defined(MBEDTLS_MD_CAN_SHA256)
+#elif defined(MBEDTLS_MD_CAN_SHA256) || defined(MBEDTLS_MD_CAN_SHA3_256)
 #define MBEDTLS_MD_MAX_SIZE         32  /* longest known is SHA256 */
-#elif defined(MBEDTLS_MD_CAN_SHA224)
+#elif defined(MBEDTLS_MD_CAN_SHA224) || defined(MBEDTLS_MD_CAN_SHA3_224)
 #define MBEDTLS_MD_MAX_SIZE         28  /* longest known is SHA224 */
 #else
 #define MBEDTLS_MD_MAX_SIZE         20  /* longest known is SHA1 or RIPE MD-160
                                            or smaller (MD5 and earlier) */
 #endif
 
-#if defined(MBEDTLS_MD_CAN_SHA512)
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE         144 /* the longest known is SHA3-224 */
+#elif defined(MBEDTLS_MD_CAN_SHA3_256)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE         136
+#elif defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_MD_CAN_SHA384)
 #define MBEDTLS_MD_MAX_BLOCK_SIZE         128
+#elif defined(MBEDTLS_MD_CAN_SHA3_384)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE         104
+#elif defined(MBEDTLS_MD_CAN_SHA3_512)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE         72
 #else
 #define MBEDTLS_MD_MAX_BLOCK_SIZE         64
 #endif
@@ -310,6 +234,20 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst,
  */
 unsigned char mbedtls_md_get_size(const mbedtls_md_info_t *md_info);
 
+/**
+ * \brief           This function gives the message-digest size associated to
+ *                  message-digest type.
+ *
+ * \param md_type   The message-digest type.
+ *
+ * \return          The size of the message-digest output in Bytes,
+ *                  or 0 if the message-digest type is not known.
+ */
+static inline unsigned char mbedtls_md_get_size_from_type(mbedtls_md_type_t md_type)
+{
+    return mbedtls_md_get_size(mbedtls_md_info_from_type(md_type));
+}
+
 /**
  * \brief           This function extracts the message-digest type from the
  *                  message-digest information structure.
@@ -424,8 +362,8 @@ const int *mbedtls_md_list(void);
 const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name);
 
 /**
- * \brief           This function extracts the message-digest name from the
- *                  message-digest information structure.
+ * \brief           This function returns the name of the message digest for
+ *                  the message-digest information structure given.
  *
  * \param md_info   The information structure of the message-digest algorithm
  *                  to use.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/md5.h b/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
index 808188694f10f9744383b3f259126fbe60d2b5c4..6bf0754a4a688f528db192331c246c5b880f5993 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/md5.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_MD5_H
 #define MBEDTLS_MD5_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h b/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
index 9694d2458ed805e81282cc7da91318387127ca1d..b527d9b66503a5245db6efd39330db23e4402485 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/memory_buffer_alloc.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_MEMORY_BUFFER_ALLOC_H
 #define MBEDTLS_MEMORY_BUFFER_ALLOC_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h b/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
index 14316fbedb7bab40b610114349bb2565094824f9..85c11971d800e94f6e6835526e7f9d3990ab3261 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/net_sockets.h
@@ -21,19 +21,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_NET_SOCKETS_H
 #define MBEDTLS_NET_SOCKETS_H
@@ -155,7 +143,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *
  * \param client_ctx Will contain the connected client socket
  * \param client_ip Will contain the client IP address, can be NULL
  * \param buf_size  Size of the client_ip buffer
- * \param ip_len    Will receive the size of the client IP written,
+ * \param cip_len   Will receive the size of the client IP written,
  *                  can be NULL if client_ip is null
  *
  * \return          0 if successful, or
@@ -168,7 +156,7 @@ int mbedtls_net_bind(mbedtls_net_context *ctx, const char *bind_ip, const char *
  */
 int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
                        mbedtls_net_context *client_ctx,
-                       void *client_ip, size_t buf_size, size_t *ip_len);
+                       void *client_ip, size_t buf_size, size_t *cip_len);
 
 /**
  * \brief          Check and wait for the context to be ready for read/write
@@ -286,6 +274,10 @@ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf, size_t len,
  * \brief          Closes down the connection and free associated data
  *
  * \param ctx      The context to close
+ *
+ * \note           This function frees and clears data associated with the
+ *                 context but does not free the memory pointed to by \p ctx.
+ *                 This memory is the responsibility of the caller.
  */
 void mbedtls_net_close(mbedtls_net_context *ctx);
 
@@ -293,6 +285,10 @@ void mbedtls_net_close(mbedtls_net_context *ctx);
  * \brief          Gracefully shutdown the connection and free associated data
  *
  * \param ctx      The context to free
+ *
+ * \note           This function frees and clears data associated with the
+ *                 context but does not free the memory pointed to by \p ctx.
+ *                 This memory is the responsibility of the caller.
  */
 void mbedtls_net_free(mbedtls_net_context *ctx);
 
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h b/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
index 0c95c902edd34ad8c0f7d8f089d8246d09f6273d..d353f3d1a8a60dfa2b774b7a88aa5ec3b6e26831 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/nist_kw.h
@@ -17,19 +17,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_NIST_KW_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/oid.h b/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
index a592e63c4fd96d099acb38db3cbfc740ba98bb26..fdc25ebf8856c600b810625ad24e27720d9a4321 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/oid.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_OID_H
 #define MBEDTLS_OID_H
@@ -63,6 +51,11 @@
 #define MBEDTLS_OID_X509_EXT_FRESHEST_CRL                (1 << 14)
 #define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE                (1 << 16)
 
+/*
+ * Maximum number of OID components allowed
+ */
+#define MBEDTLS_OID_MAX_COMPONENTS              128
+
 /*
  * Top level OID tuples
  */
@@ -90,6 +83,9 @@
 #define MBEDTLS_OID_OIW_SECSIG                  MBEDTLS_OID_ORG_OIW "\x03"
 #define MBEDTLS_OID_OIW_SECSIG_ALG              MBEDTLS_OID_OIW_SECSIG "\x02"
 #define MBEDTLS_OID_OIW_SECSIG_SHA1             MBEDTLS_OID_OIW_SECSIG_ALG "\x1a"
+#define MBEDTLS_OID_ORG_THAWTE                  "\x65"          /* thawte(101) */
+#define MBEDTLS_OID_THAWTE                      MBEDTLS_OID_ISO_IDENTIFIED_ORG \
+        MBEDTLS_OID_ORG_THAWTE
 #define MBEDTLS_OID_ORG_CERTICOM                "\x81\x04"  /* certicom(132) */
 #define MBEDTLS_OID_CERTICOM                    MBEDTLS_OID_ISO_IDENTIFIED_ORG \
         MBEDTLS_OID_ORG_CERTICOM
@@ -262,6 +258,15 @@
 
 #define MBEDTLS_OID_DIGEST_ALG_RIPEMD160        MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */
 
+#define MBEDTLS_OID_DIGEST_ALG_SHA3_224         MBEDTLS_OID_NIST_ALG "\x02\x07" /**< id-sha3-224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-224(7) } */
+
+#define MBEDTLS_OID_DIGEST_ALG_SHA3_256         MBEDTLS_OID_NIST_ALG "\x02\x08" /**< id-sha3-256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-256(8) } */
+
+#define MBEDTLS_OID_DIGEST_ALG_SHA3_384         MBEDTLS_OID_NIST_ALG "\x02\x09" /**< id-sha3-384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-384(9) } */
+
+#define MBEDTLS_OID_DIGEST_ALG_SHA3_512         MBEDTLS_OID_NIST_ALG "\x02\x0a" /**< id-sha3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) sha3-512(10) } */
+
+
 #define MBEDTLS_OID_HMAC_SHA1                   MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */
 
 #define MBEDTLS_OID_HMAC_SHA224                 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */
@@ -272,13 +277,28 @@
 
 #define MBEDTLS_OID_HMAC_SHA512                 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */
 
+#define MBEDTLS_OID_HMAC_SHA3_224               MBEDTLS_OID_NIST_ALG "\x02\x0d" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-224(13) } */
+
+#define MBEDTLS_OID_HMAC_SHA3_256               MBEDTLS_OID_NIST_ALG "\x02\x0e" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-256(14) } */
+
+#define MBEDTLS_OID_HMAC_SHA3_384               MBEDTLS_OID_NIST_ALG "\x02\x0f" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-384(15) } */
+
+#define MBEDTLS_OID_HMAC_SHA3_512               MBEDTLS_OID_NIST_ALG "\x02\x10" /**< id-hmacWithSHA3-512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) hashalgs(2) hmacWithSHA3-512(16) } */
+
+#define MBEDTLS_OID_HMAC_RIPEMD160              MBEDTLS_OID_INTERNET "\x05\x05\x08\x01\x04" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= {iso(1) iso-identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1) hmacRIPEMD160(4)} */
+
 /*
- * Encryption algorithms
+ * Encryption algorithms,
+ * the following standardized object identifiers are specified at
+ * https://datatracker.ietf.org/doc/html/rfc8018#appendix-C.
  */
 #define MBEDTLS_OID_DES_CBC                     MBEDTLS_OID_ISO_IDENTIFIED_ORG \
         MBEDTLS_OID_OIW_SECSIG_ALG "\x07"                                                                        /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */
 #define MBEDTLS_OID_DES_EDE3_CBC                MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */
 #define MBEDTLS_OID_AES                         MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */
+#define MBEDTLS_OID_AES_128_CBC                 MBEDTLS_OID_AES "\x02" /** aes128-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes128-CBC-PAD(2) } */
+#define MBEDTLS_OID_AES_192_CBC                 MBEDTLS_OID_AES "\x16" /** aes192-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes192-CBC-PAD(22) } */
+#define MBEDTLS_OID_AES_256_CBC                 MBEDTLS_OID_AES "\x2a" /** aes256-cbc-pad OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithms(4) aes(1) aes256-CBC-PAD(42) } */
 
 /*
  * Key Wrapping algorithms
@@ -437,6 +457,15 @@
  *   ecdsa-with-SHA2(3) 4 } */
 #define MBEDTLS_OID_ECDSA_SHA512            MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04"
 
+/*
+ * EC key algorithms from RFC 8410
+ */
+
+#define MBEDTLS_OID_X25519                  MBEDTLS_OID_THAWTE "\x6e" /**< id-X25519    OBJECT IDENTIFIER ::= { 1 3 101 110 } */
+#define MBEDTLS_OID_X448                    MBEDTLS_OID_THAWTE "\x6f" /**< id-X448      OBJECT IDENTIFIER ::= { 1 3 101 111 } */
+#define MBEDTLS_OID_ED25519                 MBEDTLS_OID_THAWTE "\x70" /**< id-Ed25519   OBJECT IDENTIFIER ::= { 1 3 101 112 } */
+#define MBEDTLS_OID_ED448                   MBEDTLS_OID_THAWTE "\x71" /**< id-Ed448     OBJECT IDENTIFIER ::= { 1 3 101 113 } */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -466,6 +495,25 @@ typedef struct mbedtls_oid_descriptor_t {
  */
 int mbedtls_oid_get_numeric_string(char *buf, size_t size, const mbedtls_asn1_buf *oid);
 
+/**
+ * \brief           Translate a string containing a dotted-decimal
+ *                  representation of an ASN.1 OID into its encoded form
+ *                  (e.g. "1.2.840.113549" into "\x2A\x86\x48\x86\xF7\x0D").
+ *                  On success, this function allocates oid->buf from the
+ *                  heap. It must be freed by the caller using mbedtls_free().
+ *
+ * \param oid       #mbedtls_asn1_buf to populate with the DER-encoded OID
+ * \param oid_str   string representation of the OID to parse
+ * \param size      length of the OID string, not including any null terminator
+ *
+ * \return          0 if successful
+ * \return          #MBEDTLS_ERR_ASN1_INVALID_DATA if \p oid_str does not
+ *                  represent a valid OID
+ * \return          #MBEDTLS_ERR_ASN1_ALLOC_FAILED if the function fails to
+ *                  allocate oid->buf
+ */
+int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid, const char *oid_str, size_t size);
+
 /**
  * \brief          Translate an X.509 extension OID into local values
  *
@@ -509,7 +557,7 @@ int mbedtls_oid_get_pk_alg(const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_al
 int mbedtls_oid_get_oid_by_pk_alg(mbedtls_pk_type_t pk_alg,
                                   const char **oid, size_t *olen);
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 /**
  * \brief          Translate NamedCurve OID into an EC group identifier
  *
@@ -531,7 +579,31 @@ int mbedtls_oid_get_ec_grp(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *gr
  */
 int mbedtls_oid_get_oid_by_ec_grp(mbedtls_ecp_group_id grp_id,
                                   const char **oid, size_t *olen);
-#endif /* MBEDTLS_ECP_C */
+
+/**
+ * \brief          Translate AlgorithmIdentifier OID into an EC group identifier,
+ *                 for curves that are directly encoded at this level
+ *
+ * \param oid      OID to use
+ * \param grp_id   place to store group id
+ *
+ * \return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
+ */
+int mbedtls_oid_get_ec_grp_algid(const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id);
+
+/**
+ * \brief          Translate EC group identifier into AlgorithmIdentifier OID,
+ *                 for curves that are directly encoded at this level
+ *
+ * \param grp_id   EC group identifier
+ * \param oid      place to store ASN.1 OID string pointer
+ * \param olen     length of the OID
+ *
+ * \return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
+ */
+int mbedtls_oid_get_oid_by_ec_grp_algid(mbedtls_ecp_group_id grp_id,
+                                        const char **oid, size_t *olen);
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 /**
  * \brief          Translate SignatureAlgorithm OID into md_type and pk_type
@@ -631,7 +703,6 @@ int mbedtls_oid_get_oid_by_md(mbedtls_md_type_t md_alg, const char **oid, size_t
  * \return         0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
  */
 int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg);
-#endif /* MBEDTLS_CIPHER_C */
 
 #if defined(MBEDTLS_PKCS12_C)
 /**
@@ -647,6 +718,7 @@ int mbedtls_oid_get_cipher_alg(const mbedtls_asn1_buf *oid, mbedtls_cipher_type_
 int mbedtls_oid_get_pkcs12_pbe_alg(const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg,
                                    mbedtls_cipher_type_t *cipher_alg);
 #endif /* MBEDTLS_PKCS12_C */
+#endif /* MBEDTLS_CIPHER_C */
 
 #ifdef __cplusplus
 }
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pem.h b/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
index a33fc65e5fef4d2d229dbe7ecd016d17f26bf1f1..3c6a28d98d95b93bbbd1f7601a59cc3642a56268 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pem.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PEM_H
 #define MBEDTLS_PEM_H
@@ -85,11 +73,11 @@ void mbedtls_pem_init(mbedtls_pem_context *ctx);
  * \param data      source data to look in (must be nul-terminated)
  * \param pwd       password for decryption (can be NULL)
  * \param pwdlen    length of password
- * \param use_len   destination for total length used (set after header is
- *                  correctly read, so unless you get
+ * \param use_len   destination for total length used from data buffer. It is
+ *                  set after header is correctly read, so unless you get
  *                  MBEDTLS_ERR_PEM_BAD_INPUT_DATA or
  *                  MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is
- *                  the length to skip)
+ *                  the length to skip.
  *
  * \note            Attempts to check password correctness by verifying if
  *                  the decrypted text starts with an ASN.1 sequence of
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pk.h b/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
index 3de7a8fa04e34aa620c61bd0890bc0c2d0ee265b..52f4cc6c9e80428e2b22620c7bed894c15b905c8 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pk.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_PK_H
@@ -40,7 +28,7 @@
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #include "psa/crypto.h"
 #endif
 
@@ -171,30 +159,26 @@ typedef struct mbedtls_pk_rsassa_pss_options {
 #endif
 #endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
 
-/**
- * \brief   The following defines are meant to list ECDSA capabilities of the
- *          PK module in a general way (without any reference to how this
- *          is achieved, which can be either through PSA driver or
- *          MBEDTLS_ECDSA_C)
+/* Internal helper to define which fields in the pk_context structure below
+ * should be used for EC keys: legacy ecp_keypair or the raw (PSA friendly)
+ * format. It should be noted that this only affects how data is stored, not
+ * which functions are used for various operations. The overall picture looks
+ * like this:
+ * - if USE_PSA is not defined and ECP_C is defined then use ecp_keypair data
+ *   structure and legacy functions
+ * - if USE_PSA is defined and
+ *     - if ECP_C then use ecp_keypair structure, convert data to a PSA friendly
+ *       format and use PSA functions
+ *     - if !ECP_C then use new raw data and PSA functions directly.
+ *
+ * The main reason for the "intermediate" (USE_PSA + ECP_C) above is that as long
+ * as ECP_C is defined mbedtls_pk_ec() gives the user a read/write access to the
+ * ecp_keypair structure inside the pk_context so they can modify it using
+ * ECP functions which are not under PK module's control.
  */
-#if !defined(MBEDTLS_USE_PSA_CRYPTO)
-#if defined(MBEDTLS_ECDSA_C)
-#define MBEDTLS_PK_CAN_ECDSA_SIGN
-#define MBEDTLS_PK_CAN_ECDSA_VERIFY
-#endif
-#else /* MBEDTLS_USE_PSA_CRYPTO */
-#if defined(PSA_WANT_ALG_ECDSA)
-#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
-#define MBEDTLS_PK_CAN_ECDSA_SIGN
-#endif
-#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#define MBEDTLS_PK_CAN_ECDSA_VERIFY
-#endif
-#endif /* PSA_WANT_ALG_ECDSA */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY) || defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-#define MBEDTLS_PK_CAN_ECDSA_SOME
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
+    !defined(MBEDTLS_ECP_C)
+#define MBEDTLS_PK_USE_PSA_EC_DATA
 #endif
 
 /**
@@ -204,6 +188,7 @@ typedef enum {
     MBEDTLS_PK_DEBUG_NONE = 0,
     MBEDTLS_PK_DEBUG_MPI,
     MBEDTLS_PK_DEBUG_ECP,
+    MBEDTLS_PK_DEBUG_PSA_EC,
 } mbedtls_pk_debug_type;
 
 /**
@@ -227,12 +212,56 @@ typedef struct mbedtls_pk_debug_item {
  */
 typedef struct mbedtls_pk_info_t mbedtls_pk_info_t;
 
+#define MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN \
+    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
 /**
  * \brief           Public key container
  */
 typedef struct mbedtls_pk_context {
     const mbedtls_pk_info_t *MBEDTLS_PRIVATE(pk_info);    /**< Public key information         */
     void *MBEDTLS_PRIVATE(pk_ctx);                        /**< Underlying public key context  */
+    /* The following field is used to store the ID of a private key in the
+     * following cases:
+     * - opaque key when MBEDTLS_USE_PSA_CRYPTO is defined
+     * - normal key when MBEDTLS_PK_USE_PSA_EC_DATA is defined. In this case:
+     *    - the pk_ctx above is not not used to store the private key anymore.
+     *      Actually that field not populated at all in this case because also
+     *      the public key will be stored in raw format as explained below
+     *    - this ID is used for all private key operations (ex: sign, check
+     *      key pair, key write, etc) using PSA functions
+     *
+     * Note: this private key storing solution only affects EC keys, not the
+     *       other ones. The latters still use the pk_ctx to store their own
+     *       context. */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(priv_id);      /**< Key ID for opaque keys */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    /* The following fields are meant for storing the public key in raw format
+     * which is handy for:
+     * - easily importing it into the PSA context
+     * - reducing the ECP module dependencies in the PK one.
+     *
+     * When MBEDTLS_PK_USE_PSA_EC_DATA is enabled:
+     * - the pk_ctx above is not used anymore for storing the public key
+     *   inside the ecp_keypair structure
+     * - the following fields are used for all public key operations: signature
+     *   verify, key pair check and key write.
+     * - For a key pair, priv_id contains the private key. For a public key,
+     *   priv_id is null.
+     * Of course, when MBEDTLS_PK_USE_PSA_EC_DATA is not enabled, the legacy
+     * ecp_keypair structure is used for storing the public key and performing
+     * all the operations.
+     *
+     * Note: This new public key storing solution only works for EC keys, not
+     *       other ones. The latters still use pk_ctx to store their own
+     *       context.
+     */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    uint8_t MBEDTLS_PRIVATE(pub_raw)[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN]; /**< Raw public key   */
+    size_t MBEDTLS_PRIVATE(pub_raw_len);            /**< Valid bytes in "pub_raw" */
+    psa_ecc_family_t MBEDTLS_PRIVATE(ec_family);    /**< EC family of pk */
+    size_t MBEDTLS_PRIVATE(ec_bits);                /**< Curve's bits of pk */
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 } mbedtls_pk_context;
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
@@ -330,32 +359,40 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info);
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 /**
- * \brief           Initialize a PK context to wrap a PSA key.
- *
- * \note            This function replaces mbedtls_pk_setup() for contexts
- *                  that wrap a (possibly opaque) PSA key instead of
- *                  storing and manipulating the key material directly.
- *
- * \param ctx       The context to initialize. It must be empty (type NONE).
- * \param key       The PSA key to wrap, which must hold an ECC or RSA key
- *                  pair (see notes below).
- *
- * \note            The wrapped key must remain valid as long as the
- *                  wrapping PK context is in use, that is at least between
- *                  the point this function is called and the point
- *                  mbedtls_pk_free() is called on this context. The wrapped
- *                  key might then be independently used or destroyed.
- *
- * \note            This function is currently only available for ECC or RSA
- *                  key pairs (that is, keys containing private key material).
- *                  Support for other key types may be added later.
- *
- * \return          \c 0 on success.
- * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input
- *                  (context already used, invalid key identifier).
- * \return          #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an
- *                  ECC key pair.
- * \return          #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
+ * \brief Initialize a PK context to wrap a PSA key.
+ *
+ * This function creates a PK context which wraps a PSA key. The PSA wrapped
+ * key must be an EC or RSA key pair (DH is not suported in the PK module).
+ *
+ * Under the hood PSA functions will be used to perform the required
+ * operations and, based on the key type, used algorithms will be:
+ * * EC:
+ *     * verify, verify_ext, sign, sign_ext: ECDSA.
+ * * RSA:
+ *     * sign, decrypt: use the primary algorithm in the wrapped PSA key;
+ *     * sign_ext: RSA PSS if the pk_type is #MBEDTLS_PK_RSASSA_PSS, otherwise
+ *       it falls back to the sign() case;
+ *     * verify, verify_ext, encrypt: not supported.
+ *
+ * In order for the above operations to succeed, the policy of the wrapped PSA
+ * key must allow the specified algorithm.
+ *
+ * Opaque PK contexts wrapping an EC keys also support \c mbedtls_pk_check_pair(),
+ * whereas RSA ones do not.
+ *
+ * \warning The PSA wrapped key must remain valid as long as the wrapping PK
+ *          context is in use, that is at least between the point this function
+ *          is called and the point mbedtls_pk_free() is called on this context.
+ *
+ * \param ctx The context to initialize. It must be empty (type NONE).
+ * \param key The PSA key to wrap, which must hold an ECC or RSA key pair.
+ *
+ * \return    \c 0 on success.
+ * \return    #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input (context already
+ *            used, invalid key identifier).
+ * \return    #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an ECC or
+ *            RSA key pair.
+ * \return    #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure.
  */
 int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
                             const mbedtls_svc_key_id_t key);
@@ -429,7 +466,7 @@ int mbedtls_pk_can_do(const mbedtls_pk_context *ctx, mbedtls_pk_type_t type);
  *                  PSA_ALG_RSA_PKCS1V15_CRYPT,
  *                  PSA_ALG_ECDSA(hash),
  *                  PSA_ALG_ECDH, where hash is a specific hash.
- * \param usage  PSA usage flag to check against, must be composed of:
+ * \param usage     PSA usage flag to check against, must be composed of:
  *                  PSA_KEY_USAGE_SIGN_HASH
  *                  PSA_KEY_USAGE_DECRYPT
  *                  PSA_KEY_USAGE_DERIVE.
@@ -450,6 +487,237 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
                           psa_key_usage_t usage);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+/**
+ * \brief           Determine valid PSA attributes that can be used to
+ *                  import a key into PSA.
+ *
+ * The attributes determined by this function are suitable
+ * for calling mbedtls_pk_import_into_psa() to create
+ * a PSA key with the same key material.
+ *
+ * The typical flow of operations involving this function is
+ * ```
+ * psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+ * int ret = mbedtls_pk_get_psa_attributes(pk, &attributes);
+ * if (ret != 0) ...; // error handling omitted
+ * // Tweak attributes if desired
+ * psa_key_id_t key_id = 0;
+ * ret = mbedtls_pk_import_into_psa(pk, &attributes, &key_id);
+ * if (ret != 0) ...; // error handling omitted
+ * ```
+ *
+ * \note            This function does not support RSA-alt contexts
+ *                  (set up with mbedtls_pk_setup_rsa_alt()).
+ *
+ * \param[in] pk    The PK context to use. It must have been set up.
+ *                  It can either contain a key pair or just a public key.
+ * \param usage     A single `PSA_KEY_USAGE_xxx` flag among the following:
+ *                  - #PSA_KEY_USAGE_DECRYPT: \p pk must contain a
+ *                    key pair. The output \p attributes will contain a
+ *                    key pair type, and the usage policy will allow
+ *                    #PSA_KEY_USAGE_ENCRYPT as well as
+ *                    #PSA_KEY_USAGE_DECRYPT.
+ *                  - #PSA_KEY_USAGE_DERIVE: \p pk must contain a
+ *                    key pair. The output \p attributes will contain a
+ *                    key pair type.
+ *                  - #PSA_KEY_USAGE_ENCRYPT: The output
+ *                    \p attributes will contain a public key type.
+ *                  - #PSA_KEY_USAGE_SIGN_HASH: \p pk must contain a
+ *                    key pair. The output \p attributes will contain a
+ *                    key pair type, and the usage policy will allow
+ *                    #PSA_KEY_USAGE_VERIFY_HASH as well as
+ *                    #PSA_KEY_USAGE_SIGN_HASH.
+ *                  - #PSA_KEY_USAGE_SIGN_MESSAGE: \p pk must contain a
+ *                    key pair. The output \p attributes will contain a
+ *                    key pair type, and the usage policy will allow
+ *                    #PSA_KEY_USAGE_VERIFY_MESSAGE as well as
+ *                    #PSA_KEY_USAGE_SIGN_MESSAGE.
+ *                  - #PSA_KEY_USAGE_VERIFY_HASH: The output
+ *                    \p attributes will contain a public key type.
+ *                  - #PSA_KEY_USAGE_VERIFY_MESSAGE: The output
+ *                    \p attributes will contain a public key type.
+ * \param[out] attributes
+ *                  On success, valid attributes to import the key into PSA.
+ *                  - The lifetime and key identifier are unchanged. If the
+ *                    attribute structure was initialized or reset before
+ *                    calling this function, this will result in a volatile
+ *                    key. Call psa_set_key_identifier() before or after this
+ *                    function if you wish to create a persistent key. Call
+ *                    psa_set_key_lifetime() before or after this function if
+ *                    you wish to import the key in a secure element.
+ *                  - The key type and bit-size are determined by the contents
+ *                    of the PK context. If the PK context contains a key
+ *                    pair, the key type can be either a key pair type or
+ *                    the corresponding public key type, depending on
+ *                    \p usage. If the PK context contains a public key,
+ *                    the key type is a public key type.
+ *                  - The key's policy is determined by the key type and
+ *                    the \p usage parameter. The usage always allows
+ *                    \p usage, exporting and copying the key, and
+ *                    possibly other permissions as documented for the
+ *                    \p usage parameter.
+ *                    The permitted algorithm policy is determined as follows
+ *                    based on the #mbedtls_pk_type_t type of \p pk,
+ *                    the chosen \p usage and other factors:
+ *                      - #MBEDTLS_PK_RSA whose underlying
+ *                        #mbedtls_rsa_context has the padding mode
+ *                        #MBEDTLS_RSA_PKCS_V15:
+ *                        #PSA_ALG_RSA_PKCS1V15_SIGN(#PSA_ALG_ANY_HASH)
+ *                        if \p usage is SIGN/VERIFY, and
+ *                        #PSA_ALG_RSA_PKCS1V15_CRYPT
+ *                        if \p usage is ENCRYPT/DECRYPT.
+ *                      - #MBEDTLS_PK_RSA whose underlying
+ *                        #mbedtls_rsa_context has the padding mode
+ *                        #MBEDTLS_RSA_PKCS_V21 and the digest type
+ *                        corresponding to the PSA algorithm \c hash:
+ *                        #PSA_ALG_RSA_PSS_ANY_SALT(#PSA_ALG_ANY_HASH)
+ *                        if \p usage is SIGN/VERIFY, and
+ *                        #PSA_ALG_RSA_OAEP(\c hash)
+ *                        if \p usage is ENCRYPT/DECRYPT.
+ *                      - #MBEDTLS_PK_RSA_ALT: not supported.
+ *                      - #MBEDTLS_PK_ECDSA or #MBEDTLS_PK_ECKEY
+ *                        if \p usage is SIGN/VERIFY:
+ *                        #PSA_ALG_DETERMINISTIC_ECDSA(#PSA_ALG_ANY_HASH)
+ *                        if #MBEDTLS_ECDSA_DETERMINISTIC is enabled,
+ *                        otherwise #PSA_ALG_ECDSA(#PSA_ALG_ANY_HASH).
+ *                      - #MBEDTLS_PK_ECKEY_DH or #MBEDTLS_PK_ECKEY
+ *                        if \p usage is DERIVE:
+ *                        #PSA_ALG_ECDH.
+ *                      - #MBEDTLS_PK_OPAQUE: same as the primary algorithm
+ *                        set for the underlying PSA key, except that
+ *                        sign/decrypt flags are removed if the type is
+ *                        set to a public key type.
+ *                        The underlying key must allow \p usage.
+ *                        Note that the enrollment algorithm set with
+ *                        psa_set_key_enrollment_algorithm() is not copied.
+ *
+ * \return          0 on success.
+ *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain
+ *                  a key of the type identified in \p attributes.
+ *                  Another error code on other failures.
+ */
+int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
+                                  psa_key_usage_t usage,
+                                  psa_key_attributes_t *attributes);
+
+/**
+ * \brief           Import a key into the PSA key store.
+ *
+ * This function is equivalent to calling psa_import_key()
+ * with the key material from \p pk.
+ *
+ * The typical way to use this function is:
+ * -# Call mbedtls_pk_get_psa_attributes() to obtain
+ *    attributes for the given key.
+ * -# If desired, modify the attributes, for example:
+ *     - To create a persistent key, call
+ *       psa_set_key_identifier() and optionally
+ *       psa_set_key_lifetime().
+ *     - To import only the public part of a key pair:
+ *
+ *           psa_set_key_type(&attributes,
+ *                            PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(
+ *                                psa_get_key_type(&attributes)));
+ *     - Restrict the key usage if desired.
+ * -# Call mbedtls_pk_import_into_psa().
+ *
+ * \note            This function does not support RSA-alt contexts
+ *                  (set up with mbedtls_pk_setup_rsa_alt()).
+ *
+ * \param[in] pk    The PK context to use. It must have been set up.
+ *                  It can either contain a key pair or just a public key.
+ * \param[in] attributes
+ *                  The attributes to use for the new key. They must be
+ *                  compatible with \p pk. In particular, the key type
+ *                  must match the content of \p pk.
+ *                  If \p pk contains a key pair, the key type in
+ *                  attributes can be either the key pair type or the
+ *                  corresponding public key type (to import only the
+ *                  public part).
+ * \param[out] key_id
+ *                  On success, the identifier of the newly created key.
+ *                  On error, this is #MBEDTLS_SVC_KEY_ID_INIT.
+ *
+ * \return          0 on success.
+ *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if \p pk does not contain
+ *                  a key of the type identified in \p attributes.
+ *                  Another error code on other failures.
+ */
+int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
+                               const psa_key_attributes_t *attributes,
+                               mbedtls_svc_key_id_t *key_id);
+
+/**
+ * \brief           Create a PK context starting from a key stored in PSA.
+ *                  This key:
+ *                  - must be exportable and
+ *                  - must be an RSA or EC key pair or public key (FFDH is not supported in PK).
+ *
+ *                  The resulting PK object will be a transparent type:
+ *                  - #MBEDTLS_PK_RSA for RSA keys or
+ *                  - #MBEDTLS_PK_ECKEY for EC keys.
+ *
+ *                  Once this functions returns the PK object will be completely
+ *                  independent from the original PSA key that it was generated
+ *                  from.
+ *                  Calling mbedtls_pk_sign(), mbedtls_pk_verify(),
+ *                  mbedtls_pk_encrypt(), mbedtls_pk_decrypt() on the resulting
+ *                  PK context will perform the corresponding algorithm for that
+ *                  PK context type.
+ *                  * For ECDSA, the choice of deterministic vs randomized will
+ *                    be based on the compile-time setting #MBEDTLS_ECDSA_DETERMINISTIC.
+ *                  * For an RSA key, the output PK context will allow both
+ *                    encrypt/decrypt and sign/verify regardless of the original
+ *                    key's policy.
+ *                    The original key's policy determines the output key's padding
+ *                    mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,
+ *                    otherwise PKCS1 v1.5 is set.
+ *
+ * \param key_id    The key identifier of the key stored in PSA.
+ * \param pk        The PK context that will be filled. It must be initialized,
+ *                  but not set up.
+ *
+ * \return          0 on success.
+ * \return          #MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input
+ *                  parameters are not correct.
+ */
+int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);
+
+/**
+ * \brief           Create a PK context for the public key of a PSA key.
+ *
+ *                  The key must be an RSA or ECC key. It can be either a
+ *                  public key or a key pair, and only the public key is copied.
+ *                  The resulting PK object will be a transparent type:
+ *                  - #MBEDTLS_PK_RSA for RSA keys or
+ *                  - #MBEDTLS_PK_ECKEY for EC keys.
+ *
+ *                  Once this functions returns the PK object will be completely
+ *                  independent from the original PSA key that it was generated
+ *                  from.
+ *                  Calling mbedtls_pk_verify() or
+ *                  mbedtls_pk_encrypt() on the resulting
+ *                  PK context will perform the corresponding algorithm for that
+ *                  PK context type.
+ *
+ *                  For an RSA key, the output PK context will allow both
+ *                  encrypt and verify regardless of the original key's policy.
+ *                  The original key's policy determines the output key's padding
+ *                  mode: PCKS1 v2.1 is set if the PSA key policy is OAEP or PSS,
+ *                  otherwise PKCS1 v1.5 is set.
+ *
+ * \param key_id    The key identifier of the key stored in PSA.
+ * \param pk        The PK context that will be filled. It must be initialized,
+ *                  but not set up.
+ *
+ * \return          0 on success.
+ * \return          MBEDTLS_ERR_PK_BAD_INPUT_DATA in case the provided input
+ *                  parameters are not correct.
+ */
+int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id, mbedtls_pk_context *pk);
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
 /**
  * \brief           Verify signature (including padding if relevant).
  *
@@ -468,14 +736,17 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
  * \param sig       Signature to verify
  * \param sig_len   Signature length
  *
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or PSS (accepting any salt length),
+ *                  depending on the padding mode in the underlying RSA context.
+ *                  For a pk object constructed by parsing, this is PKCS#1 v1.5
+ *                  by default. Use mbedtls_pk_verify_ext() to explicitly select
+ *                  a different algorithm.
+ *
  * \return          0 on success (signature is valid),
  *                  #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid
- *                  signature in sig but its length is less than \p siglen,
+ *                  signature in \p sig but its length is less than \p sig_len,
  *                  or a specific error code.
- *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
- *                  Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... )
- *                  to verify RSASSA_PSS signatures.
  */
 int mbedtls_pk_verify(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                       const unsigned char *hash, size_t hash_len,
@@ -524,7 +795,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
  *                  #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be
  *                  used for this type of signatures,
  *                  #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid
- *                  signature in sig but its length is less than \p siglen,
+ *                  signature in \p sig but its length is less than \p sig_len,
  *                  or a specific error code.
  *
  * \note            If hash_len is 0, then the length associated with md_alg
@@ -562,11 +833,15 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \return          0 on success, or a specific error code.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or PSS (using the largest possible salt
+ *                  length up to the hash length), depending on the padding mode
+ *                  in the underlying RSA context. For a pk object constructed
+ *                  by parsing, this is PKCS#1 v1.5 by default. Use
+ *                  mbedtls_pk_verify_ext() to explicitly select a different
+ *                  algorithm.
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
- *                  There is no interface in the PK module to make RSASSA-PSS
- *                  signatures yet.
+ * \return          0 on success, or a specific error code.
  *
  * \note            For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0.
  *                  For ECDSA, md_alg may never be MBEDTLS_MD_NONE.
@@ -576,7 +851,6 @@ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                     unsigned char *sig, size_t sig_size, size_t *sig_len,
                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
 /**
  * \brief           Make signature given a signature type.
  *
@@ -613,7 +887,6 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
                         unsigned char *sig, size_t sig_size, size_t *sig_len,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng);
-#endif /* MBEDTLS_PSA_CRYPTO_C */
 
 /**
  * \brief           Restartable version of \c mbedtls_pk_sign()
@@ -664,7 +937,10 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in
+ *                  the underlying RSA context. For a pk object constructed by
+ *                  parsing, this is PKCS#1 v1.5 by default.
  *
  * \return          0 on success, or a specific error code.
  */
@@ -685,9 +961,12 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
  * \param f_rng     RNG function, must not be \c NULL.
  * \param p_rng     RNG parameter
  *
- * \note            \p f_rng is used for padding generation.
+ * \note            For keys of type #MBEDTLS_PK_RSA, the signature algorithm is
+ *                  either PKCS#1 v1.5 or OAEP, depending on the padding mode in
+ *                  the underlying RSA context. For a pk object constructed by
+ *                  parsing, this is PKCS#1 v1.5 by default.
  *
- * \note            For RSA keys, the default padding type is PKCS#1 v1.5.
+ * \note            \p f_rng is used for padding generation.
  *
  * \return          0 on success, or a specific error code.
  */
@@ -1010,41 +1289,6 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
                             const mbedtls_pk_context *key);
 #endif /* MBEDTLS_PK_WRITE_C */
 
-/*
- * Internal module functions. You probably do not want to use these unless you
- * know you do.
- */
-#if defined(MBEDTLS_FS_IO)
-int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n);
-#endif
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/**
- * \brief           Turn an EC or RSA key into an opaque one.
- *
- * \warning         This is a temporary utility function for tests. It might
- *                  change or be removed at any time without notice.
- *
- * \param pk        Input: the EC or RSA key to import to a PSA key.
- *                  Output: a PK context wrapping that PSA key.
- * \param key       Output: a PSA key identifier.
- *                  It's the caller's responsibility to call
- *                  psa_destroy_key() on that key identifier after calling
- *                  mbedtls_pk_free() on the PK context.
- * \param alg       The algorithm to allow for use with that key.
- * \param usage     The usage to allow for use with that key.
- * \param alg2      The secondary algorithm to allow for use with that key.
- *
- * \return          \c 0 if successful.
- * \return          An Mbed TLS error code otherwise.
- */
-int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
-                              mbedtls_svc_key_id_t *key,
-                              psa_algorithm_t alg,
-                              psa_key_usage_t usage,
-                              psa_algorithm_t alg2);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
index eb9e2d9df0836f47037b0e24c65052f44a0f9d7c..87f7681f29a7be05bee7ff7a9786faf692f987f4 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs12.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PKCS12_H
 #define MBEDTLS_PKCS12_H
@@ -43,19 +31,39 @@
 #define MBEDTLS_PKCS12_DERIVE_IV        2   /**< initialization vector     */
 #define MBEDTLS_PKCS12_DERIVE_MAC_KEY   3   /**< integrity / MAC key       */
 
-#define MBEDTLS_PKCS12_PBE_DECRYPT      0
-#define MBEDTLS_PKCS12_PBE_ENCRYPT      1
+#define MBEDTLS_PKCS12_PBE_DECRYPT      MBEDTLS_DECRYPT
+#define MBEDTLS_PKCS12_PBE_ENCRYPT      MBEDTLS_ENCRYPT
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if defined(MBEDTLS_ASN1_PARSE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief            PKCS12 Password Based function (encryption / decryption)
  *                   for cipher-based and mbedtls_md-based PBE's
  *
+ * \note             When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must
+ *                   be enabled at compile time.
+ *
+ * \deprecated       This function is deprecated and will be removed in a
+ *                   future version of the library.
+ *                   Please use mbedtls_pkcs12_pbe_ext() instead.
+ *
+ * \warning          When decrypting:
+ *                   - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile
+ *                     time, this function validates the CBC padding and returns
+ *                     #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is
+ *                     invalid. Note that this can help active adversaries
+ *                     attempting to brute-forcing the password. Note also that
+ *                     there is no guarantee that an invalid password will be
+ *                     detected (the chances of a valid padding with a random
+ *                     password are about 1/255).
+ *                   - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile
+ *                     time, this function does not validate the CBC padding.
+ *
  * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure
  * \param mode       either #MBEDTLS_PKCS12_PBE_ENCRYPT or
  *                   #MBEDTLS_PKCS12_PBE_DECRYPT
@@ -64,19 +72,80 @@ extern "C" {
  * \param pwd        Latin1-encoded password used. This may only be \c NULL when
  *                   \p pwdlen is 0. No null terminator should be used.
  * \param pwdlen     length of the password (may be 0)
- * \param input      the input data
+ * \param data       the input data
  * \param len        data length
- * \param output     the output buffer
+ * \param output     Output buffer.
+ *                   On success, it contains the encrypted or decrypted data,
+ *                   possibly followed by the CBC padding.
+ *                   On failure, the content is indeterminate.
+ *                   For decryption, there must be enough room for \p len
+ *                   bytes.
+ *                   For encryption, there must be enough room for
+ *                   \p len + 1 bytes, rounded up to the block size of
+ *                   the block cipher identified by \p pbe_params.
  *
  * \return           0 if successful, or a MBEDTLS_ERR_XXX code
  */
-int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
-                       mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
-                       const unsigned char *pwd,  size_t pwdlen,
-                       const unsigned char *input, size_t len,
-                       unsigned char *output);
+int MBEDTLS_DEPRECATED mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
+                                          mbedtls_cipher_type_t cipher_type,
+                                          mbedtls_md_type_t md_type,
+                                          const unsigned char *pwd,  size_t pwdlen,
+                                          const unsigned char *data, size_t len,
+                                          unsigned char *output);
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+
+/**
+ * \brief            PKCS12 Password Based function (encryption / decryption)
+ *                   for cipher-based and mbedtls_md-based PBE's
+ *
+ *
+ * \warning          When decrypting:
+ *                   - This function validates the CBC padding and returns
+ *                     #MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH if the padding is
+ *                     invalid. Note that this can help active adversaries
+ *                     attempting to brute-forcing the password. Note also that
+ *                     there is no guarantee that an invalid password will be
+ *                     detected (the chances of a valid padding with a random
+ *                     password are about 1/255).
+ *
+ * \param pbe_params an ASN1 buffer containing the pkcs-12 PbeParams structure
+ * \param mode       either #MBEDTLS_PKCS12_PBE_ENCRYPT or
+ *                   #MBEDTLS_PKCS12_PBE_DECRYPT
+ * \param cipher_type the cipher used
+ * \param md_type    the mbedtls_md used
+ * \param pwd        Latin1-encoded password used. This may only be \c NULL when
+ *                   \p pwdlen is 0. No null terminator should be used.
+ * \param pwdlen     length of the password (may be 0)
+ * \param data       the input data
+ * \param len        data length
+ * \param output     Output buffer.
+ *                   On success, it contains the encrypted or decrypted data,
+ *                   possibly followed by the CBC padding.
+ *                   On failure, the content is indeterminate.
+ *                   For decryption, there must be enough room for \p len
+ *                   bytes.
+ *                   For encryption, there must be enough room for
+ *                   \p len + 1 bytes, rounded up to the block size of
+ *                   the block cipher identified by \p pbe_params.
+ * \param output_size size of output buffer.
+ *                    This must be big enough to accommodate for output plus
+ *                    padding data.
+ * \param output_len On success, length of actual data written to the output buffer.
+ *
+ * \return           0 if successful, or a MBEDTLS_ERR_XXX code
+ */
+int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,
+                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
+                           const unsigned char *pwd,  size_t pwdlen,
+                           const unsigned char *data, size_t len,
+                           unsigned char *output, size_t output_size,
+                           size_t *output_len);
+
+#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
 
-#endif /* MBEDTLS_ASN1_PARSE_C */
+#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */
 
 /**
  * \brief            The PKCS#12 derivation function uses a password and a salt
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
index 152b45fb1a1a2a9bf8ed1efa30806035694532b7..9ba5689d4a259338c7dbc03c1b4f4e4c7f3b1047 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs5.h
@@ -7,27 +7,17 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PKCS5_H
 #define MBEDTLS_PKCS5_H
 
 #include "mbedtls/build_info.h"
+#include "mbedtls/platform_util.h"
 
 #include "mbedtls/asn1.h"
 #include "mbedtls/md.h"
+#include "mbedtls/cipher.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -41,34 +31,106 @@
 /** Given private key password does not allow for correct decryption. */
 #define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH               -0x2e00
 
-#define MBEDTLS_PKCS5_DECRYPT      0
-#define MBEDTLS_PKCS5_ENCRYPT      1
+#define MBEDTLS_PKCS5_DECRYPT      MBEDTLS_DECRYPT
+#define MBEDTLS_PKCS5_ENCRYPT      MBEDTLS_ENCRYPT
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#if defined(MBEDTLS_ASN1_PARSE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
 
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief          PKCS#5 PBES2 function
  *
+ * \note           When encrypting, #MBEDTLS_CIPHER_PADDING_PKCS7 must
+ *                 be enabled at compile time.
+ *
+ * \deprecated     This function is deprecated and will be removed in a
+ *                 future version of the library.
+ *                 Please use mbedtls_pkcs5_pbes2_ext() instead.
+ *
+ * \warning        When decrypting:
+ *                 - if #MBEDTLS_CIPHER_PADDING_PKCS7 is enabled at compile
+ *                   time, this function validates the CBC padding and returns
+ *                   #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is
+ *                   invalid. Note that this can help active adversaries
+ *                   attempting to brute-forcing the password. Note also that
+ *                   there is no guarantee that an invalid password will be
+ *                   detected (the chances of a valid padding with a random
+ *                   password are about 1/255).
+ *                 - if #MBEDTLS_CIPHER_PADDING_PKCS7 is disabled at compile
+ *                   time, this function does not validate the CBC padding.
+ *
  * \param pbe_params the ASN.1 algorithm parameters
- * \param mode       either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT
+ * \param mode       either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT
  * \param pwd        password to use when generating key
  * \param pwdlen     length of password
  * \param data       data to process
  * \param datalen    length of data
- * \param output     output buffer
+ * \param output     Output buffer.
+ *                   On success, it contains the encrypted or decrypted data,
+ *                   possibly followed by the CBC padding.
+ *                   On failure, the content is indeterminate.
+ *                   For decryption, there must be enough room for \p datalen
+ *                   bytes.
+ *                   For encryption, there must be enough room for
+ *                   \p datalen + 1 bytes, rounded up to the block size of
+ *                   the block cipher identified by \p pbe_params.
  *
  * \returns        0 on success, or a MBEDTLS_ERR_XXX code if verification fails.
  */
-int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
-                        const unsigned char *pwd,  size_t pwdlen,
-                        const unsigned char *data, size_t datalen,
-                        unsigned char *output);
+int MBEDTLS_DEPRECATED mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
+                                           const unsigned char *pwd,  size_t pwdlen,
+                                           const unsigned char *data, size_t datalen,
+                                           unsigned char *output);
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+
+/**
+ * \brief          PKCS#5 PBES2 function
+ *
+ * \warning        When decrypting:
+ *                 - This function validates the CBC padding and returns
+ *                   #MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH if the padding is
+ *                   invalid. Note that this can help active adversaries
+ *                   attempting to brute-forcing the password. Note also that
+ *                   there is no guarantee that an invalid password will be
+ *                   detected (the chances of a valid padding with a random
+ *                   password are about 1/255).
+ *
+ * \param pbe_params the ASN.1 algorithm parameters
+ * \param mode       either #MBEDTLS_PKCS5_DECRYPT or #MBEDTLS_PKCS5_ENCRYPT
+ * \param pwd        password to use when generating key
+ * \param pwdlen     length of password
+ * \param data       data to process
+ * \param datalen    length of data
+ * \param output     Output buffer.
+ *                   On success, it contains the decrypted data.
+ *                   On failure, the content is indetermidate.
+ *                   For decryption, there must be enough room for \p datalen
+ *                   bytes.
+ *                   For encryption, there must be enough room for
+ *                   \p datalen + 1 bytes, rounded up to the block size of
+ *                   the block cipher identified by \p pbe_params.
+ * \param output_size size of output buffer.
+ *                    This must be big enough to accommodate for output plus
+ *                    padding data.
+ * \param output_len On success, length of actual data written to the output buffer.
+ *
+ * \returns        0 on success, or a MBEDTLS_ERR_XXX code if parsing or decryption fails.
+ */
+int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
+                            const unsigned char *pwd,  size_t pwdlen,
+                            const unsigned char *data, size_t datalen,
+                            unsigned char *output, size_t output_size,
+                            size_t *output_len);
+
+#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
 
-#endif /* MBEDTLS_ASN1_PARSE_C */
+#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C*/
 
 /**
  * \brief          PKCS#5 PBKDF2 using HMAC without using the HMAC context
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h
index 1231e340249a41eb2f3b8ee6c24a37c6253611b1..e9b482208e6eabcef63b3e3eb36e6349512e2fb5 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/pkcs7.h
@@ -6,19 +6,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /**
@@ -53,7 +41,6 @@
 #include "mbedtls/build_info.h"
 
 #include "mbedtls/asn1.h"
-#include "mbedtls/x509.h"
 #include "mbedtls/x509_crt.h"
 
 /**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
index f651587193a0ea1ea796d299803a33d1fd16dda0..de3d71d9dc5be5748276604adf58f972cda401ca 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform.h
@@ -21,19 +21,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PLATFORM_H
 #define MBEDTLS_PLATFORM_H
@@ -130,15 +118,28 @@ extern "C" {
 #endif
 #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
 
+/* Enable certain documented defines only when generating doxygen to avoid
+ * an "unrecognized define" error. */
+#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_CALLOC)
+#define MBEDTLS_PLATFORM_STD_CALLOC
+#endif
+
+#if defined(__DOXYGEN__) && !defined(MBEDTLS_PLATFORM_STD_FREE)
+#define MBEDTLS_PLATFORM_STD_FREE
+#endif
 
 /** \} name SECTION: Module settings */
 
 /*
  * The function pointers for calloc and free.
+ * Please see MBEDTLS_PLATFORM_STD_CALLOC and MBEDTLS_PLATFORM_STD_FREE
+ * in mbedtls_config.h for more information about behaviour and requirements.
  */
 #if defined(MBEDTLS_PLATFORM_MEMORY)
 #if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \
     defined(MBEDTLS_PLATFORM_CALLOC_MACRO)
+#undef mbedtls_free
+#undef mbedtls_calloc
 #define mbedtls_free       MBEDTLS_PLATFORM_FREE_MACRO
 #define mbedtls_calloc     MBEDTLS_PLATFORM_CALLOC_MACRO
 #else
@@ -160,6 +161,8 @@ int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t),
                                      void (*free_func)(void *));
 #endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */
 #else /* !MBEDTLS_PLATFORM_MEMORY */
+#undef mbedtls_free
+#undef mbedtls_calloc
 #define mbedtls_free       free
 #define mbedtls_calloc     calloc
 #endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */
@@ -184,6 +187,7 @@ extern int (*mbedtls_fprintf)(FILE *stream, const char *format, ...);
 int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *stream, const char *,
                                                      ...));
 #else
+#undef mbedtls_fprintf
 #if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO)
 #define mbedtls_fprintf    MBEDTLS_PLATFORM_FPRINTF_MACRO
 #else
@@ -208,6 +212,7 @@ extern int (*mbedtls_printf)(const char *format, ...);
  */
 int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...));
 #else /* !MBEDTLS_PLATFORM_PRINTF_ALT */
+#undef mbedtls_printf
 #if defined(MBEDTLS_PLATFORM_PRINTF_MACRO)
 #define mbedtls_printf     MBEDTLS_PLATFORM_PRINTF_MACRO
 #else
@@ -243,6 +248,7 @@ extern int (*mbedtls_snprintf)(char *s, size_t n, const char *format, ...);
 int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n,
                                                        const char *format, ...));
 #else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
+#undef mbedtls_snprintf
 #if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO)
 #define mbedtls_snprintf   MBEDTLS_PLATFORM_SNPRINTF_MACRO
 #else
@@ -279,6 +285,7 @@ extern int (*mbedtls_vsnprintf)(char *s, size_t n, const char *format, va_list a
 int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n,
                                                          const char *format, va_list arg));
 #else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
+#undef mbedtls_vsnprintf
 #if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO)
 #define mbedtls_vsnprintf   MBEDTLS_PLATFORM_VSNPRINTF_MACRO
 #else
@@ -320,7 +327,9 @@ extern void (*mbedtls_setbuf)(FILE *stream, char *buf);
  */
 int mbedtls_platform_set_setbuf(void (*setbuf_func)(
                                     FILE *stream, char *buf));
-#elif defined(MBEDTLS_PLATFORM_SETBUF_MACRO)
+#else
+#undef mbedtls_setbuf
+#if defined(MBEDTLS_PLATFORM_SETBUF_MACRO)
 /**
  * \brief                  Macro defining the function for the library to
  *                         call for `setbuf` functionality (changing the
@@ -334,7 +343,8 @@ int mbedtls_platform_set_setbuf(void (*setbuf_func)(
 #define mbedtls_setbuf    MBEDTLS_PLATFORM_SETBUF_MACRO
 #else
 #define mbedtls_setbuf    setbuf
-#endif /* MBEDTLS_PLATFORM_SETBUF_ALT / MBEDTLS_PLATFORM_SETBUF_MACRO */
+#endif /* MBEDTLS_PLATFORM_SETBUF_MACRO */
+#endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
 
 /*
  * The function pointers for exit
@@ -353,6 +363,7 @@ extern void (*mbedtls_exit)(int status);
  */
 int mbedtls_platform_set_exit(void (*exit_func)(int status));
 #else
+#undef mbedtls_exit
 #if defined(MBEDTLS_PLATFORM_EXIT_MACRO)
 #define mbedtls_exit   MBEDTLS_PLATFORM_EXIT_MACRO
 #else
@@ -405,6 +416,8 @@ int mbedtls_platform_set_nv_seed(
     int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len)
     );
 #else
+#undef mbedtls_nv_seed_read
+#undef mbedtls_nv_seed_write
 #if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \
     defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO)
 #define mbedtls_nv_seed_read    MBEDTLS_PLATFORM_NV_SEED_READ_MACRO
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
index eae6f5f879476aa2dd62d810eb6fb4a86dc4f57a..97f1963abaad236e74b5d5e55134b68e6e376015 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform_time.h
@@ -1,23 +1,11 @@
 /**
  * \file platform_time.h
  *
- * \brief mbed TLS Platform time abstraction
+ * \brief Mbed TLS Platform time abstraction
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PLATFORM_TIME_H
 #define MBEDTLS_PLATFORM_TIME_H
@@ -39,6 +27,29 @@ typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t;
 typedef time_t mbedtls_time_t;
 #endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */
 
+#if defined(MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO)
+typedef MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO mbedtls_ms_time_t;
+#else
+#include <stdint.h>
+#include <inttypes.h>
+typedef int64_t mbedtls_ms_time_t;
+#endif /* MBEDTLS_PLATFORM_MS_TIME_TYPE_MACRO */
+
+/**
+ * \brief   Get time in milliseconds.
+ *
+ * \return Monotonically-increasing current time in milliseconds.
+ *
+ * \note Define MBEDTLS_PLATFORM_MS_TIME_ALT to be able to provide an
+ *       alternative implementation
+ *
+ * \warning This function returns a monotonically-increasing time value from a
+ *          start time that will differ from platform to platform, and possibly
+ *          from run to run of the process.
+ *
+ */
+mbedtls_ms_time_t mbedtls_ms_time(void);
+
 /*
  * The function pointers for time
  */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h b/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
index edbde9440e845ab04e677df333a9eca748eee53f..1b371ef3f465d672eef8f680c555eca94da08f3e 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/platform_util.h
@@ -6,19 +6,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PLATFORM_UTIL_H
 #define MBEDTLS_PLATFORM_UTIL_H
@@ -35,10 +23,6 @@
 extern "C" {
 #endif
 
-/* Internal macros meant to be called only from within the library. */
-#define MBEDTLS_INTERNAL_VALIDATE_RET(cond, ret)  do { } while (0)
-#define MBEDTLS_INTERNAL_VALIDATE(cond)           do { } while (0)
-
 /* Internal helper macros for deprecating API constants. */
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 #if defined(MBEDTLS_DEPRECATED_WARNING)
@@ -145,6 +129,11 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;
 #define MBEDTLS_IGNORE_RETURN(result) ((void) !(result))
 #endif
 
+/* If the following macro is defined, the library is being built by the test
+ * framework, and the framework is going to provide a replacement
+ * mbedtls_platform_zeroize() using a preprocessor macro, so the function
+ * declaration should be omitted.  */
+#if !defined(MBEDTLS_TEST_DEFINES_ZEROIZE) //no-check-names
 /**
  * \brief       Securely zeroize a buffer
  *
@@ -168,6 +157,7 @@ MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t;
  *
  */
 void mbedtls_platform_zeroize(void *buf, size_t len);
+#endif
 
 #if defined(MBEDTLS_HAVE_TIME_DATE)
 /**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h b/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
index 3025ef1f211937bf21a8f005ecbf9a38b2d2fcde..61bcaa6b6465fd1aacaec03b65c0b88de573f6e0 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/poly1305.h
@@ -14,19 +14,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_POLY1305_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h b/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h
index 61fa8777b604b6ed0aa2f09646690aa5e54e3921..580f3eb44695c7b2e0c0ebe693dc4dcddb46ea14 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/private_access.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_PRIVATE_ACCESS_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h b/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h
index b750716a9ec672f9de77e941d804dcd6906d478b..c78cc2333359a2c854a9cdf9dfa0726383d3f6b7 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/psa_util.h
@@ -2,25 +2,10 @@
  * \file psa_util.h
  *
  * \brief Utility functions for the use of the PSA Crypto library.
- *
- * \warning This function is not part of the public API and may
- *          change at any time.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_PSA_UTIL_H
@@ -29,273 +14,31 @@
 
 #include "mbedtls/build_info.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-
 #include "psa/crypto.h"
 
-#include "mbedtls/ecp.h"
-#include "mbedtls/md.h"
-#include "mbedtls/pk.h"
-#include "mbedtls/oid.h"
-#include "mbedtls/error.h"
-
-#include <string.h>
-
-/* Translations for symmetric crypto. */
-
-static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
-    mbedtls_cipher_type_t cipher)
-{
-    switch (cipher) {
-        case MBEDTLS_CIPHER_AES_128_CCM:
-        case MBEDTLS_CIPHER_AES_192_CCM:
-        case MBEDTLS_CIPHER_AES_256_CCM:
-        case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG:
-        case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG:
-        case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG:
-        case MBEDTLS_CIPHER_AES_128_GCM:
-        case MBEDTLS_CIPHER_AES_192_GCM:
-        case MBEDTLS_CIPHER_AES_256_GCM:
-        case MBEDTLS_CIPHER_AES_128_CBC:
-        case MBEDTLS_CIPHER_AES_192_CBC:
-        case MBEDTLS_CIPHER_AES_256_CBC:
-        case MBEDTLS_CIPHER_AES_128_ECB:
-        case MBEDTLS_CIPHER_AES_192_ECB:
-        case MBEDTLS_CIPHER_AES_256_ECB:
-            return PSA_KEY_TYPE_AES;
-
-        /* ARIA not yet supported in PSA. */
-        /* case MBEDTLS_CIPHER_ARIA_128_CCM:
-           case MBEDTLS_CIPHER_ARIA_192_CCM:
-           case MBEDTLS_CIPHER_ARIA_256_CCM:
-           case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG:
-           case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG:
-           case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG:
-           case MBEDTLS_CIPHER_ARIA_128_GCM:
-           case MBEDTLS_CIPHER_ARIA_192_GCM:
-           case MBEDTLS_CIPHER_ARIA_256_GCM:
-           case MBEDTLS_CIPHER_ARIA_128_CBC:
-           case MBEDTLS_CIPHER_ARIA_192_CBC:
-           case MBEDTLS_CIPHER_ARIA_256_CBC:
-               return( PSA_KEY_TYPE_ARIA ); */
-
-        default:
-            return 0;
-    }
-}
-
-static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
-    mbedtls_cipher_mode_t mode, size_t taglen)
-{
-    switch (mode) {
-        case MBEDTLS_MODE_ECB:
-            return PSA_ALG_ECB_NO_PADDING;
-        case MBEDTLS_MODE_GCM:
-            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen);
-        case MBEDTLS_MODE_CCM:
-            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen);
-        case MBEDTLS_MODE_CCM_STAR_NO_TAG:
-            return PSA_ALG_CCM_STAR_NO_TAG;
-        case MBEDTLS_MODE_CBC:
-            if (taglen == 0) {
-                return PSA_ALG_CBC_NO_PADDING;
-            } else {
-                return 0;
-            }
-        default:
-            return 0;
-    }
-}
-
-static inline psa_key_usage_t mbedtls_psa_translate_cipher_operation(
-    mbedtls_operation_t op)
-{
-    switch (op) {
-        case MBEDTLS_ENCRYPT:
-            return PSA_KEY_USAGE_ENCRYPT;
-        case MBEDTLS_DECRYPT:
-            return PSA_KEY_USAGE_DECRYPT;
-        default:
-            return 0;
-    }
-}
-
-/* Translations for hashing. */
-
-/* Note: this function should not be used from inside the library, use
- * mbedtls_hash_info_psa_from_md() from the internal hash_info.h instead.
- * It is kept only for compatibility in case applications were using it. */
-static inline psa_algorithm_t mbedtls_psa_translate_md(mbedtls_md_type_t md_alg)
-{
-    switch (md_alg) {
-#if defined(MBEDTLS_MD5_C) || defined(PSA_WANT_ALG_MD5)
-        case MBEDTLS_MD_MD5:
-            return PSA_ALG_MD5;
-#endif
-#if defined(MBEDTLS_SHA1_C) || defined(PSA_WANT_ALG_SHA_1)
-        case MBEDTLS_MD_SHA1:
-            return PSA_ALG_SHA_1;
-#endif
-#if defined(MBEDTLS_SHA224_C) || defined(PSA_WANT_ALG_SHA_224)
-        case MBEDTLS_MD_SHA224:
-            return PSA_ALG_SHA_224;
-#endif
-#if defined(MBEDTLS_SHA256_C) || defined(PSA_WANT_ALG_SHA_256)
-        case MBEDTLS_MD_SHA256:
-            return PSA_ALG_SHA_256;
-#endif
-#if defined(MBEDTLS_SHA384_C) || defined(PSA_WANT_ALG_SHA_384)
-        case MBEDTLS_MD_SHA384:
-            return PSA_ALG_SHA_384;
-#endif
-#if defined(MBEDTLS_SHA512_C) || defined(PSA_WANT_ALG_SHA_512)
-        case MBEDTLS_MD_SHA512:
-            return PSA_ALG_SHA_512;
-#endif
-#if defined(MBEDTLS_RIPEMD160_C) || defined(PSA_WANT_ALG_RIPEMD160)
-        case MBEDTLS_MD_RIPEMD160:
-            return PSA_ALG_RIPEMD160;
-#endif
-        case MBEDTLS_MD_NONE:
-            return 0;
-        default:
-            return 0;
-    }
-}
-
-/* Translations for ECC. */
-
-static inline int mbedtls_psa_get_ecc_oid_from_id(
-    psa_ecc_family_t curve, size_t bits,
-    char const **oid, size_t *oid_len)
-{
-    switch (curve) {
-        case PSA_ECC_FAMILY_SECP_R1:
-            switch (bits) {
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-                case 192:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP192R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-                case 224:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP224R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-                case 256:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP256R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-                case 384:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP384R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP384R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-                case 521:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP521R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP521R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
-            }
-            break;
-        case PSA_ECC_FAMILY_SECP_K1:
-            switch (bits) {
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-                case 192:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP192K1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP192K1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-                case 224:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP224K1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP224K1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-                case 256:
-                    *oid = MBEDTLS_OID_EC_GRP_SECP256K1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_SECP256K1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
-            }
-            break;
-        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
-            switch (bits) {
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-                case 256:
-                    *oid = MBEDTLS_OID_EC_GRP_BP256R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP256R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-                case 384:
-                    *oid = MBEDTLS_OID_EC_GRP_BP384R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP384R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-                case 512:
-                    *oid = MBEDTLS_OID_EC_GRP_BP512R1;
-                    *oid_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_EC_GRP_BP512R1);
-                    return 0;
-#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
-            }
-            break;
-    }
-    (void) oid;
-    (void) oid_len;
-    return -1;
-}
-
-#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \
-    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
-
-#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \
-    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
-
-/* Expose whatever RNG the PSA subsystem uses to applications using the
- * mbedtls_xxx API. The declarations and definitions here need to be
- * consistent with the implementation in library/psa_crypto_random_impl.h.
- * See that file for implementation documentation. */
-
-
-/* The type of a `f_rng` random generator function that many library functions
- * take.
- *
- * This type name is not part of the Mbed TLS stable API. It may be renamed
- * or moved without warning.
- */
-typedef int mbedtls_f_rng_t(void *p_rng, unsigned char *output, size_t output_size);
+/* ASN1 defines used in the ECDSA conversion functions.
+ * Note: intentionally not adding MBEDTLS_ASN1_[PARSE|WRITE]_C guards here
+ * otherwise error codes would be unknown in test_suite_psa_crypto_util.data.*/
+#include <mbedtls/asn1write.h>
 
-#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 
 /** The random generator function for the PSA subsystem.
  *
  * This function is suitable as the `f_rng` random generator function
- * parameter of many `mbedtls_xxx` functions. Use #MBEDTLS_PSA_RANDOM_STATE
- * to obtain the \p p_rng parameter.
+ * parameter of many `mbedtls_xxx` functions.
  *
  * The implementation of this function depends on the configuration of the
  * library.
  *
- * \note Depending on the configuration, this may be a function or
- *       a pointer to a function.
- *
  * \note This function may only be used if the PSA crypto subsystem is active.
  *       This means that you must call psa_crypto_init() before any call to
  *       this function, and you must not call this function after calling
  *       mbedtls_psa_crypto_free().
  *
- * \param p_rng         The random generator context. This must be
- *                      #MBEDTLS_PSA_RANDOM_STATE. No other state is
- *                      supported.
+ * \param p_rng         This parameter is only kept for backward compatibility
+ *                      reasons with legacy `f_rng` functions and it's ignored.
+ *                      Set to #MBEDTLS_PSA_RANDOM_STATE or NULL.
  * \param output        The buffer to fill. It must have room for
  *                      \c output_size bytes.
  * \param output_size   The number of bytes to write to \p output.
@@ -317,81 +60,129 @@ int mbedtls_psa_get_random(void *p_rng,
 
 /** The random generator state for the PSA subsystem.
  *
- * This macro expands to an expression which is suitable as the `p_rng`
- * random generator state parameter of many `mbedtls_xxx` functions.
- * It must be used in combination with the random generator function
- * mbedtls_psa_get_random().
- *
- * The implementation of this macro depends on the configuration of the
- * library. Do not make any assumption on its nature.
+ * This macro always expands to NULL because the `p_rng` parameter is unused
+ * in mbedtls_psa_get_random(), but it's kept for interface's backward
+ * compatibility.
  */
-#define MBEDTLS_PSA_RANDOM_STATE NULL
-
-#else /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
-
-#if defined(MBEDTLS_CTR_DRBG_C)
-#include "mbedtls/ctr_drbg.h"
-typedef mbedtls_ctr_drbg_context mbedtls_psa_drbg_context_t;
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_ctr_drbg_random;
-#elif defined(MBEDTLS_HMAC_DRBG_C)
-#include "mbedtls/hmac_drbg.h"
-typedef mbedtls_hmac_drbg_context mbedtls_psa_drbg_context_t;
-static mbedtls_f_rng_t *const mbedtls_psa_get_random = mbedtls_hmac_drbg_random;
-#endif
-extern mbedtls_psa_drbg_context_t *const mbedtls_psa_random_state;
+#define MBEDTLS_PSA_RANDOM_STATE    NULL
 
-#define MBEDTLS_PSA_RANDOM_STATE mbedtls_psa_random_state
-
-#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
-
-typedef struct {
-    psa_status_t psa_status;
-    int16_t mbedtls_error;
-} mbedtls_error_pair_t;
+/** \defgroup psa_tls_helpers TLS helper functions
+ * @{
+ */
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#include <mbedtls/ecp.h>
 
-#if !defined(MBEDTLS_MD_C) || !defined(MBEDTLS_MD5_C) || defined(MBEDTLS_USE_PSA_CRYPTO)
-extern const mbedtls_error_pair_t psa_to_md_errors[4];
-#endif
+/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA.
+ *
+ * \param grpid         An Mbed TLS elliptic curve identifier
+ *                      (`MBEDTLS_ECP_DP_xxx`).
+ * \param[out] bits     On success the bit size of the curve; 0 on failure.
+ *
+ * \return              If the curve is supported in the PSA API, this function
+ *                      returns the proper PSA curve identifier
+ *                      (`PSA_ECC_FAMILY_xxx`). This holds even if the curve is
+ *                      not supported by the ECP module.
+ * \return              \c 0 if the curve is not supported in the PSA API.
+ */
+psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
+                                          size_t *bits);
 
-#if defined(MBEDTLS_LMS_C)
-extern const mbedtls_error_pair_t psa_to_lms_errors[3];
-#endif
+/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS.
+ *
+ * \param family        A PSA elliptic curve family identifier
+ *                      (`PSA_ECC_FAMILY_xxx`).
+ * \param bits          The bit-length of a private key on \p curve.
+ *
+ * \return              If the curve is supported in the PSA API, this function
+ *                      returns the corresponding Mbed TLS elliptic curve
+ *                      identifier (`MBEDTLS_ECP_DP_xxx`).
+ * \return              #MBEDTLS_ECP_DP_NONE if the combination of \c curve
+ *                      and \p bits is not supported.
+ */
+mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
+                                                size_t bits);
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
-extern const mbedtls_error_pair_t psa_to_ssl_errors[7];
-#endif
+/**
+ * \brief           This function returns the PSA algorithm identifier
+ *                  associated with the given digest type.
+ *
+ * \param md_type   The type of digest to search for. Must not be NONE.
+ *
+ * \warning         If \p md_type is \c MBEDTLS_MD_NONE, this function will
+ *                  not return \c PSA_ALG_NONE, but an invalid algorithm.
+ *
+ * \warning         This function does not check if the algorithm is
+ *                  supported, it always returns the corresponding identifier.
+ *
+ * \return          The PSA algorithm identifier associated with \p md_type,
+ *                  regardless of whether it is supported or not.
+ */
+static inline psa_algorithm_t mbedtls_md_psa_alg_from_type(mbedtls_md_type_t md_type)
+{
+    return PSA_ALG_CATEGORY_HASH | (psa_algorithm_t) md_type;
+}
 
-#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
-    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8];
-#endif
+/**
+ * \brief           This function returns the given digest type
+ *                  associated with the PSA algorithm identifier.
+ *
+ * \param psa_alg   The PSA algorithm identifier to search for.
+ *
+ * \warning         This function does not check if the algorithm is
+ *                  supported, it always returns the corresponding identifier.
+ *
+ * \return          The MD type associated with \p psa_alg,
+ *                  regardless of whether it is supported or not.
+ */
+static inline mbedtls_md_type_t mbedtls_md_type_from_psa_alg(psa_algorithm_t psa_alg)
+{
+    return (mbedtls_md_type_t) (psa_alg & PSA_ALG_HASH_MASK);
+}
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
-    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7];
-#endif
+#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 
-/* Generic fallback function for error translation,
- * when the received state was not module-specific. */
-int psa_generic_status_to_mbedtls(psa_status_t status);
+/** Convert an ECDSA signature from raw format to DER ASN.1 format.
+ *
+ * \param       bits        Size of each coordinate in bits.
+ * \param       raw         Buffer that contains the signature in raw format.
+ * \param       raw_len     Length of \p raw in bytes. This must be
+ *                          PSA_BITS_TO_BYTES(bits) bytes.
+ * \param[out]  der         Buffer that will be filled with the converted DER
+ *                          output. It can overlap with raw buffer.
+ * \param       der_size    Size of \p der in bytes. It is enough if \p der_size
+ *                          is at least the size of the actual output. (The size
+ *                          of the output can vary depending on the presence of
+ *                          leading zeros in the data.) You can use
+ *                          #MBEDTLS_ECDSA_MAX_SIG_LEN(\p bits) to determine a
+ *                          size that is large enough for all signatures for a
+ *                          given value of \p bits.
+ * \param[out]  der_len     On success it contains the amount of valid data
+ *                          (in bytes) written to \p der. It's undefined
+ *                          in case of failure.
+ */
+int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
+                             unsigned char *der, size_t der_size, size_t *der_len);
 
-/* This function iterates over provided local error translations,
- * and if no match was found - calls the fallback error translation function. */
-int psa_status_to_mbedtls(psa_status_t status,
-                          const mbedtls_error_pair_t *local_translations,
-                          size_t local_errors_num,
-                          int (*fallback_f)(psa_status_t));
+/** Convert an ECDSA signature from DER ASN.1 format to raw format.
+ *
+ * \param       bits        Size of each coordinate in bits.
+ * \param       der         Buffer that contains the signature in DER format.
+ * \param       der_len     Size of \p der in bytes.
+ * \param[out]  raw         Buffer that will be filled with the converted raw
+ *                          signature. It can overlap with der buffer.
+ * \param       raw_size    Size of \p raw in bytes. Must be at least
+ *                          2 * PSA_BITS_TO_BYTES(bits) bytes.
+ * \param[out]  raw_len     On success it is updated with the amount of valid
+ *                          data (in bytes) written to \p raw. It's undefined
+ *                          in case of failure.
+ */
+int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
+                             unsigned char *raw, size_t raw_size, size_t *raw_len);
 
-/* The second out of three-stage error handling functions of the pk module,
- * acts as a fallback after RSA / ECDSA error translation, and if no match
- * is found, it itself calls psa_generic_status_to_mbedtls. */
-int psa_pk_status_to_mbedtls(psa_status_t status);
+#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */
 
-/* Utility macro to shorten the defines of error translator in modules. */
-#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f)       \
-    psa_status_to_mbedtls(status, error_list,                         \
-                          sizeof(error_list)/sizeof(error_list[0]),   \
-                          fallback_f)
+/**@}*/
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
 #endif /* MBEDTLS_PSA_UTIL_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h b/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
index acec3c52dcdc46be5d8b2ff43a42e580e5896bf7..279f92b5121e66ebe404ffac59b03d38a2f85bdb 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ripemd160.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_RIPEMD160_H
 #define MBEDTLS_RIPEMD160_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h b/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
index da8639b3969fdb85f9d39e053e3dd4ce638103bc..c1e76b3927edd9a90a451f4e76cab5f062d1494a 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/rsa.h
@@ -11,19 +11,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_RSA_H
 #define MBEDTLS_RSA_H
@@ -85,6 +73,12 @@ extern "C" {
 // Regular implementation
 //
 
+#if !defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)
+#define MBEDTLS_RSA_GEN_KEY_MIN_BITS 1024
+#elif MBEDTLS_RSA_GEN_KEY_MIN_BITS < 128
+#error "MBEDTLS_RSA_GEN_KEY_MIN_BITS must be at least 128 bits"
+#endif
+
 /**
  * \brief   The RSA context structure.
  */
@@ -282,15 +276,15 @@ int mbedtls_rsa_import_raw(mbedtls_rsa_context *ctx,
  * \brief          This function completes an RSA context from
  *                 a set of imported core parameters.
  *
- *                 To setup an RSA public key, precisely \p N and \p E
+ *                 To setup an RSA public key, precisely \c N and \c E
  *                 must have been imported.
  *
  *                 To setup an RSA private key, sufficient information must
  *                 be present for the other parameters to be derivable.
  *
  *                 The default implementation supports the following:
- *                 <ul><li>Derive \p P, \p Q from \p N, \p D, \p E.</li>
- *                 <li>Derive \p N, \p D from \p P, \p Q, \p E.</li></ul>
+ *                 <ul><li>Derive \c P, \c Q from \c N, \c D, \c E.</li>
+ *                 <li>Derive \c N, \c D from \c P, \c Q, \c E.</li></ul>
  *                 Alternative implementations need not support these.
  *
  *                 If this function runs successfully, it guarantees that
@@ -432,6 +426,16 @@ int mbedtls_rsa_export_raw(const mbedtls_rsa_context *ctx,
 int mbedtls_rsa_export_crt(const mbedtls_rsa_context *ctx,
                            mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP);
 
+/**
+ * \brief          This function retrieves the length of the RSA modulus in bits.
+ *
+ * \param ctx      The initialized RSA context.
+ *
+ * \return         The length of the RSA modulus in bits.
+ *
+ */
+size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx);
+
 /**
  * \brief          This function retrieves the length of RSA modulus in Bytes.
  *
@@ -547,7 +551,7 @@ int mbedtls_rsa_check_pub_priv(const mbedtls_rsa_context *pub,
  * \note           This function does not handle message padding.
  *
  * \note           Make sure to set \p input[0] = 0 or ensure that
- *                 input is smaller than \p N.
+ *                 input is smaller than \c N.
  *
  * \return         \c 0 on success.
  * \return         An \c MBEDTLS_ERR_RSA_XXX error code on failure.
@@ -690,6 +694,10 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,
  *                 It is the generic wrapper for performing a PKCS#1 decryption
  *                 operation.
  *
+ * \warning        When \p ctx->padding is set to #MBEDTLS_RSA_PKCS_V15,
+ *                 mbedtls_rsa_rsaes_pkcs1_v15_decrypt() is called, which is an
+ *                 inherently dangerous function (CWE-242).
+ *
  * \note           The output buffer length \c output_max_len should be
  *                 as large as the size \p ctx->len of \p ctx->N (for example,
  *                 128 Bytes if RSA-1024 is used) to be able to hold an
@@ -726,6 +734,11 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,
  * \brief          This function performs a PKCS#1 v1.5 decryption
  *                 operation (RSAES-PKCS1-v1_5-DECRYPT).
  *
+ * \warning        This is an inherently dangerous function (CWE-242). Unless
+ *                 it is used in a side channel free and safe way (eg.
+ *                 implementing the TLS protocol as per 7.4.7.1 of RFC 5246),
+ *                 the calling code is vulnerable.
+ *
  * \note           The output buffer length \c output_max_len should be
  *                 as large as the size \p ctx->len of \p ctx->N, for example,
  *                 128 Bytes if RSA-1024 is used, to be able to hold an
@@ -875,6 +888,7 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,
                                       const unsigned char *hash,
                                       unsigned char *sig);
 
+#if defined(MBEDTLS_PKCS1_V21)
 /**
  * \brief          This function performs a PKCS#1 v2.1 PSS signature
  *                 operation (RSASSA-PSS-SIGN).
@@ -975,6 +989,7 @@ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
                                 unsigned int hashlen,
                                 const unsigned char *hash,
                                 unsigned char *sig);
+#endif /* MBEDTLS_PKCS1_V21 */
 
 /**
  * \brief          This function performs a public RSA operation and checks
@@ -984,8 +999,8 @@ int mbedtls_rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
  *                 verification.
  *
  * \note           For PKCS#1 v2.1 encoding, see comments on
- *                 mbedtls_rsa_rsassa_pss_verify() about \p md_alg and
- *                 \p hash_id.
+ *                 mbedtls_rsa_rsassa_pss_verify() about \c md_alg and
+ *                 \c hash_id.
  *
  * \param ctx      The initialized RSA public key context to use.
  * \param md_alg   The message-digest algorithm used to hash the original data.
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
index 18bde93d354b50ae66dd9b6b8b449c91473fc3e8..592ffd13f244947f85fa19a406db946f7b0aacdc 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha1.h
@@ -12,19 +12,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SHA1_H
 #define MBEDTLS_SHA1_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
index 87e5cc61a4a2b46e31e00d907e371c3657b5edfd..ca568e291ea773825659a58600ee8a574277a06c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha256.h
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SHA256_H
 #define MBEDTLS_SHA256_H
@@ -50,11 +38,13 @@ extern "C" {
  *                 made in the call to mbedtls_sha256_starts().
  */
 typedef struct mbedtls_sha256_context {
+    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< The data block being processed. */
     uint32_t MBEDTLS_PRIVATE(total)[2];          /*!< The number of Bytes processed.  */
     uint32_t MBEDTLS_PRIVATE(state)[8];          /*!< The intermediate digest state.  */
-    unsigned char MBEDTLS_PRIVATE(buffer)[64];   /*!< The data block being processed. */
+#if defined(MBEDTLS_SHA224_C)
     int MBEDTLS_PRIVATE(is224);                  /*!< Determines which function to use:
                                                     0: Use SHA-256, or 1: Use SHA-224. */
+#endif
 }
 mbedtls_sha256_context;
 
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha3.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha3.h
new file mode 100644
index 0000000000000000000000000000000000000000..3eeee65e66bf1ca68cec2c9019a225b7d95c030b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha3.h
@@ -0,0 +1,172 @@
+/**
+ * \file sha3.h
+ *
+ * \brief This file contains SHA-3 definitions and functions.
+ *
+ * The Secure Hash Algorithms cryptographic
+ * hash functions are defined in <em>FIPS 202: SHA-3 Standard:
+ * Permutation-Based Hash and Extendable-Output Functions </em>.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_SHA3_H
+#define MBEDTLS_SHA3_H
+#include "mbedtls/private_access.h"
+
+#include "mbedtls/build_info.h"
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** SHA-3 input data was malformed. */
+#define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA                 -0x0076
+
+/**
+ * SHA-3 family id.
+ *
+ * It identifies the family (SHA3-256, SHA3-512, etc.)
+ */
+
+typedef enum {
+    MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */
+    MBEDTLS_SHA3_224, /*!< SHA3-224 */
+    MBEDTLS_SHA3_256, /*!< SHA3-256 */
+    MBEDTLS_SHA3_384, /*!< SHA3-384 */
+    MBEDTLS_SHA3_512, /*!< SHA3-512 */
+} mbedtls_sha3_id;
+
+/**
+ * \brief          The SHA-3 context structure.
+ *
+ *                 The structure is used SHA-3 checksum calculations.
+ */
+typedef struct {
+    uint64_t MBEDTLS_PRIVATE(state[25]);
+    uint32_t MBEDTLS_PRIVATE(index);
+    uint16_t MBEDTLS_PRIVATE(olen);
+    uint16_t MBEDTLS_PRIVATE(max_block_size);
+}
+mbedtls_sha3_context;
+
+/**
+ * \brief          This function initializes a SHA-3 context.
+ *
+ * \param ctx      The SHA-3 context to initialize. This must not be \c NULL.
+ */
+void mbedtls_sha3_init(mbedtls_sha3_context *ctx);
+
+/**
+ * \brief          This function clears a SHA-3 context.
+ *
+ * \param ctx      The SHA-3 context to clear. This may be \c NULL, in which
+ *                 case this function returns immediately. If it is not \c NULL,
+ *                 it must point to an initialized SHA-3 context.
+ */
+void mbedtls_sha3_free(mbedtls_sha3_context *ctx);
+
+/**
+ * \brief          This function clones the state of a SHA-3 context.
+ *
+ * \param dst      The destination context. This must be initialized.
+ * \param src      The context to clone. This must be initialized.
+ */
+void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
+                        const mbedtls_sha3_context *src);
+
+/**
+ * \brief          This function starts a SHA-3 checksum
+ *                 calculation.
+ *
+ * \param ctx      The context to use. This must be initialized.
+ * \param id       The id of the SHA-3 family.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
+ */
+int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id);
+
+/**
+ * \brief          This function feeds an input buffer into an ongoing
+ *                 SHA-3 checksum calculation.
+ *
+ * \param ctx      The SHA-3 context. This must be initialized
+ *                 and have a hash operation started.
+ * \param input    The buffer holding the data. This must be a readable
+ *                 buffer of length \p ilen Bytes.
+ * \param ilen     The length of the input data in Bytes.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
+ */
+int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
+                        const uint8_t *input,
+                        size_t ilen);
+
+/**
+ * \brief          This function finishes the SHA-3 operation, and writes
+ *                 the result to the output buffer.
+ *
+ * \param ctx      The SHA-3 context. This must be initialized
+ *                 and have a hash operation started.
+ * \param output   The SHA-3 checksum result.
+ *                 This must be a writable buffer of length \c olen bytes.
+ * \param olen     Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,
+ *                 SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64,
+ *                 respectively.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
+ */
+int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
+                        uint8_t *output, size_t olen);
+
+/**
+ * \brief          This function calculates the SHA-3
+ *                 checksum of a buffer.
+ *
+ *                 The function allocates the context, performs the
+ *                 calculation, and frees the context.
+ *
+ *                 The SHA-3 result is calculated as
+ *                 output = SHA-3(id, input buffer, d).
+ *
+ * \param id       The id of the SHA-3 family.
+ * \param input    The buffer holding the data. This must be a readable
+ *                 buffer of length \p ilen Bytes.
+ * \param ilen     The length of the input data in Bytes.
+ * \param output   The SHA-3 checksum result.
+ *                 This must be a writable buffer of length \c olen bytes.
+ * \param olen     Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,
+ *                 SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64,
+ *                 respectively.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
+ */
+int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
+                 size_t ilen,
+                 uint8_t *output,
+                 size_t olen);
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief          Checkup routine for the algorithms implemented
+ *                 by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512.
+ *
+ * \return         0 if successful, or 1 if the test failed.
+ */
+int mbedtls_sha3_self_test(int verbose);
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedtls_sha3.h */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h b/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
index ea54678299e5c66c960dcd79d31bc4c3dbc065d5..1c20e4c228d7c7f2e18abdb933e1d8c68a5c579c 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/sha512.h
@@ -7,19 +7,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SHA512_H
 #define MBEDTLS_SHA512_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
index 68e8d040fee352425d0bd6fc33c68e1fc409a378..42fffbf860b2642f76307ebab4d29c32fa967821 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_H
 #define MBEDTLS_SSL_H
@@ -40,11 +28,9 @@
 #include "mbedtls/dhm.h"
 #endif
 
-/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
- * to guards in TLS code. There is a gap in functionality that access to
- * ecdh_ctx structure is needed for MBEDTLS_ECDSA_C which does not seem correct.
- */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#include "mbedtls/md.h"
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED)
 #include "mbedtls/ecdh.h"
 #endif
 
@@ -97,20 +83,28 @@
 /** Processing of the Certificate handshake message failed. */
 #define MBEDTLS_ERR_SSL_BAD_CERTIFICATE                   -0x7A00
 /* Error space gap */
-/**
- * Received NewSessionTicket Post Handshake Message.
- * This error code is experimental and may be changed or removed without notice.
- */
+/** A TLS 1.3 NewSessionTicket message has been received. */
 #define MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET       -0x7B00
 /** Not possible to read early data */
 #define MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA            -0x7B80
+/**
+ * Early data has been received as part of an on-going handshake.
+ * This error code can be returned only on server side if and only if early
+ * data has been enabled by means of the mbedtls_ssl_conf_early_data() API.
+ * This error code can then be returned by mbedtls_ssl_handshake(),
+ * mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if
+ * early data has been received as part of the handshake sequence they
+ * triggered. To read the early data, call mbedtls_ssl_read_early_data().
+ */
+#define MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA               -0x7C00
 /** Not possible to write early data */
-#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA           -0x7C00
-/* Error space gap */
+#define MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA           -0x7C80
 /* Error space gap */
 /* Error space gap */
 /* Error space gap */
 /* Error space gap */
+/** Cache entry not found */
+#define MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND             -0x7E80
 /** Memory allocation failed */
 #define MBEDTLS_ERR_SSL_ALLOC_FAILED                      -0x7F00
 /** Hardware acceleration function returned with error */
@@ -327,6 +321,9 @@
 #define MBEDTLS_SSL_SESSION_TICKETS_DISABLED     0
 #define MBEDTLS_SSL_SESSION_TICKETS_ENABLED      1
 
+#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED  0
+#define MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED   1
+
 #define MBEDTLS_SSL_PRESET_DEFAULT              0
 #define MBEDTLS_SSL_PRESET_SUITEB               2
 
@@ -356,6 +353,26 @@
 #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN    1000
 #define MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX   60000
 
+/*
+ * Whether early data record should be discarded or not and how.
+ *
+ * The client has indicated early data and the server has rejected them.
+ * The server has then to skip past early data by either:
+ * - attempting to deprotect received records using the handshake traffic
+ *   key, discarding records which fail deprotection (up to the configured
+ *   max_early_data_size). Once a record is deprotected successfully,
+ *   it is treated as the start of the client's second flight and the
+ *   server proceeds as with an ordinary 1-RTT handshake.
+ * - skipping all records with an external content type of
+ *   "application_data" (indicating that they are encrypted), up to the
+ *   configured max_early_data_size. This is the expected behavior if the
+ *   server has sent an HelloRetryRequest message. The server ignores
+ *   application data message before 2nd ClientHello.
+ */
+#define MBEDTLS_SSL_EARLY_DATA_NO_DISCARD 0
+#define MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD 1
+#define MBEDTLS_SSL_EARLY_DATA_DISCARD 2
+
 /**
  * \name SECTION: Module settings
  *
@@ -406,6 +423,22 @@
 #define MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY 16
 #endif
 
+#if !defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)
+#define MBEDTLS_SSL_MAX_EARLY_DATA_SIZE        1024
+#endif
+
+#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE)
+#define MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE 6000
+#endif
+
+#if !defined(MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH)
+#define MBEDTLS_SSL_TLS1_3_TICKET_NONCE_LENGTH 32
+#endif
+
+#if !defined(MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS)
+#define MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS 1
+#endif
+
 /** \} name SECTION: Module settings */
 
 /*
@@ -444,7 +477,7 @@
 
 /*
  * TLS 1.3 signature algorithms
- * RFC 8446, Section 4.2.2
+ * RFC 8446, Section 4.2.3
  */
 
 /* RSASSA-PKCS1-v1_5 algorithms */
@@ -610,8 +643,8 @@
  */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
     defined(MBEDTLS_SSL_SESSION_TICKETS) && \
-    defined(MBEDTLS_AES_C) && defined(MBEDTLS_GCM_C) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+    defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM) && \
+    defined(MBEDTLS_MD_CAN_SHA384)
 #define MBEDTLS_PSK_MAX_LEN 48 /* 384 bits */
 #else
 #define MBEDTLS_PSK_MAX_LEN 32 /* 256 bits */
@@ -620,6 +653,7 @@
 
 /* Dummy type used only for its size */
 union mbedtls_ssl_premaster_secret {
+    unsigned char dummy; /* Make the union non-empty even with SSL disabled */
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
     unsigned char _pms_rsa[48];                         /* RFC 5246 8.1.1 */
 #endif
@@ -683,7 +717,6 @@ typedef enum {
     MBEDTLS_SSL_SERVER_FINISHED,
     MBEDTLS_SSL_FLUSH_BUFFERS,
     MBEDTLS_SSL_HANDSHAKE_WRAPUP,
-
     MBEDTLS_SSL_NEW_SESSION_TICKET,
     MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT,
     MBEDTLS_SSL_HELLO_RETRY_REQUEST,
@@ -701,6 +734,21 @@ typedef enum {
 }
 mbedtls_ssl_states;
 
+/*
+ * Early data status, client side only.
+ */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+typedef enum {
+/*
+ * See documentation of mbedtls_ssl_get_early_data_status().
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED,
+    MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED,
+    MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED,
+} mbedtls_ssl_early_data_status;
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
+
 /**
  * \brief          Callback type: send data on the network.
  *
@@ -1105,13 +1153,13 @@ typedef void mbedtls_ssl_async_cancel_t(mbedtls_ssl_context *ssl);
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) &&        \
     !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN  48
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  32
-#elif defined(MBEDTLS_SHA384_C)
+#elif defined(MBEDTLS_MD_CAN_SHA384)
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  48
-#elif defined(MBEDTLS_SHA1_C)
+#elif defined(MBEDTLS_MD_CAN_SHA1)
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1
 #define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN  20
 #else
@@ -1185,7 +1233,13 @@ struct mbedtls_ssl_session {
     unsigned char MBEDTLS_PRIVATE(mfl_code);     /*!< MaxFragmentLength negotiated by peer */
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
+/*!< RecordSizeLimit received from the peer */
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    uint16_t MBEDTLS_PRIVATE(record_size_limit);
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
     unsigned char MBEDTLS_PRIVATE(exported);
+    uint8_t MBEDTLS_PRIVATE(endpoint);          /*!< 0: client, 1: server */
 
     /** TLS version negotiated in the session. Used if and when renegotiating
      *  or resuming a session instead of the configured minor TLS version.
@@ -1193,7 +1247,7 @@ struct mbedtls_ssl_session {
     mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version);
 
 #if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t MBEDTLS_PRIVATE(start);       /*!< starting time      */
+    mbedtls_time_t MBEDTLS_PRIVATE(start);       /*!< start time of current session */
 #endif
     int MBEDTLS_PRIVATE(ciphersuite);            /*!< chosen ciphersuite */
     size_t MBEDTLS_PRIVATE(id_len);              /*!< session id length  */
@@ -1219,23 +1273,52 @@ struct mbedtls_ssl_session {
     uint32_t MBEDTLS_PRIVATE(ticket_lifetime);   /*!< ticket lifetime hint    */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_HAVE_TIME)
+    /*! When a ticket is created by a TLS server as part of an established TLS
+     *  session, the ticket creation time may need to be saved for the ticket
+     *  module to be able to check the ticket age when the ticket is used.
+     *  That's the purpose of this field.
+     *  Before creating a new ticket, an Mbed TLS server set this field with
+     *  its current time in milliseconds. This time may then be saved in the
+     *  session ticket data by the session ticket writing function and
+     *  recovered by the ticket parsing function later when the ticket is used.
+     *  The ticket module may then use this time to compute the ticket age and
+     *  determine if it has expired or not.
+     *  The Mbed TLS implementations of the session ticket writing and parsing
+     *  functions save and retrieve the ticket creation time as part of the
+     *  session ticket data. The session ticket parsing function relies on
+     *  the mbedtls_ssl_session_get_ticket_creation_time() API to get the
+     *  ticket creation time from the session ticket data.
+     */
+    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_creation_time);
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-    uint8_t MBEDTLS_PRIVATE(endpoint);          /*!< 0: client, 1: server */
-    uint8_t MBEDTLS_PRIVATE(ticket_flags);      /*!< Ticket flags */
-    uint32_t MBEDTLS_PRIVATE(ticket_age_add);               /*!< Randomly generated value used to obscure the age of the ticket */
-    uint8_t MBEDTLS_PRIVATE(resumption_key_len);            /*!< resumption_key length */
+    uint32_t MBEDTLS_PRIVATE(ticket_age_add);     /*!< Randomly generated value used to obscure the age of the ticket */
+    uint8_t MBEDTLS_PRIVATE(ticket_flags);        /*!< Ticket flags */
+    uint8_t MBEDTLS_PRIVATE(resumption_key_len);  /*!< resumption_key length */
     unsigned char MBEDTLS_PRIVATE(resumption_key)[MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN];
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_SSL_CLI_C)
     char *MBEDTLS_PRIVATE(hostname);             /*!< host name binded with tickets */
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION && MBEDTLS_SSL_CLI_C */
 
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)
-    mbedtls_time_t MBEDTLS_PRIVATE(ticket_received);        /*!< time ticket was received */
-#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C)
+    char *ticket_alpn;                      /*!< ALPN negotiated in the session
+                                                 during which the ticket was generated. */
+#endif
 
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_CLI_C)
+    /*! Time in milliseconds when the last ticket was received. */
+    mbedtls_ms_time_t MBEDTLS_PRIVATE(ticket_reception_time);
+#endif
 #endif /*  MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    uint32_t MBEDTLS_PRIVATE(max_early_data_size);          /*!< maximum amount of early data in tickets */
+#endif
+
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
     int MBEDTLS_PRIVATE(encrypt_then_mac);       /*!< flag for EtM activation                */
 #endif
@@ -1363,6 +1446,12 @@ struct mbedtls_ssl_config {
 #endif
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
     defined(MBEDTLS_SSL_CLI_C)
+    /** Encodes two booleans, one stating whether TLS 1.2 session tickets are
+     *  enabled or not, the other one whether the handling of TLS 1.3
+     *  NewSessionTicket messages is enabled or not. They are respectively set
+     *  by mbedtls_ssl_conf_session_tickets() and
+     *  mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().
+     */
     uint8_t MBEDTLS_PRIVATE(session_tickets);   /*!< use session tickets? */
 #endif
 
@@ -1609,22 +1698,32 @@ struct mbedtls_ssl_context {
                                                     renego_max_records is < 0           */
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-    /** Server: Negotiated TLS protocol version.
-     *  Client: Maximum TLS version to be negotiated, then negotiated TLS
-     *          version.
+    /**
+     * Maximum TLS version to be negotiated, then negotiated TLS version.
+     *
+     * It is initialized as the configured maximum TLS version to be
+     * negotiated by mbedtls_ssl_setup().
+     *
+     * When renegotiating or resuming a session, it is overwritten in the
+     * ClientHello writing preparation stage with the previously negotiated
+     * TLS version.
      *
-     *  It is initialized as the maximum TLS version to be negotiated in the
-     *  ClientHello writing preparation stage and used throughout the
-     *  ClientHello writing. For a fresh handshake not linked to any previous
-     *  handshake, it is initialized to the configured maximum TLS version
-     *  to be negotiated. When renegotiating or resuming a session, it is
-     *  initialized to the previously negotiated TLS version.
+     * On client side, it is updated to the TLS version selected by the server
+     * for the handshake when the ServerHello is received.
      *
-     *  Updated to the negotiated TLS version as soon as the ServerHello is
-     *  received.
+     * On server side, it is updated to the TLS version the server selects for
+     * the handshake when the ClientHello is received.
      */
     mbedtls_ssl_protocol_version MBEDTLS_PRIVATE(tls_version);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+    /**
+     * State of the negotiation and transfer of early data. Reset to
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IDLE when the context is reset.
+     */
+    int MBEDTLS_PRIVATE(early_data_state);
+#endif
+
     unsigned MBEDTLS_PRIVATE(badmac_seen);       /*!< records with a bad MAC received    */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
@@ -1741,6 +1840,19 @@ struct mbedtls_ssl_context {
                                                          *   within a single datagram.  */
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#if defined(MBEDTLS_SSL_SRV_C)
+    /*
+     * One of:
+     * MBEDTLS_SSL_EARLY_DATA_NO_DISCARD
+     * MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD
+     * MBEDTLS_SSL_EARLY_DATA_DISCARD
+     */
+    uint8_t MBEDTLS_PRIVATE(discard_early_data_record);
+#endif
+    uint32_t MBEDTLS_PRIVATE(total_early_data_size); /*!< Number of received/written early data bytes */
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
     /*
      * Record layer (outgoing data)
      */
@@ -1822,10 +1934,6 @@ struct mbedtls_ssl_context {
                                              *   and #MBEDTLS_SSL_CID_DISABLED. */
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
-    int MBEDTLS_PRIVATE(early_data_status);
-#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
-
     /** Callback to export key block and master secret                      */
     mbedtls_ssl_export_keys_t *MBEDTLS_PRIVATE(f_export_keys);
     void *MBEDTLS_PRIVATE(p_export_keys);            /*!< context for key export callback    */
@@ -1917,6 +2025,19 @@ int mbedtls_ssl_session_reset(mbedtls_ssl_context *ssl);
  */
 void mbedtls_ssl_conf_endpoint(mbedtls_ssl_config *conf, int endpoint);
 
+/**
+ * \brief          Get the current endpoint type
+ *
+ * \param conf     SSL configuration
+ *
+ * \return         Endpoint type, either MBEDTLS_SSL_IS_CLIENT
+ *                 or MBEDTLS_SSL_IS_SERVER
+ */
+static inline int mbedtls_ssl_conf_get_endpoint(const mbedtls_ssl_config *conf)
+{
+    return conf->MBEDTLS_PRIVATE(endpoint);
+}
+
 /**
  * \brief           Set the transport type (TLS or DTLS).
  *                  Default: TLS
@@ -1961,7 +2082,7 @@ void mbedtls_ssl_conf_transport(mbedtls_ssl_config *conf, int transport);
  */
 void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode);
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_EARLY_DATA)
+#if defined(MBEDTLS_SSL_EARLY_DATA)
 /**
  * \brief    Set the early data mode
  *           Default: disabled on server and client
@@ -1969,20 +2090,27 @@ void mbedtls_ssl_conf_authmode(mbedtls_ssl_config *conf, int authmode);
  * \param conf   The SSL configuration to use.
  * \param early_data_enabled can be:
  *
- *  MBEDTLS_SSL_EARLY_DATA_DISABLED:  early data functionality is disabled
- *                                    This is the default on client and server.
- *
- *  MBEDTLS_SSL_EARLY_DATA_ENABLED:  early data functionality is enabled and
- *                        may be negotiated in the handshake. Application using
- *                        early data functionality needs to be aware of the
- *                        lack of replay protection of the early data application
- *                        payloads.
- *
- * \warning This interface is experimental and may change without notice.
- *
- */
-void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf,
-                                       int early_data_enabled);
+ *  MBEDTLS_SSL_EARLY_DATA_DISABLED:
+ *  Early data functionality is disabled. This is the default on client and
+ *  server.
+ *
+ *  MBEDTLS_SSL_EARLY_DATA_ENABLED:
+ *  Early data functionality is enabled and may be negotiated in the handshake.
+ *  Application using early data functionality needs to be aware that the
+ *  security properties for early data (also refered to as 0-RTT data) are
+ *  weaker than those for other kinds of TLS data. See the documentation of
+ *  mbedtls_ssl_write_early_data() and mbedtls_ssl_read_early_data() for more
+ *  information.
+ *  When early data functionality is enabled on server and only in that case,
+ *  the call to one of the APIs that trigger or resume an handshake sequence,
+ *  namely mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(),
+ *  mbedtls_ssl_read() or mbedtls_ssl_write() may return with the error code
+ *  MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA indicating that some early data have
+ *  been received. To read the early data, call mbedtls_ssl_read_early_data()
+ *  before calling the original function again.
+ */
+void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf,
+                                 int early_data_enabled);
 
 #if defined(MBEDTLS_SSL_SRV_C)
 /**
@@ -2005,14 +2133,15 @@ void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf,
  * \param[in] conf                  The SSL configuration to use.
  * \param[in] max_early_data_size   The maximum amount of 0-RTT data.
  *
- * \warning This interface is experimental and may change without notice.
- *
+ * \warning This interface DOES NOT influence/limit the amount of early data
+ *          that can be received through previously created and issued tickets,
+ *          which clients may have stored.
  */
-void mbedtls_ssl_tls13_conf_max_early_data_size(
+void mbedtls_ssl_conf_max_early_data_size(
     mbedtls_ssl_config *conf, uint32_t max_early_data_size);
 #endif /* MBEDTLS_SSL_SRV_C */
 
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_EARLY_DATA */
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 /**
@@ -2156,10 +2285,10 @@ void mbedtls_ssl_set_bio(mbedtls_ssl_context *ssl,
  * \param own_cid     The address of the readable buffer holding the CID we want
  *                    the peer to use when sending encrypted messages to us.
  *                    This may be \c NULL if \p own_cid_len is \c 0.
- *                    This parameter is unused if \p enabled is set to
+ *                    This parameter is unused if \p enable is set to
  *                    MBEDTLS_SSL_CID_DISABLED.
  * \param own_cid_len The length of \p own_cid.
- *                    This parameter is unused if \p enabled is set to
+ *                    This parameter is unused if \p enable is set to
  *                    MBEDTLS_SSL_CID_DISABLED.
  *
  * \note              The value of \p own_cid_len must match the value of the
@@ -2241,7 +2370,7 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
  */
 int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,
                             int *enabled,
-                            unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
+                            unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],
                             size_t *own_cid_len);
 
 /**
@@ -2536,8 +2665,73 @@ void mbedtls_ssl_conf_session_tickets_cb(mbedtls_ssl_config *conf,
                                          mbedtls_ssl_ticket_write_t *f_ticket_write,
                                          mbedtls_ssl_ticket_parse_t *f_ticket_parse,
                                          void *p_ticket);
+
+#if defined(MBEDTLS_HAVE_TIME)
+/**
+ * \brief Get the creation time of a session ticket.
+ *
+ * \note See the documentation of \c ticket_creation_time for information about
+ *       the intended usage of this function.
+ *
+ * \param session  SSL session
+ * \param ticket_creation_time  On exit, holds the ticket creation time in
+ *                              milliseconds.
+ *
+ * \return         0 on success,
+ *                 MBEDTLS_ERR_SSL_BAD_INPUT_DATA if an input is not valid.
+ */
+static inline int mbedtls_ssl_session_get_ticket_creation_time(
+    mbedtls_ssl_session *session, mbedtls_ms_time_t *ticket_creation_time)
+{
+    if (session == NULL || ticket_creation_time == NULL ||
+        session->MBEDTLS_PRIVATE(endpoint) != MBEDTLS_SSL_IS_SERVER) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    *ticket_creation_time = session->MBEDTLS_PRIVATE(ticket_creation_time);
+
+    return 0;
+}
+#endif /* MBEDTLS_HAVE_TIME */
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_SRV_C */
 
+/**
+ * \brief          Get the session-id buffer.
+ *
+ * \param session  SSL session.
+ *
+ * \return         The address of the session-id buffer.
+ */
+static inline unsigned const char (*mbedtls_ssl_session_get_id(const mbedtls_ssl_session *
+                                                               session))[32]
+{
+    return &session->MBEDTLS_PRIVATE(id);
+}
+
+/**
+ * \brief          Get the size of the session-id.
+ *
+ * \param session  SSL session.
+ *
+ * \return         size_t size of session-id buffer.
+ */
+static inline size_t mbedtls_ssl_session_get_id_len(const mbedtls_ssl_session *session)
+{
+    return session->MBEDTLS_PRIVATE(id_len);
+}
+
+/**
+ * \brief          Get the ciphersuite-id.
+ *
+ * \param session  SSL session.
+ *
+ * \return         int represetation for ciphersuite.
+ */
+static inline int mbedtls_ssl_session_get_ciphersuite_id(const mbedtls_ssl_session *session)
+{
+    return session->MBEDTLS_PRIVATE(ciphersuite);
+}
+
 /**
  * \brief   Configure a key export callback.
  *          (Default: none.)
@@ -3028,16 +3222,16 @@ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
  *                 a full handshake.
  *
  * \note           This function can handle a variety of mechanisms for session
- *                 resumption: For TLS 1.2, both session ID-based resumption and
- *                 ticket-based resumption will be considered. For TLS 1.3,
- *                 once implemented, sessions equate to tickets, and loading
- *                 one or more sessions via this call will lead to their
- *                 corresponding tickets being advertised as resumption PSKs
- *                 by the client.
- *
- * \note           Calling this function multiple times will only be useful
- *                 once TLS 1.3 is supported. For TLS 1.2 connections, this
- *                 function should be called at most once.
+ *                 resumption: For TLS 1.2, both session ID-based resumption
+ *                 and ticket-based resumption will be considered. For TLS 1.3,
+ *                 sessions equate to tickets, and loading one session by
+ *                 calling this function will lead to its corresponding ticket
+ *                 being advertised as resumption PSK by the client. This
+ *                 depends on session tickets being enabled (see
+ *                 #MBEDTLS_SSL_SESSION_TICKETS configuration option) though.
+ *                 If session tickets are disabled, a call to this function
+ *                 with a TLS 1.3 session, will not have any effect on the next
+ *                 handshake for the SSL context \p ssl.
  *
  * \param ssl      The SSL context representing the connection which should
  *                 be attempted to be setup using session resumption. This
@@ -3052,9 +3246,10 @@ void mbedtls_ssl_conf_session_cache(mbedtls_ssl_config *conf,
  *
  * \return         \c 0 if successful.
  * \return         \c MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the session
- *                 could not be loaded because of an implementation limitation.
- *                 This error is non-fatal, and has no observable effect on
- *                 the SSL context or the session that was attempted to be loaded.
+ *                 could not be loaded because one session has already been
+ *                 loaded. This error is non-fatal, and has no observable
+ *                 effect on the SSL context or the session that was attempted
+ *                 to be loaded.
  * \return         Another negative error code on other kinds of failure.
  *
  * \sa             mbedtls_ssl_get_session()
@@ -3110,8 +3305,8 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
  *
  * \param session  The session structure to be saved.
  * \param buf      The buffer to write the serialized data to. It must be a
- *                 writeable buffer of at least \p len bytes, or may be \c
- *                 NULL if \p len is \c 0.
+ *                 writeable buffer of at least \p buf_len bytes, or may be \c
+ *                 NULL if \p buf_len is \c 0.
  * \param buf_len  The number of bytes available for writing in \p buf.
  * \param olen     The size in bytes of the data that has been or would have
  *                 been written. It must point to a valid \c size_t.
@@ -3121,8 +3316,16 @@ int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
  *                 to determine the necessary size by calling this function
  *                 with \p buf set to \c NULL and \p buf_len to \c 0.
  *
+ * \note           For TLS 1.3 sessions, this feature is supported only if the
+ *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is enabled,
+ *                 as in TLS 1.3 session resumption is possible only with
+ *                 tickets.
+ *
  * \return         \c 0 if successful.
  * \return         #MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL if \p buf is too small.
+ * \return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if the
+ *                 MBEDTLS_SSL_SESSION_TICKETS configuration option is disabled
+ *                 and the session is a TLS 1.3 session.
  */
 int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
                              unsigned char *buf,
@@ -3252,7 +3455,7 @@ void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,
  *                      record headers.
  *
  * \return              \c 0 on success.
- * \return              #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p own_cid_len
+ * \return              #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if \p len
  *                      is too large.
  */
 int mbedtls_ssl_conf_cid(mbedtls_ssl_config *conf, size_t len,
@@ -3720,6 +3923,8 @@ void mbedtls_ssl_conf_groups(mbedtls_ssl_config *conf,
  *                 used for certificate signature are controlled by the
  *                 verification profile, see \c mbedtls_ssl_conf_cert_profile().
  *
+ * \deprecated     Superseded by mbedtls_ssl_conf_sig_algs().
+ *
  * \note           This list should be ordered by decreasing preference
  *                 (preferred hash first).
  *
@@ -3744,13 +3949,16 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_sig_hashes(mbedtls_ssl_config *conf,
 #endif /* !MBEDTLS_DEPRECATED_REMOVED && MBEDTLS_SSL_PROTO_TLS1_2 */
 
 /**
- * \brief          Configure allowed signature algorithms for use in TLS 1.3
+ * \brief          Configure allowed signature algorithms for use in TLS
  *
  * \param conf     The SSL configuration to use.
  * \param sig_algs List of allowed IANA values for TLS 1.3 signature algorithms,
- *                 terminated by \c MBEDTLS_TLS1_3_SIG_NONE. The list must remain
- *                 available throughout the lifetime of the conf object. Supported
- *                 values are available as \c MBEDTLS_TLS1_3_SIG_XXXX
+ *                 terminated by #MBEDTLS_TLS1_3_SIG_NONE. The list must remain
+ *                 available throughout the lifetime of the conf object.
+ *                 - For TLS 1.3, values of \c MBEDTLS_TLS1_3_SIG_XXXX should be
+ *                   used.
+ *                 - For TLS 1.2, values should be given as
+ *                   "(HashAlgorithm << 8) | SignatureAlgorithm".
  */
 void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,
                                const uint16_t *sig_algs);
@@ -3776,13 +3984,28 @@ void mbedtls_ssl_conf_sig_algs(mbedtls_ssl_config *conf,
  *                 On too long input failure, old hostname is unchanged.
  */
 int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname);
+
+/**
+ * \brief          Get the hostname that checked against the received
+ *                 server certificate. It is used to set the ServerName
+ *                 TLS extension, too, if that extension is enabled.
+ *                 (client-side only)
+ *
+ * \param ssl      SSL context
+ *
+ * \return         const pointer to the hostname value
+ */
+static inline const char *mbedtls_ssl_get_hostname(mbedtls_ssl_context *ssl)
+{
+    return ssl->MBEDTLS_PRIVATE(hostname);
+}
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
 /**
  * \brief          Retrieve SNI extension value for the current handshake.
- *                 Available in \p f_cert_cb of \c mbedtls_ssl_conf_cert_cb(),
- *                 this is the same value passed to \p f_sni callback of
+ *                 Available in \c f_cert_cb of \c mbedtls_ssl_conf_cert_cb(),
+ *                 this is the same value passed to \c f_sni callback of
  *                 \c mbedtls_ssl_conf_sni() and may be used instead of
  *                 \c mbedtls_ssl_conf_sni().
  *
@@ -3791,10 +4014,10 @@ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname);
  *                 0 if SNI extension is not present or not yet processed.
  *
  * \return         const pointer to SNI extension value.
- *                 - value is valid only when called in \p f_cert_cb
+ *                 - value is valid only when called in \c f_cert_cb
  *                   registered with \c mbedtls_ssl_conf_cert_cb().
  *                 - value is NULL if SNI extension is not present.
- *                 - value is not '\0'-terminated.  Use \c name_len for len.
+ *                 - value is not '\0'-terminated. Use \c name_len for len.
  *                 - value must not be freed.
  */
 const unsigned char *mbedtls_ssl_get_hs_sni(mbedtls_ssl_context *ssl,
@@ -4087,7 +4310,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, i
  *                 negotiated.
  *
  * \param conf         SSL configuration
- * \param tls_version  TLS protocol version number (\p mbedtls_ssl_protocol_version)
+ * \param tls_version  TLS protocol version number (\c mbedtls_ssl_protocol_version)
  *                     (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)
  */
 static inline void mbedtls_ssl_conf_max_tls_version(mbedtls_ssl_config *conf,
@@ -4144,7 +4367,7 @@ void MBEDTLS_DEPRECATED mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, i
  *                 negotiated.
  *
  * \param conf         SSL configuration
- * \param tls_version  TLS protocol version number (\p mbedtls_ssl_protocol_version)
+ * \param tls_version  TLS protocol version number (\c mbedtls_ssl_protocol_version)
  *                     (#MBEDTLS_SSL_VERSION_UNKNOWN is not valid)
  */
 static inline void mbedtls_ssl_conf_min_tls_version(mbedtls_ssl_config *conf,
@@ -4248,21 +4471,50 @@ int mbedtls_ssl_conf_max_frag_len(mbedtls_ssl_config *conf, unsigned char mfl_co
 void mbedtls_ssl_conf_preference_order(mbedtls_ssl_config *conf, int order);
 #endif /* MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
-    defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
 /**
- * \brief          Enable / Disable session tickets (client only).
- *                 (Default: MBEDTLS_SSL_SESSION_TICKETS_ENABLED.)
+ * \brief          Enable / Disable TLS 1.2 session tickets (client only,
+ *                 TLS 1.2 only). Enabled by default.
  *
  * \note           On server, use \c mbedtls_ssl_conf_session_tickets_cb().
  *
  * \param conf     SSL configuration
- * \param use_tickets   Enable or disable (MBEDTLS_SSL_SESSION_TICKETS_ENABLED or
- *                                         MBEDTLS_SSL_SESSION_TICKETS_DISABLED)
+ * \param use_tickets   Enable or disable (#MBEDTLS_SSL_SESSION_TICKETS_ENABLED or
+ *                                         #MBEDTLS_SSL_SESSION_TICKETS_DISABLED)
  */
 void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets);
-#endif /* MBEDTLS_SSL_SESSION_TICKETS &&
-          MBEDTLS_SSL_CLI_C */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/**
+ * \brief Enable / Disable handling of TLS 1.3 NewSessionTicket messages
+ *        (client only, TLS 1.3 only).
+ *
+ *        The handling of TLS 1.3 NewSessionTicket messages is disabled by
+ *        default.
+ *
+ *        In TLS 1.3, servers may send a NewSessionTicket message at any time,
+ *        and may send multiple NewSessionTicket messages. By default, TLS 1.3
+ *        clients ignore NewSessionTicket messages.
+ *
+ *        To support session tickets in TLS 1.3 clients, call this function
+ *        with #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED. When
+ *        this is enabled, when a client receives a NewSessionTicket message,
+ *        the next call to a message processing functions (notably
+ *        mbedtls_ssl_handshake() and mbedtls_ssl_read()) will return
+ *        #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET. The client should then
+ *        call mbedtls_ssl_get_session() to retrieve the session ticket before
+ *        calling the same message processing function again.
+ *
+ * \param conf  SSL configuration
+ * \param signal_new_session_tickets Enable or disable
+ *                                   (#MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED or
+ *                                    #MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED)
+ */
+void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
+    mbedtls_ssl_config *conf, int signal_new_session_tickets);
+
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && \
     defined(MBEDTLS_SSL_SRV_C) && \
@@ -4623,29 +4875,22 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert(const mbedtls_ssl_context *ssl
  * \param ssl      The SSL context representing the connection for which to
  *                 to export a session structure for later resumption.
  * \param session  The target structure in which to store the exported session.
- *                 This must have been initialized with mbedtls_ssl_init_session()
+ *                 This must have been initialized with mbedtls_ssl_session_init()
  *                 but otherwise be unused.
  *
  * \note           This function can handle a variety of mechanisms for session
  *                 resumption: For TLS 1.2, both session ID-based resumption and
  *                 ticket-based resumption will be considered. For TLS 1.3,
- *                 once implemented, sessions equate to tickets, and calling
- *                 this function multiple times will export the available
- *                 tickets one a time until no further tickets are available,
- *                 in which case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE will
- *                 be returned.
- *
- * \note           Calling this function multiple times will only be useful
- *                 once TLS 1.3 is supported. For TLS 1.2 connections, this
- *                 function should be called at most once.
+ *                 sessions equate to tickets, and if session tickets are
+ *                 enabled (see #MBEDTLS_SSL_SESSION_TICKETS configuration
+ *                 option), this function exports the last received ticket and
+ *                 the exported session may be used to resume the TLS 1.3
+ *                 session. If session tickets are disabled, exported sessions
+ *                 cannot be used to resume a TLS 1.3 session.
  *
  * \return         \c 0 if successful. In this case, \p session can be used for
  *                 session resumption by passing it to mbedtls_ssl_set_session(),
  *                 and serialized for storage via mbedtls_ssl_session_save().
- * \return         #MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE if no further session
- *                 is available for export.
- *                 This error is a non-fatal, and has no observable effect on
- *                 the SSL context or the destination session.
  * \return         Another negative error code on other kinds of failure.
  *
  * \sa             mbedtls_ssl_set_session()
@@ -4677,6 +4922,17 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
  * \return         #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use
  *                 and the client did not demonstrate reachability yet - in
  *                 this case you must stop using the context (see below).
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
+ *                 NewSessionTicket message has been received. See the
+ *                 documentation of mbedtls_ssl_read() for more information
+ *                 about this error code.
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
+ *                 defined in RFC 8446 (TLS 1.3 specification), has been
+ *                 received as part of the handshake. This is server specific
+ *                 and may occur only if the early data feature has been
+ *                 enabled on server (see mbedtls_ssl_conf_early_data()
+ *                 documentation). You must call mbedtls_ssl_read_early_data()
+ *                 to read the early data before resuming the handshake.
  * \return         Another SSL error code - in this case you must stop using
  *                 the context (see below).
  *
@@ -4685,7 +4941,9 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
  *                 #MBEDTLS_ERR_SSL_WANT_READ,
  *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
  *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
- *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
  *                 you must stop using the SSL context for reading or writing,
  *                 and either free it or call \c mbedtls_ssl_session_reset()
  *                 on it before re-using it for a new connection; the current
@@ -4705,10 +4963,13 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
  *                 currently being processed might or might not contain further
  *                 DTLS records.
  *
- * \note           If the context is configured to allow TLS 1.3, or if
- *                 #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
  *                 subsystem must have been initialized by calling
  *                 psa_crypto_init() before calling this function.
+ *                 Otherwise, the handshake may call psa_crypto_init()
+ *                 if a negotiation involving TLS 1.3 takes place (this may
+ *                 be the case even if TLS 1.3 is offered but eventually
+ *                 not selected).
  */
 int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl);
 
@@ -4754,8 +5015,10 @@ static inline int mbedtls_ssl_is_handshake_over(mbedtls_ssl_context *ssl)
  *
  * \warning        If this function returns something other than \c 0,
  *                 #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE,
- *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
- *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA, you must stop using
  *                 the SSL context for reading or writing, and either free it
  *                 or call \c mbedtls_ssl_session_reset() on it before
  *                 re-using it for a new connection; the current connection
@@ -4823,6 +5086,24 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl);
  * \return         #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server
  *                 side of a DTLS connection and the client is initiating a
  *                 new connection using the same source port. See below.
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
+ *                 NewSessionTicket message has been received.
+ *                 This error code is only returned on the client side. It is
+ *                 only returned if handling of TLS 1.3 NewSessionTicket
+ *                 messages has been enabled through
+ *                 mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets().
+ *                 This error code indicates that a TLS 1.3 NewSessionTicket
+ *                 message has been received and parsed successfully by the
+ *                 client. The ticket data can be retrieved from the SSL
+ *                 context by calling mbedtls_ssl_get_session(). It remains
+ *                 available until the next call to mbedtls_ssl_read().
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
+ *                 defined in RFC 8446 (TLS 1.3 specification), has been
+ *                 received as part of the handshake. This is server specific
+ *                 and may occur only if the early data feature has been
+ *                 enabled on server (see mbedtls_ssl_conf_early_data()
+ *                 documentation). You must call mbedtls_ssl_read_early_data()
+ *                 to read the early data before resuming the handshake.
  * \return         Another SSL error code - in this case you must stop using
  *                 the context (see below).
  *
@@ -4831,8 +5112,10 @@ int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl);
  *                 #MBEDTLS_ERR_SSL_WANT_READ,
  *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
  *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
- *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
- *                 #MBEDTLS_ERR_SSL_CLIENT_RECONNECT,
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_CLIENT_RECONNECT or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
  *                 you must stop using the SSL context for reading or writing,
  *                 and either free it or call \c mbedtls_ssl_session_reset()
  *                 on it before re-using it for a new connection; the current
@@ -4897,6 +5180,17 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len);
  *                 operation is in progress (see mbedtls_ecp_set_max_ops()) -
  *                 in this case you must call this function again to complete
  *                 the handshake when you're done attending other tasks.
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET if a TLS 1.3
+ *                 NewSessionTicket message has been received. See the
+ *                 documentation of mbedtls_ssl_read() for more information
+ *                 about this error code.
+ * \return         #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA if early data, as
+ *                 defined in RFC 8446 (TLS 1.3 specification), has been
+ *                 received as part of the handshake. This is server specific
+ *                 and may occur only if the early data feature has been
+ *                 enabled on server (see mbedtls_ssl_conf_early_data()
+ *                 documentation). You must call mbedtls_ssl_read_early_data()
+ *                 to read the early data before resuming the handshake.
  * \return         Another SSL error code - in this case you must stop using
  *                 the context (see below).
  *
@@ -4904,8 +5198,10 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len);
  *                 a non-negative value,
  *                 #MBEDTLS_ERR_SSL_WANT_READ,
  *                 #MBEDTLS_ERR_SSL_WANT_WRITE,
- *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or
- *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS,
+ *                 #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET or
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA,
  *                 you must stop using the SSL context for reading or writing,
  *                 and either free it or call \c mbedtls_ssl_session_reset()
  *                 on it before re-using it for a new connection; the current
@@ -4969,48 +5265,51 @@ int mbedtls_ssl_close_notify(mbedtls_ssl_context *ssl);
 
 #if defined(MBEDTLS_SSL_SRV_C)
 /**
- * \brief          Read at most 'len' application data bytes while performing
- *                 the handshake (early data).
- *
- * \note           This function behaves mainly as mbedtls_ssl_read(). The
- *                 specification of mbedtls_ssl_read() relevant to TLS 1.3
- *                 (thus not the parts specific to (D)TLS 1.2) applies to this
- *                 function and the present documentation is restricted to the
- *                 differences with mbedtls_ssl_read().
- *
- * \param ssl      SSL context
+ * \brief          Read at most 'len' bytes of early data
+ *
+ * \note           This API is server specific.
+ *
+ * \warning        Early data is defined in the TLS 1.3 specification, RFC 8446.
+ *                 IMPORTANT NOTE from section 2.3 of the specification:
+ *
+ *                 The security properties for 0-RTT data are weaker than
+ *                 those for other kinds of TLS data. Specifically:
+ *                 - This data is not forward secret, as it is encrypted
+ *                   solely under keys derived using the offered PSK.
+ *                 - There are no guarantees of non-replay between connections.
+ *                   Protection against replay for ordinary TLS 1.3 1-RTT data
+ *                   is provided via the server's Random value, but 0-RTT data
+ *                   does not depend on the ServerHello and therefore has
+ *                   weaker guarantees. This is especially relevant if the
+ *                   data is authenticated either with TLS client
+ *                   authentication or inside the application protocol. The
+ *                   same warnings apply to any use of the
+ *                   early_exporter_master_secret.
+ *
+ * \warning        Mbed TLS does not implement any of the anti-replay defenses
+ *                 defined in section 8 of the TLS 1.3 specification:
+ *                 single-use of tickets or ClientHello recording within a
+ *                 given time window.
+ *
+ * \note           This function is used in conjunction with
+ *                 mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(),
+ *                 mbedtls_ssl_read() and mbedtls_ssl_write() to read early
+ *                 data when these functions return
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.
+ *
+ * \param ssl      SSL context, it must have been initialized and set up.
  * \param buf      buffer that will hold the data
  * \param len      maximum number of bytes to read
  *
- * \return         One additional specific return value:
- *                 #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA.
- *
- *                 #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA is returned when it
- *                 is not possible to read early data for the SSL context
- *                 \p ssl.
- *
- *                 It may have been possible and it is not possible
- *                 anymore because the server received the End of Early Data
- *                 message or the maximum number of allowed early data for the
- *                 PSK in use has been reached.
- *
- *                 It may never have been possible and will never be possible
- *                 for the SSL context \p ssl because the use of early data
- *                 is disabled for that context or more generally the context
- *                 is not suitably configured to enable early data or the
- *                 client does not use early data or the first call to the
- *                 function was done while the handshake was already too
- *                 advanced to gather and accept early data.
- *
- *                 It is not possible to read early data for the SSL context
- *                 \p ssl but this does not preclude for using it with
- *                 mbedtls_ssl_write(), mbedtls_ssl_read() or
- *                 mbedtls_ssl_handshake().
- *
- * \note           When a server wants to retrieve early data, it is expected
- *                 that this function starts the handshake for the SSL context
- *                 \p ssl. But this is not mandatory.
- *
+ * \return         The (positive) number of bytes read if successful.
+ * \return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if input data is invalid.
+ * \return         #MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA if it is not
+ *                 possible to read early data for the SSL context \p ssl. Note
+ *                 that this function is intended to be called for an SSL
+ *                 context \p ssl only after a call to mbedtls_ssl_handshake(),
+ *                 mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or
+ *                 mbedtls_ssl_write() for \p ssl that has returned
+ *                 #MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA.
  */
 int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
                                 unsigned char *buf, size_t len);
@@ -5021,17 +5320,43 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
  * \brief          Try to write exactly 'len' application data bytes while
  *                 performing the handshake (early data).
  *
+ * \warning        Early data is defined in the TLS 1.3 specification, RFC 8446.
+ *                 IMPORTANT NOTE from section 2.3 of the specification:
+ *
+ *                 The security properties for 0-RTT data are weaker than
+ *                 those for other kinds of TLS data. Specifically:
+ *                 - This data is not forward secret, as it is encrypted
+ *                   solely under keys derived using the offered PSK.
+ *                 - There are no guarantees of non-replay between connections.
+ *                   Protection against replay for ordinary TLS 1.3 1-RTT data
+ *                   is provided via the server's Random value, but 0-RTT data
+ *                   does not depend on the ServerHello and therefore has
+ *                   weaker guarantees. This is especially relevant if the
+ *                   data is authenticated either with TLS client
+ *                   authentication or inside the application protocol. The
+ *                   same warnings apply to any use of the
+ *                   early_exporter_master_secret.
+ *
  * \note           This function behaves mainly as mbedtls_ssl_write(). The
  *                 specification of mbedtls_ssl_write() relevant to TLS 1.3
  *                 (thus not the parts specific to (D)TLS1.2) applies to this
- *                 function and the present documentation is restricted to the
- *                 differences with mbedtls_ssl_write().
+ *                 function and the present documentation is mainly restricted
+ *                 to the differences with mbedtls_ssl_write(). One noticeable
+ *                 difference though is that mbedtls_ssl_write() aims to
+ *                 complete the handshake before to write application data
+ *                 while mbedtls_ssl_write_early() aims to drive the handshake
+ *                 just past the point where it is not possible to send early
+ *                 data anymore.
  *
  * \param ssl      SSL context
  * \param buf      buffer holding the data
  * \param len      how many bytes must be written
  *
- * \return         One additional specific return value:
+ * \return         The (non-negative) number of bytes actually written if
+ *                 successful (may be less than \p len).
+ *
+ * \return         One additional specific error code compared to
+ *                 mbedtls_ssl_write():
  *                 #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA.
  *
  *                 #MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA is returned when it
@@ -5052,9 +5377,11 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
  *                 already completed.
  *
  *                 It is not possible to write early data for the SSL context
- *                 \p ssl but this does not preclude for using it with
+ *                 \p ssl and any subsequent call to this API will return this
+ *                 error code. But this does not preclude for using it with
  *                 mbedtls_ssl_write(), mbedtls_ssl_read() or
- *                 mbedtls_ssl_handshake().
+ *                 mbedtls_ssl_handshake() and the handshake can be
+ *                 completed by calling one of these APIs.
  *
  * \note           This function may write early data only if the SSL context
  *                 has been configured for the handshake with a PSK for which
@@ -5076,9 +5403,6 @@ int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
 int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
                                  const unsigned char *buf, size_t len);
 
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT  0
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED  1
-#define MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED  2
 /**
  * \brief Get the status of the negotiation of the use of early data.
  *
@@ -5090,8 +5414,8 @@ int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
  * \return         #MBEDTLS_ERR_SSL_BAD_INPUT_DATA if this function is called
  *                 prior to completion of the handshake.
  *
- * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT if the client has
- *                 not indicated the use of early data to the server.
+ * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED if the client
+ *                 has not indicated the use of early data to the server.
  *
  * \return         #MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED if the client has
  *                 indicated the use of early data and the server has accepted
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
index 55dcf77c3b3ca3f910a6cdba88c558a44bd50ed9..a1307b450876236c7a7e10d53c895a002443d049 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cache.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_CACHE_H
 #define MBEDTLS_SSL_CACHE_H
@@ -102,6 +90,11 @@ void mbedtls_ssl_cache_init(mbedtls_ssl_cache_context *cache);
  * \param session_id_len  The length of \p session_id in bytes.
  * \param session         The address at which to store the session
  *                        associated with \p session_id, if present.
+ *
+ * \return                \c 0 on success.
+ * \return                #MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND if there is
+ *                        no cache entry with specified session ID found, or
+ *                        any other negative error code for other failures.
  */
 int mbedtls_ssl_cache_get(void *data,
                           unsigned char const *session_id,
@@ -117,6 +110,9 @@ int mbedtls_ssl_cache_get(void *data,
  *                        associated to \p session.
  * \param session_id_len  The length of \p session_id in bytes.
  * \param session         The session to store.
+ *
+ * \return                \c 0 on success.
+ * \return                A negative error code on failure.
  */
 int mbedtls_ssl_cache_set(void *data,
                           unsigned char const *session_id,
@@ -129,12 +125,13 @@ int mbedtls_ssl_cache_set(void *data,
  *
  * \param data            The SSL cache context to use.
  * \param session_id      The pointer to the buffer holding the session ID
- *                        associated to \p session.
+ *                        associated to session.
  * \param session_id_len  The length of \p session_id in bytes.
  *
- * \return                0: The cache entry for session with provided ID
- *                           is removed or does not exist.
- *                        Otherwise: fail.
+ * \return                \c 0 on success. This indicates the cache entry for
+ *                        the session with provided ID is removed or does not
+ *                        exist.
+ * \return                A negative error code on failure.
  */
 int mbedtls_ssl_cache_remove(void *data,
                              unsigned char const *session_id,
@@ -151,6 +148,20 @@ int mbedtls_ssl_cache_remove(void *data,
  * \param timeout  cache entry timeout in seconds
  */
 void mbedtls_ssl_cache_set_timeout(mbedtls_ssl_cache_context *cache, int timeout);
+
+/**
+ * \brief          Get the cache timeout
+ *
+ *                 A timeout of 0 indicates no timeout.
+ *
+ * \param cache    SSL cache context
+ *
+ * \return         cache entry timeout in seconds
+ */
+static inline int mbedtls_ssl_cache_get_timeout(mbedtls_ssl_cache_context *cache)
+{
+    return cache->MBEDTLS_PRIVATE(timeout);
+}
 #endif /* MBEDTLS_HAVE_TIME */
 
 /**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
index 17b8ff789bf978cdff26bd696aabf3a99445af84..12d446200f3b61670994e638941cc3baf7905970 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ciphersuites.h
@@ -1,23 +1,11 @@
 /**
  * \file ssl_ciphersuites.h
  *
- * \brief SSL Ciphersuites for mbed TLS
+ * \brief SSL Ciphersuites for Mbed TLS
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_CIPHERSUITES_H
 #define MBEDTLS_SSL_CIPHERSUITES_H
@@ -292,21 +280,49 @@ typedef enum {
 #define MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED
 #endif
 
+/* Key exchanges in either TLS 1.2 or 1.3 which are using an ECDSA
+ * signature */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED
+#endif
+
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) || \
     defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
 #define MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED
 #endif
 
-/* Key exchanges allowing client certificate requests */
+/* Key exchanges allowing client certificate requests.
+ *
+ * Note: that's almost the same as MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED
+ * above, except RSA-PSK uses a server certificate but no client cert.
+ *
+ * Note: this difference is specific to TLS 1.2, as with TLS 1.3, things are
+ * more symmetrical: client certs and server certs are either both allowed
+ * (Ephemeral mode) or both disallowed (PSK and PKS-Ephemeral modes).
+ */
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)           ||       \
     defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       ||       \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)      ||       \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     ||       \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)   ||       \
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)    ||       \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
+    defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
 #define MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED
 #endif
 
+/* Helper to state that certificate-based client authentication through ECDSA
+ * is supported in TLS 1.2 */
+#if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
+#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED
+#endif
+
+/* ECDSA required for certificates in either TLS 1.2 or 1.3 */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED
+#endif
+
 /* Key exchanges involving server signature in ServerKeyExchange */
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)     || \
@@ -346,11 +362,6 @@ typedef enum {
 #define MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
 #endif
 
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \
-    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
-#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED
-#endif
-
 /* Key exchanges using DHE */
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)       || \
     defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
@@ -364,6 +375,62 @@ typedef enum {
 #define MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED
 #endif
 
+/* TLS 1.2 key exchanges using ECDH or ECDHE*/
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED
+#endif
+
+/* TLS 1.3 PSK key exchanges */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED
+#endif
+
+/* TLS 1.2 or 1.3 key exchanges with PSK */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+#define MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED
+#endif
+
+/* TLS 1.3 ephemeral key exchanges */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
+#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED
+#endif
+
+/* TLS 1.3 key exchanges using ECDHE */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED) && \
+    defined(PSA_WANT_ALG_ECDH)
+#define MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED
+#endif
+
+/* TLS 1.2 or 1.3 key exchanges using ECDH or ECDHE */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_ECDHE_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED
+#endif
+
+/* TLS 1.2 XXDH key exchanges: ECDH or ECDHE or FFDH */
+#if (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED))
+#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_1_2_ENABLED
+#endif
+
+/* The handshake params structure has a set of fields called xxdh_psa which are used:
+ * - by TLS 1.2 with `USE_PSA` to do ECDH or ECDHE;
+ * - by TLS 1.3 to do ECDHE or FFDHE.
+ * The following macros can be used to guard their declaration and use.
+ */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_1_2_ENABLED) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+#define MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED
+#endif
+
 typedef struct mbedtls_ssl_ciphersuite_t mbedtls_ssl_ciphersuite_t;
 
 #define MBEDTLS_CIPHERSUITE_WEAK       0x01    /**< Weak ciphersuite flag  */
@@ -396,151 +463,17 @@ const int *mbedtls_ssl_list_ciphersuites(void);
 const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_string(const char *ciphersuite_name);
 const mbedtls_ssl_ciphersuite_t *mbedtls_ssl_ciphersuite_from_id(int ciphersuite_id);
 
-#if defined(MBEDTLS_PK_C)
-mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info);
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info);
-psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info);
-#endif
-mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info);
-#endif
-
-int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info);
-int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info);
-
 static inline const char *mbedtls_ssl_ciphersuite_get_name(const mbedtls_ssl_ciphersuite_t *info)
 {
     return info->MBEDTLS_PRIVATE(name);
 }
 
-size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info);
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-        case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-        case MBEDTLS_KEY_EXCHANGE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_PSK:
-        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
-
-static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info)
+static inline int mbedtls_ssl_ciphersuite_get_id(const mbedtls_ssl_ciphersuite_t *info)
 {
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return 1;
-
-        default:
-            return 0;
-    }
+    return info->MBEDTLS_PRIVATE(id);
 }
 
-static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
-        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */
-
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
-static inline int mbedtls_ssl_ciphersuite_uses_server_signature(
-    const mbedtls_ssl_ciphersuite_t *info)
-{
-    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
-        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return 1;
-
-        default:
-            return 0;
-    }
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersuite_t *info);
 
 #ifdef __cplusplus
 }
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
index 5cd1847d0661a9ccf63778a1750920ec27e9b14d..71c258ea48d60a0a0d341c71327504aae544e9b4 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_cookie.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_COOKIE_H
 #define MBEDTLS_SSL_COOKIE_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
index 0cefe43a1a51136948329ca21479a94ff66bc33b..2ee1400210371cdbcbdff6aa2aff13f7a4a9c300 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/ssl_ticket.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_TICKET_H
 #define MBEDTLS_SSL_TICKET_H
@@ -62,6 +50,10 @@ typedef struct mbedtls_ssl_ticket_key {
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */
 #endif
+    /*! Lifetime of the key in seconds. This is also the lifetime of the
+     *  tickets created under that key.
+     */
+    uint32_t MBEDTLS_PRIVATE(lifetime);
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx);   /*!< context for auth enc/decryption    */
 #else
@@ -116,10 +108,16 @@ void mbedtls_ssl_ticket_init(mbedtls_ssl_ticket_context *ctx);
  *                  least as strong as the strongest ciphersuite
  *                  supported. Usually that means a 256-bit key.
  *
- * \note            The lifetime of the keys is twice the lifetime of tickets.
- *                  It is recommended to pick a reasonable lifetime so as not
+ * \note            It is recommended to pick a reasonable lifetime so as not
  *                  to negate the benefits of forward secrecy.
  *
+ * \note            The TLS 1.3 specification states that ticket lifetime must
+ *                  be smaller than seven days. If ticket lifetime has been
+ *                  set to a value greater than seven days in this module then
+ *                  if the TLS 1.3 is configured to send tickets after the
+ *                  handshake it will fail the connection when trying to send
+ *                  the first ticket.
+ *
  * \return          0 if successful,
  *                  or a specific MBEDTLS_ERR_XXX error code
  */
@@ -153,10 +151,16 @@ int mbedtls_ssl_ticket_setup(mbedtls_ssl_ticket_context *ctx,
  * \note            \c klength must be sufficient for use by cipher specified
  *                  to \c mbedtls_ssl_ticket_setup
  *
- * \note            The lifetime of the keys is twice the lifetime of tickets.
- *                  It is recommended to pick a reasonable lifetime so as not
+ * \note            It is recommended to pick a reasonable lifetime so as not
  *                  to negate the benefits of forward secrecy.
  *
+ * \note            The TLS 1.3 specification states that ticket lifetime must
+ *                  be smaller than seven days. If ticket lifetime has been
+ *                  set to a value greater than seven days in this module then
+ *                  if the TLS 1.3 is configured to send tickets after the
+ *                  handshake it will fail the connection when trying to send
+ *                  the first ticket.
+ *
  * \return          0 if successful,
  *                  or a specific MBEDTLS_ERR_XXX error code
  */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/threading.h b/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
index 1b9c7ced2562dc8bca64f639c0b40e3670515626..d50d04ead105373111b9742316b9ba5a0e1edccf 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/threading.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_THREADING_H
 #define MBEDTLS_THREADING_H
@@ -40,10 +28,14 @@ extern "C" {
 #include <pthread.h>
 typedef struct mbedtls_threading_mutex_t {
     pthread_mutex_t MBEDTLS_PRIVATE(mutex);
-    /* is_valid is 0 after a failed init or a free, and nonzero after a
-     * successful init. This field is not considered part of the public
-     * API of Mbed TLS and may change without notice. */
-    char MBEDTLS_PRIVATE(is_valid);
+
+    /* WARNING - state should only be accessed when holding the mutex lock in
+     * tests/src/threading_helpers.c, otherwise corruption can occur.
+     * state will be 0 after a failed init or a free, and nonzero after a
+     * successful init. This field is for testing only and thus not considered
+     * part of the public API of Mbed TLS and may change without notice.*/
+    char MBEDTLS_PRIVATE(state);
+
 } mbedtls_threading_mutex_t;
 #endif
 
@@ -55,9 +47,9 @@ typedef struct mbedtls_threading_mutex_t {
  * \brief           Set your alternate threading implementation function
  *                  pointers and initialize global mutexes. If used, this
  *                  function must be called once in the main thread before any
- *                  other mbed TLS function is called, and
+ *                  other Mbed TLS function is called, and
  *                  mbedtls_threading_free_alt() must be called once in the main
- *                  thread after all other mbed TLS functions.
+ *                  thread after all other Mbed TLS functions.
  *
  * \note            mutex_init() and mutex_free() don't return a status code.
  *                  If mutex_init() fails, it should leave its argument (the
@@ -108,6 +100,34 @@ extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex;
 extern mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex;
 #endif /* MBEDTLS_HAVE_TIME_DATE && !MBEDTLS_PLATFORM_GMTIME_R_ALT */
 
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+/*
+ * A mutex used to make the PSA subsystem thread safe.
+ *
+ * key_slot_mutex protects the registered_readers and
+ * state variable for all key slots in &global_data.key_slots.
+ *
+ * This mutex must be held when any read from or write to a state or
+ * registered_readers field is performed, i.e. when calling functions:
+ * psa_key_slot_state_transition(), psa_register_read(), psa_unregister_read(),
+ * psa_key_slot_has_readers() and psa_wipe_key_slot(). */
+extern mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex;
+
+/*
+ * A mutex used to make the non-rng PSA global_data struct members thread safe.
+ *
+ * This mutex must be held when reading or writing to any of the PSA global_data
+ * structure members, other than the rng_state or rng struct. */
+extern mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex;
+
+/*
+ * A mutex used to make the PSA global_data rng data thread safe.
+ *
+ * This mutex must be held when reading or writing to the PSA
+ * global_data rng_state or rng struct members. */
+extern mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex;
+#endif
+
 #endif /* MBEDTLS_THREADING_C */
 
 #ifdef __cplusplus
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/timing.h b/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
index 2d4a19c01af420c2fb50263be8b56ed869a88184..62ae1022d91d355edb71e5694e8e347d6059f07f 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/timing.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_TIMING_H
 #define MBEDTLS_TIMING_H
@@ -39,7 +27,7 @@ extern "C" {
  * \brief          timer structure
  */
 struct mbedtls_timing_hr_time {
-    unsigned char MBEDTLS_PRIVATE(opaque)[32];
+    uint64_t MBEDTLS_PRIVATE(opaque)[4];
 };
 
 /**
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/version.h b/lib/libmbedtls/mbedtls/include/mbedtls/version.h
index bb1a4c3cbe7752cc105103890d6addcd1f445483..637f9d38bf6df3ef5c45ca61f4c7a2c7e4d86675 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/version.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/version.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * This set of run-time variables can be used to determine the version number of
@@ -52,9 +40,9 @@ unsigned int mbedtls_version_get_number(void);
 void mbedtls_version_get_string(char *string);
 
 /**
- * Get the full version string ("mbed TLS x.y.z").
+ * Get the full version string ("Mbed TLS x.y.z").
  *
- * \param string    The string that will receive the value. The mbed TLS version
+ * \param string    The string that will receive the value. The Mbed TLS version
  *                  string will use 18 bytes AT MOST including a terminating
  *                  null byte.
  *                  (So the buffer should be at least 18 bytes to receive this
@@ -64,12 +52,12 @@ void mbedtls_version_get_string_full(char *string);
 
 /**
  * \brief           Check if support for a feature was compiled into this
- *                  mbed TLS binary. This allows you to see at runtime if the
+ *                  Mbed TLS binary. This allows you to see at runtime if the
  *                  library was for instance compiled with or without
  *                  Multi-threading support.
  *
  * \note            only checks against defines in the sections "System
- *                  support", "mbed TLS modules" and "mbed TLS feature
+ *                  support", "Mbed TLS modules" and "Mbed TLS feature
  *                  support" in mbedtls_config.h
  *
  * \param feature   The string for the define to check (e.g. "MBEDTLS_AES_C")
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
index bd1947e465fb10036baff303893bc4e30ec2b1be..453f598c746bbedf4b42ac361f3bae450fddef1b 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_X509_H
 #define MBEDTLS_X509_H
@@ -243,6 +231,17 @@ typedef mbedtls_asn1_named_data mbedtls_x509_name;
  */
 typedef mbedtls_asn1_sequence mbedtls_x509_sequence;
 
+/*
+ * Container for the fields of the Authority Key Identifier object
+ */
+typedef struct mbedtls_x509_authority {
+    mbedtls_x509_buf keyIdentifier;
+    mbedtls_x509_sequence authorityCertIssuer;
+    mbedtls_x509_buf authorityCertSerialNumber;
+    mbedtls_x509_buf raw;
+}
+mbedtls_x509_authority;
+
 /** Container for date and time (precision in seconds). */
 typedef struct mbedtls_x509_time {
     int year, mon, day;         /**< Date. */
@@ -293,14 +292,22 @@ mbedtls_x509_san_other_name;
 typedef struct mbedtls_x509_subject_alternative_name {
     int type;                              /**< The SAN type, value of MBEDTLS_X509_SAN_XXX. */
     union {
-        mbedtls_x509_san_other_name other_name; /**< The otherName supported type. */
-        mbedtls_x509_buf   unstructured_name; /**< The buffer for the unconstructed types. Only rfc822Name, dnsName and uniformResourceIdentifier are currently supported */
+        mbedtls_x509_san_other_name other_name;
+        mbedtls_x509_name directory_name;
+        mbedtls_x509_buf unstructured_name; /**< The buffer for the unstructured types. rfc822Name, dnsName and uniformResourceIdentifier are currently supported. */
     }
     san; /**< A union of the supported SAN types */
 }
 mbedtls_x509_subject_alternative_name;
 
+typedef struct mbedtls_x509_san_list {
+    mbedtls_x509_subject_alternative_name node;
+    struct mbedtls_x509_san_list *next;
+}
+mbedtls_x509_san_list;
+
 /** \} name Structures for parsing X.509 certificates, CRLs and CSRs */
+/** \} addtogroup x509_module */
 
 /**
  * \brief          Store the certificate DN in printable form into buf;
@@ -315,6 +322,23 @@ mbedtls_x509_subject_alternative_name;
  */
 int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn);
 
+/**
+ * \brief            Convert the certificate DN string \p name into
+ *                   a linked list of mbedtls_x509_name (equivalent to
+ *                   mbedtls_asn1_named_data).
+ *
+ * \note             This function allocates a linked list, and places the head
+ *                   pointer in \p head. This list must later be freed by a
+ *                   call to mbedtls_asn1_free_named_data_list().
+ *
+ * \param[out] head  Address in which to store the pointer to the head of the
+ *                   allocated list of mbedtls_x509_name
+ * \param[in] name   The string representation of a DN to convert
+ *
+ * \return           0 on success, or a negative error code.
+ */
+int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name);
+
 /**
  * \brief          Return the next relative DN in an X509 name.
  *
@@ -348,6 +372,31 @@ static inline mbedtls_x509_name *mbedtls_x509_dn_get_next(
  */
 int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial);
 
+/**
+ * \brief          Compare pair of mbedtls_x509_time.
+ *
+ * \param t1       mbedtls_x509_time to compare
+ * \param t2       mbedtls_x509_time to compare
+ *
+ * \return         < 0 if t1 is before t2
+ *                   0 if t1 equals t2
+ *                 > 0 if t1 is after t2
+ */
+int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1, const mbedtls_x509_time *t2);
+
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+/**
+ * \brief          Fill mbedtls_x509_time with provided mbedtls_time_t.
+ *
+ * \param tt       mbedtls_time_t to convert
+ * \param now      mbedtls_x509_time to fill with converted mbedtls_time_t
+ *
+ * \return         \c 0 on success
+ * \return         A non-zero return value on failure.
+ */
+int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now);
+#endif /* MBEDTLS_HAVE_TIME_DATE */
+
 /**
  * \brief          Check a given mbedtls_x509_time against the system time
  *                 and tell if it's in the past.
@@ -378,21 +427,25 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
 
 /**
  * \brief          This function parses an item in the SubjectAlternativeNames
- *                 extension.
+ *                 extension. Please note that this function might allocate
+ *                 additional memory for a subject alternative name, thus
+ *                 mbedtls_x509_free_subject_alt_name has to be called
+ *                 to dispose of this additional memory afterwards.
  *
  * \param san_buf  The buffer holding the raw data item of the subject
  *                 alternative name.
  * \param san      The target structure to populate with the parsed presentation
- *                 of the subject alternative name encoded in \p san_raw.
+ *                 of the subject alternative name encoded in \p san_buf.
  *
  * \note           Supported GeneralName types, as defined in RFC 5280:
- *                 "rfc822Name", "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
+ *                 "rfc822Name", "dnsName", "directoryName",
+ *                 "uniformResourceIdentifier" and "hardware_module_name"
  *                 of type "otherName", as defined in RFC 4108.
  *
  * \note           This function should be called on a single raw data of
  *                 subject alternative name. For example, after successful
  *                 certificate parsing, one must iterate on every item in the
- *                 \p crt->subject_alt_names sequence, and pass it to
+ *                 \c crt->subject_alt_names sequence, and pass it to
  *                 this function.
  *
  * \warning        The target structure contains pointers to the raw data of the
@@ -406,68 +459,29 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from);
  */
 int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
                                         mbedtls_x509_subject_alternative_name *san);
+/**
+ * \brief          Unallocate all data related to subject alternative name
+ *
+ * \param san      SAN structure - extra memory owned by this structure will be freed
+ */
+void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san);
 
-/** \} addtogroup x509_module */
-
-/*
- * Internal module functions. You probably do not want to use these unless you
- * know you do.
+/**
+ * \brief          This function parses a CN string as an IP address.
+ *
+ * \param cn       The CN string to parse. CN string MUST be null-terminated.
+ * \param dst      The target buffer to populate with the binary IP address.
+ *                 The buffer MUST be 16 bytes to save IPv6, and should be
+ *                 4-byte aligned if the result will be used as struct in_addr.
+ *                 e.g. uint32_t dst[4]
+ *
+ * \note           \p cn is parsed as an IPv6 address if string contains ':',
+ *                 else \p cn is parsed as an IPv4 address.
+ *
+ * \return         Length of binary IP address; num bytes written to target.
+ * \return         \c 0 on failure to parse CN string as an IP address.
  */
-int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
-                          mbedtls_x509_name *cur);
-int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
-                              mbedtls_x509_buf *alg);
-int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
-                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params);
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
-                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
-                                       int *salt_len);
-#endif
-int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig);
-int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
-                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
-                             void **sig_opts);
-int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
-                          mbedtls_x509_time *t);
-int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
-                            mbedtls_x509_buf *serial);
-int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
-                         mbedtls_x509_buf *ext, int tag);
-#if !defined(MBEDTLS_X509_REMOVE_INFO)
-int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
-                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
-                              const void *sig_opts);
-#endif
-int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name);
-int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name);
-int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
-                               int critical, const unsigned char *val,
-                               size_t val_len);
-int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,
-                                  mbedtls_asn1_named_data *first);
-int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
-                             mbedtls_asn1_named_data *first);
-int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
-                           const char *oid, size_t oid_len,
-                           unsigned char *sig, size_t size);
-int mbedtls_x509_get_ns_cert_type(unsigned char **p,
-                                  const unsigned char *end,
-                                  unsigned char *ns_cert_type);
-int mbedtls_x509_get_key_usage(unsigned char **p,
-                               const unsigned char *end,
-                               unsigned int *key_usage);
-int mbedtls_x509_get_subject_alt_name(unsigned char **p,
-                                      const unsigned char *end,
-                                      mbedtls_x509_sequence *subject_alt_name);
-int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
-                                       const mbedtls_x509_sequence
-                                       *subject_alt_name,
-                                       const char *prefix);
-int mbedtls_x509_info_cert_type(char **buf, size_t *size,
-                                unsigned char ns_cert_type);
-int mbedtls_x509_info_key_usage(char **buf, size_t *size,
-                                unsigned int key_usage);
+size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst);
 
 #define MBEDTLS_X509_SAFE_SNPRINTF                          \
     do {                                                    \
@@ -482,4 +496,4 @@ int mbedtls_x509_info_key_usage(char **buf, size_t *size,
 }
 #endif
 
-#endif /* x509.h */
+#endif /* MBEDTLS_X509_H */
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
index 62694ae7fbb0f6462a9b5ecde077b281c88a136a..6625a44f468c29475d68f68b6a597ba44629a61d 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crl.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_X509_CRL_H
 #define MBEDTLS_X509_CRL_H
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
index 11e5951f60cc6293eaa50bc405aa3d77a359c132..1ce0d23619f5845d5df20485066ab999ae842fa3 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_crt.h
@@ -5,26 +5,13 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_X509_CRT_H
 #define MBEDTLS_X509_CRT_H
 #include "mbedtls/private_access.h"
 
 #include "mbedtls/build_info.h"
-#include "mbedtls/legacy_or_psa.h"
 
 #include "mbedtls/x509.h"
 #include "mbedtls/x509_crl.h"
@@ -76,7 +63,9 @@ typedef struct mbedtls_x509_crt {
     mbedtls_x509_buf issuer_id;         /**< Optional X.509 v2/v3 issuer unique identifier. */
     mbedtls_x509_buf subject_id;        /**< Optional X.509 v2/v3 subject unique identifier. */
     mbedtls_x509_buf v3_ext;            /**< Optional X.509 v3 extensions.  */
-    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName, uniformResourceIdentifier and OtherName are listed). */
+    mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */
+    mbedtls_x509_buf subject_key_id;    /**< Optional X.509 v3 extension subject key identifier. */
+    mbedtls_x509_authority authority_key_id;    /**< Optional X.509 v3 extension authority key identifier. */
 
     mbedtls_x509_sequence certificate_policies; /**< Optional list of certificate policies (Only anyPolicy is printed and enforced, however the rest of the policies are still listed). */
 
@@ -240,6 +229,21 @@ typedef struct mbedtls_x509write_cert {
 }
 mbedtls_x509write_cert;
 
+/**
+ * \brief           Set Subject Alternative Name
+ *
+ * \param ctx       Certificate context to use
+ * \param san_list  List of SAN values
+ *
+ * \return          0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED
+ *
+ * \note            "dnsName", "uniformResourceIdentifier", "IP address",
+ *                  "otherName", and "DirectoryName", as defined in RFC 5280,
+ *                  are supported.
+ */
+int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx,
+                                                       const mbedtls_x509_san_list *san_list);
+
 /**
  * Item in a verification chain: cert and flags for it
  */
@@ -560,6 +564,7 @@ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path);
 int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path);
 
 #endif /* MBEDTLS_FS_IO */
+
 #if !defined(MBEDTLS_X509_REMOVE_INFO)
 /**
  * \brief          Returns an informational string about the
@@ -639,8 +644,12 @@ int mbedtls_x509_crt_verify_info(char *buf, size_t size, const char *prefix,
  * \param cn       The expected Common Name. This will be checked to be
  *                 present in the certificate's subjectAltNames extension or,
  *                 if this extension is absent, as a CN component in its
- *                 Subject name. Currently only DNS names are supported. This
- *                 may be \c NULL if the CN need not be verified.
+ *                 Subject name. DNS names and IP addresses are fully
+ *                 supported, while the URI subtype is partially supported:
+ *                 only exact matching, without any normalization procedures
+ *                 described in 7.4 of RFC5280, will result in a positive
+ *                 URI verification.
+ *                 This may be \c NULL if the CN need not be verified.
  * \param flags    The address at which to store the result of the verification.
  *                 If the verification couldn't be completed, the flag value is
  *                 set to (uint32_t) -1.
@@ -907,6 +916,18 @@ static inline int mbedtls_x509_crt_has_ext_type(const mbedtls_x509_crt *ctx,
     return ctx->MBEDTLS_PRIVATE(ext_types) & ext_type;
 }
 
+/**
+ * \brief               Access the ca_istrue field
+ *
+ * \param[in] crt       Certificate to be queried, must not be \c NULL
+ *
+ * \return              \c 1 if this a CA certificate \c 0 otherwise.
+ * \return              MBEDTLS_ERR_X509_INVALID_EXTENSIONS if the certificate does not contain
+ *                      the Optional Basic Constraint extension.
+ *
+ */
+int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt);
+
 /** \} name Structures and functions for parsing and writing X.509 certificates */
 
 #if defined(MBEDTLS_X509_CRT_WRITE_C)
@@ -986,7 +1007,7 @@ int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx, const char *
  * \brief           Set the issuer name for a Certificate
  *                  Issuer names should contain a comma-separated list
  *                  of OID types and values:
- *                  e.g. "C=UK,O=ARM,CN=mbed TLS CA"
+ *                  e.g. "C=UK,O=ARM,CN=Mbed TLS CA"
  *
  * \param ctx           CRT context to use
  * \param issuer_name   issuer name to set
@@ -1001,7 +1022,7 @@ int mbedtls_x509write_crt_set_issuer_name(mbedtls_x509write_cert *ctx,
  * \brief           Set the subject name for a Certificate
  *                  Subject names should contain a comma-separated list
  *                  of OID types and values:
- *                  e.g. "C=UK,O=ARM,CN=mbed TLS Server 1"
+ *                  e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1"
  *
  * \param ctx           CRT context to use
  * \param subject_name  subject name to set
@@ -1069,7 +1090,7 @@ int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,
 int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,
                                                 int is_ca, int max_pathlen);
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
 /**
  * \brief           Set the subjectKeyIdentifier extension for a CRT
  *                  Requires that mbedtls_x509write_crt_set_subject_key() has been
@@ -1091,7 +1112,7 @@ int mbedtls_x509write_crt_set_subject_key_identifier(mbedtls_x509write_cert *ctx
  * \return          0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED
  */
 int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *ctx);
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
 /**
  * \brief           Set the Key Usage Extension flags
diff --git a/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h b/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
index f3f9e13a03655d50daacbd457499d0b711893c06..8c31c09af4c30ad1f0110a4a4836a48a1502dbab 100644
--- a/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
+++ b/lib/libmbedtls/mbedtls/include/mbedtls/x509_csr.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_X509_CSR_H
 #define MBEDTLS_X509_CSR_H
@@ -60,7 +48,7 @@ typedef struct mbedtls_x509_csr {
 
     unsigned int key_usage;     /**< Optional key usage extension value: See the values in x509.h */
     unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */
-    mbedtls_x509_sequence subject_alt_names;    /**< Optional list of raw entries of Subject Alternative Names extension (currently only dNSName and OtherName are listed). */
+    mbedtls_x509_sequence subject_alt_names; /**< Optional list of raw entries of Subject Alternative Names extension. These can be later parsed by mbedtls_x509_parse_subject_alt_name. */
 
     int MBEDTLS_PRIVATE(ext_types);              /**< Bit string containing detected and parsed extensions */
 
@@ -83,17 +71,13 @@ typedef struct mbedtls_x509write_csr {
 }
 mbedtls_x509write_csr;
 
-typedef struct mbedtls_x509_san_list {
-    mbedtls_x509_subject_alternative_name node;
-    struct mbedtls_x509_san_list *next;
-}
-mbedtls_x509_san_list;
-
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
 /**
  * \brief          Load a Certificate Signing Request (CSR) in DER format
  *
- * \note           CSR attributes (if any) are currently silently ignored.
+ * \note           Any unsupported requested extensions are silently
+ *                 ignored, unless the critical flag is set, in which case
+ *                 the CSR is rejected.
  *
  * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
  *                 subsystem must have been initialized by calling
@@ -108,6 +92,67 @@ mbedtls_x509_san_list;
 int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
                                const unsigned char *buf, size_t buflen);
 
+/**
+ * \brief          The type of certificate extension callbacks.
+ *
+ *                 Callbacks of this type are passed to and used by the
+ *                 mbedtls_x509_csr_parse_der_with_ext_cb() routine when
+ *                 it encounters either an unsupported extension.
+ *                 Future versions of the library may invoke the callback
+ *                 in other cases, if and when the need arises.
+ *
+ * \param p_ctx    An opaque context passed to the callback.
+ * \param csr      The CSR being parsed.
+ * \param oid      The OID of the extension.
+ * \param critical Whether the extension is critical.
+ * \param p        Pointer to the start of the extension value
+ *                 (the content of the OCTET STRING).
+ * \param end      End of extension value.
+ *
+ * \note           The callback must fail and return a negative error code
+ *                 if it can not parse or does not support the extension.
+ *                 When the callback fails to parse a critical extension
+ *                 mbedtls_x509_csr_parse_der_with_ext_cb() also fails.
+ *                 When the callback fails to parse a non critical extension
+ *                 mbedtls_x509_csr_parse_der_with_ext_cb() simply skips
+ *                 the extension and continues parsing.
+ *
+ * \return         \c 0 on success.
+ * \return         A negative error code on failure.
+ */
+typedef int (*mbedtls_x509_csr_ext_cb_t)(void *p_ctx,
+                                         mbedtls_x509_csr const *csr,
+                                         mbedtls_x509_buf const *oid,
+                                         int critical,
+                                         const unsigned char *p,
+                                         const unsigned char *end);
+
+/**
+ * \brief          Load a Certificate Signing Request (CSR) in DER format
+ *
+ * \note           Any unsupported requested extensions are silently
+ *                 ignored, unless the critical flag is set, in which case
+ *                 the result of the callback function decides whether
+ *                 CSR is rejected.
+ *
+ * \note           If #MBEDTLS_USE_PSA_CRYPTO is enabled, the PSA crypto
+ *                 subsystem must have been initialized by calling
+ *                 psa_crypto_init() before calling this function.
+ *
+ * \param csr      CSR context to fill
+ * \param buf      buffer holding the CRL data
+ * \param buflen   size of the buffer
+ * \param cb       A callback invoked for every unsupported certificate
+ *                 extension.
+ * \param p_ctx    An opaque context passed to the callback.
+ *
+ * \return         0 if successful, or a specific X509 error code
+ */
+int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,
+                                           const unsigned char *buf, size_t buflen,
+                                           mbedtls_x509_csr_ext_cb_t cb,
+                                           void *p_ctx);
+
 /**
  * \brief          Load a Certificate Signing Request (CSR), DER or PEM format
  *
@@ -186,7 +231,7 @@ void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx);
  * \brief           Set the subject name for a CSR
  *                  Subject names should contain a comma-separated list
  *                  of OID types and values:
- *                  e.g. "C=UK,O=ARM,CN=mbed TLS Server 1"
+ *                  e.g. "C=UK,O=ARM,CN=Mbed TLS Server 1"
  *
  * \param ctx           CSR context to use
  * \param subject_name  subject name to set
diff --git a/lib/libmbedtls/mbedtls/include/psa/build_info.h b/lib/libmbedtls/mbedtls/include/psa/build_info.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ee6cd7b1bcaa200cc583498a86e0ddb237ea4d8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/build_info.h
@@ -0,0 +1,20 @@
+/**
+ * \file psa/build_info.h
+ *
+ * \brief Build-time PSA configuration info
+ *
+ *  Include this file if you need to depend on the
+ *  configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE
+ *  in PSA cryptography core specific files.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_BUILD_INFO_H
+#define PSA_CRYPTO_BUILD_INFO_H
+
+#include "mbedtls/build_info.h"
+
+#endif /* PSA_CRYPTO_BUILD_INFO_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto.h b/lib/libmbedtls/mbedtls/include/psa/crypto.h
index 8a05efd8b423ae84e97069e17af076d0c18139ad..2bbcea3ee0f7f8aa93e3cdbde51aad599c9afd0b 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto.h
@@ -4,19 +4,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_H
@@ -131,8 +119,9 @@ static psa_key_attributes_t psa_key_attributes_init(void);
  * value in the structure.
  * The persistent key will be written to storage when the attribute
  * structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_custom(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()
+ * or psa_copy_key().
  *
  * This function may be declared as `static` (i.e. without external
  * linkage). This function may be provided as a function-like macro,
@@ -140,6 +129,9 @@ static psa_key_attributes_t psa_key_attributes_init(void);
  *
  * \param[out] attributes  The attribute structure to write to.
  * \param key              The persistent identifier for the key.
+ *                         This can be any value in the range from
+ *                         #PSA_KEY_ID_USER_MIN to #PSA_KEY_ID_USER_MAX
+ *                         inclusive.
  */
 static void psa_set_key_id(psa_key_attributes_t *attributes,
                            mbedtls_svc_key_id_t key);
@@ -175,8 +167,9 @@ static void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes,
  * value in the structure.
  * The persistent key will be written to storage when the attribute
  * structure is passed to a key creation function such as
- * psa_import_key(), psa_generate_key(),
- * psa_key_derivation_output_key() or psa_copy_key().
+ * psa_import_key(), psa_generate_key(), psa_generate_key_custom(),
+ * psa_key_derivation_output_key(), psa_key_derivation_output_key_custom()
+ * or psa_copy_key().
  *
  * This function may be declared as `static` (i.e. without external
  * linkage). This function may be provided as a function-like macro,
@@ -537,6 +530,11 @@ psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,
  * If a key is currently in use in a multipart operation, then destroying the
  * key will cause the multipart operation to fail.
  *
+ * \warning    We can only guarantee that the the key material will
+ *             eventually be wiped from memory. With threading enabled
+ *             and during concurrent execution, copies of the key material may
+ *             still exist until all threads have finished using the key.
+ *
  * \param key  Identifier of the key to erase. If this is \c 0, do nothing and
  *             return #PSA_SUCCESS.
  *
@@ -876,7 +874,7 @@ psa_status_t psa_hash_compute(psa_algorithm_t alg,
  *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
  * \param[in] input         Buffer containing the message to hash.
  * \param input_length      Size of the \p input buffer in bytes.
- * \param[out] hash         Buffer containing the expected hash value.
+ * \param[in] hash          Buffer containing the expected hash value.
  * \param hash_length       Size of the \p hash buffer in bytes.
  *
  * \retval #PSA_SUCCESS
@@ -1229,7 +1227,7 @@ psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
  *                          such that #PSA_ALG_IS_MAC(\p alg) is true).
  * \param[in] input         Buffer containing the input message.
  * \param input_length      Size of the \p input buffer in bytes.
- * \param[out] mac          Buffer containing the expected MAC value.
+ * \param[in] mac           Buffer containing the expected MAC value.
  * \param mac_length        Size of the \p mac buffer in bytes.
  *
  * \retval #PSA_SUCCESS
@@ -2915,7 +2913,7 @@ psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
  *                              \p key.
  * \param[in]  input            The message whose signature is to be verified.
  * \param[in]  input_length     Size of the \p input buffer in bytes.
- * \param[out] signature        Buffer containing the signature to verify.
+ * \param[in] signature         Buffer containing the signature to verify.
  * \param[in]  signature_length Size of the \p signature buffer in bytes.
  *
  * \retval #PSA_SUCCESS \emptydescription
@@ -3238,7 +3236,8 @@ static psa_key_derivation_operation_t psa_key_derivation_operation_init(void);
  *    psa_key_derivation_set_capacity(). You may do this before, in the middle
  *    of or after providing inputs. For some algorithms, this step is mandatory
  *    because the output depends on the maximum capacity.
- * -# To derive a key, call psa_key_derivation_output_key().
+ * -# To derive a key, call psa_key_derivation_output_key() or
+ *    psa_key_derivation_output_key_custom().
  *    To derive a byte string for a different purpose, call
  *    psa_key_derivation_output_bytes().
  *    Successive calls to these functions use successive output bytes
@@ -3461,7 +3460,8 @@ psa_status_t psa_key_derivation_input_integer(
  * \note Once all inputs steps are completed, the operations will allow:
  * - psa_key_derivation_output_bytes() if each input was either a direct input
  *   or  a key with #PSA_KEY_USAGE_DERIVE set;
- * - psa_key_derivation_output_key() if the input for step
+ * - psa_key_derivation_output_key() or psa_key_derivation_output_key_custom()
+ *   if the input for step
  *   #PSA_KEY_DERIVATION_INPUT_SECRET or #PSA_KEY_DERIVATION_INPUT_PASSWORD
  *   was from a key slot with #PSA_KEY_USAGE_DERIVE and each other input was
  *   either a direct input or a key with #PSA_KEY_USAGE_DERIVE set;
@@ -3709,6 +3709,11 @@ psa_status_t psa_key_derivation_output_bytes(
  * Future versions of this specification may include additional restrictions
  * on the derived key based on the attributes and strength of the secret key.
  *
+ * \note This function is equivalent to calling
+ *       psa_key_derivation_output_key_custom()
+ *       with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT
+ *       and `custom_data_length == 0` (i.e. `custom_data` is empty).
+ *
  * \param[in] attributes    The attributes for the new key.
  *                          If the key type to be created is
  *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
@@ -3762,6 +3767,163 @@ psa_status_t psa_key_derivation_output_key(
     psa_key_derivation_operation_t *operation,
     mbedtls_svc_key_id_t *key);
 
+/** Derive a key from an ongoing key derivation operation with custom
+ *  production parameters.
+ *
+ * See the description of psa_key_derivation_out_key() for the operation of
+ * this function with the default production parameters.
+ * Mbed TLS currently does not currently support any non-default production
+ * parameters.
+ *
+ * \note This function is experimental and may change in future minor
+ *       versions of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ *                          If the key type to be created is
+ *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ *                          the policy must be the same as in the current
+ *                          operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] custom        Customization parameters for the key generation.
+ *                          When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT
+ *                          with \p custom_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_key_derivation_output_key().
+ * \param[in] custom_data   Variable-length data associated with \c custom.
+ * \param custom_data_length
+ *                          Length of `custom_data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ *         There was not enough data to create the desired key.
+ *         Note that in this case, no output is written to the output buffer.
+ *         The operation's capacity is set to 0, thus subsequent calls to
+ *         this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ *         key; or one of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active and completed
+ *         all required input steps), or the library has not been previously
+ *         initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_key_derivation_output_key_custom(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_custom_key_parameters_t *custom,
+    const uint8_t *custom_data,
+    size_t custom_data_length,
+    mbedtls_svc_key_id_t *key);
+
+#ifndef __cplusplus
+/* Omitted when compiling in C++, because one of the parameters is a
+ * pointer to a struct with a flexible array member, and that is not
+ * standard C++.
+ * https://github.com/Mbed-TLS/mbedtls/issues/9020
+ */
+/** Derive a key from an ongoing key derivation operation with custom
+ *  production parameters.
+ *
+ * \note
+ * This is a deprecated variant of psa_key_derivation_output_key_custom().
+ * It is equivalent except that the associated variable-length data
+ * is passed in `params->data` instead of a separate parameter.
+ * This function will be removed in a future version of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ *                          If the key type to be created is
+ *                          #PSA_KEY_TYPE_PASSWORD_HASH then the algorithm in
+ *                          the policy must be the same as in the current
+ *                          operation.
+ * \param[in,out] operation The key derivation operation object to read from.
+ * \param[in] params        Customization parameters for the key derivation.
+ *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *                          with \p params_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_key_derivation_output_key().
+ *                          Mbed TLS currently only supports the default
+ *                          production parameters, i.e.
+ *                          #PSA_KEY_PRODUCTION_PARAMETERS_INIT,
+ *                          for all key types.
+ * \param params_data_length
+ *                          Length of `params->data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_DATA
+ *         There was not enough data to create the desired key.
+ *         Note that in this case, no output is written to the output buffer.
+ *         The operation's capacity is set to 0, thus subsequent calls to
+ *         this function will not succeed, even with a smaller output buffer.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The key type or key size is not supported, either by the
+ *         implementation in general or in this particular location.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The provided key attributes are not valid for the operation.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The #PSA_KEY_DERIVATION_INPUT_SECRET or
+ *         #PSA_KEY_DERIVATION_INPUT_PASSWORD input was not provided through a
+ *         key; or one of the inputs was a key whose policy didn't allow
+ *         #PSA_KEY_USAGE_DERIVE.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active and completed
+ *         all required input steps), or the library has not been previously
+ *         initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length,
+    mbedtls_svc_key_id_t *key);
+#endif /* !__cplusplus */
+
 /** Compare output data from a key derivation operation to an expected value.
  *
  * This function calculates output bytes from a key derivation algorithm and
@@ -3786,8 +3948,8 @@ psa_status_t psa_key_derivation_output_key(
  * psa_key_derivation_abort().
  *
  * \param[in,out] operation The key derivation operation object to read from.
- * \param[in] expected_output Buffer containing the expected derivation output.
- * \param output_length     Length of the expected output; this is also the
+ * \param[in] expected      Buffer containing the expected derivation output.
+ * \param expected_length   Length of the expected output; this is also the
  *                          number of bytes that will be read.
  *
  * \retval #PSA_SUCCESS \emptydescription
@@ -3817,8 +3979,8 @@ psa_status_t psa_key_derivation_output_key(
  */
 psa_status_t psa_key_derivation_verify_bytes(
     psa_key_derivation_operation_t *operation,
-    const uint8_t *expected_output,
-    size_t output_length);
+    const uint8_t *expected,
+    size_t expected_length);
 
 /** Compare output data from a key derivation operation to an expected value
  * stored in a key object.
@@ -3847,7 +4009,8 @@ psa_status_t psa_key_derivation_verify_bytes(
  *                          and the permitted algorithm must match the
  *                          operation. The value of this key was likely
  *                          computed by a previous call to
- *                          psa_key_derivation_output_key().
+ *                          psa_key_derivation_output_key() or
+ *                          psa_key_derivation_output_key_custom().
  *
  * \retval #PSA_SUCCESS \emptydescription
  * \retval #PSA_ERROR_INVALID_SIGNATURE
@@ -4015,6 +4178,10 @@ psa_status_t psa_generate_random(uint8_t *output,
  *   between 2^{n-1} and 2^n where n is the bit size specified in the
  *   attributes.
  *
+ * \note This function is equivalent to calling psa_generate_key_custom()
+ *       with the custom production parameters #PSA_CUSTOM_KEY_PARAMETERS_INIT
+ *       and `custom_data_length == 0` (i.e. `custom_data` is empty).
+ *
  * \param[in] attributes    The attributes for the new key.
  * \param[out] key          On success, an identifier for the newly created
  *                          key. For persistent keys, this is the key
@@ -4047,6 +4214,119 @@ psa_status_t psa_generate_random(uint8_t *output,
 psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
                               mbedtls_svc_key_id_t *key);
 
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * See the description of psa_generate_key() for the operation of this
+ * function with the default production parameters. In addition, this function
+ * supports the following production customizations, described in more detail
+ * in the documentation of ::psa_custom_key_parameters_t:
+ *
+ * - RSA keys: generation with a custom public exponent.
+ *
+ * \note This function is experimental and may change in future minor
+ *       versions of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ * \param[in] custom        Customization parameters for the key generation.
+ *                          When this is #PSA_CUSTOM_KEY_PARAMETERS_INIT
+ *                          with \p custom_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_generate_key().
+ * \param[in] custom_data   Variable-length data associated with \c custom.
+ * \param custom_data_length
+ *                          Length of `custom_data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,
+                                     const psa_custom_key_parameters_t *custom,
+                                     const uint8_t *custom_data,
+                                     size_t custom_data_length,
+                                     mbedtls_svc_key_id_t *key);
+
+#ifndef __cplusplus
+/* Omitted when compiling in C++, because one of the parameters is a
+ * pointer to a struct with a flexible array member, and that is not
+ * standard C++.
+ * https://github.com/Mbed-TLS/mbedtls/issues/9020
+ */
+/**
+ * \brief Generate a key or key pair using custom production parameters.
+ *
+ * \note
+ * This is a deprecated variant of psa_key_derivation_output_key_custom().
+ * It is equivalent except that the associated variable-length data
+ * is passed in `params->data` instead of a separate parameter.
+ * This function will be removed in a future version of Mbed TLS.
+ *
+ * \param[in] attributes    The attributes for the new key.
+ * \param[in] params        Customization parameters for the key generation.
+ *                          When this is #PSA_KEY_PRODUCTION_PARAMETERS_INIT
+ *                          with \p params_data_length = 0,
+ *                          this function is equivalent to
+ *                          psa_generate_key().
+ * \param params_data_length
+ *                          Length of `params->data` in bytes.
+ * \param[out] key          On success, an identifier for the newly created
+ *                          key. For persistent keys, this is the key
+ *                          identifier defined in \p attributes.
+ *                          \c 0 on failure.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *         If the key is persistent, the key material and the key's metadata
+ *         have been saved to persistent storage.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         This is an attempt to create a persistent key, and there is
+ *         already a persistent key with the given identifier.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+                                  const psa_key_production_parameters_t *params,
+                                  size_t params_data_length,
+                                  mbedtls_svc_key_id_t *key);
+#endif /* !__cplusplus */
+
 /**@}*/
 
 /** \defgroup interruptible_hash Interruptible sign/verify hash
@@ -4407,9 +4687,9 @@ psa_status_t psa_sign_hash_start(
  * \retval #PSA_ERROR_BUFFER_TOO_SMALL
  *         The size of the \p signature buffer is too small. You can
  *         determine a sufficient buffer size by calling
- *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \c alg)
  *         where \c key_type and \c key_bits are the type and bit-size
- *         respectively of \p key.
+ *         respectively of \c key.
  *
  * \retval #PSA_ERROR_BAD_STATE
  *         An operation was not previously started on this context via
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_auto_enabled.h b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_auto_enabled.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a2af151806957c5cf85db76410619bd3fff8b4e
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_auto_enabled.h
@@ -0,0 +1,31 @@
+/**
+ * \file psa/crypto_adjust_auto_enabled.h
+ * \brief Adjust PSA configuration: enable always-on features
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * Always enable certain features which require a negligible amount of code
+ * to implement, to avoid some edge cases in the configuration combinatorics.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
+#define PSA_CRYPTO_ADJUST_AUTO_ENABLED_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+#define PSA_WANT_KEY_TYPE_DERIVE 1
+#define PSA_WANT_KEY_TYPE_PASSWORD 1
+#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1
+#define PSA_WANT_KEY_TYPE_RAW_DATA 1
+
+#endif /* PSA_CRYPTO_ADJUST_AUTO_ENABLED_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_dependencies.h b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_dependencies.h
new file mode 100644
index 0000000000000000000000000000000000000000..92e9c4de28798ee5e9b549d469cdc5fe1cbc16a9
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_dependencies.h
@@ -0,0 +1,51 @@
+/**
+ * \file psa/crypto_adjust_config_dependencies.h
+ * \brief Adjust PSA configuration by resolving some dependencies.
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * See docs/proposed/psa-conditional-inclusion-c.md.
+ * If the Mbed TLS implementation of a cryptographic mechanism A depends on a
+ * cryptographic mechanism B then if the cryptographic mechanism A is enabled
+ * and not accelerated enable B. Note that if A is enabled and accelerated, it
+ * is not necessary to enable B for A support.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
+#define PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+#if (defined(PSA_WANT_ALG_TLS12_PRF) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PRF)) || \
+    (defined(PSA_WANT_ALG_TLS12_PSK_TO_MS) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_TLS12_PSK_TO_MS)) || \
+    (defined(PSA_WANT_ALG_HKDF) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF)) || \
+    (defined(PSA_WANT_ALG_HKDF_EXTRACT) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXTRACT)) || \
+    (defined(PSA_WANT_ALG_HKDF_EXPAND) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_HKDF_EXPAND)) || \
+    (defined(PSA_WANT_ALG_PBKDF2_HMAC) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_HMAC))
+#define PSA_WANT_ALG_HMAC 1
+#define PSA_WANT_KEY_TYPE_HMAC 1
+#endif
+
+#if (defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) && \
+    !defined(MBEDTLS_PSA_ACCEL_ALG_PBKDF2_AES_CMAC_PRF_128))
+#define PSA_WANT_KEY_TYPE_AES 1
+#define PSA_WANT_ALG_CMAC 1
+#endif
+
+#endif /* PSA_CRYPTO_ADJUST_CONFIG_DEPENDENCIES_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h
new file mode 100644
index 0000000000000000000000000000000000000000..cec39e01ceda38da4409adc95a75aa1253a339d4
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h
@@ -0,0 +1,101 @@
+/**
+ * \file psa/crypto_adjust_config_key_pair_types.h
+ * \brief Adjust PSA configuration for key pair types.
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * See docs/proposed/psa-conditional-inclusion-c.md.
+ * - Support non-basic operations in a keypair type implicitly enables basic
+ *   support for that keypair type.
+ * - Support for a keypair type implicitly enables the corresponding public
+ *   key type.
+ * - Basic support for a keypair type implicilty enables import/export support
+ *   for that keypair type. Warning: this is implementation-specific (mainly
+ *   for the benefit of testing) and may change in the future!
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
+#define PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/*****************************************************************
+ * ANYTHING -> BASIC
+ ****************************************************************/
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE)
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1
+#endif
+
+/*****************************************************************
+ * BASIC -> corresponding PUBLIC
+ ****************************************************************/
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1
+#endif
+
+/*****************************************************************
+ * BASIC -> IMPORT+EXPORT
+ *
+ * (Implementation-specific, may change in the future.)
+ ****************************************************************/
+
+/* Even though KEY_PAIR symbols' feature several level of support (BASIC, IMPORT,
+ * EXPORT, GENERATE, DERIVE) we're not planning to have support only for BASIC
+ * without IMPORT/EXPORT since these last 2 features are strongly used in tests.
+ * In general it is allowed to include more feature than what is strictly
+ * requested.
+ * As a consequence IMPORT and EXPORT features will be automatically enabled
+ * as soon as the BASIC one is. */
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1
+#endif
+
+#endif /* PSA_CRYPTO_ADJUST_KEYPAIR_TYPES_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_synonyms.h b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_synonyms.h
new file mode 100644
index 0000000000000000000000000000000000000000..54b116f434705fbb1f7a91302e605af5bf2bf74b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_adjust_config_synonyms.h
@@ -0,0 +1,49 @@
+/**
+ * \file psa/crypto_adjust_config_synonyms.h
+ * \brief Adjust PSA configuration: enable quasi-synonyms
+ *
+ * This is an internal header. Do not include it directly.
+ *
+ * When two features require almost the same code, we automatically enable
+ * both when either one is requested, to reduce the combinatorics of
+ * possible configurations.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
+#define PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H
+
+#if !defined(MBEDTLS_CONFIG_FILES_READ)
+#error "Do not include psa/crypto_adjust_*.h manually! This can lead to problems, " \
+    "up to and including runtime errors such as buffer overflows. " \
+    "If you're trying to fix a complaint from check_config.h, just remove " \
+    "it from your configuration file: since Mbed TLS 3.0, it is included " \
+    "automatically at the right point."
+#endif /* */
+
+/****************************************************************/
+/* De facto synonyms */
+/****************************************************************/
+
+#if defined(PSA_WANT_ALG_ECDSA_ANY) && !defined(PSA_WANT_ALG_ECDSA)
+#define PSA_WANT_ALG_ECDSA PSA_WANT_ALG_ECDSA_ANY
+#elif !defined(PSA_WANT_ALG_ECDSA_ANY) && defined(PSA_WANT_ALG_ECDSA)
+#define PSA_WANT_ALG_ECDSA_ANY PSA_WANT_ALG_ECDSA
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW
+#elif !defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW) && defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN)
+#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN_RAW PSA_WANT_ALG_RSA_PKCS1V15_SIGN
+#endif
+
+#if defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && !defined(PSA_WANT_ALG_RSA_PSS)
+#define PSA_WANT_ALG_RSA_PSS PSA_WANT_ALG_RSA_PSS_ANY_SALT
+#elif !defined(PSA_WANT_ALG_RSA_PSS_ANY_SALT) && defined(PSA_WANT_ALG_RSA_PSS)
+#define PSA_WANT_ALG_RSA_PSS_ANY_SALT PSA_WANT_ALG_RSA_PSS
+#endif
+
+#endif /* PSA_CRYPTO_ADJUST_CONFIG_SYNONYMS_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h
index 932c50366792e4ad8aaf6aec51255fe6332485b1..c14f5dd110f5214d999ecd731b9396c6dc78468f 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_composites.h
@@ -7,27 +7,15 @@
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
  *
- * \note This header and its content is not part of the Mbed TLS API and
+ * \note This header and its content are not part of the Mbed TLS API and
  * applications must not depend on it. Its main purpose is to define the
  * multi-part state objects of the Mbed TLS software-based PSA drivers. The
- * definition of these objects are then used by crypto_struct.h to define the
+ * definitions of these objects are then used by crypto_struct.h to define the
  * implementation-defined types of PSA multi-part state objects.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_BUILTIN_COMPOSITES_H
@@ -36,6 +24,15 @@
 
 #include <psa/crypto_driver_common.h>
 
+#include "mbedtls/cmac.h"
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+#include "mbedtls/gcm.h"
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+#include "mbedtls/ccm.h"
+#endif
+#include "mbedtls/chachapoly.h"
+
 /*
  * MAC multi-part operation definitions.
  */
@@ -57,8 +54,6 @@ typedef struct {
 #define MBEDTLS_PSA_HMAC_OPERATION_INIT { 0, PSA_HASH_OPERATION_INIT, { 0 } }
 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
 
-#include "mbedtls/cmac.h"
-
 typedef struct {
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
     union {
@@ -199,7 +194,7 @@ typedef struct {
     uint8_t *MBEDTLS_PRIVATE(password);
     size_t MBEDTLS_PRIVATE(password_len);
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
-    uint8_t MBEDTLS_PRIVATE(role);
+    mbedtls_ecjpake_role MBEDTLS_PRIVATE(role);
     uint8_t MBEDTLS_PRIVATE(buffer[MBEDTLS_PSA_JPAKE_BUFFER_SIZE]);
     size_t MBEDTLS_PRIVATE(buffer_length);
     size_t MBEDTLS_PRIVATE(buffer_offset);
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_key_derivation.h b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_key_derivation.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b91ae73f1e2f4174a23715c06955a9fab57d40f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_key_derivation.h
@@ -0,0 +1,118 @@
+/*
+ *  Context structure declaration of the Mbed TLS software-based PSA drivers
+ *  called through the PSA Crypto driver dispatch layer.
+ *  This file contains the context structures of key derivation algorithms
+ *  which need to rely on other algorithms.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * \note This header and its content are not part of the Mbed TLS API and
+ * applications must not depend on it. Its main purpose is to define the
+ * multi-part state objects of the Mbed TLS software-based PSA drivers. The
+ * definitions of these objects are then used by crypto_struct.h to define the
+ * implementation-defined types of PSA multi-part state objects.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H
+#define PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H
+#include "mbedtls/private_access.h"
+
+#include <psa/crypto_driver_common.h>
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+typedef struct {
+    uint8_t *MBEDTLS_PRIVATE(info);
+    size_t MBEDTLS_PRIVATE(info_length);
+#if PSA_HASH_MAX_SIZE > 0xff
+#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
+#endif
+    uint8_t MBEDTLS_PRIVATE(offset_in_block);
+    uint8_t MBEDTLS_PRIVATE(block_number);
+    unsigned int MBEDTLS_PRIVATE(state) : 2;
+    unsigned int MBEDTLS_PRIVATE(info_set) : 1;
+    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
+    uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE];
+    struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac);
+} psa_hkdf_key_derivation_t;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF ||
+          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT ||
+          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+typedef struct {
+    uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE];
+} psa_tls12_ecjpake_to_pms_t;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+typedef enum {
+    PSA_TLS12_PRF_STATE_INIT,             /* no input provided */
+    PSA_TLS12_PRF_STATE_SEED_SET,         /* seed has been set */
+    PSA_TLS12_PRF_STATE_OTHER_KEY_SET,    /* other key has been set - optional */
+    PSA_TLS12_PRF_STATE_KEY_SET,          /* key has been set */
+    PSA_TLS12_PRF_STATE_LABEL_SET,        /* label has been set */
+    PSA_TLS12_PRF_STATE_OUTPUT            /* output has been started */
+} psa_tls12_prf_key_derivation_state_t;
+
+typedef struct psa_tls12_prf_key_derivation_s {
+#if PSA_HASH_MAX_SIZE > 0xff
+#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
+#endif
+
+    /* Indicates how many bytes in the current HMAC block have
+     * not yet been read by the user. */
+    uint8_t MBEDTLS_PRIVATE(left_in_block);
+
+    /* The 1-based number of the block. */
+    uint8_t MBEDTLS_PRIVATE(block_number);
+
+    psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state);
+
+    uint8_t *MBEDTLS_PRIVATE(secret);
+    size_t MBEDTLS_PRIVATE(secret_length);
+    uint8_t *MBEDTLS_PRIVATE(seed);
+    size_t MBEDTLS_PRIVATE(seed_length);
+    uint8_t *MBEDTLS_PRIVATE(label);
+    size_t MBEDTLS_PRIVATE(label_length);
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    uint8_t *MBEDTLS_PRIVATE(other_secret);
+    size_t MBEDTLS_PRIVATE(other_secret_length);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+
+    uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE];
+
+    /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */
+    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
+} psa_tls12_prf_key_derivation_t;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+typedef enum {
+    PSA_PBKDF2_STATE_INIT,             /* no input provided */
+    PSA_PBKDF2_STATE_INPUT_COST_SET,   /* input cost has been set */
+    PSA_PBKDF2_STATE_SALT_SET,         /* salt has been set */
+    PSA_PBKDF2_STATE_PASSWORD_SET,     /* password has been set */
+    PSA_PBKDF2_STATE_OUTPUT            /* output has been started */
+} psa_pbkdf2_key_derivation_state_t;
+
+typedef struct {
+    psa_pbkdf2_key_derivation_state_t MBEDTLS_PRIVATE(state);
+    uint64_t MBEDTLS_PRIVATE(input_cost);
+    uint8_t *MBEDTLS_PRIVATE(salt);
+    size_t MBEDTLS_PRIVATE(salt_length);
+    uint8_t MBEDTLS_PRIVATE(password)[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    size_t MBEDTLS_PRIVATE(password_length);
+    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
+    uint8_t MBEDTLS_PRIVATE(bytes_used);
+    uint32_t MBEDTLS_PRIVATE(block_number);
+} psa_pbkdf2_key_derivation_t;
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+
+#endif /* PSA_CRYPTO_BUILTIN_KEY_DERIVATION_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h
index c76bc781439a1be7902516deb30d25d9a9d3a549..98ab4d333983599417202672de88184cb2bd4f8f 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_builtin_primitives.h
@@ -7,27 +7,15 @@
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
  *
- * \note This header and its content is not part of the Mbed TLS API and
+ * \note This header and its content are not part of the Mbed TLS API and
  * applications must not depend on it. Its main purpose is to define the
  * multi-part state objects of the Mbed TLS software-based PSA drivers. The
- * definition of these objects are then used by crypto_struct.h to define the
+ * definitions of these objects are then used by crypto_struct.h to define the
  * implementation-defined types of PSA multi-part state objects.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_BUILTIN_PRIMITIVES_H
@@ -45,6 +33,7 @@
 #include "mbedtls/sha1.h"
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
+#include "mbedtls/sha3.h"
 
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160) || \
@@ -52,7 +41,11 @@
     defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
 #define MBEDTLS_PSA_BUILTIN_HASH
 #endif
 
@@ -76,6 +69,12 @@ typedef struct {
 #if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512) || \
         defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
         mbedtls_sha512_context sha512;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        mbedtls_sha3_context sha3;
 #endif
     } MBEDTLS_PRIVATE(ctx);
 } mbedtls_psa_hash_operation_t;
@@ -94,7 +93,8 @@ typedef struct {
     defined(MBEDTLS_PSA_BUILTIN_ALG_OFB) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING) || \
     defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
 #define MBEDTLS_PSA_BUILTIN_CIPHER  1
 #endif
 
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h b/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h
index 3544f96327c06087ad38823641cf11a32e836d9f..2a226c01a890b3a1039980e2c565720738ad9cc7 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_compat.h
@@ -5,26 +5,14 @@
  *
  * This header declares alternative names for macro and functions.
  * New application code should not use these names.
- * These names may be removed in a future version of Mbed Crypto.
+ * These names may be removed in a future version of Mbed TLS.
  *
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_COMPAT_H
@@ -158,6 +146,83 @@ psa_status_t psa_open_key(mbedtls_svc_key_id_t key,
  */
 psa_status_t psa_close_key(psa_key_handle_t handle);
 
+/** \addtogroup attributes
+ * @{
+ */
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+/** Custom Diffie-Hellman group.
+ *
+ * Mbed TLS does not support custom DH groups.
+ *
+ * \deprecated This value is not useful, so this macro will be removed in
+ *             a future version of the library.
+ */
+#define PSA_DH_FAMILY_CUSTOM                                            \
+    ((psa_dh_family_t) MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(0x7e))
+
+/**
+ * \brief Set domain parameters for a key.
+ *
+ * \deprecated  Mbed TLS no longer supports any domain parameters.
+ *              This function only does the equivalent of
+ *              psa_set_key_type() and will be removed in a future version
+ *              of the library.
+ *
+ * \param[in,out] attributes    Attribute structure where \p type will be set.
+ * \param type                  Key type (a \c PSA_KEY_TYPE_XXX value).
+ * \param[in] data              Ignored.
+ * \param data_length           Must be 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_set_key_domain_parameters(
+    psa_key_attributes_t *attributes,
+    psa_key_type_t type, const uint8_t *data, size_t data_length)
+{
+    (void) data;
+    if (data_length != 0) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    psa_set_key_type(attributes, type);
+    return PSA_SUCCESS;
+}
+
+/**
+ * \brief Get domain parameters for a key.
+ *
+ * \deprecated  Mbed TLS no longer supports any domain parameters.
+ *              This function alwaya has an empty output and will be
+ *              removed in a future version of the library.
+
+ * \param[in] attributes        Ignored.
+ * \param[out] data             Ignored.
+ * \param data_size             Ignored.
+ * \param[out] data_length      Set to 0.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ */
+static inline psa_status_t MBEDTLS_DEPRECATED psa_get_key_domain_parameters(
+    const psa_key_attributes_t *attributes,
+    uint8_t *data, size_t data_size, size_t *data_length)
+{
+    (void) attributes;
+    (void) data;
+    (void) data_size;
+    *data_length = 0;
+    return PSA_SUCCESS;
+}
+
+/** Safe output buffer size for psa_get_key_domain_parameters().
+ *
+ */
+#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)      \
+    MBEDTLS_DEPRECATED_NUMERIC_CONSTANT(1u)
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+/**@}*/
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_config.h b/lib/libmbedtls/mbedtls/include/psa/crypto_config.h
index e68fac8b4492cf96a5176efa959bc067222b519d..36e937ad35d2ef48a591af26ca3919c69d3591aa 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_config.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_config.h
@@ -32,19 +32,7 @@
 #endif
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_CONFIG_H
@@ -65,6 +53,7 @@
 #define PSA_WANT_ALG_DETERMINISTIC_ECDSA        1
 #define PSA_WANT_ALG_ECB_NO_PADDING             1
 #define PSA_WANT_ALG_ECDH                       1
+#define PSA_WANT_ALG_FFDH                       1
 #define PSA_WANT_ALG_ECDSA                      1
 #define PSA_WANT_ALG_JPAKE                      1
 #define PSA_WANT_ALG_GCM                        1
@@ -74,9 +63,8 @@
 #define PSA_WANT_ALG_HMAC                       1
 #define PSA_WANT_ALG_MD5                        1
 #define PSA_WANT_ALG_OFB                        1
-/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
- * Note: when adding support, also adjust include/mbedtls/config_psa.h */
-//#define PSA_WANT_ALG_PBKDF2_HMAC                1
+#define PSA_WANT_ALG_PBKDF2_HMAC                1
+#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128    1
 #define PSA_WANT_ALG_RIPEMD160                  1
 #define PSA_WANT_ALG_RSA_OAEP                   1
 #define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT         1
@@ -87,12 +75,16 @@
 #define PSA_WANT_ALG_SHA_256                    1
 #define PSA_WANT_ALG_SHA_384                    1
 #define PSA_WANT_ALG_SHA_512                    1
+#define PSA_WANT_ALG_SHA3_224                   1
+#define PSA_WANT_ALG_SHA3_256                   1
+#define PSA_WANT_ALG_SHA3_384                   1
+#define PSA_WANT_ALG_SHA3_512                   1
 #define PSA_WANT_ALG_STREAM_CIPHER              1
 #define PSA_WANT_ALG_TLS12_PRF                  1
 #define PSA_WANT_ALG_TLS12_PSK_TO_MS            1
 #define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS       1
 
-/* PBKDF2-HMAC is not yet supported via the PSA API in Mbed TLS.
+/* XTS is not yet supported via the PSA API in Mbed TLS.
  * Note: when adding support, also adjust include/mbedtls/config_psa.h */
 //#define PSA_WANT_ALG_XTS                        1
 
@@ -111,10 +103,18 @@
 #define PSA_WANT_ECC_SECP_K1_256                1
 #define PSA_WANT_ECC_SECP_R1_192                1
 #define PSA_WANT_ECC_SECP_R1_224                1
+/* For secp256r1, consider enabling #MBEDTLS_PSA_P256M_DRIVER_ENABLED
+ * (see the description in mbedtls/mbedtls_config.h for details). */
 #define PSA_WANT_ECC_SECP_R1_256                1
 #define PSA_WANT_ECC_SECP_R1_384                1
 #define PSA_WANT_ECC_SECP_R1_521                1
 
+#define PSA_WANT_DH_RFC7919_2048                1
+#define PSA_WANT_DH_RFC7919_3072                1
+#define PSA_WANT_DH_RFC7919_4096                1
+#define PSA_WANT_DH_RFC7919_6144                1
+#define PSA_WANT_DH_RFC7919_8192                1
+
 #define PSA_WANT_KEY_TYPE_DERIVE                1
 #define PSA_WANT_KEY_TYPE_PASSWORD              1
 #define PSA_WANT_KEY_TYPE_PASSWORD_HASH         1
@@ -124,10 +124,36 @@
 #define PSA_WANT_KEY_TYPE_CAMELLIA              1
 #define PSA_WANT_KEY_TYPE_CHACHA20              1
 #define PSA_WANT_KEY_TYPE_DES                   1
-#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR          1
+//#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR          1 /* Deprecated */
 #define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY        1
+#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY         1
 #define PSA_WANT_KEY_TYPE_RAW_DATA              1
-#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR          1
+//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR          1 /* Deprecated */
 #define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY        1
 
+/*
+ * The following symbols extend and deprecate the legacy
+ * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR ones. They include the usage of that key in
+ * the name's suffix. "_USE" is the most generic and it can be used to describe
+ * a generic suport, whereas other ones add more features on top of that and
+ * they are more specific.
+ */
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC      1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT   1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE   1
+
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC      1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT   1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT   1
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
+//#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE   1 /* Not supported */
+
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC       1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT    1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT    1
+#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE  1
+//#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE    1 /* Not supported */
+
 #endif /* PSA_CRYPTO_CONFIG_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h
index 26363c6b2f3ed48b3e3122b59da935bba7367c82..cc11d3b9a2d589fa5be80d794d52c2ce305bb35a 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_common.h
@@ -17,19 +17,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef PSA_CRYPTO_DRIVER_COMMON_H
 #define PSA_CRYPTO_DRIVER_COMMON_H
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h
index 6c56a51dbcb714d3e70ef4f6a9378416532b83f9..d717c519091abe81d0787312b79db473e8fd999f 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_composites.h
@@ -9,26 +9,14 @@
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
  *
- * \note This header and its content is not part of the Mbed TLS API and
+ * \note This header and its content are not part of the Mbed TLS API and
  * applications must not depend on it. Its main purpose is to define the
  * multi-part state objects of the PSA drivers included in the cryptographic
- * library. The definition of these objects are then used by crypto_struct.h
+ * library. The definitions of these objects are then used by crypto_struct.h
  * to define the implementation-defined types of PSA multi-part state objects.
  */
 /*  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_COMPOSITES_H
@@ -121,7 +109,7 @@ typedef mbedtls_psa_pake_operation_t
  *
  * The union members are the driver's context structures, and the member names
  * are formatted as `'drivername'_ctx`. This allows for procedural generation
- * of both this file and the content of psa_crypto_driver_wrappers.c */
+ * of both this file and the content of psa_crypto_driver_wrappers.h */
 
 typedef union {
     unsigned dummy; /* Make sure this union is always non-empty */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h
new file mode 100644
index 0000000000000000000000000000000000000000..21190515cee78cd1ed09e664e3693e65fb86c4ee
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h
@@ -0,0 +1,52 @@
+/*
+ *  Declaration of context structures for use with the PSA driver wrapper
+ *  interface. This file contains the context structures for key derivation
+ *  operations.
+ *
+ *  Warning: This file will be auto-generated in the future.
+ *
+ * \note This file may not be included directly. Applications must
+ * include psa/crypto.h.
+ *
+ * \note This header and its content are not part of the Mbed TLS API and
+ * applications must not depend on it. Its main purpose is to define the
+ * multi-part state objects of the PSA drivers included in the cryptographic
+ * library. The definitions of these objects are then used by crypto_struct.h
+ * to define the implementation-defined types of PSA multi-part state objects.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H
+#define PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H
+
+#include "psa/crypto_driver_common.h"
+
+/* Include the context structure definitions for the Mbed TLS software drivers */
+#include "psa/crypto_builtin_key_derivation.h"
+
+/* Include the context structure definitions for those drivers that were
+ * declared during the autogeneration process. */
+
+typedef union {
+    unsigned dummy; /* Make sure this union is always non-empty */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+    psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf);
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf);
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);
+#endif
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+    psa_pbkdf2_key_derivation_t MBEDTLS_PRIVATE(pbkdf2);
+#endif
+} psa_driver_key_derivation_context_t;
+
+#endif /* PSA_CRYPTO_DRIVER_CONTEXTS_KEY_DERIVATION_H */
+/* End of automatically generated file. */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h
index 620a4b3a77837d9ba7998f0ccb0874af60013bad..c90a5fbe742663c610712295795d4ad0d6039658 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_driver_contexts_primitives.h
@@ -8,26 +8,14 @@
  * \note This file may not be included directly. Applications must
  * include psa/crypto.h.
  *
- * \note This header and its content is not part of the Mbed TLS API and
+ * \note This header and its content are not part of the Mbed TLS API and
  * applications must not depend on it. Its main purpose is to define the
  * multi-part state objects of the PSA drivers included in the cryptographic
- * library. The definition of these objects are then used by crypto_struct.h
+ * library. The definitions of these objects are then used by crypto_struct.h
  * to define the implementation-defined types of PSA multi-part state objects.
  */
 /*  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_DRIVER_CONTEXTS_PRIMITIVES_H
@@ -94,7 +82,7 @@ typedef struct {
  *
  * The union members are the driver's context structures, and the member names
  * are formatted as `'drivername'_ctx`. This allows for procedural generation
- * of both this file and the content of psa_crypto_driver_wrappers.c */
+ * of both this file and the content of psa_crypto_driver_wrappers.h */
 
 typedef union {
     unsigned dummy; /* Make sure this union is always non-empty */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h b/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h
index 4920508d7b6f505704083e7eda80496b6b7db8bd..0cf42c605514ec5bc2ed5ad5cd1e7c779bc77425 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_extra.h
@@ -10,27 +10,13 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_EXTRA_H
 #define PSA_CRYPTO_EXTRA_H
 #include "mbedtls/private_access.h"
 
-#include "mbedtls/platform_util.h"
-
 #include "crypto_types.h"
 #include "crypto_compat.h"
 
@@ -73,7 +59,7 @@ static inline void psa_set_key_enrollment_algorithm(
     psa_key_attributes_t *attributes,
     psa_algorithm_t alg2)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2;
+    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2) = alg2;
 }
 
 /** Retrieve the enrollment algorithm policy from key attributes.
@@ -85,7 +71,7 @@ static inline void psa_set_key_enrollment_algorithm(
 static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2);
+    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg2);
 }
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
@@ -108,7 +94,7 @@ static inline psa_algorithm_t psa_get_key_enrollment_algorithm(
  *         indicates the slot number that contains it.
  * \retval #PSA_ERROR_NOT_PERMITTED
  *         The caller is not permitted to query the slot number.
- *         Mbed Crypto currently does not return this error.
+ *         Mbed TLS currently does not return this error.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
  *         The key is not located in a secure element.
  */
@@ -143,7 +129,7 @@ static inline void psa_set_key_slot_number(
     psa_key_attributes_t *attributes,
     psa_key_slot_number_t slot_number)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) |= MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
+    attributes->MBEDTLS_PRIVATE(has_slot_number) = 1;
     attributes->MBEDTLS_PRIVATE(slot_number) = slot_number;
 }
 
@@ -156,8 +142,7 @@ static inline void psa_set_key_slot_number(
 static inline void psa_clear_key_slot_number(
     psa_key_attributes_t *attributes)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(flags) &=
-        ~MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER;
+    attributes->MBEDTLS_PRIVATE(has_slot_number) = 0;
 }
 
 /** Register a key that is already present in a secure element.
@@ -169,6 +154,14 @@ static inline void psa_clear_key_slot_number(
  * specified in \p attributes.
  *
  * \param[in] attributes        The attributes of the existing key.
+ *                              - The lifetime must be a persistent lifetime
+ *                                in a secure element. Volatile lifetimes are
+ *                                not currently supported.
+ *                              - The key identifier must be in the valid
+ *                                range for persistent keys.
+ *                              - The key type and size must be specified and
+ *                                must be consistent with the key material
+ *                                in the secure element.
  *
  * \retval #PSA_SUCCESS
  *         The key was successfully registered.
@@ -212,6 +205,8 @@ psa_status_t mbedtls_psa_register_se_key(
  *
  * This function clears all data associated with the PSA layer,
  * including the whole key store.
+ * This function is not thread safe, it wipes every key slot regardless of
+ * state and reader count. It should only be called when no slot is in use.
  *
  * This is an Mbed TLS extension.
  */
@@ -221,7 +216,7 @@ void mbedtls_psa_crypto_free(void);
  * resource consumption related to the PSA keystore.
  *
  * \note The content of this structure is not part of the stable API and ABI
- *       of Mbed Crypto and may change arbitrarily from version to version.
+ *       of Mbed TLS and may change arbitrarily from version to version.
  */
 typedef struct mbedtls_psa_stats_s {
     /** Number of slots containing key material for a volatile key. */
@@ -250,7 +245,7 @@ typedef struct mbedtls_psa_stats_s {
 /** \brief Get statistics about
  * resource consumption related to the PSA keystore.
  *
- * \note When Mbed Crypto is built as part of a service, with isolation
+ * \note When Mbed TLS is built as part of a service, with isolation
  *       between the application and the keystore, the service may or
  *       may not expose this function.
  */
@@ -421,250 +416,13 @@ psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
  * @{
  */
 
-/** Custom Diffie-Hellman group.
- *
- * For keys of type #PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or
- * #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM), the group data comes
- * from domain parameters set by psa_set_key_domain_parameters().
- */
-#define PSA_DH_FAMILY_CUSTOM             ((psa_dh_family_t) 0x7e)
-
 /** PAKE operation stages. */
 #define PSA_PAKE_OPERATION_STAGE_SETUP 0
 #define PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS 1
 #define PSA_PAKE_OPERATION_STAGE_COMPUTATION 2
 
-/**
- * \brief Set domain parameters for a key.
- *
- * Some key types require additional domain parameters in addition to
- * the key type identifier and the key size. Use this function instead
- * of psa_set_key_type() when you need to specify domain parameters.
- *
- * The format for the required domain parameters varies based on the key type.
- *
- * - For RSA keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY or #PSA_KEY_TYPE_RSA_KEY_PAIR),
- *   the domain parameter data consists of the public exponent,
- *   represented as a big-endian integer with no leading zeros.
- *   This information is used when generating an RSA key pair.
- *   When importing a key, the public exponent is read from the imported
- *   key data and the exponent recorded in the attribute structure is ignored.
- *   As an exception, the public exponent 65537 is represented by an empty
- *   byte string.
- * - For DSA keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY or #PSA_KEY_TYPE_DSA_KEY_PAIR),
- *   the `Dss-Params` format as defined by RFC 3279 &sect;2.3.2.
- *   ```
- *   Dss-Params ::= SEQUENCE  {
- *      p       INTEGER,
- *      q       INTEGER,
- *      g       INTEGER
- *   }
- *   ```
- * - For Diffie-Hellman key exchange keys
- *   (#PSA_KEY_TYPE_DH_PUBLIC_KEY(#PSA_DH_FAMILY_CUSTOM) or
- *   #PSA_KEY_TYPE_DH_KEY_PAIR(#PSA_DH_FAMILY_CUSTOM)), the
- *   `DomainParameters` format as defined by RFC 3279 &sect;2.3.3.
- *   ```
- *   DomainParameters ::= SEQUENCE {
- *      p               INTEGER,                    -- odd prime, p=jq +1
- *      g               INTEGER,                    -- generator, g
- *      q               INTEGER,                    -- factor of p-1
- *      j               INTEGER OPTIONAL,           -- subgroup factor
- *      validationParams ValidationParams OPTIONAL
- *   }
- *   ValidationParams ::= SEQUENCE {
- *      seed            BIT STRING,
- *      pgenCounter     INTEGER
- *   }
- *   ```
- *
- * \note This function may allocate memory or other resources.
- *       Once you have called this function on an attribute structure,
- *       you must call psa_reset_key_attributes() to free these resources.
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \param[in,out] attributes    Attribute structure where the specified domain
- *                              parameters will be stored.
- *                              If this function fails, the content of
- *                              \p attributes is not modified.
- * \param type                  Key type (a \c PSA_KEY_TYPE_XXX value).
- * \param[in] data              Buffer containing the key domain parameters.
- *                              The content of this buffer is interpreted
- *                              according to \p type as described above.
- * \param data_length           Size of the \p data buffer in bytes.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
- * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
- * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
- */
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length);
-
-/**
- * \brief Get domain parameters for a key.
- *
- * Get the domain parameters for a key with this function, if any. The format
- * of the domain parameters written to \p data is specified in the
- * documentation for psa_set_key_domain_parameters().
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \param[in] attributes        The key attribute structure to query.
- * \param[out] data             On success, the key domain parameters.
- * \param data_size             Size of the \p data buffer in bytes.
- *                              The buffer is guaranteed to be large
- *                              enough if its size in bytes is at least
- *                              the value given by
- *                              PSA_KEY_DOMAIN_PARAMETERS_SIZE().
- * \param[out] data_length      On success, the number of bytes
- *                              that make up the key domain parameters data.
- *
- * \retval #PSA_SUCCESS \emptydescription
- * \retval #PSA_ERROR_BUFFER_TOO_SMALL \emptydescription
- */
-psa_status_t psa_get_key_domain_parameters(
-    const psa_key_attributes_t *attributes,
-    uint8_t *data,
-    size_t data_size,
-    size_t *data_length);
-
-/** Safe output buffer size for psa_get_key_domain_parameters().
- *
- * This macro returns a compile-time constant if its arguments are
- * compile-time constants.
- *
- * \warning This function may call its arguments multiple times or
- *          zero times, so you should not pass arguments that contain
- *          side effects.
- *
- * \note This is an experimental extension to the interface. It may change
- *       in future versions of the library.
- *
- * \param key_type  A supported key type.
- * \param key_bits  The size of the key in bits.
- *
- * \return If the parameters are valid and supported, return
- *         a buffer size in bytes that guarantees that
- *         psa_get_key_domain_parameters() will not fail with
- *         #PSA_ERROR_BUFFER_TOO_SMALL.
- *         If the parameters are a valid combination that is not supported
- *         by the implementation, this macro shall return either a
- *         sensible size or 0.
- *         If the parameters are not valid, the
- *         return value is unspecified.
- */
-#define PSA_KEY_DOMAIN_PARAMETERS_SIZE(key_type, key_bits)              \
-    (PSA_KEY_TYPE_IS_RSA(key_type) ? sizeof(int) :                      \
-     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
-     PSA_KEY_TYPE_IS_DSA(key_type) ? PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits) : \
-     0)
-#define PSA_DH_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)     \
-    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 3 /*without optional parts*/)
-#define PSA_DSA_KEY_DOMAIN_PARAMETERS_SIZE(key_bits)    \
-    (4 + (PSA_BITS_TO_BYTES(key_bits) + 5) * 2 /*p, g*/ + 34 /*q*/)
-
 /**@}*/
 
-/** \defgroup psa_tls_helpers TLS helper functions
- * @{
- */
-
-#if defined(MBEDTLS_ECP_C)
-#include <mbedtls/ecp.h>
-
-/** Convert an ECC curve identifier from the Mbed TLS encoding to PSA.
- *
- * \note This function is provided solely for the convenience of
- *       Mbed TLS and may be removed at any time without notice.
- *
- * \param grpid         An Mbed TLS elliptic curve identifier
- *                      (`MBEDTLS_ECP_DP_xxx`).
- * \param[out] bits     On success, the bit size of the curve.
- *
- * \return              The corresponding PSA elliptic curve identifier
- *                      (`PSA_ECC_FAMILY_xxx`).
- * \return              \c 0 on failure (\p grpid is not recognized).
- */
-static inline psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
-                                                        size_t *bits)
-{
-    switch (grpid) {
-        case MBEDTLS_ECP_DP_SECP192R1:
-            *bits = 192;
-            return PSA_ECC_FAMILY_SECP_R1;
-        case MBEDTLS_ECP_DP_SECP224R1:
-            *bits = 224;
-            return PSA_ECC_FAMILY_SECP_R1;
-        case MBEDTLS_ECP_DP_SECP256R1:
-            *bits = 256;
-            return PSA_ECC_FAMILY_SECP_R1;
-        case MBEDTLS_ECP_DP_SECP384R1:
-            *bits = 384;
-            return PSA_ECC_FAMILY_SECP_R1;
-        case MBEDTLS_ECP_DP_SECP521R1:
-            *bits = 521;
-            return PSA_ECC_FAMILY_SECP_R1;
-        case MBEDTLS_ECP_DP_BP256R1:
-            *bits = 256;
-            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
-        case MBEDTLS_ECP_DP_BP384R1:
-            *bits = 384;
-            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
-        case MBEDTLS_ECP_DP_BP512R1:
-            *bits = 512;
-            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
-        case MBEDTLS_ECP_DP_CURVE25519:
-            *bits = 255;
-            return PSA_ECC_FAMILY_MONTGOMERY;
-        case MBEDTLS_ECP_DP_SECP192K1:
-            *bits = 192;
-            return PSA_ECC_FAMILY_SECP_K1;
-        case MBEDTLS_ECP_DP_SECP224K1:
-            *bits = 224;
-            return PSA_ECC_FAMILY_SECP_K1;
-        case MBEDTLS_ECP_DP_SECP256K1:
-            *bits = 256;
-            return PSA_ECC_FAMILY_SECP_K1;
-        case MBEDTLS_ECP_DP_CURVE448:
-            *bits = 448;
-            return PSA_ECC_FAMILY_MONTGOMERY;
-        default:
-            *bits = 0;
-            return 0;
-    }
-}
-
-/** Convert an ECC curve identifier from the PSA encoding to Mbed TLS.
- *
- * \note This function is provided solely for the convenience of
- *       Mbed TLS and may be removed at any time without notice.
- *
- * \param curve         A PSA elliptic curve identifier
- *                      (`PSA_ECC_FAMILY_xxx`).
- * \param bits          The bit-length of a private key on \p curve.
- * \param bits_is_sloppy If true, \p bits may be the bit-length rounded up
- *                      to the nearest multiple of 8. This allows the caller
- *                      to infer the exact curve from the length of a key
- *                      which is supplied as a byte string.
- *
- * \return              The corresponding Mbed TLS elliptic curve identifier
- *                      (`MBEDTLS_ECP_DP_xxx`).
- * \return              #MBEDTLS_ECP_DP_NONE if \c curve is not recognized.
- * \return              #MBEDTLS_ECP_DP_NONE if \p bits is not
- *                      correct for \p curve.
- */
-mbedtls_ecp_group_id mbedtls_ecc_group_of_psa(psa_ecc_family_t curve,
-                                              size_t bits,
-                                              int bits_is_sloppy);
-#endif /* MBEDTLS_ECP_C */
-
-/**@}*/
 
 /** \defgroup psa_external_rng External random generator
  * @{
@@ -729,7 +487,7 @@ psa_status_t mbedtls_psa_external_get_random(
  * #PSA_KEY_ID_VENDOR_MIN and #PSA_KEY_ID_VENDOR_MAX and must not intersect
  * with any other set of implementation-chosen key identifiers.
  *
- * This value is part of the library's ABI since changing it would invalidate
+ * This value is part of the library's API since changing it would invalidate
  * the values of built-in key identifiers in applications.
  */
 #define MBEDTLS_PSA_KEY_ID_BUILTIN_MIN          ((psa_key_id_t) 0x7fff0000)
@@ -958,7 +716,7 @@ psa_status_t mbedtls_psa_platform_get_builtin_key(
  * the official PSA Crypto API yet.
  *
  * \note The content of this section is not part of the stable API and ABI
- *       of Mbed Crypto and may change arbitrarily from version to version.
+ *       of Mbed TLS and may change arbitrarily from version to version.
  *       Same holds for the corresponding macros #PSA_ALG_CATEGORY_PAKE and
  *       #PSA_ALG_JPAKE.
  * @{
@@ -1085,12 +843,12 @@ typedef uint32_t psa_pake_primitive_t;
  *                      (value of type ::psa_pake_primitive_type_t).
  * \param pake_family   The family of the primitive
  *                      (the type and interpretation of this parameter depends
- *                      on \p type, for more information consult the
+ *                      on \p pake_type, for more information consult the
  *                      documentation of individual ::psa_pake_primitive_type_t
  *                      constants).
  * \param pake_bits     The bit-size of the primitive
  *                      (Value of type \c size_t. The interpretation
- *                      of this parameter depends on \p family, for more
+ *                      of this parameter depends on \p pake_family, for more
  *                      information consult the documentation of individual
  *                      ::psa_pake_primitive_type_t constants).
  *
@@ -1330,20 +1088,6 @@ psa_status_t psa_crypto_driver_pake_get_password(
     const psa_crypto_driver_pake_inputs_t *inputs,
     uint8_t *buffer, size_t buffer_size, size_t *buffer_length);
 
-/** Get the role from given inputs.
- *
- * \param[in]  inputs           Operation inputs.
- * \param[out] role             Return buffer for role.
- *
- * \retval #PSA_SUCCESS
- *         Success.
- * \retval #PSA_ERROR_BAD_STATE
- *         Role hasn't been set yet.
- */
-psa_status_t psa_crypto_driver_pake_get_role(
-    const psa_crypto_driver_pake_inputs_t *inputs,
-    psa_pake_role_t *role);
-
 /** Get the length of the user id in bytes from given inputs.
  *
  * \param[in]  inputs           Operation inputs.
@@ -1562,7 +1306,6 @@ psa_status_t psa_pake_set_password_key(psa_pake_operation_t *operation,
  *                              been set (psa_pake_set_user() hasn't been
  *                              called yet).
  * \param[in] user_id           The user ID to authenticate with.
- *                              (temporary limitation: "client" or "server" only)
  * \param user_id_len           Size of the \p user_id buffer in bytes.
  *
  * \retval #PSA_SUCCESS
@@ -1604,13 +1347,12 @@ psa_status_t psa_pake_set_user(psa_pake_operation_t *operation,
  *                              been set (psa_pake_set_peer() hasn't been
  *                              called yet).
  * \param[in] peer_id           The peer's ID to authenticate.
- *                              (temporary limitation: "client" or "server" only)
  * \param peer_id_len           Size of the \p peer_id buffer in bytes.
  *
  * \retval #PSA_SUCCESS
  *         Success.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p user_id is not valid for the \p operation's algorithm and cipher
+ *         \p peer_id is not valid for the \p operation's algorithm and cipher
  *         suite.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         The algorithm doesn't associate a second identity with the session.
@@ -1692,8 +1434,8 @@ psa_status_t psa_pake_set_role(psa_pake_operation_t *operation,
  *                             \c PSA_PAKE_STEP_XXX constants for more
  *                             information.
  * \param output_size          Size of the \p output buffer in bytes. This must
- *                             be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p
- *                             primitive, \p step) where \p alg and
+ *                             be at least #PSA_PAKE_OUTPUT_SIZE(\c alg, \c
+ *                             primitive, \p output_step) where \c alg and
  *                             \p primitive are the PAKE algorithm and primitive
  *                             in the operation's cipher suite, and \p step is
  *                             the output step.
@@ -1758,9 +1500,9 @@ psa_status_t psa_pake_output(psa_pake_operation_t *operation,
  * \retval #PSA_ERROR_INVALID_SIGNATURE
  *         The verification fails for a #PSA_PAKE_STEP_ZK_PROOF input step.
  * \retval #PSA_ERROR_INVALID_ARGUMENT
- *         \p is not compatible with the \p operation’s algorithm, or the
- *         \p input is not valid for the \p operation's algorithm, cipher suite
- *         or \p step.
+ *         \p input_length is not compatible with the \p operation’s algorithm,
+ *         or the \p input is not valid for the \p operation's algorithm,
+ *         cipher suite or \p step.
  * \retval #PSA_ERROR_NOT_SUPPORTED
  *         \p step p is not supported with the \p operation's algorithm, or the
  *         \p input is not supported for the \p operation's algorithm, cipher
@@ -1809,7 +1551,7 @@ psa_status_t psa_pake_input(psa_pake_operation_t *operation,
  *
  * When this function returns successfully, \p operation becomes inactive.
  * If this function returns an error status, both \p operation
- * and \p key_derivation operations enter an error state and must be aborted by
+ * and \c key_derivation operations enter an error state and must be aborted by
  * calling psa_pake_abort() and psa_key_derivation_abort() respectively.
  *
  * \param[in,out] operation    Active PAKE operation.
@@ -1939,7 +1681,10 @@ psa_status_t psa_pake_abort(psa_pake_operation_t *operation);
  *
  * This macro must expand to a compile-time constant integer.
  *
- * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p step).
+ * The value of this macro must be at least as large as the largest value
+ * returned by PSA_PAKE_OUTPUT_SIZE()
+ *
+ * See also #PSA_PAKE_OUTPUT_SIZE(\p alg, \p primitive, \p output_step).
  */
 #define PSA_PAKE_OUTPUT_MAX_SIZE 65
 
@@ -1948,7 +1693,10 @@ psa_status_t psa_pake_abort(psa_pake_operation_t *operation);
  *
  * This macro must expand to a compile-time constant integer.
  *
- * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p step).
+ * The value of this macro must be at least as large as the largest value
+ * returned by PSA_PAKE_INPUT_SIZE()
+ *
+ * See also #PSA_PAKE_INPUT_SIZE(\p alg, \p primitive, \p output_step).
  */
 #define PSA_PAKE_INPUT_MAX_SIZE 65
 
@@ -1960,8 +1708,12 @@ psa_status_t psa_pake_abort(psa_pake_operation_t *operation);
 /** Returns a suitable initializer for a PAKE operation object of type
  * psa_pake_operation_t.
  */
-#define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, PSA_PAKE_OPERATION_STAGE_SETUP, \
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_PAKE_OPERATION_INIT { 0 }
+#else
+#define PSA_PAKE_OPERATION_INIT { 0, PSA_ALG_NONE, 0, PSA_PAKE_OPERATION_STAGE_SETUP, \
                                   { 0 }, { { 0 } } }
+#endif
 
 struct psa_pake_cipher_suite_s {
     psa_algorithm_t algorithm;
@@ -2035,7 +1787,6 @@ static inline void psa_pake_cs_set_hash(psa_pake_cipher_suite_t *cipher_suite,
 struct psa_crypto_driver_pake_inputs_s {
     uint8_t *MBEDTLS_PRIVATE(password);
     size_t MBEDTLS_PRIVATE(password_len);
-    psa_pake_role_t MBEDTLS_PRIVATE(role);
     uint8_t *MBEDTLS_PRIVATE(user);
     size_t MBEDTLS_PRIVATE(user_len);
     uint8_t *MBEDTLS_PRIVATE(peer);
@@ -2044,34 +1795,6 @@ struct psa_crypto_driver_pake_inputs_s {
     psa_pake_cipher_suite_t MBEDTLS_PRIVATE(cipher_suite);
 };
 
-typedef enum psa_jpake_step {
-    PSA_PAKE_STEP_INVALID       = 0,
-    PSA_PAKE_STEP_X1_X2         = 1,
-    PSA_PAKE_STEP_X2S           = 2,
-    PSA_PAKE_STEP_DERIVE        = 3,
-} psa_jpake_step_t;
-
-typedef enum psa_jpake_state {
-    PSA_PAKE_STATE_INVALID      = 0,
-    PSA_PAKE_STATE_SETUP        = 1,
-    PSA_PAKE_STATE_READY        = 2,
-    PSA_PAKE_OUTPUT_X1_X2       = 3,
-    PSA_PAKE_OUTPUT_X2S         = 4,
-    PSA_PAKE_INPUT_X1_X2        = 5,
-    PSA_PAKE_INPUT_X4S          = 6,
-} psa_jpake_state_t;
-
-typedef enum psa_jpake_sequence {
-    PSA_PAKE_SEQ_INVALID        = 0,
-    PSA_PAKE_X1_STEP_KEY_SHARE  = 1,    /* also X2S & X4S KEY_SHARE */
-    PSA_PAKE_X1_STEP_ZK_PUBLIC  = 2,    /* also X2S & X4S ZK_PUBLIC */
-    PSA_PAKE_X1_STEP_ZK_PROOF   = 3,    /* also X2S & X4S ZK_PROOF */
-    PSA_PAKE_X2_STEP_KEY_SHARE  = 4,
-    PSA_PAKE_X2_STEP_ZK_PUBLIC  = 5,
-    PSA_PAKE_X2_STEP_ZK_PROOF   = 6,
-    PSA_PAKE_SEQ_END            = 7,
-} psa_jpake_sequence_t;
-
 typedef enum psa_crypto_driver_pake_step {
     PSA_JPAKE_STEP_INVALID        = 0,  /* Invalid step */
     PSA_JPAKE_X1_STEP_KEY_SHARE   = 1,  /* Round 1: input/output key share (for ephemeral private key X1).*/
@@ -2088,15 +1811,39 @@ typedef enum psa_crypto_driver_pake_step {
     PSA_JPAKE_X4S_STEP_ZK_PROOF   = 12  /* Round 2: input Schnorr NIZKP proof for the X4S key (from peer) */
 } psa_crypto_driver_pake_step_t;
 
+typedef enum psa_jpake_round {
+    PSA_JPAKE_FIRST = 0,
+    PSA_JPAKE_SECOND = 1,
+    PSA_JPAKE_FINISHED = 2
+} psa_jpake_round_t;
+
+typedef enum psa_jpake_io_mode {
+    PSA_JPAKE_INPUT = 0,
+    PSA_JPAKE_OUTPUT = 1
+} psa_jpake_io_mode_t;
 
 struct psa_jpake_computation_stage_s {
-    psa_jpake_state_t MBEDTLS_PRIVATE(state);
-    psa_jpake_sequence_t MBEDTLS_PRIVATE(sequence);
-    psa_jpake_step_t MBEDTLS_PRIVATE(input_step);
-    psa_jpake_step_t MBEDTLS_PRIVATE(output_step);
+    /* The J-PAKE round we are currently on */
+    psa_jpake_round_t MBEDTLS_PRIVATE(round);
+    /* The 'mode' we are currently in (inputting or outputting) */
+    psa_jpake_io_mode_t MBEDTLS_PRIVATE(io_mode);
+    /* The number of completed inputs so far this round */
+    uint8_t MBEDTLS_PRIVATE(inputs);
+    /* The number of completed outputs so far this round */
+    uint8_t MBEDTLS_PRIVATE(outputs);
+    /* The next expected step (KEY_SHARE, ZK_PUBLIC or ZK_PROOF) */
+    psa_pake_step_t MBEDTLS_PRIVATE(step);
 };
 
+#define PSA_JPAKE_EXPECTED_INPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \
+                                          ((round) == PSA_JPAKE_FIRST ? 2 : 1))
+#define PSA_JPAKE_EXPECTED_OUTPUTS(round) ((round) == PSA_JPAKE_FINISHED ? 0 : \
+                                           ((round) == PSA_JPAKE_FIRST ? 2 : 1))
+
 struct psa_pake_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -2106,6 +1853,8 @@ struct psa_pake_operation_s {
     unsigned int MBEDTLS_PRIVATE(id);
     /* Algorithm of the PAKE operation */
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
+    /* A primitive of type compatible with algorithm */
+    psa_pake_primitive_t MBEDTLS_PRIVATE(primitive);
     /* Stage of the PAKE operation: waiting for the setup, collecting inputs
      * or computing. */
     uint8_t MBEDTLS_PRIVATE(stage);
@@ -2120,6 +1869,7 @@ struct psa_pake_operation_s {
         psa_driver_pake_context_t MBEDTLS_PRIVATE(ctx);
         psa_crypto_driver_pake_inputs_t MBEDTLS_PRIVATE(inputs);
     } MBEDTLS_PRIVATE(data);
+#endif
 };
 
 static inline struct psa_pake_cipher_suite_s psa_pake_cipher_suite_init(void)
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_legacy.h b/lib/libmbedtls/mbedtls/include/psa/crypto_legacy.h
new file mode 100644
index 0000000000000000000000000000000000000000..7df3614d6a7d5253fb8653ed79c8dd5596136a64
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_legacy.h
@@ -0,0 +1,88 @@
+/**
+ * \file psa/crypto_legacy.h
+ *
+ * \brief Add temporary suppport for deprecated symbols before they are
+ *        removed from the library.
+ *
+ * PSA_WANT_KEY_TYPE_xxx_KEY_PAIR and MBEDTLS_PSA_ACCEL_KEY_TYPE_xxx_KEY_PAIR
+ * symbols are deprecated.
+ * New symols add a suffix to that base name in order to clearly state what is
+ * the expected use for the key (use, import, export, generate, derive).
+ * Here we define some backward compatibility support for uses stil using
+ * the legacy symbols.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_PSA_CRYPTO_LEGACY_H
+#define MBEDTLS_PSA_CRYPTO_LEGACY_H
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) //no-check-names
+#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC      1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT   1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT   1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE   1
+#endif
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) //no-check-names
+#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC      1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT   1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT   1
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1
+#endif
+#endif
+
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR) //no-check-names
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_BASIC
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_IMPORT
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_EXPORT
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_GENERATE
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR_DERIVE
+#endif
+#endif
+
+#if defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR) //no-check-names
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_BASIC
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_IMPORT
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_EXPORT
+#endif
+#if !defined(MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_RSA_KEY_PAIR_GENERATE
+#endif
+#endif
+
+#endif /* MBEDTLS_PSA_CRYPTO_LEGACY_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h b/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h
index e8d241bc7a1a4f821b7eaedb77765ae414f03343..a871ee12468c97fa0aaf67ef761c682b286a50fb 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_platform.h
@@ -15,32 +15,21 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_PLATFORM_H
 #define PSA_CRYPTO_PLATFORM_H
 #include "mbedtls/private_access.h"
 
-/* Include the Mbed TLS configuration file, the way Mbed TLS does it
- * in each of its header files. */
-#include "mbedtls/build_info.h"
-
-/* Translate between classic MBEDTLS_xxx feature symbols and PSA_xxx
- * feature symbols. */
-#include "mbedtls/config_psa.h"
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
 
 /* PSA requires several types which C99 provides in stdint.h. */
 #include <stdint.h>
@@ -100,4 +89,14 @@ typedef struct {
 } mbedtls_psa_external_random_context_t;
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+/** The type of the client handle used in context structures
+ *
+ * When a client view of the multipart context structures is required,
+ * this handle is used to keep a mapping with the service side of the
+ * context which contains the actual data.
+ */
+typedef uint32_t mbedtls_psa_client_handle_t;
+#endif
+
 #endif /* PSA_CRYPTO_PLATFORM_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h b/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h
index 9ae631ffec4bb0d82a11d425fecd884193251701..9ce14bba621c80470c2e61e3046f0919722853a4 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_se_driver.h
@@ -17,19 +17,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef PSA_CRYPTO_SE_DRIVER_H
 #define PSA_CRYPTO_SE_DRIVER_H
@@ -138,7 +126,7 @@ typedef psa_status_t (*psa_drv_se_init_t)(psa_drv_se_context_t *drv_context,
                                           psa_key_location_t location);
 
 #if defined(__DOXYGEN_ONLY__) || !defined(MBEDTLS_PSA_CRYPTO_SE_C)
-/* Mbed Crypto with secure element support enabled defines this type in
+/* Mbed TLS with secure element support enabled defines this type in
  * crypto_types.h because it is also visible to applications through an
  * implementation-specific extension.
  * For the PSA Cryptography specification, this type is only visible
@@ -837,7 +825,7 @@ typedef enum {
      * and #PSA_ERROR_DOES_NOT_EXIST if the driver can determine that there
      * is no key with the specified slot number.
      *
-     * This is an Mbed Crypto extension.
+     * This is an Mbed TLS extension.
      */
     PSA_KEY_CREATION_REGISTER,
 #endif
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h b/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h
index 3d6bb2c1e8141ed3681a384e0f15e23317953fde..635ee98f80283d640ca3f71602a9a2a4fb4d6cc9 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_sizes.h
@@ -22,30 +22,25 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_SIZES_H
 #define PSA_CRYPTO_SIZES_H
 
-/* Include the Mbed TLS configuration file, the way Mbed TLS does it
- * in each of its header files. */
-#include "mbedtls/build_info.h"
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
 
-#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8)
-#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8)
+#define PSA_BITS_TO_BYTES(bits) (((bits) + 7u) / 8u)
+#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8u)
+#define PSA_MAX_OF_THREE(a, b, c) ((a) <= (b) ? (b) <= (c) ? \
+                                   (c) : (b) : (a) <= (c) ? (c) : (a))
 
 #define PSA_ROUND_UP_TO_MULTIPLE(block_size, length) \
     (((length) + (block_size) - 1) / (block_size) * (block_size))
@@ -64,20 +59,20 @@
  */
 #define PSA_HASH_LENGTH(alg)                                        \
     (                                                               \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 :            \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 :      \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 :          \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 :    \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 :    \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 :       \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 :       \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 :       \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 :       \
-        0)
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16u :           \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20u :     \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20u :         \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28u :   \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32u :   \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28u :      \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32u :      \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48u :      \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64u :      \
+        0u)
 
 /** The input block size of a hash algorithm, in bytes.
  *
@@ -96,20 +91,20 @@
  */
 #define PSA_HASH_BLOCK_LENGTH(alg)                                  \
     (                                                               \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64 :            \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64 :      \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64 :          \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64 :        \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128 :       \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128 :       \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128 :   \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128 :   \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144 :      \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136 :      \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104 :      \
-        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72 :       \
-        0)
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 64u :           \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 64u :     \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 64u :         \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 64u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 64u :       \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 128u :      \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 128u :      \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 128u :  \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 128u :  \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 144u :     \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 136u :     \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 104u :     \
+        PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 72u :      \
+        0u)
 
 /** \def PSA_HASH_MAX_SIZE
  *
@@ -118,15 +113,41 @@
  * This macro expands to a compile-time constant integer. This value
  * is the maximum size of a hash in bytes.
  */
-/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-226,
+/* Note: for HMAC-SHA-3, the block size is 144 bytes for HMAC-SHA3-224,
  * 136 bytes for HMAC-SHA3-256, 104 bytes for SHA3-384, 72 bytes for
  * HMAC-SHA3-512. */
-#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA_384)
-#define PSA_HASH_MAX_SIZE 64
-#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128
-#else
-#define PSA_HASH_MAX_SIZE 32
-#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64
+/* Note: PSA_HASH_MAX_SIZE should be kept in sync with MBEDTLS_MD_MAX_SIZE,
+ * see the note on MBEDTLS_MD_MAX_SIZE for details. */
+#if defined(PSA_WANT_ALG_SHA3_224)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 144u
+#elif defined(PSA_WANT_ALG_SHA3_256)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 136u
+#elif defined(PSA_WANT_ALG_SHA_512)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u
+#elif defined(PSA_WANT_ALG_SHA_384)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 128u
+#elif defined(PSA_WANT_ALG_SHA3_384)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 104u
+#elif defined(PSA_WANT_ALG_SHA3_512)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 72u
+#elif defined(PSA_WANT_ALG_SHA_256)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u
+#elif defined(PSA_WANT_ALG_SHA_224)
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u
+#else /* SHA-1 or smaller */
+#define PSA_HMAC_MAX_HASH_BLOCK_SIZE 64u
+#endif
+
+#if defined(PSA_WANT_ALG_SHA_512) || defined(PSA_WANT_ALG_SHA3_512)
+#define PSA_HASH_MAX_SIZE 64u
+#elif defined(PSA_WANT_ALG_SHA_384) || defined(PSA_WANT_ALG_SHA3_384)
+#define PSA_HASH_MAX_SIZE 48u
+#elif defined(PSA_WANT_ALG_SHA_256) || defined(PSA_WANT_ALG_SHA3_256)
+#define PSA_HASH_MAX_SIZE 32u
+#elif defined(PSA_WANT_ALG_SHA_224) || defined(PSA_WANT_ALG_SHA3_224)
+#define PSA_HASH_MAX_SIZE 28u
+#else /* SHA-1 or smaller */
+#define PSA_HASH_MAX_SIZE 20u
 #endif
 
 /** \def PSA_MAC_MAX_SIZE
@@ -167,13 +188,13 @@
 #define PSA_AEAD_TAG_LENGTH(key_type, key_bits, alg)                        \
     (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                            \
      PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :                                     \
-     ((void) (key_bits), 0))
+     ((void) (key_bits), 0u))
 
 /** The maximum tag size for all supported AEAD algorithms, in bytes.
  *
  * See also #PSA_AEAD_TAG_LENGTH(\p key_type, \p key_bits, \p alg).
  */
-#define PSA_AEAD_TAG_MAX_SIZE       16
+#define PSA_AEAD_TAG_MAX_SIZE       16u
 
 /* The maximum size of an RSA key on this implementation, in bits.
  * This is a vendor-specific macro.
@@ -188,38 +209,66 @@
  *
  * Note that an implementation may set different size limits for different
  * operations, and does not need to accept all key sizes up to the limit. */
-#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096
+#define PSA_VENDOR_RSA_MAX_KEY_BITS 4096u
+
+/* The minimum size of an RSA key on this implementation, in bits.
+ * This is a vendor-specific macro.
+ *
+ * Limits RSA key generation to a minimum due to avoid accidental misuse.
+ * This value cannot be less than 128 bits.
+ */
+#if defined(MBEDTLS_RSA_GEN_KEY_MIN_BITS)
+#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS MBEDTLS_RSA_GEN_KEY_MIN_BITS
+#else
+#define PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS 1024
+#endif
+
+/* The maximum size of an DH key on this implementation, in bits.
+ * This is a vendor-specific macro.*/
+#if defined(PSA_WANT_DH_RFC7919_8192)
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 8192u
+#elif defined(PSA_WANT_DH_RFC7919_6144)
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 6144u
+#elif defined(PSA_WANT_DH_RFC7919_4096)
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 4096u
+#elif defined(PSA_WANT_DH_RFC7919_3072)
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 3072u
+#elif defined(PSA_WANT_DH_RFC7919_2048)
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 2048u
+#else
+#define PSA_VENDOR_FFDH_MAX_KEY_BITS 0u
+#endif
 
 /* The maximum size of an ECC key on this implementation, in bits.
  * This is a vendor-specific macro. */
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521
-#elif defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512
-#elif defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448
-#elif defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
-#elif defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384
-#elif defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
-#elif defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
-#elif defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256
-#elif defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255
-#elif defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
-#elif defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224
-#elif defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
-#elif defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192
+#if defined(PSA_WANT_ECC_SECP_R1_521)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 521u
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 512u
+#elif defined(PSA_WANT_ECC_MONTGOMERY_448)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 448u
+#elif defined(PSA_WANT_ECC_SECP_R1_384)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 384u
+#elif defined(PSA_WANT_ECC_SECP_R1_256)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u
+#elif defined(PSA_WANT_ECC_SECP_K1_256)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u
+#elif defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 256u
+#elif defined(PSA_WANT_ECC_MONTGOMERY_255)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 255u
+#elif defined(PSA_WANT_ECC_SECP_R1_224)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u
+#elif defined(PSA_WANT_ECC_SECP_K1_224)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 224u
+#elif defined(PSA_WANT_ECC_SECP_R1_192)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u
+#elif defined(PSA_WANT_ECC_SECP_K1_192)
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 192u
 #else
-#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0
+#define PSA_VENDOR_ECC_MAX_CURVE_BITS 0u
 #endif
 
 /** This macro returns the maximum supported length of the PSK for the
@@ -237,19 +286,23 @@
  * Therefore, no implementation should define a value smaller than 64
  * for #PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE.
  */
-#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128
+#define PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE 128u
 
 /* The expected size of input passed to psa_tls12_ecjpake_to_pms_input,
  * which is expected to work with P-256 curve only. */
-#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65
+#define PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE 65u
 
 /* The size of a serialized K.X coordinate to be used in
  * psa_tls12_ecjpake_to_pms_input. This function only accepts the P-256
  * curve. */
-#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32
+#define PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE 32u
+
+/* The maximum number of iterations for PBKDF2 on this implementation, in bits.
+ * This is a vendor-specific macro. This can be configured if necessary */
+#define PSA_VENDOR_PBKDF2_MAX_ITERATIONS 0xffffffffU
 
 /** The maximum size of a block cipher. */
-#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16
+#define PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE 16u
 
 /** The size of the output of psa_mac_sign_finish(), in bytes.
  *
@@ -276,7 +329,7 @@
     ((alg) & PSA_ALG_MAC_TRUNCATION_MASK ? PSA_MAC_TRUNCATED_LENGTH(alg) :        \
      PSA_ALG_IS_HMAC(alg) ? PSA_HASH_LENGTH(PSA_ALG_HMAC_GET_HASH(alg)) :         \
      PSA_ALG_IS_BLOCK_CIPHER_MAC(alg) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
-     ((void) (key_type), (void) (key_bits), 0))
+     ((void) (key_type), (void) (key_bits), 0u))
 
 /** The maximum size of the output of psa_aead_encrypt(), in bytes.
  *
@@ -307,7 +360,7 @@
 #define PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg, plaintext_length) \
     (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 ?                      \
      (plaintext_length) + PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :          \
-     0)
+     0u)
 
 /** A sufficient output buffer size for psa_aead_encrypt(), for any of the
  *  supported key types and AEAD algorithms.
@@ -361,7 +414,7 @@
     (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&                      \
      (ciphertext_length) > PSA_ALG_AEAD_GET_TAG_LENGTH(alg) ?      \
      (ciphertext_length) - PSA_ALG_AEAD_GET_TAG_LENGTH(alg) :      \
-     0)
+     0u)
 
 /** A sufficient output buffer size for psa_aead_decrypt(), for any of the
  *  supported key types and AEAD algorithms.
@@ -411,12 +464,12 @@
  */
 #define PSA_AEAD_NONCE_LENGTH(key_type, alg) \
     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) == 16 ? \
-     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13 : \
-     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12 : \
-     0 : \
+     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CCM) ? 13u : \
+     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_GCM) ? 12u : \
+     0u : \
      (key_type) == PSA_KEY_TYPE_CHACHA20 && \
-     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12 : \
-     0)
+     MBEDTLS_PSA_ALG_AEAD_EQUAL(alg, PSA_ALG_CHACHA20_POLY1305) ? 12u : \
+     0u)
 
 /** The maximum default nonce size among all supported pairs of key types and
  *  AEAD algorithms, in bytes.
@@ -429,7 +482,7 @@
  *       just the largest size that may be generated by
  *       #psa_aead_generate_nonce().
  */
-#define PSA_AEAD_NONCE_MAX_SIZE 13
+#define PSA_AEAD_NONCE_MAX_SIZE 13u
 
 /** A sufficient output buffer size for psa_aead_update().
  *
@@ -466,7 +519,7 @@
      PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?                                              \
      PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), (input_length)) : \
      (input_length) : \
-     0)
+     0u)
 
 /** A sufficient output buffer size for psa_aead_update(), for any of the
  *  supported key types and AEAD algorithms.
@@ -506,7 +559,7 @@
     (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \
      PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \
      PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
-     0)
+     0u)
 
 /** A sufficient ciphertext buffer size for psa_aead_finish(), for any of the
  *  supported key types and AEAD algorithms.
@@ -540,7 +593,7 @@
     (PSA_AEAD_NONCE_LENGTH(key_type, alg) != 0 &&  \
      PSA_ALG_IS_AEAD_ON_BLOCK_CIPHER(alg) ?    \
      PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
-     0)
+     0u)
 
 /** A sufficient plaintext buffer size for psa_aead_verify(), for any of the
  *  supported key types and AEAD algorithms.
@@ -551,8 +604,8 @@
 
 #define PSA_RSA_MINIMUM_PADDING_SIZE(alg)                         \
     (PSA_ALG_IS_RSA_OAEP(alg) ?                                   \
-     2 * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 :    \
-     11 /*PKCS#1v1.5*/)
+     2u * PSA_HASH_LENGTH(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1u :   \
+     11u /*PKCS#1v1.5*/)
 
 /**
  * \brief ECDSA signature size for a given curve bit size
@@ -563,7 +616,7 @@
  * \note This macro returns a compile-time constant if its argument is one.
  */
 #define PSA_ECDSA_SIGNATURE_SIZE(curve_bits)    \
-    (PSA_BITS_TO_BYTES(curve_bits) * 2)
+    (PSA_BITS_TO_BYTES(curve_bits) * 2u)
 
 /** Sufficient signature buffer size for psa_sign_hash().
  *
@@ -593,7 +646,7 @@
 #define PSA_SIGN_OUTPUT_SIZE(key_type, key_bits, alg)        \
     (PSA_KEY_TYPE_IS_RSA(key_type) ? ((void) alg, PSA_BITS_TO_BYTES(key_bits)) : \
      PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_ECDSA_SIGNATURE_SIZE(key_bits) : \
-     ((void) alg, 0))
+     ((void) alg, 0u))
 
 #define PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE     \
     PSA_ECDSA_SIGNATURE_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
@@ -605,10 +658,18 @@
  * This macro expands to a compile-time constant integer. This value
  * is the maximum size of a signature in bytes.
  */
-#define PSA_SIGNATURE_MAX_SIZE                               \
-    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE ? \
-     PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) :                   \
-     PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE)
+#define PSA_SIGNATURE_MAX_SIZE      1
+
+#if (defined(PSA_WANT_ALG_ECDSA) || defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA)) && \
+    (PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE > PSA_SIGNATURE_MAX_SIZE)
+#undef PSA_SIGNATURE_MAX_SIZE
+#define PSA_SIGNATURE_MAX_SIZE      PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE
+#endif
+#if (defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) || defined(PSA_WANT_ALG_RSA_PSS)) && \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS) > PSA_SIGNATURE_MAX_SIZE)
+#undef PSA_SIGNATURE_MAX_SIZE
+#define PSA_SIGNATURE_MAX_SIZE      PSA_BITS_TO_BYTES(PSA_VENDOR_RSA_MAX_KEY_BITS)
+#endif
 
 /** Sufficient output buffer size for psa_asymmetric_encrypt().
  *
@@ -638,7 +699,7 @@
 #define PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \
     (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \
      ((void) alg, PSA_BITS_TO_BYTES(key_bits)) :                         \
-     0)
+     0u)
 
 /** A sufficient output buffer size for psa_asymmetric_encrypt(), for any
  *  supported asymmetric encryption.
@@ -677,7 +738,7 @@
 #define PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(key_type, key_bits, alg)     \
     (PSA_KEY_TYPE_IS_RSA(key_type) ?                                    \
      PSA_BITS_TO_BYTES(key_bits) - PSA_RSA_MINIMUM_PADDING_SIZE(alg) :  \
-     0)
+     0u)
 
 /** A sufficient output buffer size for psa_asymmetric_decrypt(), for any
  *  supported asymmetric decryption.
@@ -700,7 +761,7 @@
  * - 0 to 1 bytes of leading 0 due to the sign bit.
  */
 #define PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(bits)      \
-    ((bits) / 8 + 5)
+    ((bits) / 8u + 5u)
 
 /* Maximum size of the export encoding of an RSA public key.
  * Assumes that the public exponent is less than 2^32.
@@ -714,7 +775,7 @@
  * - 7 bytes for the public exponent.
  */
 #define PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits)        \
-    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11)
+    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11u)
 
 /* Maximum size of the export encoding of an RSA key pair.
  * Assumes that the public exponent is less than 2^32 and that the size
@@ -739,7 +800,7 @@
  * - 7 bytes for the public exponent.
  */
 #define PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits)   \
-    (9 * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2 + 1) + 14)
+    (9u * PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE((key_bits) / 2u + 1u) + 14u)
 
 /* Maximum size of the export encoding of a DSA public key.
  *
@@ -758,7 +819,7 @@
  * - 1 + 1 + 32 bytes for 1 sub-size INTEGER (q <= 256 bits).
  */
 #define PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits)        \
-    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 59)
+    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 59u)
 
 /* Maximum size of the export encoding of a DSA key pair.
  *
@@ -777,7 +838,7 @@
  * - 2 * (1 + 1 + 32) bytes for 2 sub-size INTEGERs (q, x <= 256 bits).
  */
 #define PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits)   \
-    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3 + 75)
+    (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) * 3u + 75u)
 
 /* Maximum size of the export encoding of an ECC public key.
  *
@@ -790,7 +851,7 @@
  * - 1 byte + 2 * point size.
  */
 #define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits)        \
-    (2 * PSA_BITS_TO_BYTES(key_bits) + 1)
+    (2u * PSA_BITS_TO_BYTES(key_bits) + 1u)
 
 /* Maximum size of the export encoding of an ECC key pair.
  *
@@ -799,6 +860,18 @@
 #define PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits)   \
     (PSA_BITS_TO_BYTES(key_bits))
 
+/* Maximum size of the export encoding of an DH key pair.
+ *
+ * An DH key pair is represented by the secret value.
+ */
+#define PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(key_bits)   \
+    (PSA_BITS_TO_BYTES(key_bits))
+
+/* Maximum size of the export encoding of an DH public key.
+ */
+#define PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(key_bits)   \
+    (PSA_BITS_TO_BYTES(key_bits))
+
 /** Sufficient output buffer size for psa_export_key() or
  * psa_export_public_key().
  *
@@ -840,13 +913,14 @@
  */
 #define PSA_EXPORT_KEY_OUTPUT_SIZE(key_type, key_bits)                                              \
     (PSA_KEY_TYPE_IS_UNSTRUCTURED(key_type) ? PSA_BITS_TO_BYTES(key_bits) :                         \
+     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) :                                   \
      (key_type) == PSA_KEY_TYPE_RSA_KEY_PAIR ? PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(key_bits) :     \
      (key_type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
      (key_type) == PSA_KEY_TYPE_DSA_KEY_PAIR ? PSA_KEY_EXPORT_DSA_KEY_PAIR_MAX_SIZE(key_bits) :     \
      (key_type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY ? PSA_KEY_EXPORT_DSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
      PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ? PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(key_bits) :      \
      PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) :  \
-     0)
+     0u)
 
 /** Sufficient output buffer size for psa_export_public_key().
  *
@@ -896,7 +970,8 @@
 #define PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(key_type, key_bits)                           \
     (PSA_KEY_TYPE_IS_RSA(key_type) ? PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(key_bits) : \
      PSA_KEY_TYPE_IS_ECC(key_type) ? PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) : \
-     0)
+     PSA_KEY_TYPE_IS_DH(key_type) ? PSA_BITS_TO_BYTES(key_bits) : \
+     0u)
 
 /** Sufficient buffer size for exporting any asymmetric key pair.
  *
@@ -906,11 +981,29 @@
  *
  * See also #PSA_EXPORT_KEY_OUTPUT_SIZE(\p key_type, \p key_bits).
  */
-#define PSA_EXPORT_KEY_PAIR_MAX_SIZE                                            \
-    (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) >        \
-     PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ?      \
-     PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) :        \
-     PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS))
+#define PSA_EXPORT_KEY_PAIR_MAX_SIZE            1
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) && \
+    (PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
+     PSA_EXPORT_KEY_PAIR_MAX_SIZE)
+#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
+#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \
+    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+#endif
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) && \
+    (PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \
+     PSA_EXPORT_KEY_PAIR_MAX_SIZE)
+#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
+#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \
+    PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
+#endif
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) && \
+    (PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \
+     PSA_EXPORT_KEY_PAIR_MAX_SIZE)
+#undef PSA_EXPORT_KEY_PAIR_MAX_SIZE
+#define PSA_EXPORT_KEY_PAIR_MAX_SIZE    \
+    PSA_KEY_EXPORT_FFDH_KEY_PAIR_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)
+#endif
 
 /** Sufficient buffer size for exporting any asymmetric public key.
  *
@@ -921,11 +1014,29 @@
  *
  * See also #PSA_EXPORT_PUBLIC_KEY_OUTPUT_SIZE(\p key_type, \p key_bits).
  */
-#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE                                          \
-    (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) >      \
-     PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) ?    \
-     PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) :      \
-     PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS))
+#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE            1
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) && \
+    (PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
+     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
+#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \
+    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+#endif
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) && \
+    (PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS) > \
+     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
+#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \
+    PSA_KEY_EXPORT_RSA_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)
+#endif
+#if defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) && \
+    (PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS) > \
+     PSA_EXPORT_PUBLIC_KEY_MAX_SIZE)
+#undef PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PSA_EXPORT_PUBLIC_KEY_MAX_SIZE    \
+    PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)
+#endif
 
 /** Sufficient output buffer size for psa_raw_key_agreement().
  *
@@ -950,11 +1061,9 @@
  *                      If the parameters are not valid,
  *                      the return value is unspecified.
  */
-/* FFDH is not yet supported in PSA. */
 #define PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(key_type, key_bits)   \
-    (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ?                   \
-     PSA_BITS_TO_BYTES(key_bits) :                              \
-     0)
+    ((PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) || \
+      PSA_KEY_TYPE_IS_DH_KEY_PAIR(key_type)) ? PSA_BITS_TO_BYTES(key_bits) : 0u)
 
 /** Maximum size of the output from psa_raw_key_agreement().
  *
@@ -963,8 +1072,18 @@
  *
  * See also #PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(\p key_type, \p key_bits).
  */
-#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE   \
-    (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS))
+#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE       1
+
+#if defined(PSA_WANT_ALG_ECDH) && \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)
+#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE
+#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE    PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+#endif
+#if defined(PSA_WANT_ALG_FFDH) && \
+    (PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS) > PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE)
+#undef PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE
+#define PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE    PSA_BITS_TO_BYTES(PSA_VENDOR_FFDH_MAX_KEY_BITS)
+#endif
 
 /** The default IV size for a cipher algorithm, in bytes.
  *
@@ -999,15 +1118,15 @@
       (alg) == PSA_ALG_CBC_NO_PADDING || \
       (alg) == PSA_ALG_CBC_PKCS7) ? PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) : \
      (key_type) == PSA_KEY_TYPE_CHACHA20 && \
-     (alg) == PSA_ALG_STREAM_CIPHER ? 12 : \
-     (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13 : \
-     0)
+     (alg) == PSA_ALG_STREAM_CIPHER ? 12u : \
+     (alg) == PSA_ALG_CCM_STAR_NO_TAG ? 13u : \
+     0u)
 
 /** The maximum IV size for all supported cipher algorithms, in bytes.
  *
  * See also #PSA_CIPHER_IV_LENGTH().
  */
-#define PSA_CIPHER_IV_MAX_SIZE 16
+#define PSA_CIPHER_IV_MAX_SIZE 16u
 
 /** The maximum size of the output of psa_cipher_encrypt(), in bytes.
  *
@@ -1032,15 +1151,15 @@
  *                      recognized, or the parameters are incompatible,
  *                      return 0.
  */
-#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length)             \
-    (alg == PSA_ALG_CBC_PKCS7 ?                                                 \
-     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                            \
-      PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type),          \
-                               (input_length) + 1) +                             \
-      PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0) :                             \
-     (PSA_ALG_IS_CIPHER(alg) ?                                                  \
-      (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) :                \
-      0))
+#define PSA_CIPHER_ENCRYPT_OUTPUT_SIZE(key_type, alg, input_length)     \
+    (alg == PSA_ALG_CBC_PKCS7 ?                                         \
+     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                    \
+      PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \
+                               (input_length) + 1u) +                   \
+      PSA_CIPHER_IV_LENGTH((key_type), (alg)) : 0u) :                   \
+     (PSA_ALG_IS_CIPHER(alg) ?                                          \
+      (input_length) + PSA_CIPHER_IV_LENGTH((key_type), (alg)) :        \
+      0u))
 
 /** A sufficient output buffer size for psa_cipher_encrypt(), for any of the
  *  supported key types and cipher algorithms.
@@ -1053,9 +1172,9 @@
  * \param input_length  Size of the input in bytes.
  *
  */
-#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length)                        \
-    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE,                  \
-                              (input_length) + 1) +                             \
+#define PSA_CIPHER_ENCRYPT_OUTPUT_MAX_SIZE(input_length)                \
+    (PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE,          \
+                              (input_length) + 1u) +                    \
      PSA_CIPHER_IV_MAX_SIZE)
 
 /** The maximum size of the output of psa_cipher_decrypt(), in bytes.
@@ -1077,11 +1196,11 @@
  *                      recognized, or the parameters are incompatible,
  *                      return 0.
  */
-#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length)                 \
-    (PSA_ALG_IS_CIPHER(alg) &&                                                      \
+#define PSA_CIPHER_DECRYPT_OUTPUT_SIZE(key_type, alg, input_length)     \
+    (PSA_ALG_IS_CIPHER(alg) &&                                          \
      ((key_type) & PSA_KEY_TYPE_CATEGORY_MASK) == PSA_KEY_TYPE_CATEGORY_SYMMETRIC ? \
-     (input_length) :                                                               \
-     0)
+     (input_length) :                                                   \
+     0u)
 
 /** A sufficient output buffer size for psa_cipher_decrypt(), for any of the
  *  supported key types and cipher algorithms.
@@ -1114,16 +1233,16 @@
  *                      algorithm. If the key type or cipher algorithm is not
  *                      recognized, or the parameters are incompatible, return 0.
  */
-#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)              \
-    (PSA_ALG_IS_CIPHER(alg) ?                                                   \
-     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                             \
-      (((alg) == PSA_ALG_CBC_PKCS7      ||                                       \
-        (alg) == PSA_ALG_CBC_NO_PADDING ||                                       \
-        (alg) == PSA_ALG_ECB_NO_PADDING) ?                                       \
-       PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type),         \
-                                input_length) :                                 \
-       (input_length)) : 0) :                                                    \
-     0)
+#define PSA_CIPHER_UPDATE_OUTPUT_SIZE(key_type, alg, input_length)      \
+    (PSA_ALG_IS_CIPHER(alg) ?                                           \
+     (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) != 0 ?                    \
+      (((alg) == PSA_ALG_CBC_PKCS7      ||                              \
+        (alg) == PSA_ALG_CBC_NO_PADDING ||                              \
+        (alg) == PSA_ALG_ECB_NO_PADDING) ?                              \
+       PSA_ROUND_UP_TO_MULTIPLE(PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type), \
+                                input_length) :                         \
+       (input_length)) : 0u) :                                          \
+     0u)
 
 /** A sufficient output buffer size for psa_cipher_update(), for any of the
  *  supported key types and cipher algorithms.
@@ -1159,8 +1278,8 @@
     (PSA_ALG_IS_CIPHER(alg) ?                           \
      (alg == PSA_ALG_CBC_PKCS7 ?                        \
       PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) :         \
-      0) :                                              \
-     0)
+      0u) :                                             \
+     0u)
 
 /** A sufficient ciphertext buffer size for psa_cipher_finish(), for any of the
  *  supported key types and cipher algorithms.
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h b/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h
index 934bc176effa002f93071b5f3a72e5496e56aff2..362e921a36495e34322830280365f468cb426134 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_struct.h
@@ -35,27 +35,15 @@
  * GCC and Clang initialize the whole structure to 0 (at the time of writing),
  * but MSVC and CompCert don't.
  *
- * In Mbed Crypto, multipart operation structures live independently from
- * the key. This allows Mbed Crypto to free the key objects when destroying
+ * In Mbed TLS, multipart operation structures live independently from
+ * the key. This allows Mbed TLS to free the key objects when destroying
  * a key slot. If a multipart operation needs to remember the key after
  * the setup function returns, the operation structure needs to contain a
  * copy of the key.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_STRUCT_H
@@ -66,20 +54,23 @@
 extern "C" {
 #endif
 
-/* Include the Mbed TLS configuration file, the way Mbed TLS does it
- * in each of its header files. */
-#include "mbedtls/build_info.h"
-
-#include "mbedtls/cmac.h"
-#include "mbedtls/gcm.h"
-#include "mbedtls/ccm.h"
-#include "mbedtls/chachapoly.h"
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
 
 /* Include the context definition for the compiled-in drivers for the primitive
  * algorithms. */
 #include "psa/crypto_driver_contexts_primitives.h"
 
 struct psa_hash_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -88,9 +79,13 @@ struct psa_hash_operation_s {
      * any driver (i.e. the driver context is not active, in use). */
     unsigned int MBEDTLS_PRIVATE(id);
     psa_driver_hash_context_t MBEDTLS_PRIVATE(ctx);
+#endif
 };
-
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_HASH_OPERATION_INIT { 0 }
+#else
 #define PSA_HASH_OPERATION_INIT { 0, { 0 } }
+#endif
 static inline struct psa_hash_operation_s psa_hash_operation_init(void)
 {
     const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT;
@@ -98,6 +93,9 @@ static inline struct psa_hash_operation_s psa_hash_operation_init(void)
 }
 
 struct psa_cipher_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -112,9 +110,14 @@ struct psa_cipher_operation_s {
     uint8_t MBEDTLS_PRIVATE(default_iv_length);
 
     psa_driver_cipher_context_t MBEDTLS_PRIVATE(ctx);
+#endif
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_CIPHER_OPERATION_INIT { 0 }
+#else
 #define PSA_CIPHER_OPERATION_INIT { 0, 0, 0, 0, { 0 } }
+#endif
 static inline struct psa_cipher_operation_s psa_cipher_operation_init(void)
 {
     const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT;
@@ -126,6 +129,9 @@ static inline struct psa_cipher_operation_s psa_cipher_operation_init(void)
 #include "psa/crypto_driver_contexts_composites.h"
 
 struct psa_mac_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -136,9 +142,14 @@ struct psa_mac_operation_s {
     uint8_t MBEDTLS_PRIVATE(mac_size);
     unsigned int MBEDTLS_PRIVATE(is_sign) : 1;
     psa_driver_mac_context_t MBEDTLS_PRIVATE(ctx);
+#endif
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_MAC_OPERATION_INIT { 0 }
+#else
 #define PSA_MAC_OPERATION_INIT { 0, 0, 0, { 0 } }
+#endif
 static inline struct psa_mac_operation_s psa_mac_operation_init(void)
 {
     const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT;
@@ -146,7 +157,9 @@ static inline struct psa_mac_operation_s psa_mac_operation_init(void)
 }
 
 struct psa_aead_operation_s {
-
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -168,109 +181,41 @@ struct psa_aead_operation_s {
     unsigned int MBEDTLS_PRIVATE(is_encrypt) : 1;
 
     psa_driver_aead_context_t MBEDTLS_PRIVATE(ctx);
+#endif
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_AEAD_OPERATION_INIT { 0 }
+#else
 #define PSA_AEAD_OPERATION_INIT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, { 0 } }
+#endif
 static inline struct psa_aead_operation_s psa_aead_operation_init(void)
 {
     const struct psa_aead_operation_s v = PSA_AEAD_OPERATION_INIT;
     return v;
 }
 
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
-typedef struct {
-    uint8_t *MBEDTLS_PRIVATE(info);
-    size_t MBEDTLS_PRIVATE(info_length);
-#if PSA_HASH_MAX_SIZE > 0xff
-#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
-#endif
-    uint8_t MBEDTLS_PRIVATE(offset_in_block);
-    uint8_t MBEDTLS_PRIVATE(block_number);
-    unsigned int MBEDTLS_PRIVATE(state) : 2;
-    unsigned int MBEDTLS_PRIVATE(info_set) : 1;
-    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
-    uint8_t MBEDTLS_PRIVATE(prk)[PSA_HASH_MAX_SIZE];
-    struct psa_mac_operation_s MBEDTLS_PRIVATE(hmac);
-} psa_hkdf_key_derivation_t;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF ||
-          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT ||
-          MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
-typedef struct {
-    uint8_t MBEDTLS_PRIVATE(data)[PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE];
-} psa_tls12_ecjpake_to_pms_t;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
-
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
-    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
-typedef enum {
-    PSA_TLS12_PRF_STATE_INIT,             /* no input provided */
-    PSA_TLS12_PRF_STATE_SEED_SET,         /* seed has been set */
-    PSA_TLS12_PRF_STATE_OTHER_KEY_SET,    /* other key has been set - optional */
-    PSA_TLS12_PRF_STATE_KEY_SET,          /* key has been set */
-    PSA_TLS12_PRF_STATE_LABEL_SET,        /* label has been set */
-    PSA_TLS12_PRF_STATE_OUTPUT            /* output has been started */
-} psa_tls12_prf_key_derivation_state_t;
-
-typedef struct psa_tls12_prf_key_derivation_s {
-#if PSA_HASH_MAX_SIZE > 0xff
-#error "PSA_HASH_MAX_SIZE does not fit in uint8_t"
-#endif
-
-    /* Indicates how many bytes in the current HMAC block have
-     * not yet been read by the user. */
-    uint8_t MBEDTLS_PRIVATE(left_in_block);
-
-    /* The 1-based number of the block. */
-    uint8_t MBEDTLS_PRIVATE(block_number);
-
-    psa_tls12_prf_key_derivation_state_t MBEDTLS_PRIVATE(state);
-
-    uint8_t *MBEDTLS_PRIVATE(secret);
-    size_t MBEDTLS_PRIVATE(secret_length);
-    uint8_t *MBEDTLS_PRIVATE(seed);
-    size_t MBEDTLS_PRIVATE(seed_length);
-    uint8_t *MBEDTLS_PRIVATE(label);
-    size_t MBEDTLS_PRIVATE(label_length);
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
-    uint8_t *MBEDTLS_PRIVATE(other_secret);
-    size_t MBEDTLS_PRIVATE(other_secret_length);
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
-
-    uint8_t MBEDTLS_PRIVATE(Ai)[PSA_HASH_MAX_SIZE];
-
-    /* `HMAC_hash( prk, A( i ) + seed )` in the notation of RFC 5246, Sect. 5. */
-    uint8_t MBEDTLS_PRIVATE(output_block)[PSA_HASH_MAX_SIZE];
-} psa_tls12_prf_key_derivation_t;
-#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
-        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+/* Include the context definition for the compiled-in drivers for the key
+ * derivation algorithms. */
+#include "psa/crypto_driver_contexts_key_derivation.h"
 
 struct psa_key_derivation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
     unsigned int MBEDTLS_PRIVATE(can_output_key) : 1;
     size_t MBEDTLS_PRIVATE(capacity);
-    union {
-        /* Make the union non-empty even with no supported algorithms. */
-        uint8_t MBEDTLS_PRIVATE(dummy);
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) || \
-        defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) || \
-        defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
-        psa_hkdf_key_derivation_t MBEDTLS_PRIVATE(hkdf);
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
-        defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
-        psa_tls12_prf_key_derivation_t MBEDTLS_PRIVATE(tls12_prf);
-#endif
-#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
-        psa_tls12_ecjpake_to_pms_t MBEDTLS_PRIVATE(tls12_ecjpake_to_pms);
+    psa_driver_key_derivation_context_t MBEDTLS_PRIVATE(ctx);
 #endif
-    } MBEDTLS_PRIVATE(ctx);
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_KEY_DERIVATION_OPERATION_INIT { 0 }
+#else
 /* This only zeroes out the first byte in the union, the rest is unspecified. */
 #define PSA_KEY_DERIVATION_OPERATION_INIT { 0, 0, 0, { 0 } }
+#endif
 static inline struct psa_key_derivation_s psa_key_derivation_operation_init(
     void)
 {
@@ -278,6 +223,48 @@ static inline struct psa_key_derivation_s psa_key_derivation_operation_init(
     return v;
 }
 
+struct psa_custom_key_parameters_s {
+    /* Future versions may add other fields in this structure. */
+    uint32_t flags;
+};
+
+/** The default production parameters for key generation or key derivation.
+ *
+ * Calling psa_generate_key_custom() or psa_key_derivation_output_key_custom()
+ * with `custom=PSA_CUSTOM_KEY_PARAMETERS_INIT` and `custom_data_length=0` is
+ * equivalent to calling psa_generate_key() or psa_key_derivation_output_key()
+ * respectively.
+ */
+#define PSA_CUSTOM_KEY_PARAMETERS_INIT { 0 }
+
+#ifndef __cplusplus
+/* Omitted when compiling in C++, because one of the parameters is a
+ * pointer to a struct with a flexible array member, and that is not
+ * standard C++.
+ * https://github.com/Mbed-TLS/mbedtls/issues/9020
+ */
+/* This is a deprecated variant of `struct psa_custom_key_parameters_s`.
+ * It has exactly the same layout, plus an extra field which is a flexible
+ * array member. Thus a `const struct psa_key_production_parameters_s *`
+ * can be passed to any function that reads a
+ * `const struct psa_custom_key_parameters_s *`.
+ */
+struct psa_key_production_parameters_s {
+    uint32_t flags;
+    uint8_t data[];
+};
+
+/** The default production parameters for key generation or key derivation.
+ *
+ * Calling psa_generate_key_ext() or psa_key_derivation_output_key_ext()
+ * with `params=PSA_KEY_PRODUCTION_PARAMETERS_INIT` and
+ * `params_data_length == 0` is equivalent to
+ * calling psa_generate_key() or psa_key_derivation_output_key()
+ * respectively.
+ */
+#define PSA_KEY_PRODUCTION_PARAMETERS_INIT { 0 }
+#endif /* !__cplusplus */
+
 struct psa_key_policy_s {
     psa_key_usage_t MBEDTLS_PRIVATE(usage);
     psa_algorithm_t MBEDTLS_PRIVATE(alg);
@@ -305,57 +292,39 @@ typedef uint16_t psa_key_bits_t;
  * conditionals. */
 #define PSA_MAX_KEY_BITS 0xfff8
 
-/** A mask of flags that can be stored in key attributes.
- *
- * This type is also used internally to store flags in slots. Internal
- * flags are defined in library/psa_crypto_core.h. Internal flags may have
- * the same value as external flags if they are properly handled during
- * key creation and in psa_get_key_attributes.
- */
-typedef uint16_t psa_key_attributes_flag_t;
-
-#define MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER     \
-    ((psa_key_attributes_flag_t) 0x0001)
-
-/* A mask of key attribute flags used externally only.
- * Only meant for internal checks inside the library. */
-#define MBEDTLS_PSA_KA_MASK_EXTERNAL_ONLY (      \
-        MBEDTLS_PSA_KA_FLAG_HAS_SLOT_NUMBER |    \
-        0)
-
-/* A mask of key attribute flags used both internally and externally.
- * Currently there aren't any. */
-#define MBEDTLS_PSA_KA_MASK_DUAL_USE (          \
-        0)
-
-typedef struct {
-    psa_key_type_t MBEDTLS_PRIVATE(type);
-    psa_key_bits_t MBEDTLS_PRIVATE(bits);
-    psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime);
-    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id);
-    psa_key_policy_t MBEDTLS_PRIVATE(policy);
-    psa_key_attributes_flag_t MBEDTLS_PRIVATE(flags);
-} psa_core_key_attributes_t;
-
-#define PSA_CORE_KEY_ATTRIBUTES_INIT { PSA_KEY_TYPE_NONE, 0,            \
-                                       PSA_KEY_LIFETIME_VOLATILE,       \
-                                       MBEDTLS_SVC_KEY_ID_INIT,         \
-                                       PSA_KEY_POLICY_INIT, 0 }
-
 struct psa_key_attributes_s {
-    psa_core_key_attributes_t MBEDTLS_PRIVATE(core);
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
     psa_key_slot_number_t MBEDTLS_PRIVATE(slot_number);
+    int MBEDTLS_PRIVATE(has_slot_number);
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
-    void *MBEDTLS_PRIVATE(domain_parameters);
-    size_t MBEDTLS_PRIVATE(domain_parameters_size);
+    psa_key_type_t MBEDTLS_PRIVATE(type);
+    psa_key_bits_t MBEDTLS_PRIVATE(bits);
+    psa_key_lifetime_t MBEDTLS_PRIVATE(lifetime);
+    psa_key_policy_t MBEDTLS_PRIVATE(policy);
+    /* This type has a different layout in the client view wrt the
+     * service view of the key id, i.e. in service view usually is
+     * expected to have MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined
+     * thus adding an owner field to the standard psa_key_id_t. For
+     * implementations with client/service separation, this means the
+     * object will be marshalled through a transport channel and
+     * interpreted differently at each side of the transport. Placing
+     * it at the end of structures allows to interpret the structure
+     * at the client without reorganizing the memory layout of the
+     * struct
+     */
+    mbedtls_svc_key_id_t MBEDTLS_PRIVATE(id);
 };
 
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, 0, NULL, 0 }
+#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER 0, 0,
 #else
-#define PSA_KEY_ATTRIBUTES_INIT { PSA_CORE_KEY_ATTRIBUTES_INIT, NULL, 0 }
+#define PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER
 #endif
+#define PSA_KEY_ATTRIBUTES_INIT { PSA_KEY_ATTRIBUTES_MAYBE_SLOT_NUMBER \
+                                      PSA_KEY_TYPE_NONE, 0,            \
+                                      PSA_KEY_LIFETIME_VOLATILE,       \
+                                      PSA_KEY_POLICY_INIT,             \
+                                      MBEDTLS_SVC_KEY_ID_INIT }
 
 static inline struct psa_key_attributes_s psa_key_attributes_init(void)
 {
@@ -366,12 +335,12 @@ static inline struct psa_key_attributes_s psa_key_attributes_init(void)
 static inline void psa_set_key_id(psa_key_attributes_t *attributes,
                                   mbedtls_svc_key_id_t key)
 {
-    psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime);
+    psa_key_lifetime_t lifetime = attributes->MBEDTLS_PRIVATE(lifetime);
 
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = key;
+    attributes->MBEDTLS_PRIVATE(id) = key;
 
     if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) =
+        attributes->MBEDTLS_PRIVATE(lifetime) =
             PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
                 PSA_KEY_LIFETIME_PERSISTENT,
                 PSA_KEY_LIFETIME_GET_LOCATION(lifetime));
@@ -381,26 +350,26 @@ static inline void psa_set_key_id(psa_key_attributes_t *attributes,
 static inline mbedtls_svc_key_id_t psa_get_key_id(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id);
+    return attributes->MBEDTLS_PRIVATE(id);
 }
 
 #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
 static inline void mbedtls_set_key_owner_id(psa_key_attributes_t *attributes,
                                             mbedtls_key_owner_id_t owner)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner;
+    attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(owner) = owner;
 }
 #endif
 
 static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
                                         psa_key_lifetime_t lifetime)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime) = lifetime;
+    attributes->MBEDTLS_PRIVATE(lifetime) = lifetime;
     if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
 #ifdef MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0;
+        attributes->MBEDTLS_PRIVATE(id).MBEDTLS_PRIVATE(key_id) = 0;
 #else
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(id) = 0;
+        attributes->MBEDTLS_PRIVATE(id) = 0;
 #endif
     }
 }
@@ -408,7 +377,7 @@ static inline void psa_set_key_lifetime(psa_key_attributes_t *attributes,
 static inline psa_key_lifetime_t psa_get_key_lifetime(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(lifetime);
+    return attributes->MBEDTLS_PRIVATE(lifetime);
 }
 
 static inline void psa_extend_key_usage_flags(psa_key_usage_t *usage_flags)
@@ -426,75 +395,62 @@ static inline void psa_set_key_usage_flags(psa_key_attributes_t *attributes,
                                            psa_key_usage_t usage_flags)
 {
     psa_extend_key_usage_flags(&usage_flags);
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags;
+    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage) = usage_flags;
 }
 
 static inline psa_key_usage_t psa_get_key_usage_flags(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage);
+    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(usage);
 }
 
 static inline void psa_set_key_algorithm(psa_key_attributes_t *attributes,
                                          psa_algorithm_t alg)
 {
-    attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg;
+    attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg) = alg;
 }
 
 static inline psa_algorithm_t psa_get_key_algorithm(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg);
+    return attributes->MBEDTLS_PRIVATE(policy).MBEDTLS_PRIVATE(alg);
 }
 
-/* This function is declared in crypto_extra.h, which comes after this
- * header file, but we need the function here, so repeat the declaration. */
-psa_status_t psa_set_key_domain_parameters(psa_key_attributes_t *attributes,
-                                           psa_key_type_t type,
-                                           const uint8_t *data,
-                                           size_t data_length);
-
 static inline void psa_set_key_type(psa_key_attributes_t *attributes,
                                     psa_key_type_t type)
 {
-    if (attributes->MBEDTLS_PRIVATE(domain_parameters) == NULL) {
-        /* Common case: quick path */
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type) = type;
-    } else {
-        /* Call the bigger function to free the old domain parameters.
-         * Ignore any errors which may arise due to type requiring
-         * non-default domain parameters, since this function can't
-         * report errors. */
-        (void) psa_set_key_domain_parameters(attributes, type, NULL, 0);
-    }
+    attributes->MBEDTLS_PRIVATE(type) = type;
 }
 
 static inline psa_key_type_t psa_get_key_type(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(type);
+    return attributes->MBEDTLS_PRIVATE(type);
 }
 
 static inline void psa_set_key_bits(psa_key_attributes_t *attributes,
                                     size_t bits)
 {
     if (bits > PSA_MAX_KEY_BITS) {
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE;
+        attributes->MBEDTLS_PRIVATE(bits) = PSA_KEY_BITS_TOO_LARGE;
     } else {
-        attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits;
+        attributes->MBEDTLS_PRIVATE(bits) = (psa_key_bits_t) bits;
     }
 }
 
 static inline size_t psa_get_key_bits(
     const psa_key_attributes_t *attributes)
 {
-    return attributes->MBEDTLS_PRIVATE(core).MBEDTLS_PRIVATE(bits);
+    return attributes->MBEDTLS_PRIVATE(bits);
 }
 
 /**
  * \brief The context for PSA interruptible hash signing.
  */
 struct psa_sign_hash_interruptible_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -508,9 +464,14 @@ struct psa_sign_hash_interruptible_operation_s {
     unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;
 
     uint32_t MBEDTLS_PRIVATE(num_ops);
+#endif
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }
+#else
 #define PSA_SIGN_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }
+#endif
 
 static inline struct psa_sign_hash_interruptible_operation_s
 psa_sign_hash_interruptible_operation_init(void)
@@ -525,6 +486,9 @@ psa_sign_hash_interruptible_operation_init(void)
  * \brief The context for PSA interruptible hash verification.
  */
 struct psa_verify_hash_interruptible_operation_s {
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_psa_client_handle_t handle;
+#else
     /** Unique ID indicating which driver got assigned to do the
      * operation. Since driver contexts are driver-specific, swapping
      * drivers halfway through the operation is not supported.
@@ -538,9 +502,14 @@ struct psa_verify_hash_interruptible_operation_s {
     unsigned int MBEDTLS_PRIVATE(error_occurred) : 1;
 
     uint32_t MBEDTLS_PRIVATE(num_ops);
+#endif
 };
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT) && !defined(MBEDTLS_PSA_CRYPTO_C)
+#define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0 }
+#else
 #define PSA_VERIFY_HASH_INTERRUPTIBLE_OPERATION_INIT { 0, { 0 }, 0, 0 }
+#endif
 
 static inline struct psa_verify_hash_interruptible_operation_s
 psa_verify_hash_interruptible_operation_init(void)
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_types.h b/lib/libmbedtls/mbedtls/include/psa/crypto_types.h
index a5154fcd6be3a8494d85a66d81371538d1e7675e..f831486f4e40ca7883d8ce9a79fb6b9d79891f53 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_types.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_types.h
@@ -15,26 +15,21 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_TYPES_H
 #define PSA_CRYPTO_TYPES_H
 
-/* Make sure the Mbed TLS configuration is visible. */
-#include "mbedtls/build_info.h"
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
+
 /* Define the MBEDTLS_PRIVATE macro. */
 #include "mbedtls/private_access.h"
 
@@ -297,7 +292,7 @@ typedef uint32_t psa_key_id_t;
 typedef psa_key_id_t mbedtls_svc_key_id_t;
 
 #else /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
-/* Implementation-specific: The Mbed Cryptography library can be built as
+/* Implementation-specific: The Mbed TLS library can be built as
  * part of a multi-client service that exposes the PSA Cryptography API in each
  * client and encodes the client identity in the key identifier argument of
  * functions such as psa_open_key().
@@ -439,7 +434,7 @@ typedef struct psa_key_attributes_s psa_key_attributes_t;
 
 #ifndef __DOXYGEN_ONLY__
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-/* Mbed Crypto defines this type in crypto_types.h because it is also
+/* Mbed TLS defines this type in crypto_types.h because it is also
  * visible to applications through an implementation-specific extension.
  * For the PSA Cryptography specification, this type is only visible
  * via crypto_se_driver.h. */
@@ -460,6 +455,54 @@ typedef uint64_t psa_key_slot_number_t;
  */
 typedef uint16_t psa_key_derivation_step_t;
 
+/** \brief Custom parameters for key generation or key derivation.
+ *
+ * This is a structure type with at least the following field:
+ *
+ * - \c flags: an unsigned integer type. 0 for the default production parameters.
+ *
+ * Functions that take such a structure as input also take an associated
+ * input buffer \c custom_data of length \c custom_data_length.
+ *
+ * The interpretation of this structure and the associated \c custom_data
+ * parameter depend on the type of the created key.
+ *
+ * - #PSA_KEY_TYPE_RSA_KEY_PAIR:
+ *     - \c flags: must be 0.
+ *     - \c custom_data: the public exponent, in little-endian order.
+ *       This must be an odd integer and must not be 1.
+ *       Implementations must support 65537, should support 3 and may
+ *       support other values.
+ *       When not using a driver, Mbed TLS supports values up to \c INT_MAX.
+ *       If this is empty, the default value 65537 is used.
+ * - Other key types: reserved for future use. \c flags must be 0.
+ */
+typedef struct psa_custom_key_parameters_s psa_custom_key_parameters_t;
+
+/** \brief Custom parameters for key generation or key derivation.
+ *
+ * This is a structure type with at least the following fields:
+ *
+ * - \c flags: an unsigned integer type. 0 for the default production parameters.
+ * - \c data: a flexible array of bytes.
+ *
+ * The interpretation of this structure depend on the type of the
+ * created key.
+ *
+ * - #PSA_KEY_TYPE_RSA_KEY_PAIR:
+ *     - \c flags: must be 0.
+ *     - \c data: the public exponent, in little-endian order.
+ *       This must be an odd integer and must not be 1.
+ *       Implementations must support 65537, should support 3 and may
+ *       support other values.
+ *       When not using a driver, Mbed TLS supports values up to \c INT_MAX.
+ *       If this is empty or if the custom production parameters are omitted
+ *       altogether, the default value 65537 is used.
+ * - Other key types: reserved for future use. \c flags must be 0.
+ *
+ */
+typedef struct psa_key_production_parameters_s psa_key_production_parameters_t;
+
 /**@}*/
 
 #endif /* PSA_CRYPTO_TYPES_H */
diff --git a/lib/libmbedtls/mbedtls/include/psa/crypto_values.h b/lib/libmbedtls/mbedtls/include/psa/crypto_values.h
index 39acd96c52878d4af9faaa94498c30c4a0c62df0..1d678dbfc29c57ca1b516643e5d2b55ff2d2c37b 100644
--- a/lib/libmbedtls/mbedtls/include/psa/crypto_values.h
+++ b/lib/libmbedtls/mbedtls/include/psa/crypto_values.h
@@ -21,19 +21,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef PSA_CRYPTO_VALUES_H
@@ -291,6 +279,11 @@
  * to read from a resource. */
 #define PSA_ERROR_INSUFFICIENT_DATA     ((psa_status_t)-143)
 
+/** This can be returned if a function can no longer operate correctly.
+ * For example, if an essential initialization operation failed or
+ * a mutex operation failed. */
+#define PSA_ERROR_SERVICE_FAILURE       ((psa_status_t)-144)
+
 /** The key identifier is not valid. See also :ref:\`key-handles\`.
  */
 #define PSA_ERROR_INVALID_HANDLE        ((psa_status_t)-136)
@@ -420,7 +413,7 @@
     ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR)
 /** The public key type corresponding to a key pair type.
  *
- * You may also pass a key pair type as \p type, it will be left unchanged.
+ * You may also pass a public key type as \p type, it will be left unchanged.
  *
  * \param type      A public key type or key pair type.
  *
@@ -606,19 +599,23 @@
  * They are defined in _Standards for Efficient Cryptography_,
  * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
  * https://www.secg.org/sec2-v2.pdf
+ *
+ * \note For secp224k1, the bit-size is 225 (size of a private value).
+ *
+ * \note Mbed TLS only supports secp192k1 and secp256k1.
  */
 #define PSA_ECC_FAMILY_SECP_K1           ((psa_ecc_family_t) 0x17)
 
 /** SEC random curves over prime fields.
  *
  * This family comprises the following curves:
- * secp192k1, secp224r1, secp256r1, secp384r1, secp521r1.
+ * secp192r1, secp224r1, secp256r1, secp384r1, secp521r1.
  * They are defined in _Standards for Efficient Cryptography_,
  * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
  * https://www.secg.org/sec2-v2.pdf
  */
 #define PSA_ECC_FAMILY_SECP_R1           ((psa_ecc_family_t) 0x12)
-/* SECP160R2 (SEC2 v1, obsolete) */
+/* SECP160R2 (SEC2 v1, obsolete, not supported in Mbed TLS) */
 #define PSA_ECC_FAMILY_SECP_R2           ((psa_ecc_family_t) 0x1b)
 
 /** SEC Koblitz curves over binary fields.
@@ -628,6 +625,8 @@
  * They are defined in _Standards for Efficient Cryptography_,
  * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
  * https://www.secg.org/sec2-v2.pdf
+ *
+ * \note Mbed TLS does not support any curve in this family.
  */
 #define PSA_ECC_FAMILY_SECT_K1           ((psa_ecc_family_t) 0x27)
 
@@ -638,6 +637,8 @@
  * They are defined in _Standards for Efficient Cryptography_,
  * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
  * https://www.secg.org/sec2-v2.pdf
+ *
+ * \note Mbed TLS does not support any curve in this family.
  */
 #define PSA_ECC_FAMILY_SECT_R1           ((psa_ecc_family_t) 0x22)
 
@@ -648,6 +649,8 @@
  * It is defined in _Standards for Efficient Cryptography_,
  * _SEC 2: Recommended Elliptic Curve Domain Parameters_.
  * https://www.secg.org/sec2-v2.pdf
+ *
+ * \note Mbed TLS does not support any curve in this family.
  */
 #define PSA_ECC_FAMILY_SECT_R2           ((psa_ecc_family_t) 0x2b)
 
@@ -657,6 +660,9 @@
  * brainpoolP160r1, brainpoolP192r1, brainpoolP224r1, brainpoolP256r1,
  * brainpoolP320r1, brainpoolP384r1, brainpoolP512r1.
  * It is defined in RFC 5639.
+ *
+ * \note Mbed TLS only supports the 256-bit, 384-bit and 512-bit curves
+ *       in this family.
  */
 #define PSA_ECC_FAMILY_BRAINPOOL_P_R1    ((psa_ecc_family_t) 0x30)
 
@@ -685,6 +691,8 @@
  * - 448-bit: Edwards448, the twisted Edwards curve birationally equivalent
  *   to Curve448.
  *   Hamburg, _Ed448-Goldilocks, a new elliptic curve_, NIST ECC Workshop, 2015.
+ *
+ * \note Mbed TLS does not support Edwards curves yet.
  */
 #define PSA_ECC_FAMILY_TWISTED_EDWARDS   ((psa_ecc_family_t) 0x42)
 
@@ -1748,6 +1756,13 @@
      0)
 
 /** RSA PKCS#1 v1.5 encryption.
+ *
+ * \warning     Calling psa_asymmetric_decrypt() with this algorithm as a
+ *              parameter is considered an inherently dangerous function
+ *              (CWE-242). Unless it is used in a side channel free and safe
+ *              way (eg. implementing the TLS protocol as per 7.4.7.1 of
+ *              RFC 5246), the calling code is vulnerable.
+ *
  */
 #define PSA_ALG_RSA_PKCS1V15_CRYPT              ((psa_algorithm_t) 0x07000200)
 
@@ -2102,7 +2117,8 @@
  */
 #define PSA_ALG_IS_PBKDF2_HMAC(alg)                                    \
     (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_PBKDF2_HMAC_BASE)
-
+#define PSA_ALG_PBKDF2_HMAC_GET_HASH(pbkdf2_alg)                         \
+    (PSA_ALG_CATEGORY_HASH | ((pbkdf2_alg) & PSA_ALG_HASH_MASK))
 /** The PBKDF2-AES-CMAC-PRF-128 password hashing / key stretching algorithm.
  *
  * PBKDF2 is defined by PKCS#5, republished as RFC 8018 (section 5.2).
@@ -2114,6 +2130,10 @@
  */
 #define PSA_ALG_PBKDF2_AES_CMAC_PRF_128         ((psa_algorithm_t) 0x08800200)
 
+#define PSA_ALG_IS_PBKDF2(kdf_alg)                                      \
+    (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg) || \
+     ((kdf_alg) == PSA_ALG_PBKDF2_AES_CMAC_PRF_128))
+
 #define PSA_ALG_KEY_DERIVATION_MASK             ((psa_algorithm_t) 0xfe00ffff)
 #define PSA_ALG_KEY_AGREEMENT_MASK              ((psa_algorithm_t) 0xffff0000)
 
diff --git a/lib/libmbedtls/mbedtls/library/aes.c b/lib/libmbedtls/mbedtls/library/aes.c
index 69da5828ac619ed837559df5c54b6bb1e11076b0..b1a5c3ed104827c7f25df8e35a8934b3fb89e77a 100644
--- a/lib/libmbedtls/mbedtls/library/aes.c
+++ b/lib/libmbedtls/mbedtls/library/aes.c
@@ -2,24 +2,12 @@
  *  FIPS-197 compliant AES implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
  *
- *  http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ *  https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf
  *  http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
  */
 
@@ -33,6 +21,27 @@
 #include "mbedtls/platform.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#if !((defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_AESCE_C)) || \
+    (defined(MBEDTLS_ARCH_IS_X64)       && defined(MBEDTLS_AESNI_C)) || \
+    (defined(MBEDTLS_ARCH_IS_X86)       && defined(MBEDTLS_AESNI_C)))
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
+#endif
+#endif
+
+#if defined(MBEDTLS_ARCH_IS_X86)
+#if defined(MBEDTLS_PADLOCK_C)
+#if !defined(MBEDTLS_HAVE_ASM)
+#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
+#endif
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \
+    "MBEDTLS_PADLOCK_C is set"
+#endif
+#endif
+#endif
+
 #if defined(MBEDTLS_PADLOCK_C)
 #include "padlock.h"
 #endif
@@ -44,10 +53,21 @@
 #endif
 
 #include "mbedtls/platform.h"
+#include "ctr.h"
+
+/*
+ * This is a convenience shorthand macro to check if we need reverse S-box and
+ * reverse tables. It's private and only defined in this file.
+ */
+#if (!defined(MBEDTLS_AES_DECRYPT_ALT) || \
+    (!defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY))) && \
+    !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+#define MBEDTLS_AES_NEED_REVERSE_TABLES
+#endif
 
 #if !defined(MBEDTLS_AES_ALT)
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
 static int aes_padlock_ace = -1;
 #endif
 
@@ -55,7 +75,7 @@ static int aes_padlock_ace = -1;
 /*
  * Forward S-box
  */
-static const unsigned char FSb[256] =
+MBEDTLS_MAYBE_UNUSED static const unsigned char FSb[256] =
 {
     0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
     0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
@@ -162,31 +182,27 @@ static const unsigned char FSb[256] =
     V(CB, B0, B0, 7B), V(FC, 54, 54, A8), V(D6, BB, BB, 6D), V(3A, 16, 16, 2C)
 
 #define V(a, b, c, d) 0x##a##b##c##d
-static const uint32_t FT0[256] = { FT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t FT0[256] = { FT };
 #undef V
 
-#if !defined(MBEDTLS_AES_FEWER_TABLES)
-
 #define V(a, b, c, d) 0x##b##c##d##a
-static const uint32_t FT1[256] = { FT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t FT1[256] = { FT };
 #undef V
 
 #define V(a, b, c, d) 0x##c##d##a##b
-static const uint32_t FT2[256] = { FT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t FT2[256] = { FT };
 #undef V
 
 #define V(a, b, c, d) 0x##d##a##b##c
-static const uint32_t FT3[256] = { FT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t FT3[256] = { FT };
 #undef V
 
-#endif /* !MBEDTLS_AES_FEWER_TABLES */
-
 #undef FT
 
 /*
  * Reverse S-box
  */
-static const unsigned char RSb[256] =
+MBEDTLS_MAYBE_UNUSED static const unsigned char RSb[256] =
 {
     0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
     0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
@@ -292,32 +308,29 @@ static const unsigned char RSb[256] =
     V(71, 01, A8, 39), V(DE, B3, 0C, 08), V(9C, E4, B4, D8), V(90, C1, 56, 64), \
     V(61, 84, CB, 7B), V(70, B6, 32, D5), V(74, 5C, 6C, 48), V(42, 57, B8, D0)
 
+
 #define V(a, b, c, d) 0x##a##b##c##d
-static const uint32_t RT0[256] = { RT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t RT0[256] = { RT };
 #undef V
 
-#if !defined(MBEDTLS_AES_FEWER_TABLES)
-
 #define V(a, b, c, d) 0x##b##c##d##a
-static const uint32_t RT1[256] = { RT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t RT1[256] = { RT };
 #undef V
 
 #define V(a, b, c, d) 0x##c##d##a##b
-static const uint32_t RT2[256] = { RT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t RT2[256] = { RT };
 #undef V
 
 #define V(a, b, c, d) 0x##d##a##b##c
-static const uint32_t RT3[256] = { RT };
+MBEDTLS_MAYBE_UNUSED static const uint32_t RT3[256] = { RT };
 #undef V
 
-#endif /* !MBEDTLS_AES_FEWER_TABLES */
-
 #undef RT
 
 /*
  * Round constants
  */
-static const uint32_t RCON[10] =
+MBEDTLS_MAYBE_UNUSED static const uint32_t round_constants[10] =
 {
     0x00000001, 0x00000002, 0x00000004, 0x00000008,
     0x00000010, 0x00000020, 0x00000040, 0x00000080,
@@ -329,29 +342,26 @@ static const uint32_t RCON[10] =
 /*
  * Forward S-box & tables
  */
-static unsigned char FSb[256];
-static uint32_t FT0[256];
-#if !defined(MBEDTLS_AES_FEWER_TABLES)
-static uint32_t FT1[256];
-static uint32_t FT2[256];
-static uint32_t FT3[256];
-#endif /* !MBEDTLS_AES_FEWER_TABLES */
+MBEDTLS_MAYBE_UNUSED static unsigned char FSb[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t FT0[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t FT1[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t FT2[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t FT3[256];
 
 /*
  * Reverse S-box & tables
  */
-static unsigned char RSb[256];
-static uint32_t RT0[256];
-#if !defined(MBEDTLS_AES_FEWER_TABLES)
-static uint32_t RT1[256];
-static uint32_t RT2[256];
-static uint32_t RT3[256];
-#endif /* !MBEDTLS_AES_FEWER_TABLES */
+MBEDTLS_MAYBE_UNUSED static unsigned char RSb[256];
+
+MBEDTLS_MAYBE_UNUSED static uint32_t RT0[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t RT1[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t RT2[256];
+MBEDTLS_MAYBE_UNUSED static uint32_t RT3[256];
 
 /*
  * Round constants
  */
-static uint32_t RCON[10];
+MBEDTLS_MAYBE_UNUSED static uint32_t round_constants[10];
 
 /*
  * Tables generation code
@@ -360,48 +370,53 @@ static uint32_t RCON[10];
 #define XTIME(x) (((x) << 1) ^ (((x) & 0x80) ? 0x1B : 0x00))
 #define MUL(x, y) (((x) && (y)) ? pow[(log[(x)]+log[(y)]) % 255] : 0)
 
-static int aes_init_done = 0;
+MBEDTLS_MAYBE_UNUSED static int aes_init_done = 0;
 
-static void aes_gen_tables(void)
+MBEDTLS_MAYBE_UNUSED static void aes_gen_tables(void)
 {
-    int i, x, y, z;
-    int pow[256];
-    int log[256];
+    int i;
+    uint8_t x, y, z;
+    uint8_t pow[256];
+    uint8_t log[256];
 
     /*
      * compute pow and log tables over GF(2^8)
      */
     for (i = 0, x = 1; i < 256; i++) {
         pow[i] = x;
-        log[x] = i;
-        x = MBEDTLS_BYTE_0(x ^ XTIME(x));
+        log[x] = (uint8_t) i;
+        x ^= XTIME(x);
     }
 
     /*
      * calculate the round constants
      */
     for (i = 0, x = 1; i < 10; i++) {
-        RCON[i] = (uint32_t) x;
-        x = MBEDTLS_BYTE_0(XTIME(x));
+        round_constants[i] = x;
+        x = XTIME(x);
     }
 
     /*
      * generate the forward and reverse S-boxes
      */
     FSb[0x00] = 0x63;
+#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)
     RSb[0x63] = 0x00;
+#endif
 
     for (i = 1; i < 256; i++) {
         x = pow[255 - log[i]];
 
-        y  = x; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
-        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
-        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
-        x ^= y; y = MBEDTLS_BYTE_0((y << 1) | (y >> 7));
+        y  = x; y = (y << 1) | (y >> 7);
+        x ^= y; y = (y << 1) | (y >> 7);
+        x ^= y; y = (y << 1) | (y >> 7);
+        x ^= y; y = (y << 1) | (y >> 7);
         x ^= y ^ 0x63;
 
-        FSb[i] = (unsigned char) x;
+        FSb[i] = x;
+#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)
         RSb[x] = (unsigned char) i;
+#endif
     }
 
     /*
@@ -409,8 +424,8 @@ static void aes_gen_tables(void)
      */
     for (i = 0; i < 256; i++) {
         x = FSb[i];
-        y = MBEDTLS_BYTE_0(XTIME(x));
-        z = MBEDTLS_BYTE_0(y ^ x);
+        y = XTIME(x);
+        z = y ^ x;
 
         FT0[i] = ((uint32_t) y) ^
                  ((uint32_t) x <<  8) ^
@@ -423,6 +438,7 @@ static void aes_gen_tables(void)
         FT3[i] = ROTL8(FT2[i]);
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
 
+#if defined(MBEDTLS_AES_NEED_REVERSE_TABLES)
         x = RSb[i];
 
         RT0[i] = ((uint32_t) MUL(0x0E, x)) ^
@@ -435,6 +451,7 @@ static void aes_gen_tables(void)
         RT2[i] = ROTL8(RT1[i]);
         RT3[i] = ROTL8(RT2[i]);
 #endif /* !MBEDTLS_AES_FEWER_TABLES */
+#endif /* MBEDTLS_AES_NEED_REVERSE_TABLES */
     }
 }
 
@@ -510,16 +527,17 @@ void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx)
  * Note that the offset is in units of elements of buf, i.e. 32-bit words,
  * i.e. an offset of 1 means 4 bytes and so on.
  */
-#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) ||        \
+#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) ||        \
     (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
 #define MAY_NEED_TO_ALIGN
 #endif
-static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
+
+MBEDTLS_MAYBE_UNUSED static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
 {
 #if defined(MAY_NEED_TO_ALIGN)
     int align_16_bytes = 0;
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace == -1) {
         aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
     }
@@ -558,13 +576,14 @@ static unsigned mbedtls_aes_rk_offset(uint32_t *buf)
 int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits)
 {
-    unsigned int i;
     uint32_t *RK;
 
     switch (keybits) {
         case 128: ctx->nr = 10; break;
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
         case 192: ctx->nr = 12; break;
         case 256: ctx->nr = 14; break;
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
         default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
 
@@ -584,21 +603,22 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
     }
 #endif
 
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-    if (mbedtls_aesce_has_support()) {
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
         return mbedtls_aesce_setkey_enc((unsigned char *) RK, key, keybits);
     }
 #endif
 
-    for (i = 0; i < (keybits >> 5); i++) {
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+    for (unsigned int i = 0; i < (keybits >> 5); i++) {
         RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
     }
 
     switch (ctx->nr) {
         case 10:
 
-            for (i = 0; i < 10; i++, RK += 4) {
-                RK[4]  = RK[0] ^ RCON[i] ^
+            for (unsigned int i = 0; i < 10; i++, RK += 4) {
+                RK[4]  = RK[0] ^ round_constants[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] <<  8) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[3])] << 16) ^
@@ -610,10 +630,11 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
             }
             break;
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
         case 12:
 
-            for (i = 0; i < 8; i++, RK += 6) {
-                RK[6]  = RK[0] ^ RCON[i] ^
+            for (unsigned int i = 0; i < 8; i++, RK += 6) {
+                RK[6]  = RK[0] ^ round_constants[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] <<  8) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[5])] << 16) ^
@@ -629,8 +650,8 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
 
         case 14:
 
-            for (i = 0; i < 7; i++, RK += 8) {
-                RK[8]  = RK[0] ^ RCON[i] ^
+            for (unsigned int i = 0; i < 7; i++, RK += 8) {
+                RK[8]  = RK[0] ^ round_constants[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] <<  8) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_3(RK[7])] << 16) ^
@@ -651,23 +672,28 @@ int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
                 RK[15] = RK[7] ^ RK[14];
             }
             break;
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
     }
 
     return 0;
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 }
 #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
 
 /*
  * AES key schedule (decryption)
  */
-#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT)
+#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits)
 {
-    int i, j, ret;
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+    uint32_t *SK;
+#endif
+    int ret;
     mbedtls_aes_context cty;
     uint32_t *RK;
-    uint32_t *SK;
+
 
     mbedtls_aes_init(&cty);
 
@@ -689,8 +715,8 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
     }
 #endif
 
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-    if (mbedtls_aesce_has_support()) {
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
         mbedtls_aesce_inverse_key(
             (unsigned char *) RK,
             (const unsigned char *) (cty.buf + cty.rk_offset),
@@ -699,15 +725,16 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
     }
 #endif
 
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
     SK = cty.buf + cty.rk_offset + cty.nr * 4;
 
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
-
-    for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
-        for (j = 0; j < 4; j++, SK++) {
+    SK -= 8;
+    for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) {
+        for (int j = 0; j < 4; j++, SK++) {
             *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^
                     AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^
                     AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^
@@ -719,13 +746,13 @@ int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
-
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 exit:
     mbedtls_aes_free(&cty);
 
     return ret;
 }
-#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */
+#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
 static int mbedtls_aes_xts_decode_keys(const unsigned char *key,
@@ -914,7 +941,7 @@ int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx,
 /*
  * AES-ECB block decryption
  */
-#if !defined(MBEDTLS_AES_DECRYPT_ALT)
+#if !defined(MBEDTLS_AES_DECRYPT_ALT) && !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
                                  const unsigned char input[16],
                                  unsigned char output[16])
@@ -971,9 +998,8 @@ int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
 
     return 0;
 }
-#endif /* !MBEDTLS_AES_DECRYPT_ALT */
+#endif /* !MBEDTLS_AES_DECRYPT_ALT && !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
-#if defined(MAY_NEED_TO_ALIGN)
 /* VIA Padlock and our intrinsics-based implementation of AESNI require
  * the round keys to be aligned on a 16-byte boundary. We take care of this
  * before creating them, but the AES context may have moved (this can happen
@@ -981,7 +1007,7 @@ int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx,
  * calls it might have a different alignment with respect to 16-byte memory.
  * So we may need to realign.
  */
-static void aes_maybe_realign(mbedtls_aes_context *ctx)
+MBEDTLS_MAYBE_UNUSED static void aes_maybe_realign(mbedtls_aes_context *ctx)
 {
     unsigned new_offset = mbedtls_aes_rk_offset(ctx->buf);
     if (new_offset != ctx->rk_offset) {
@@ -991,7 +1017,6 @@ static void aes_maybe_realign(mbedtls_aes_context *ctx)
         ctx->rk_offset = new_offset;
     }
 }
-#endif
 
 /*
  * AES-ECB block encryption/decryption
@@ -1015,26 +1040,32 @@ int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx,
     }
 #endif
 
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-    if (mbedtls_aesce_has_support()) {
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
         return mbedtls_aesce_crypt_ecb(ctx, mode, input, output);
     }
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace > 0) {
         return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
     }
 #endif
 
-    if (mode == MBEDTLS_AES_ENCRYPT) {
-        return mbedtls_internal_aes_encrypt(ctx, input, output);
-    } else {
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+    if (mode == MBEDTLS_AES_DECRYPT) {
         return mbedtls_internal_aes_decrypt(ctx, input, output);
+    } else
+#endif
+    {
+        return mbedtls_internal_aes_encrypt(ctx, input, output);
     }
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
+
 /*
  * AES-CBC buffer encryption/decryption
  */
@@ -1052,11 +1083,16 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
         return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
     }
 
+    /* Nothing to do if length is zero. */
+    if (length == 0) {
+        return 0;
+    }
+
     if (length % 16) {
         return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
     }
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace > 0) {
         if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {
             return 0;
@@ -1068,6 +1104,8 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
     }
 #endif
 
+    const unsigned char *ivp = iv;
+
     if (mode == MBEDTLS_AES_DECRYPT) {
         while (length > 0) {
             memcpy(temp, input, 16);
@@ -1075,8 +1113,10 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
             if (ret != 0) {
                 goto exit;
             }
-
-            mbedtls_xor(output, output, iv, 16);
+            /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on
+             * the result for the next block in CBC, and the cost of transferring that data from
+             * NEON registers, NEON is slower on aarch64. */
+            mbedtls_xor_no_simd(output, output, iv, 16);
 
             memcpy(iv, temp, 16);
 
@@ -1086,18 +1126,19 @@ int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx,
         }
     } else {
         while (length > 0) {
-            mbedtls_xor(output, input, iv, 16);
+            mbedtls_xor_no_simd(output, input, ivp, 16);
 
             ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output);
             if (ret != 0) {
                 goto exit;
             }
-            memcpy(iv, output, 16);
+            ivp = output;
 
             input  += 16;
             output += 16;
             length -= 16;
         }
+        memcpy(iv, ivp, 16);
     }
     ret = 0;
 
@@ -1118,8 +1159,11 @@ typedef unsigned char mbedtls_be128[16];
  * for machine endianness and hence works correctly on both big and little
  * endian machines.
  */
-static void mbedtls_gf128mul_x_ble(unsigned char r[16],
-                                   const unsigned char x[16])
+#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)
+MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
+#endif
+static inline void mbedtls_gf128mul_x_ble(unsigned char r[16],
+                                          const unsigned char x[16])
 {
     uint64_t a, b, ra, rb;
 
@@ -1135,7 +1179,13 @@ static void mbedtls_gf128mul_x_ble(unsigned char r[16],
 
 /*
  * AES-XTS buffer encryption/decryption
+ *
+ * Use of MBEDTLS_OPTIMIZE_FOR_PERFORMANCE here and for mbedtls_gf128mul_x_ble()
+ * is a 3x performance improvement for gcc -Os, if we have hardware AES support.
  */
+#if defined(MBEDTLS_AESCE_C) || defined(MBEDTLS_AESNI_C)
+MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
+#endif
 int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,
                           int mode,
                           size_t length,
@@ -1172,7 +1222,7 @@ int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx,
     }
 
     while (blocks--) {
-        if (leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0) {
+        if (MBEDTLS_UNLIKELY(leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0)) {
             /* We are on the last block in a decrypt operation that has
              * leftover bytes, so we need to use the next tweak for this block,
              * and this tweak for the leftover bytes. Save the current tweak for
@@ -1392,36 +1442,38 @@ int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx,
                           const unsigned char *input,
                           unsigned char *output)
 {
-    int c, i;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n;
 
-    n = *nc_off;
+    size_t offset = *nc_off;
 
-    if (n > 0x0F) {
+    if (offset > 0x0F) {
         return MBEDTLS_ERR_AES_BAD_INPUT_DATA;
     }
 
-    while (length--) {
-        if (n == 0) {
+    for (size_t i = 0; i < length;) {
+        size_t n = 16;
+        if (offset == 0) {
             ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block);
             if (ret != 0) {
                 goto exit;
             }
-
-            for (i = 16; i > 0; i--) {
-                if (++nonce_counter[i - 1] != 0) {
-                    break;
-                }
-            }
+            mbedtls_ctr_increment_counter(nonce_counter);
+        } else {
+            n -= offset;
         }
-        c = *input++;
-        *output++ = (unsigned char) (c ^ stream_block[n]);
 
-        n = (n + 1) & 0x0F;
+        if (n > (length - i)) {
+            n = (length - i);
+        }
+        mbedtls_xor(&output[i], &input[i], &stream_block[offset], n);
+        // offset might be non-zero for the last block, but in that case, we don't use it again
+        offset = 0;
+        i += n;
     }
 
-    *nc_off = n;
+    // capture offset for future resumption
+    *nc_off = (*nc_off + length) % 16;
+
     ret = 0;
 
 exit:
@@ -1437,45 +1489,55 @@ exit:
  *
  * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip
  */
-static const unsigned char aes_test_ecb_dec[3][16] =
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+static const unsigned char aes_test_ecb_dec[][16] =
 {
     { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
       0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
       0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 },
     { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
       0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE }
+#endif
 };
+#endif
 
-static const unsigned char aes_test_ecb_enc[3][16] =
+static const unsigned char aes_test_ecb_enc[][16] =
 {
     { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
       0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
       0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 },
     { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
       0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 }
+#endif
 };
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-static const unsigned char aes_test_cbc_dec[3][16] =
+static const unsigned char aes_test_cbc_dec[][16] =
 {
     { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73,
       0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75,
       0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B },
     { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75,
       0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 }
+#endif
 };
 
-static const unsigned char aes_test_cbc_enc[3][16] =
+static const unsigned char aes_test_cbc_enc[][16] =
 {
     { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84,
       0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB,
       0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 },
     { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5,
       0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 }
+#endif
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1485,10 +1547,11 @@ static const unsigned char aes_test_cbc_enc[3][16] =
  *
  * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
  */
-static const unsigned char aes_test_cfb128_key[3][32] =
+static const unsigned char aes_test_cfb128_key[][32] =
 {
     { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
       0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
       0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
       0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
@@ -1496,6 +1559,7 @@ static const unsigned char aes_test_cfb128_key[3][32] =
       0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
       0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
       0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+#endif
 };
 
 static const unsigned char aes_test_cfb128_iv[16] =
@@ -1516,7 +1580,7 @@ static const unsigned char aes_test_cfb128_pt[64] =
     0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
 };
 
-static const unsigned char aes_test_cfb128_ct[3][64] =
+static const unsigned char aes_test_cfb128_ct[][64] =
 {
     { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
       0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
@@ -1526,6 +1590,7 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
       0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF,
       0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E,
       0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
       0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
       0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21,
@@ -1542,6 +1607,7 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
       0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9,
       0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8,
       0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 }
+#endif
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
@@ -1551,10 +1617,11 @@ static const unsigned char aes_test_cfb128_ct[3][64] =
  *
  * https://csrc.nist.gov/publications/detail/sp/800-38a/final
  */
-static const unsigned char aes_test_ofb_key[3][32] =
+static const unsigned char aes_test_ofb_key[][32] =
 {
     { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6,
       0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52,
       0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5,
       0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B },
@@ -1562,6 +1629,7 @@ static const unsigned char aes_test_ofb_key[3][32] =
       0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
       0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
       0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 }
+#endif
 };
 
 static const unsigned char aes_test_ofb_iv[16] =
@@ -1582,7 +1650,7 @@ static const unsigned char aes_test_ofb_pt[64] =
     0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10
 };
 
-static const unsigned char aes_test_ofb_ct[3][64] =
+static const unsigned char aes_test_ofb_ct[][64] =
 {
     { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20,
       0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A,
@@ -1592,6 +1660,7 @@ static const unsigned char aes_test_ofb_ct[3][64] =
       0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc,
       0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78,
       0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB,
       0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74,
       0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c,
@@ -1608,6 +1677,7 @@ static const unsigned char aes_test_ofb_ct[3][64] =
       0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08,
       0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8,
       0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 }
+#endif
 };
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
@@ -1618,7 +1688,7 @@ static const unsigned char aes_test_ofb_ct[3][64] =
  * http://www.faqs.org/rfcs/rfc3686.html
  */
 
-static const unsigned char aes_test_ctr_key[3][16] =
+static const unsigned char aes_test_ctr_key[][16] =
 {
     { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC,
       0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E },
@@ -1628,7 +1698,7 @@ static const unsigned char aes_test_ctr_key[3][16] =
       0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC }
 };
 
-static const unsigned char aes_test_ctr_nonce_counter[3][16] =
+static const unsigned char aes_test_ctr_nonce_counter[][16] =
 {
     { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
@@ -1638,11 +1708,10 @@ static const unsigned char aes_test_ctr_nonce_counter[3][16] =
       0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 }
 };
 
-static const unsigned char aes_test_ctr_pt[3][48] =
+static const unsigned char aes_test_ctr_pt[][48] =
 {
     { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62,
       0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 },
-
     { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
       0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
@@ -1655,7 +1724,7 @@ static const unsigned char aes_test_ctr_pt[3][48] =
       0x20, 0x21, 0x22, 0x23 }
 };
 
-static const unsigned char aes_test_ctr_ct[3][48] =
+static const unsigned char aes_test_ctr_ct[][48] =
 {
     { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79,
       0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 },
@@ -1779,312 +1848,359 @@ int mbedtls_aes_self_test(int verbose)
 #if defined(MBEDTLS_AES_ALT)
         mbedtls_printf("  AES note: alternative implementation.\n");
 #else /* MBEDTLS_AES_ALT */
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
-        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
-            mbedtls_printf("  AES note: using VIA Padlock.\n");
-        } else
-#endif
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
+#if MBEDTLS_AESNI_HAVE_CODE == 1
+        mbedtls_printf("  AES note: AESNI code present (assembly implementation).\n");
+#elif MBEDTLS_AESNI_HAVE_CODE == 2
+        mbedtls_printf("  AES note: AESNI code present (intrinsics implementation).\n");
+#else
+#error "Unrecognised value for MBEDTLS_AESNI_HAVE_CODE"
+#endif
         if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) {
             mbedtls_printf("  AES note: using AESNI.\n");
         } else
 #endif
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-        if (mbedtls_aesce_has_support()) {
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
+        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
+            mbedtls_printf("  AES note: using VIA Padlock.\n");
+        } else
+#endif
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+        if (MBEDTLS_AESCE_HAS_SUPPORT()) {
             mbedtls_printf("  AES note: using AESCE.\n");
         } else
 #endif
-        mbedtls_printf("  AES note: built-in implementation.\n");
+        {
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+            mbedtls_printf("  AES note: built-in implementation.\n");
+#endif
+        }
 #endif /* MBEDTLS_AES_ALT */
     }
 
     /*
      * ECB mode
      */
-    for (i = 0; i < 6; i++) {
-        u = i >> 1;
-        keybits = 128 + u * 64;
-        mode = i & 1;
+    {
+        static const int num_tests =
+            sizeof(aes_test_ecb_enc) / sizeof(*aes_test_ecb_enc);
 
-        if (verbose != 0) {
-            mbedtls_printf("  AES-ECB-%3u (%s): ", keybits,
-                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
-        }
+        for (i = 0; i < num_tests << 1; i++) {
+            u = i >> 1;
+            keybits = 128 + u * 64;
+            mode = i & 1;
 
-        memset(buf, 0, 16);
+            if (verbose != 0) {
+                mbedtls_printf("  AES-ECB-%3u (%s): ", keybits,
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                if (verbose != 0) {
+                    mbedtls_printf("skipped\n");
+                }
+                continue;
+            }
+#endif
 
-        if (mode == MBEDTLS_AES_DECRYPT) {
-            ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
-            aes_tests = aes_test_ecb_dec[u];
-        } else {
-            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
-            aes_tests = aes_test_ecb_enc[u];
-        }
+            memset(buf, 0, 16);
 
-        /*
-         * AES-192 is an optional feature that may be unavailable when
-         * there is an alternative underlying implementation i.e. when
-         * MBEDTLS_AES_ALT is defined.
-         */
-        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
-            mbedtls_printf("skipped\n");
-            continue;
-        } else if (ret != 0) {
-            goto exit;
-        }
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
+                aes_tests = aes_test_ecb_dec[u];
+            } else
+#endif
+            {
+                ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
+                aes_tests = aes_test_ecb_enc[u];
+            }
 
-        for (j = 0; j < 10000; j++) {
-            ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf);
-            if (ret != 0) {
+            /*
+             * AES-192 is an optional feature that may be unavailable when
+             * there is an alternative underlying implementation i.e. when
+             * MBEDTLS_AES_ALT is defined.
+             */
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+                mbedtls_printf("skipped\n");
+                continue;
+            } else if (ret != 0) {
                 goto exit;
             }
-        }
 
-        if (memcmp(buf, aes_tests, 16) != 0) {
-            ret = 1;
-            goto exit;
+            for (j = 0; j < 10000; j++) {
+                ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf);
+                if (ret != 0) {
+                    goto exit;
+                }
+            }
+
+            if (memcmp(buf, aes_tests, 16) != 0) {
+                ret = 1;
+                goto exit;
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
 
         if (verbose != 0) {
-            mbedtls_printf("passed\n");
+            mbedtls_printf("\n");
         }
     }
 
-    if (verbose != 0) {
-        mbedtls_printf("\n");
-    }
-
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     /*
      * CBC mode
      */
-    for (i = 0; i < 6; i++) {
-        u = i >> 1;
-        keybits = 128 + u * 64;
-        mode = i & 1;
+    {
+        static const int num_tests =
+            sizeof(aes_test_cbc_dec) / sizeof(*aes_test_cbc_dec);
 
-        if (verbose != 0) {
-            mbedtls_printf("  AES-CBC-%3u (%s): ", keybits,
-                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
-        }
+        for (i = 0; i < num_tests << 1; i++) {
+            u = i >> 1;
+            keybits = 128 + u * 64;
+            mode = i & 1;
 
-        memset(iv, 0, 16);
-        memset(prv, 0, 16);
-        memset(buf, 0, 16);
+            if (verbose != 0) {
+                mbedtls_printf("  AES-CBC-%3u (%s): ", keybits,
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
 
-        if (mode == MBEDTLS_AES_DECRYPT) {
-            ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
-            aes_tests = aes_test_cbc_dec[u];
-        } else {
-            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
-            aes_tests = aes_test_cbc_enc[u];
-        }
+            memset(iv, 0, 16);
+            memset(prv, 0, 16);
+            memset(buf, 0, 16);
 
-        /*
-         * AES-192 is an optional feature that may be unavailable when
-         * there is an alternative underlying implementation i.e. when
-         * MBEDTLS_AES_ALT is defined.
-         */
-        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
-            mbedtls_printf("skipped\n");
-            continue;
-        } else if (ret != 0) {
-            goto exit;
-        }
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                ret = mbedtls_aes_setkey_dec(&ctx, key, keybits);
+                aes_tests = aes_test_cbc_dec[u];
+            } else {
+                ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
+                aes_tests = aes_test_cbc_enc[u];
+            }
+
+            /*
+             * AES-192 is an optional feature that may be unavailable when
+             * there is an alternative underlying implementation i.e. when
+             * MBEDTLS_AES_ALT is defined.
+             */
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+                mbedtls_printf("skipped\n");
+                continue;
+            } else if (ret != 0) {
+                goto exit;
+            }
 
-        for (j = 0; j < 10000; j++) {
-            if (mode == MBEDTLS_AES_ENCRYPT) {
-                unsigned char tmp[16];
+            for (j = 0; j < 10000; j++) {
+                if (mode == MBEDTLS_AES_ENCRYPT) {
+                    unsigned char tmp[16];
+
+                    memcpy(tmp, prv, 16);
+                    memcpy(prv, buf, 16);
+                    memcpy(buf, tmp, 16);
+                }
+
+                ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf);
+                if (ret != 0) {
+                    goto exit;
+                }
 
-                memcpy(tmp, prv, 16);
-                memcpy(prv, buf, 16);
-                memcpy(buf, tmp, 16);
             }
 
-            ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf);
-            if (ret != 0) {
+            if (memcmp(buf, aes_tests, 16) != 0) {
+                ret = 1;
                 goto exit;
             }
 
-        }
-
-        if (memcmp(buf, aes_tests, 16) != 0) {
-            ret = 1;
-            goto exit;
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
 
         if (verbose != 0) {
-            mbedtls_printf("passed\n");
+            mbedtls_printf("\n");
         }
     }
-
-    if (verbose != 0) {
-        mbedtls_printf("\n");
-    }
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     /*
      * CFB128 mode
      */
-    for (i = 0; i < 6; i++) {
-        u = i >> 1;
-        keybits = 128 + u * 64;
-        mode = i & 1;
+    {
+        static const int num_tests =
+            sizeof(aes_test_cfb128_key) / sizeof(*aes_test_cfb128_key);
 
-        if (verbose != 0) {
-            mbedtls_printf("  AES-CFB128-%3u (%s): ", keybits,
-                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
-        }
+        for (i = 0; i < num_tests << 1; i++) {
+            u = i >> 1;
+            keybits = 128 + u * 64;
+            mode = i & 1;
 
-        memcpy(iv,  aes_test_cfb128_iv, 16);
-        memcpy(key, aes_test_cfb128_key[u], keybits / 8);
+            if (verbose != 0) {
+                mbedtls_printf("  AES-CFB128-%3u (%s): ", keybits,
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
 
-        offset = 0;
-        ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
-        /*
-         * AES-192 is an optional feature that may be unavailable when
-         * there is an alternative underlying implementation i.e. when
-         * MBEDTLS_AES_ALT is defined.
-         */
-        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
-            mbedtls_printf("skipped\n");
-            continue;
-        } else if (ret != 0) {
-            goto exit;
-        }
+            memcpy(iv,  aes_test_cfb128_iv, 16);
+            memcpy(key, aes_test_cfb128_key[u], keybits / 8);
 
-        if (mode == MBEDTLS_AES_DECRYPT) {
-            memcpy(buf, aes_test_cfb128_ct[u], 64);
-            aes_tests = aes_test_cfb128_pt;
-        } else {
-            memcpy(buf, aes_test_cfb128_pt, 64);
-            aes_tests = aes_test_cfb128_ct[u];
-        }
+            offset = 0;
+            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
+            /*
+             * AES-192 is an optional feature that may be unavailable when
+             * there is an alternative underlying implementation i.e. when
+             * MBEDTLS_AES_ALT is defined.
+             */
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+                mbedtls_printf("skipped\n");
+                continue;
+            } else if (ret != 0) {
+                goto exit;
+            }
 
-        ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf);
-        if (ret != 0) {
-            goto exit;
-        }
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                memcpy(buf, aes_test_cfb128_ct[u], 64);
+                aes_tests = aes_test_cfb128_pt;
+            } else {
+                memcpy(buf, aes_test_cfb128_pt, 64);
+                aes_tests = aes_test_cfb128_ct[u];
+            }
 
-        if (memcmp(buf, aes_tests, 64) != 0) {
-            ret = 1;
-            goto exit;
+            ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf);
+            if (ret != 0) {
+                goto exit;
+            }
+
+            if (memcmp(buf, aes_tests, 64) != 0) {
+                ret = 1;
+                goto exit;
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
 
         if (verbose != 0) {
-            mbedtls_printf("passed\n");
+            mbedtls_printf("\n");
         }
     }
-
-    if (verbose != 0) {
-        mbedtls_printf("\n");
-    }
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
     /*
      * OFB mode
      */
-    for (i = 0; i < 6; i++) {
-        u = i >> 1;
-        keybits = 128 + u * 64;
-        mode = i & 1;
+    {
+        static const int num_tests =
+            sizeof(aes_test_ofb_key) / sizeof(*aes_test_ofb_key);
 
-        if (verbose != 0) {
-            mbedtls_printf("  AES-OFB-%3u (%s): ", keybits,
-                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
-        }
+        for (i = 0; i < num_tests << 1; i++) {
+            u = i >> 1;
+            keybits = 128 + u * 64;
+            mode = i & 1;
+
+            if (verbose != 0) {
+                mbedtls_printf("  AES-OFB-%3u (%s): ", keybits,
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
 
-        memcpy(iv,  aes_test_ofb_iv, 16);
-        memcpy(key, aes_test_ofb_key[u], keybits / 8);
+            memcpy(iv,  aes_test_ofb_iv, 16);
+            memcpy(key, aes_test_ofb_key[u], keybits / 8);
 
-        offset = 0;
-        ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
-        /*
-         * AES-192 is an optional feature that may be unavailable when
-         * there is an alternative underlying implementation i.e. when
-         * MBEDTLS_AES_ALT is defined.
-         */
-        if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
-            mbedtls_printf("skipped\n");
-            continue;
-        } else if (ret != 0) {
-            goto exit;
-        }
+            offset = 0;
+            ret = mbedtls_aes_setkey_enc(&ctx, key, keybits);
+            /*
+             * AES-192 is an optional feature that may be unavailable when
+             * there is an alternative underlying implementation i.e. when
+             * MBEDTLS_AES_ALT is defined.
+             */
+            if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) {
+                mbedtls_printf("skipped\n");
+                continue;
+            } else if (ret != 0) {
+                goto exit;
+            }
 
-        if (mode == MBEDTLS_AES_DECRYPT) {
-            memcpy(buf, aes_test_ofb_ct[u], 64);
-            aes_tests = aes_test_ofb_pt;
-        } else {
-            memcpy(buf, aes_test_ofb_pt, 64);
-            aes_tests = aes_test_ofb_ct[u];
-        }
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                memcpy(buf, aes_test_ofb_ct[u], 64);
+                aes_tests = aes_test_ofb_pt;
+            } else {
+                memcpy(buf, aes_test_ofb_pt, 64);
+                aes_tests = aes_test_ofb_ct[u];
+            }
 
-        ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf);
-        if (ret != 0) {
-            goto exit;
-        }
+            ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf);
+            if (ret != 0) {
+                goto exit;
+            }
 
-        if (memcmp(buf, aes_tests, 64) != 0) {
-            ret = 1;
-            goto exit;
+            if (memcmp(buf, aes_tests, 64) != 0) {
+                ret = 1;
+                goto exit;
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
 
         if (verbose != 0) {
-            mbedtls_printf("passed\n");
+            mbedtls_printf("\n");
         }
     }
-
-    if (verbose != 0) {
-        mbedtls_printf("\n");
-    }
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     /*
      * CTR mode
      */
-    for (i = 0; i < 6; i++) {
-        u = i >> 1;
-        mode = i & 1;
+    {
+        static const int num_tests =
+            sizeof(aes_test_ctr_key) / sizeof(*aes_test_ctr_key);
 
-        if (verbose != 0) {
-            mbedtls_printf("  AES-CTR-128 (%s): ",
-                           (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
-        }
+        for (i = 0; i < num_tests << 1; i++) {
+            u = i >> 1;
+            mode = i & 1;
 
-        memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16);
-        memcpy(key, aes_test_ctr_key[u], 16);
+            if (verbose != 0) {
+                mbedtls_printf("  AES-CTR-128 (%s): ",
+                               (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc");
+            }
 
-        offset = 0;
-        if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) {
-            goto exit;
-        }
+            memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16);
+            memcpy(key, aes_test_ctr_key[u], 16);
 
-        len = aes_test_ctr_len[u];
+            offset = 0;
+            if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) {
+                goto exit;
+            }
 
-        if (mode == MBEDTLS_AES_DECRYPT) {
-            memcpy(buf, aes_test_ctr_ct[u], len);
-            aes_tests = aes_test_ctr_pt[u];
-        } else {
-            memcpy(buf, aes_test_ctr_pt[u], len);
-            aes_tests = aes_test_ctr_ct[u];
-        }
+            len = aes_test_ctr_len[u];
 
-        ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter,
-                                    stream_block, buf, buf);
-        if (ret != 0) {
-            goto exit;
-        }
+            if (mode == MBEDTLS_AES_DECRYPT) {
+                memcpy(buf, aes_test_ctr_ct[u], len);
+                aes_tests = aes_test_ctr_pt[u];
+            } else {
+                memcpy(buf, aes_test_ctr_pt[u], len);
+                aes_tests = aes_test_ctr_ct[u];
+            }
 
-        if (memcmp(buf, aes_tests, len) != 0) {
-            ret = 1;
-            goto exit;
-        }
+            ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter,
+                                        stream_block, buf, buf);
+            if (ret != 0) {
+                goto exit;
+            }
 
-        if (verbose != 0) {
-            mbedtls_printf("passed\n");
+            if (memcmp(buf, aes_tests, len) != 0) {
+                ret = 1;
+                goto exit;
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf("passed\n");
+            }
         }
     }
 
@@ -2094,14 +2210,14 @@ int mbedtls_aes_self_test(int verbose)
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
+    /*
+     * XTS mode
+     */
     {
         static const int num_tests =
             sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
         mbedtls_aes_xts_context ctx_xts;
 
-        /*
-         * XTS mode
-         */
         mbedtls_aes_xts_init(&ctx_xts);
 
         for (i = 0; i < num_tests << 1; i++) {
diff --git a/lib/libmbedtls/mbedtls/library/aesce.c b/lib/libmbedtls/mbedtls/library/aesce.c
index fe056dc4c0640dd0cefd1866c80b278a10381243..6a9e0a1c6bd03f3a23a22b874597faa8b13a308c 100644
--- a/lib/libmbedtls/mbedtls/library/aesce.c
+++ b/lib/libmbedtls/mbedtls/library/aesce.c
@@ -2,23 +2,20 @@
  *  Armv8-A Cryptographic Extension support functions for Aarch64
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
-    defined(__clang__) && __clang_major__ >= 4
+#if defined(__clang__) &&  (__clang_major__ >= 4)
+
+/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,
+ * but that is defined by build_info.h, and we need this block to happen first. */
+#if defined(__ARM_ARCH)
+#if __ARM_ARCH >= 8
+#define MBEDTLS_AESCE_ARCH_IS_ARMV8_A
+#endif
+#endif
+
+#if defined(MBEDTLS_AESCE_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)
 /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
  *
  * The intrinsic declaration are guarded by predefined ACLE macros in clang:
@@ -26,7 +23,7 @@
  * By defining the macros ourselves we gain access to those declarations without
  * requiring -march on the command line.
  *
- * `arm_neon.h` could be included by any header file, so we put these defines
+ * `arm_neon.h` is included by common.h, so we put these defines
  * at the top of this file, before any includes.
  */
 #define __ARM_FEATURE_CRYPTO 1
@@ -39,6 +36,8 @@
 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
 #endif
 
+#endif /* defined(__clang__) &&  (__clang_major__ >= 4) */
+
 #include <string.h>
 #include "common.h"
 
@@ -46,105 +45,219 @@
 
 #include "aesce.h"
 
-#if defined(MBEDTLS_HAVE_ARM64)
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
 
-#if !defined(__ARM_FEATURE_AES) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
-#   if defined(__clang__)
-#       if __clang_major__ < 4
-#           error "A more recent Clang is required for MBEDTLS_AESCE_C"
+/* Compiler version checks. */
+#if defined(__clang__)
+#   if defined(MBEDTLS_ARCH_IS_ARM32) && (__clang_major__ < 11)
+#       error "Minimum version of Clang for MBEDTLS_AESCE_C on 32-bit Arm or Thumb is 11.0."
+#   elif defined(MBEDTLS_ARCH_IS_ARM64) && (__clang_major__ < 4)
+#       error "Minimum version of Clang for MBEDTLS_AESCE_C on aarch64 is 4.0."
+#   endif
+#elif defined(__GNUC__)
+#   if __GNUC__ < 6
+#       error "Minimum version of GCC for MBEDTLS_AESCE_C is 6.0."
+#   endif
+#elif defined(_MSC_VER)
+/* TODO: We haven't verified MSVC from 1920 to 1928. If someone verified that,
+ *       please update this and document of `MBEDTLS_AESCE_C` in
+ *       `mbedtls_config.h`. */
+#   if _MSC_VER < 1929
+#       error "Minimum version of MSVC for MBEDTLS_AESCE_C is 2019 version 16.11.2."
+#   endif
+#elif defined(__ARMCC_VERSION)
+#    if defined(MBEDTLS_ARCH_IS_ARM32) && (__ARMCC_VERSION < 6200002)
+/* TODO: We haven't verified armclang for 32-bit Arm/Thumb prior to 6.20.
+ * If someone verified that, please update this and document of
+ * `MBEDTLS_AESCE_C` in `mbedtls_config.h`. */
+#         error "Minimum version of armclang for MBEDTLS_AESCE_C on 32-bit Arm is 6.20."
+#    elif defined(MBEDTLS_ARCH_IS_ARM64) && (__ARMCC_VERSION < 6060000)
+#         error "Minimum version of armclang for MBEDTLS_AESCE_C on aarch64 is 6.6."
+#    endif
+#endif
+
+#if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \
+    defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
+#   if defined(__ARMCOMPILER_VERSION)
+#       if __ARMCOMPILER_VERSION <= 6090000
+#           error "Must use minimum -march=armv8-a+crypto for MBEDTLS_AESCE_C"
+#       else
+#           pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
+#           define MBEDTLS_POP_TARGET_PRAGMA
 #       endif
-#       pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
+#   elif defined(__clang__)
+#       pragma clang attribute push (__attribute__((target("aes"))), apply_to=function)
 #       define MBEDTLS_POP_TARGET_PRAGMA
 #   elif defined(__GNUC__)
-#       if __GNUC__ < 6
-#           error "A more recent GCC is required for MBEDTLS_AESCE_C"
-#       endif
 #       pragma GCC push_options
-#       pragma GCC target ("arch=armv8-a+crypto")
+#       pragma GCC target ("+crypto")
 #       define MBEDTLS_POP_TARGET_PRAGMA
-#   else
-#       error "Only GCC and Clang supported for MBEDTLS_AESCE_C"
+#   elif defined(_MSC_VER)
+#       error "Required feature(__ARM_FEATURE_AES) is not enabled."
 #   endif
-#endif /* !__ARM_FEATURE_AES || MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
+#endif /* !(__ARM_FEATURE_CRYPTO || __ARM_FEATURE_AES) ||
+          MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG */
 
-#include <arm_neon.h>
+#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 
-#if defined(__linux__)
-#include <asm/hwcap.h>
 #include <sys/auxv.h>
+#if !defined(HWCAP_NEON)
+#define HWCAP_NEON  (1 << 12)
+#endif
+#if !defined(HWCAP2_AES)
+#define HWCAP2_AES  (1 << 0)
+#endif
+#if !defined(HWCAP_AES)
+#define HWCAP_AES   (1 << 3)
+#endif
+#if !defined(HWCAP_ASIMD)
+#define HWCAP_ASIMD (1 << 1)
 #endif
 
+signed char mbedtls_aesce_has_support_result = -1;
+
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 /*
  * AES instruction support detection routine
  */
-int mbedtls_aesce_has_support(void)
+int mbedtls_aesce_has_support_impl(void)
 {
-#if defined(__linux__)
-    unsigned long auxval = getauxval(AT_HWCAP);
-    return (auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
-           (HWCAP_ASIMD | HWCAP_AES);
+    /* To avoid many calls to getauxval, cache the result. This is
+     * thread-safe, because we store the result in a char so cannot
+     * be vulnerable to non-atomic updates.
+     * It is possible that we could end up setting result more than
+     * once, but that is harmless.
+     */
+    if (mbedtls_aesce_has_support_result == -1) {
+#if defined(MBEDTLS_ARCH_IS_ARM32)
+        unsigned long auxval  = getauxval(AT_HWCAP);
+        unsigned long auxval2 = getauxval(AT_HWCAP2);
+        if (((auxval  & HWCAP_NEON) == HWCAP_NEON) &&
+            ((auxval2 & HWCAP2_AES) == HWCAP2_AES)) {
+            mbedtls_aesce_has_support_result = 1;
+        } else {
+            mbedtls_aesce_has_support_result = 0;
+        }
 #else
-    /* Assume AES instructions are supported. */
-    return 1;
+        unsigned long auxval = getauxval(AT_HWCAP);
+        if ((auxval & (HWCAP_ASIMD | HWCAP_AES)) ==
+            (HWCAP_ASIMD | HWCAP_AES)) {
+            mbedtls_aesce_has_support_result = 1;
+        } else {
+            mbedtls_aesce_has_support_result = 0;
+        }
 #endif
+    }
+    return mbedtls_aesce_has_support_result;
 }
+#endif
+
+#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
 
+/* Single round of AESCE encryption */
+#define AESCE_ENCRYPT_ROUND                   \
+    block = vaeseq_u8(block, vld1q_u8(keys)); \
+    block = vaesmcq_u8(block);                \
+    keys += 16
+/* Two rounds of AESCE encryption */
+#define AESCE_ENCRYPT_ROUND_X2        AESCE_ENCRYPT_ROUND; AESCE_ENCRYPT_ROUND
+
+MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
 static uint8x16_t aesce_encrypt_block(uint8x16_t block,
                                       unsigned char *keys,
                                       int rounds)
 {
-    for (int i = 0; i < rounds - 1; i++) {
-        /* AES AddRoundKey, SubBytes, ShiftRows (in this order).
-         * AddRoundKey adds the round key for the previous round. */
-        block = vaeseq_u8(block, vld1q_u8(keys + i * 16));
-        /* AES mix columns */
-        block = vaesmcq_u8(block);
+    /* 10, 12 or 14 rounds. Unroll loop. */
+    if (rounds == 10) {
+        goto rounds_10;
+    }
+    if (rounds == 12) {
+        goto rounds_12;
     }
+    AESCE_ENCRYPT_ROUND_X2;
+rounds_12:
+    AESCE_ENCRYPT_ROUND_X2;
+rounds_10:
+    AESCE_ENCRYPT_ROUND_X2;
+    AESCE_ENCRYPT_ROUND_X2;
+    AESCE_ENCRYPT_ROUND_X2;
+    AESCE_ENCRYPT_ROUND_X2;
+    AESCE_ENCRYPT_ROUND;
 
     /* AES AddRoundKey for the previous round.
      * SubBytes, ShiftRows for the final round.  */
-    block = vaeseq_u8(block, vld1q_u8(keys + (rounds -1) * 16));
+    block = vaeseq_u8(block, vld1q_u8(keys));
+    keys += 16;
 
     /* Final round: no MixColumns */
 
     /* Final AddRoundKey */
-    block = veorq_u8(block, vld1q_u8(keys + rounds  * 16));
+    block = veorq_u8(block, vld1q_u8(keys));
 
     return block;
 }
 
+/* Single round of AESCE decryption
+ *
+ * AES AddRoundKey, SubBytes, ShiftRows
+ *
+ *      block = vaesdq_u8(block, vld1q_u8(keys));
+ *
+ * AES inverse MixColumns for the next round.
+ *
+ * This means that we switch the order of the inverse AddRoundKey and
+ * inverse MixColumns operations. We have to do this as AddRoundKey is
+ * done in an atomic instruction together with the inverses of SubBytes
+ * and ShiftRows.
+ *
+ * It works because MixColumns is a linear operation over GF(2^8) and
+ * AddRoundKey is an exclusive or, which is equivalent to addition over
+ * GF(2^8). (The inverse of MixColumns needs to be applied to the
+ * affected round keys separately which has been done when the
+ * decryption round keys were calculated.)
+ *
+ *      block = vaesimcq_u8(block);
+ */
+#define AESCE_DECRYPT_ROUND                   \
+    block = vaesdq_u8(block, vld1q_u8(keys)); \
+    block = vaesimcq_u8(block);               \
+    keys += 16
+/* Two rounds of AESCE decryption */
+#define AESCE_DECRYPT_ROUND_X2        AESCE_DECRYPT_ROUND; AESCE_DECRYPT_ROUND
+
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 static uint8x16_t aesce_decrypt_block(uint8x16_t block,
                                       unsigned char *keys,
                                       int rounds)
 {
-
-    for (int i = 0; i < rounds - 1; i++) {
-        /* AES AddRoundKey, SubBytes, ShiftRows */
-        block = vaesdq_u8(block, vld1q_u8(keys + i * 16));
-        /* AES inverse MixColumns for the next round.
-         *
-         * This means that we switch the order of the inverse AddRoundKey and
-         * inverse MixColumns operations. We have to do this as AddRoundKey is
-         * done in an atomic instruction together with the inverses of SubBytes
-         * and ShiftRows.
-         *
-         * It works because MixColumns is a linear operation over GF(2^8) and
-         * AddRoundKey is an exclusive or, which is equivalent to addition over
-         * GF(2^8). (The inverse of MixColumns needs to be applied to the
-         * affected round keys separately which has been done when the
-         * decryption round keys were calculated.) */
-        block = vaesimcq_u8(block);
+    /* 10, 12 or 14 rounds. Unroll loop. */
+    if (rounds == 10) {
+        goto rounds_10;
+    }
+    if (rounds == 12) {
+        goto rounds_12;
     }
+    AESCE_DECRYPT_ROUND_X2;
+rounds_12:
+    AESCE_DECRYPT_ROUND_X2;
+rounds_10:
+    AESCE_DECRYPT_ROUND_X2;
+    AESCE_DECRYPT_ROUND_X2;
+    AESCE_DECRYPT_ROUND_X2;
+    AESCE_DECRYPT_ROUND_X2;
+    AESCE_DECRYPT_ROUND;
 
     /* The inverses of AES AddRoundKey, SubBytes, ShiftRows finishing up the
      * last full round. */
-    block = vaesdq_u8(block, vld1q_u8(keys + (rounds - 1) * 16));
+    block = vaesdq_u8(block, vld1q_u8(keys));
+    keys += 16;
 
     /* Inverse AddRoundKey for inverting the initial round key addition. */
-    block = veorq_u8(block, vld1q_u8(keys + rounds * 16));
+    block = veorq_u8(block, vld1q_u8(keys));
 
     return block;
 }
+#endif
 
 /*
  * AES-ECB block en(de)cryption
@@ -157,10 +270,15 @@ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
     uint8x16_t block = vld1q_u8(&input[0]);
     unsigned char *keys = (unsigned char *) (ctx->buf + ctx->rk_offset);
 
-    if (mode == MBEDTLS_AES_ENCRYPT) {
-        block = aesce_encrypt_block(block, keys, ctx->nr);
-    } else {
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+    if (mode == MBEDTLS_AES_DECRYPT) {
         block = aesce_decrypt_block(block, keys, ctx->nr);
+    } else
+#else
+    (void) mode;
+#endif
+    {
+        block = aesce_encrypt_block(block, keys, ctx->nr);
     }
     vst1q_u8(&output[0], block);
 
@@ -170,6 +288,7 @@ int mbedtls_aesce_crypt_ecb(mbedtls_aes_context *ctx,
 /*
  * Compute decryption round keys from encryption round keys
  */
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 void mbedtls_aesce_inverse_key(unsigned char *invkey,
                                const unsigned char *fwdkey,
                                int nr)
@@ -184,6 +303,7 @@ void mbedtls_aesce_inverse_key(unsigned char *invkey,
     vst1q_u8(invkey + i * 16, vld1q_u8(fwdkey + j * 16));
 
 }
+#endif
 
 static inline uint32_t aes_rot_word(uint32_t word)
 {
@@ -214,7 +334,7 @@ static void aesce_setkey_enc(unsigned char *rk,
      *   - Section 5, Nr = Nk + 6
      *   - Section 5.2, the length of round keys is Nb*(Nr+1)
      */
-    const uint32_t key_len_in_words = key_bit_length / 32;  /* Nk */
+    const size_t key_len_in_words = key_bit_length / 32;    /* Nk */
     const size_t round_key_len_in_words = 4;                /* Nb */
     const size_t rounds_needed = key_len_in_words + 6;      /* Nr */
     const size_t round_keys_len_in_words =
@@ -227,7 +347,7 @@ static void aesce_setkey_enc(unsigned char *rk,
          rki + key_len_in_words < rko_end;
          rki += key_len_in_words) {
 
-        size_t iteration = (rki - (uint32_t *) rk) / key_len_in_words;
+        size_t iteration = (size_t) (rki - (uint32_t *) rk) / key_len_in_words;
         uint32_t *rko;
         rko = rki + key_len_in_words;
         rko[0] = aes_rot_word(aes_sub_word(rki[key_len_in_words - 1]));
@@ -239,6 +359,7 @@ static void aesce_setkey_enc(unsigned char *rk,
             /* Do not write overflow words.*/
             continue;
         }
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
         switch (key_bit_length) {
             case 128:
                 break;
@@ -253,6 +374,7 @@ static void aesce_setkey_enc(unsigned char *rk,
                 rko[7] = rko[6] ^ rki[7];
                 break;
         }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
     }
 }
 
@@ -278,29 +400,109 @@ int mbedtls_aesce_setkey_enc(unsigned char *rk,
 
 #if defined(MBEDTLS_GCM_C)
 
-#if !defined(__clang__) && defined(__GNUC__) && __GNUC__ == 5
+#if defined(MBEDTLS_ARCH_IS_ARM32)
+
+#if defined(__clang__)
+/* On clang for A32/T32, work around some missing intrinsics and types which are listed in
+ * [ACLE](https://arm-software.github.io/acle/neon_intrinsics/advsimd.html#polynomial-1)
+ * These are only required for GCM.
+ */
+#define vreinterpretq_u64_p64(a) ((uint64x2_t) a)
+
+typedef uint8x16_t poly128_t;
+
+static inline poly128_t vmull_p64(poly64_t a, poly64_t b)
+{
+    poly128_t r;
+    asm ("vmull.p64 %[r], %[a], %[b]" : [r] "=w" (r) : [a] "w" (a), [b] "w" (b) :);
+    return r;
+}
+
+/* This is set to cause some more missing intrinsics to be defined below */
+#define COMMON_MISSING_INTRINSICS
+
+static inline poly128_t vmull_high_p64(poly64x2_t a, poly64x2_t b)
+{
+    return vmull_p64((poly64_t) (vget_high_u64((uint64x2_t) a)),
+                     (poly64_t) (vget_high_u64((uint64x2_t) b)));
+}
+
+#endif /* defined(__clang__) */
+
+static inline uint8x16_t vrbitq_u8(uint8x16_t x)
+{
+    /* There is no vrbitq_u8 instruction in A32/T32, so provide
+     * an equivalent non-Neon implementation. Reverse bit order in each
+     * byte with 4x rbit, rev. */
+    asm ("ldm  %[p], { r2-r5 } \n\t"
+         "rbit r2, r2          \n\t"
+         "rev  r2, r2          \n\t"
+         "rbit r3, r3          \n\t"
+         "rev  r3, r3          \n\t"
+         "rbit r4, r4          \n\t"
+         "rev  r4, r4          \n\t"
+         "rbit r5, r5          \n\t"
+         "rev  r5, r5          \n\t"
+         "stm  %[p], { r2-r5 } \n\t"
+         :
+         /* Output: 16 bytes of memory pointed to by &x */
+         "+m" (*(uint8_t(*)[16]) &x)
+         :
+         [p] "r" (&x)
+         :
+         "r2", "r3", "r4", "r5"
+         );
+    return x;
+}
+
+#endif /* defined(MBEDTLS_ARCH_IS_ARM32) */
+
+#if defined(MBEDTLS_COMPILER_IS_GCC) && __GNUC__ == 5
 /* Some intrinsics are not available for GCC 5.X. */
-#define vreinterpretq_p64_u8(a) ((poly64x2_t) a)
+#define COMMON_MISSING_INTRINSICS
+#endif /* MBEDTLS_COMPILER_IS_GCC && __GNUC__ == 5 */
+
+
+#if defined(COMMON_MISSING_INTRINSICS)
+
+/* Missing intrinsics common to both GCC 5, and Clang on 32-bit */
+
+#define vreinterpretq_p64_u8(a)  ((poly64x2_t) a)
 #define vreinterpretq_u8_p128(a) ((uint8x16_t) a)
-static inline poly64_t vget_low_p64(poly64x2_t __a)
+
+static inline poly64x1_t vget_low_p64(poly64x2_t a)
 {
-    uint64x2_t tmp = (uint64x2_t) (__a);
-    uint64x1_t lo = vcreate_u64(vgetq_lane_u64(tmp, 0));
-    return (poly64_t) (lo);
+    uint64x1_t r = vget_low_u64(vreinterpretq_u64_p64(a));
+    return (poly64x1_t) r;
+
 }
-#endif /* !__clang__ && __GNUC__ && __GNUC__ == 5*/
+
+#endif /* COMMON_MISSING_INTRINSICS */
 
 /* vmull_p64/vmull_high_p64 wrappers.
  *
  * Older compilers miss some intrinsic functions for `poly*_t`. We use
  * uint8x16_t and uint8x16x3_t as input/output parameters.
  */
+#if defined(MBEDTLS_COMPILER_IS_GCC)
+/* GCC reports incompatible type error without cast. GCC think poly64_t and
+ * poly64x1_t are different, that is different with MSVC and Clang. */
+#define MBEDTLS_VMULL_P64(a, b) vmull_p64((poly64_t) a, (poly64_t) b)
+#else
+/* MSVC reports `error C2440: 'type cast'` with cast. Clang does not report
+ * error with/without cast. And I think poly64_t and poly64x1_t are same, no
+ * cast for clang also. */
+#define MBEDTLS_VMULL_P64(a, b) vmull_p64(a, b)
+#endif /* MBEDTLS_COMPILER_IS_GCC */
+
 static inline uint8x16_t pmull_low(uint8x16_t a, uint8x16_t b)
 {
+
     return vreinterpretq_u8_p128(
-        vmull_p64(
+        MBEDTLS_VMULL_P64(
             (poly64_t) vget_low_p64(vreinterpretq_p64_u8(a)),
-            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))));
+            (poly64_t) vget_low_p64(vreinterpretq_p64_u8(b))
+            ));
 }
 
 static inline uint8x16_t pmull_high(uint8x16_t a, uint8x16_t b)
@@ -362,9 +564,14 @@ static inline uint8x16x3_t poly_mult_128(uint8x16_t a, uint8x16_t b)
 static inline uint8x16_t poly_mult_reduce(uint8x16x3_t input)
 {
     uint8x16_t const ZERO = vdupq_n_u8(0);
-    /* use 'asm' as an optimisation barrier to prevent loading MODULO from memory */
+
     uint64x2_t r = vreinterpretq_u64_u8(vdupq_n_u8(0x87));
-    asm ("" : "+w" (r));
+#if defined(__GNUC__)
+    /* use 'asm' as an optimisation barrier to prevent loading MODULO from
+     * memory. It is for GNUC compatible compilers.
+     */
+    asm volatile ("" : "+w" (r));
+#endif
     uint8x16_t const MODULO = vreinterpretq_u8_u64(vshrq_n_u64(r, 64 - 8));
     uint8x16_t h, m, l; /* input high/middle/low 128b */
     uint8x16_t c, d, e, f, g, n, o;
@@ -406,6 +613,6 @@ void mbedtls_aesce_gcm_mult(unsigned char c[16],
 #undef MBEDTLS_POP_TARGET_PRAGMA
 #endif
 
-#endif /* MBEDTLS_HAVE_ARM64 */
+#endif /* MBEDTLS_AESCE_HAVE_CODE */
 
 #endif /* MBEDTLS_AESCE_C */
diff --git a/lib/libmbedtls/mbedtls/library/aesce.h b/lib/libmbedtls/mbedtls/library/aesce.h
index 12ddc74b37c109f6b82c5bc7a7754cc233ce709a..a14d085efa28ee7be653d8f401b8e33ad2da84da 100644
--- a/lib/libmbedtls/mbedtls/library/aesce.h
+++ b/lib/libmbedtls/mbedtls/library/aesce.h
@@ -2,56 +2,67 @@
  * \file aesce.h
  *
  * \brief Support hardware AES acceleration on Armv8-A processors with
- *        the Armv8-A Cryptographic Extension in AArch64 execution state.
+ *        the Armv8-A Cryptographic Extension.
  *
  * \warning These functions are only for internal use by other library
  *          functions; you must not call them directly.
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_AESCE_H
 #define MBEDTLS_AESCE_H
 
 #include "mbedtls/build_info.h"
+#include "common.h"
 
 #include "mbedtls/aes.h"
 
 
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
-    defined(__aarch64__) && !defined(MBEDTLS_HAVE_ARM64)
-#define MBEDTLS_HAVE_ARM64
-#endif
+#if defined(MBEDTLS_AESCE_C) \
+    && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \
+    && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER))
 
-#if defined(MBEDTLS_HAVE_ARM64)
+/* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a
+ * potentially suitable compiler (compiler version & flags are not checked when defining
+ * this). */
+#define MBEDTLS_AESCE_HAVE_CODE
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+
+extern signed char mbedtls_aesce_has_support_result;
+
 /**
  * \brief          Internal function to detect the crypto extension in CPUs.
  *
  * \return         1 if CPU has support for the feature, 0 otherwise
  */
-int mbedtls_aesce_has_support(void);
+int mbedtls_aesce_has_support_impl(void);
+
+#define MBEDTLS_AESCE_HAS_SUPPORT() (mbedtls_aesce_has_support_result == -1 ? \
+                                     mbedtls_aesce_has_support_impl() : \
+                                     mbedtls_aesce_has_support_result)
+
+#else /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
+
+/* If we are not on Linux, we can't detect support so assume that it's supported.
+ * Similarly, assume support if MBEDTLS_AES_USE_HARDWARE_ONLY is set.
+ */
+#define MBEDTLS_AESCE_HAS_SUPPORT() 1
+
+#endif /* defined(__linux__) && !defined(MBEDTLS_AES_USE_HARDWARE_ONLY) */
 
 /**
  * \brief          Internal AES-ECB block encryption and decryption
  *
+ * \warning        This assumes that the context specifies either 10, 12 or 14
+ *                 rounds and will behave incorrectly if this is not the case.
+ *
  * \param ctx      AES context
  * \param mode     MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
  * \param input    16-byte input block
@@ -82,6 +93,7 @@ void mbedtls_aesce_gcm_mult(unsigned char c[16],
                             const unsigned char b[16]);
 
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief           Internal round key inversion. This function computes
  *                  decryption round keys from the encryption round keys.
@@ -93,6 +105,7 @@ void mbedtls_aesce_gcm_mult(unsigned char c[16],
 void mbedtls_aesce_inverse_key(unsigned char *invkey,
                                const unsigned char *fwdkey,
                                int nr);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /**
  * \brief           Internal key expansion for encryption
@@ -111,6 +124,13 @@ int mbedtls_aesce_setkey_enc(unsigned char *rk,
 }
 #endif
 
-#endif /* MBEDTLS_HAVE_ARM64 */
+#else
+
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && defined(MBEDTLS_ARCH_IS_ARMV8_A)
+#error "AES hardware acceleration not supported on this platform / compiler"
+#endif
+
+#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS &&
+          (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */
 
 #endif /* MBEDTLS_AESCE_H */
diff --git a/lib/libmbedtls/mbedtls/library/aesni.c b/lib/libmbedtls/mbedtls/library/aesni.c
index a23c5b595bce5f5d800ca73224b825e58c761faa..8e5bd55ab9068f6497a0c080fa79a63fb65ce466 100644
--- a/lib/libmbedtls/mbedtls/library/aesni.c
+++ b/lib/libmbedtls/mbedtls/library/aesni.c
@@ -2,19 +2,7 @@
  *  AES-NI support functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -33,12 +21,28 @@
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
 
 #if MBEDTLS_AESNI_HAVE_CODE == 2
-#if !defined(_WIN32)
+#if defined(__GNUC__)
 #include <cpuid.h>
+#elif defined(_MSC_VER)
+#include <intrin.h>
+#else
+#error "`__cpuid` required by MBEDTLS_AESNI_C is not supported by the compiler"
 #endif
 #include <immintrin.h>
 #endif
 
+#if defined(MBEDTLS_ARCH_IS_X86)
+#if defined(MBEDTLS_COMPILER_IS_GCC)
+#pragma GCC push_options
+#pragma GCC target ("pclmul,sse2,aes")
+#define MBEDTLS_POP_TARGET_PRAGMA
+#elif defined(__clang__) && (__clang_major__ >= 5)
+#pragma clang attribute push (__attribute__((target("pclmul,sse2,aes"))), apply_to=function)
+#define MBEDTLS_POP_TARGET_PRAGMA
+#endif
+#endif
+
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 /*
  * AES-NI support detection routine
  */
@@ -49,7 +53,7 @@ int mbedtls_aesni_has_support(unsigned int what)
 
     if (!done) {
 #if MBEDTLS_AESNI_HAVE_CODE == 2
-        static unsigned info[4] = { 0, 0, 0, 0 };
+        static int info[4] = { 0, 0, 0, 0 };
 #if defined(_MSC_VER)
         __cpuid(info, 1);
 #else
@@ -68,6 +72,7 @@ int mbedtls_aesni_has_support(unsigned int what)
 
     return (c & what) != 0;
 }
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 
 #if MBEDTLS_AESNI_HAVE_CODE == 2
 
@@ -89,14 +94,19 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
     ++rk;
     --nr;
 
-    if (mode == 0) {
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+    if (mode == MBEDTLS_AES_DECRYPT) {
         while (nr != 0) {
             state = _mm_aesdec_si128(state, *rk);
             ++rk;
             --nr;
         }
         state = _mm_aesdeclast_si128(state, *rk);
-    } else {
+    } else
+#else
+    (void) mode;
+#endif
+    {
         while (nr != 0) {
             state = _mm_aesenc_si128(state, *rk);
             ++rk;
@@ -183,7 +193,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
                             const unsigned char a[16],
                             const unsigned char b[16])
 {
-    __m128i aa, bb, cc, dd;
+    __m128i aa = { 0 }, bb = { 0 }, cc, dd;
 
     /* The inputs are in big-endian order, so byte-reverse them */
     for (size_t i = 0; i < 16; i++) {
@@ -213,6 +223,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
 /*
  * Compute decryption round keys from encryption round keys
  */
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 void mbedtls_aesni_inverse_key(unsigned char *invkey,
                                const unsigned char *fwdkey, int nr)
 {
@@ -225,6 +236,7 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey,
     }
     *ik = *fk;
 }
+#endif
 
 /*
  * Key expansion, 128-bit case
@@ -273,6 +285,7 @@ static void aesni_setkey_enc_128(unsigned char *rk_bytes,
 /*
  * Key expansion, 192-bit case
  */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static void aesni_set_rk_192(__m128i *state0, __m128i *state1, __m128i xword,
                              unsigned char *rk)
 {
@@ -327,10 +340,12 @@ static void aesni_setkey_enc_192(unsigned char *rk,
     aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x40), rk + 24 * 7);
     aesni_set_rk_192(&state0, &state1, _mm_aeskeygenassist_si128(state1, 0x80), rk + 24 * 8);
 }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 
 /*
  * Key expansion, 256-bit case
  */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static void aesni_set_rk_256(__m128i state0, __m128i state1, __m128i xword,
                              __m128i *rk0, __m128i *rk1)
 {
@@ -387,6 +402,16 @@ static void aesni_setkey_enc_256(unsigned char *rk_bytes,
     aesni_set_rk_256(rk[10], rk[11], _mm_aeskeygenassist_si128(rk[11], 0x20), &rk[12], &rk[13]);
     aesni_set_rk_256(rk[12], rk[13], _mm_aeskeygenassist_si128(rk[13], 0x40), &rk[14], &rk[15]);
 }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
+
+#if defined(MBEDTLS_POP_TARGET_PRAGMA)
+#if defined(__clang__)
+#pragma clang attribute pop
+#elif defined(__GNUC__)
+#pragma GCC pop_options
+#endif
+#undef MBEDTLS_POP_TARGET_PRAGMA
+#endif
 
 #else /* MBEDTLS_AESNI_HAVE_CODE == 1 */
 
@@ -447,6 +472,7 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
          "jnz       1b              \n\t"
          "movdqu    (%1), %%xmm1    \n\t" // load round key
          AESENCLAST(xmm1_xmm0)            // last round
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
          "jmp       3f              \n\t"
 
          "2:                        \n\t" // decryption loop
@@ -457,6 +483,7 @@ int mbedtls_aesni_crypt_ecb(mbedtls_aes_context *ctx,
          "jnz       2b              \n\t"
          "movdqu    (%1), %%xmm1    \n\t" // load round key
          AESDECLAST(xmm1_xmm0)            // last round
+#endif
 
          "3:                        \n\t"
          "movdqu    %%xmm0, (%4)    \n\t" // export output
@@ -583,6 +610,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
 /*
  * Compute decryption round keys from encryption round keys
  */
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 void mbedtls_aesni_inverse_key(unsigned char *invkey,
                                const unsigned char *fwdkey, int nr)
 {
@@ -602,6 +630,7 @@ void mbedtls_aesni_inverse_key(unsigned char *invkey,
 
     memcpy(ik, fk, 16);
 }
+#endif
 
 /*
  * Key expansion, 128-bit case
@@ -656,6 +685,7 @@ static void aesni_setkey_enc_128(unsigned char *rk,
 /*
  * Key expansion, 192-bit case
  */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static void aesni_setkey_enc_192(unsigned char *rk,
                                  const unsigned char *key)
 {
@@ -709,10 +739,12 @@ static void aesni_setkey_enc_192(unsigned char *rk,
          : "r" (rk), "r" (key)
          : "memory", "cc", "0");
 }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 
 /*
  * Key expansion, 256-bit case
  */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static void aesni_setkey_enc_256(unsigned char *rk,
                                  const unsigned char *key)
 {
@@ -775,6 +807,7 @@ static void aesni_setkey_enc_256(unsigned char *rk,
          : "r" (rk), "r" (key)
          : "memory", "cc", "0");
 }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 
 #endif  /* MBEDTLS_AESNI_HAVE_CODE */
 
@@ -787,8 +820,10 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk,
 {
     switch (bits) {
         case 128: aesni_setkey_enc_128(rk, key); break;
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
         case 192: aesni_setkey_enc_192(rk, key); break;
         case 256: aesni_setkey_enc_256(rk, key); break;
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
         default: return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
     }
 
diff --git a/lib/libmbedtls/mbedtls/library/aesni.h b/lib/libmbedtls/mbedtls/library/aesni.h
index 51b770f31657a15d2bd75132ddbc1172634f8f83..59e27afd3ec62586bd59524f0c9215159a4a1074 100644
--- a/lib/libmbedtls/mbedtls/library/aesni.h
+++ b/lib/libmbedtls/mbedtls/library/aesni.h
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_AESNI_H
 #define MBEDTLS_AESNI_H
@@ -32,22 +20,14 @@
 #define MBEDTLS_AESNI_AES      0x02000000u
 #define MBEDTLS_AESNI_CLMUL    0x00000002u
 
-/* Can we do AESNI with inline assembly?
- * (Only implemented with gas syntax, only for 64-bit.)
- */
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
-    (defined(__amd64__) || defined(__x86_64__))   &&  \
-    !defined(MBEDTLS_HAVE_X86_64)
-#define MBEDTLS_HAVE_X86_64
-#endif
-
-#if defined(MBEDTLS_AESNI_C)
+#if defined(MBEDTLS_AESNI_C) && \
+    (defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_X86))
 
 /* Can we do AESNI with intrinsics?
  * (Only implemented with certain compilers, only for certain targets.)
  */
 #undef MBEDTLS_AESNI_HAVE_INTRINSICS
-#if defined(_MSC_VER)
+#if defined(_MSC_VER) && !defined(__clang__)
 /* Visual Studio supports AESNI intrinsics since VS 2008 SP1. We only support
  * VS 2013 and up for other reasons anyway, so no need to check the version. */
 #define MBEDTLS_AESNI_HAVE_INTRINSICS
@@ -55,20 +35,30 @@
 /* GCC-like compilers: currently, we only support intrinsics if the requisite
  * target flag is enabled when building the library (e.g. `gcc -mpclmul -msse2`
  * or `clang -maes -mpclmul`). */
-#if defined(__GNUC__) && defined(__AES__) && defined(__PCLMUL__)
+#if (defined(__GNUC__) || defined(__clang__)) && defined(__AES__) && defined(__PCLMUL__)
+#define MBEDTLS_AESNI_HAVE_INTRINSICS
+#endif
+/* For 32-bit, we only support intrinsics */
+#if defined(MBEDTLS_ARCH_IS_X86) && (defined(__GNUC__) || defined(__clang__))
 #define MBEDTLS_AESNI_HAVE_INTRINSICS
 #endif
 
-/* Choose the implementation of AESNI, if one is available. */
-#undef MBEDTLS_AESNI_HAVE_CODE
-/* To minimize disruption when releasing the intrinsics-based implementation,
- * favor the assembly-based implementation if it's available. We intend to
- * revise this in a later release of Mbed TLS 3.x. In the long run, we will
- * likely remove the assembly implementation. */
-#if defined(MBEDTLS_HAVE_X86_64)
-#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
-#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
+/* Choose the implementation of AESNI, if one is available.
+ *
+ * Favor the intrinsics-based implementation if it's available, for better
+ * maintainability.
+ * Performance is about the same (see #7380).
+ * In the long run, we will likely remove the assembly implementation. */
+#if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
 #define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
+#elif defined(MBEDTLS_HAVE_ASM) && \
+    (defined(__GNUC__) || defined(__clang__)) && defined(MBEDTLS_ARCH_IS_X64)
+/* Can we do AESNI with inline assembly?
+ * (Only implemented with gas syntax, only for 64-bit.)
+ */
+#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
+#else
+#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available"
 #endif
 
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
@@ -88,7 +78,11 @@ extern "C" {
  *
  * \return         1 if CPU has support for the feature, 0 otherwise
  */
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 int mbedtls_aesni_has_support(unsigned int what);
+#else
+#define mbedtls_aesni_has_support(what) 1
+#endif
 
 /**
  * \brief          Internal AES-NI AES-ECB block encryption and decryption
@@ -125,6 +119,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
                             const unsigned char a[16],
                             const unsigned char b[16]);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 /**
  * \brief           Internal round key inversion. This function computes
  *                  decryption round keys from the encryption round keys.
@@ -139,6 +134,7 @@ void mbedtls_aesni_gcm_mult(unsigned char c[16],
 void mbedtls_aesni_inverse_key(unsigned char *invkey,
                                const unsigned char *fwdkey,
                                int nr);
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /**
  * \brief           Internal key expansion for encryption
@@ -161,6 +157,6 @@ int mbedtls_aesni_setkey_enc(unsigned char *rk,
 #endif
 
 #endif /* MBEDTLS_AESNI_HAVE_CODE */
-#endif  /* MBEDTLS_AESNI_C */
+#endif  /* MBEDTLS_AESNI_C && (MBEDTLS_ARCH_IS_X64 || MBEDTLS_ARCH_IS_X86) */
 
 #endif /* MBEDTLS_AESNI_H */
diff --git a/lib/libmbedtls/mbedtls/library/alignment.h b/lib/libmbedtls/mbedtls/library/alignment.h
index a518a8a3ae430acf7657178794133ed8c6421416..a17001dd91b1247f83213a80442800dbb2614604 100644
--- a/lib/libmbedtls/mbedtls/library/alignment.h
+++ b/lib/libmbedtls/mbedtls/library/alignment.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_LIBRARY_ALIGNMENT_H
@@ -27,8 +15,6 @@
 #include <string.h>
 #include <stdlib.h>
 
-#include "mbedtls/build_info.h"
-
 /*
  * Define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS for architectures where unaligned memory
  * accesses are known to be efficient.
@@ -37,15 +23,83 @@
  * efficient when this is not defined.
  */
 #if defined(__ARM_FEATURE_UNALIGNED) \
-    || defined(__i386__) || defined(__amd64__) || defined(__x86_64__)
+    || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \
+    || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
 /*
  * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9
  * (and later versions) for Arm v7 and later; all x86 platforms should have
  * efficient unaligned access.
+ *
+ * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment
+ * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached
+ * device memory).
  */
 #define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS
 #endif
 
+#if defined(__IAR_SYSTEMS_ICC__) && \
+    (defined(MBEDTLS_ARCH_IS_ARM64) || defined(MBEDTLS_ARCH_IS_ARM32) \
+    || defined(__ICCRX__) || defined(__ICCRL78__) || defined(__ICCRISCV__))
+#pragma language=save
+#pragma language=extended
+#define MBEDTLS_POP_IAR_LANGUAGE_PRAGMA
+/* IAR recommend this technique for accessing unaligned data in
+ * https://www.iar.com/knowledge/support/technical-notes/compiler/accessing-unaligned-data
+ * This results in a single load / store instruction (if unaligned access is supported).
+ * According to that document, this is only supported on certain architectures.
+ */
+    #define UINT_UNALIGNED
+typedef uint16_t __packed mbedtls_uint16_unaligned_t;
+typedef uint32_t __packed mbedtls_uint32_unaligned_t;
+typedef uint64_t __packed mbedtls_uint64_unaligned_t;
+#elif defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 40504) && \
+    ((MBEDTLS_GCC_VERSION < 60300) || (!defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)))
+/*
+ * gcc may generate a branch to memcpy for calls like `memcpy(dest, src, 4)` rather than
+ * generating some LDR or LDRB instructions (similar for stores).
+ *
+ * This is architecture dependent: x86-64 seems fine even with old gcc; 32-bit Arm
+ * is affected. To keep it simple, we enable for all architectures.
+ *
+ * For versions of gcc < 5.4.0 this issue always happens.
+ * For gcc < 6.3.0, this issue happens at -O0
+ * For all versions, this issue happens iff unaligned access is not supported.
+ *
+ * For gcc 4.x, this implementation will generate byte-by-byte loads even if unaligned access is
+ * supported, which is correct but not optimal.
+ *
+ * For performance (and code size, in some cases), we want to avoid the branch and just generate
+ * some inline load/store instructions since the access is small and constant-size.
+ *
+ * The manual states:
+ * "The packed attribute specifies that a variable or structure field should have the smallest
+ *  possible alignment—one byte for a variable"
+ * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Variable-Attributes.html
+ *
+ * Previous implementations used __attribute__((__aligned__(1)), but had issues with a gcc bug:
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94662
+ *
+ * Tested with several versions of GCC from 4.5.0 up to 13.2.0
+ * We don't enable for older than 4.5.0 as this has not been tested.
+ */
+ #define UINT_UNALIGNED_STRUCT
+typedef struct {
+    uint16_t x;
+} __attribute__((packed)) mbedtls_uint16_unaligned_t;
+typedef struct {
+    uint32_t x;
+} __attribute__((packed)) mbedtls_uint32_unaligned_t;
+typedef struct {
+    uint64_t x;
+} __attribute__((packed)) mbedtls_uint64_unaligned_t;
+ #endif
+
+/*
+ * We try to force mbedtls_(get|put)_unaligned_uintXX to be always inline, because this results
+ * in code that is both smaller and faster. IAR and gcc both benefit from this when optimising
+ * for size.
+ */
+
 /**
  * Read the unsigned 16 bits integer from the given address, which need not
  * be aligned.
@@ -53,10 +107,23 @@
  * \param   p pointer to 2 bytes of data
  * \return  Data at the given address
  */
-inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
 {
     uint16_t r;
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+    r = *p16;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+    r = p16->x;
+#else
     memcpy(&r, p, sizeof(r));
+#endif
     return r;
 }
 
@@ -67,9 +134,22 @@ inline uint16_t mbedtls_get_unaligned_uint16(const void *p)
  * \param   p pointer to 2 bytes of data
  * \param   x data to write
  */
-inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
 {
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+    *p16 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint16_unaligned_t *p16 = (mbedtls_uint16_unaligned_t *) p;
+    p16->x = x;
+#else
     memcpy(p, &x, sizeof(x));
+#endif
 }
 
 /**
@@ -79,10 +159,23 @@ inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x)
  * \param   p pointer to 4 bytes of data
  * \return  Data at the given address
  */
-inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
 {
     uint32_t r;
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+    r = *p32;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+    r = p32->x;
+#else
     memcpy(&r, p, sizeof(r));
+#endif
     return r;
 }
 
@@ -93,9 +186,22 @@ inline uint32_t mbedtls_get_unaligned_uint32(const void *p)
  * \param   p pointer to 4 bytes of data
  * \param   x data to write
  */
-inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
 {
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+    *p32 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint32_unaligned_t *p32 = (mbedtls_uint32_unaligned_t *) p;
+    p32->x = x;
+#else
     memcpy(p, &x, sizeof(x));
+#endif
 }
 
 /**
@@ -105,10 +211,23 @@ inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x)
  * \param   p pointer to 8 bytes of data
  * \return  Data at the given address
  */
-inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
 {
     uint64_t r;
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+    r = *p64;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+    r = p64->x;
+#else
     memcpy(&r, p, sizeof(r));
+#endif
     return r;
 }
 
@@ -119,11 +238,28 @@ inline uint64_t mbedtls_get_unaligned_uint64(const void *p)
  * \param   p pointer to 8 bytes of data
  * \param   x data to write
  */
-inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+static inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
 {
+#if defined(UINT_UNALIGNED)
+    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+    *p64 = x;
+#elif defined(UINT_UNALIGNED_STRUCT)
+    mbedtls_uint64_unaligned_t *p64 = (mbedtls_uint64_unaligned_t *) p;
+    p64->x = x;
+#else
     memcpy(p, &x, sizeof(x));
+#endif
 }
 
+#if defined(MBEDTLS_POP_IAR_LANGUAGE_PRAGMA)
+#pragma language=restore
+#endif
+
 /** Byte Reading Macros
  *
  * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th
@@ -183,9 +319,22 @@ inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x)
 
 /* Detect armcc built-in byteswap routine */
 #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 410000) && !defined(MBEDTLS_BSWAP32)
+#if defined(__ARM_ACLE)  /* ARM Compiler 6 - earlier versions don't need a header */
+#include <arm_acle.h>
+#endif
 #define MBEDTLS_BSWAP32 __rev
 #endif
 
+/* Detect IAR built-in byteswap routine */
+#if defined(__IAR_SYSTEMS_ICC__)
+#if defined(__ARM_ACLE)
+#include <arm_acle.h>
+#define MBEDTLS_BSWAP16(x) ((uint16_t) __rev16((uint32_t) (x)))
+#define MBEDTLS_BSWAP32 __rev
+#define MBEDTLS_BSWAP64 __revll
+#endif
+#endif
+
 /*
  * Where compiler built-ins are not present, fall back to C code that the
  * compiler may be able to detect and transform into the relevant bswap or
@@ -230,10 +379,25 @@ static inline uint64_t mbedtls_bswap64(uint64_t x)
 #endif /* !defined(MBEDTLS_BSWAP64) */
 
 #if !defined(__BYTE_ORDER__)
+
+#if defined(__LITTLE_ENDIAN__)
+/* IAR defines __xxx_ENDIAN__, but not __BYTE_ORDER__ */
+#define MBEDTLS_IS_BIG_ENDIAN 0
+#elif defined(__BIG_ENDIAN__)
+#define MBEDTLS_IS_BIG_ENDIAN 1
+#else
 static const uint16_t mbedtls_byte_order_detector = { 0x100 };
 #define MBEDTLS_IS_BIG_ENDIAN (*((unsigned char *) (&mbedtls_byte_order_detector)) == 0x01)
+#endif
+
+#else
+
+#if (__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__)
+#define MBEDTLS_IS_BIG_ENDIAN 1
 #else
-#define MBEDTLS_IS_BIG_ENDIAN ((__BYTE_ORDER__) == (__ORDER_BIG_ENDIAN__))
+#define MBEDTLS_IS_BIG_ENDIAN 0
+#endif
+
 #endif /* !defined(__BYTE_ORDER__) */
 
 /**
diff --git a/lib/libmbedtls/mbedtls/library/aria.c b/lib/libmbedtls/mbedtls/library/aria.c
index 0980362253cee83021d2795ae5873fdf64595de1..d9f84cc59d7811ab98e5c84bf09086cae20f162e 100644
--- a/lib/libmbedtls/mbedtls/library/aria.c
+++ b/lib/libmbedtls/mbedtls/library/aria.c
@@ -2,19 +2,7 @@
  *  ARIA implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -37,12 +25,6 @@
 
 #include "mbedtls/platform_util.h"
 
-/* Parameter validation macros */
-#define ARIA_VALIDATE_RET(cond)                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ARIA_BAD_INPUT_DATA)
-#define ARIA_VALIDATE(cond)                                           \
-    MBEDTLS_INTERNAL_VALIDATE(cond)
-
 /*
  * modify byte order: ( A B C D ) -> ( B A D C ), i.e. swap pairs of bytes
  *
@@ -375,8 +357,6 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
 
     int i;
     uint32_t w[4][4], *w2;
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(key != NULL);
 
     if (keybits != 128 && keybits != 192 && keybits != 256) {
         return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
@@ -425,12 +405,11 @@ int mbedtls_aria_setkey_enc(mbedtls_aria_context *ctx,
 /*
  * Set decryption key
  */
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,
                             const unsigned char *key, unsigned int keybits)
 {
     int i, j, k, ret;
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(key != NULL);
 
     ret = mbedtls_aria_setkey_enc(ctx, key, keybits);
     if (ret != 0) {
@@ -454,6 +433,7 @@ int mbedtls_aria_setkey_dec(mbedtls_aria_context *ctx,
 
     return 0;
 }
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /*
  * Encrypt a block
@@ -465,9 +445,6 @@ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,
     int i;
 
     uint32_t a, b, c, d;
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(input != NULL);
-    ARIA_VALIDATE_RET(output != NULL);
 
     a = MBEDTLS_GET_UINT32_LE(input,  0);
     b = MBEDTLS_GET_UINT32_LE(input,  4);
@@ -515,7 +492,6 @@ int mbedtls_aria_crypt_ecb(mbedtls_aria_context *ctx,
 /* Initialize context */
 void mbedtls_aria_init(mbedtls_aria_context *ctx)
 {
-    ARIA_VALIDATE(ctx != NULL);
     memset(ctx, 0, sizeof(mbedtls_aria_context));
 }
 
@@ -542,12 +518,9 @@ int mbedtls_aria_crypt_cbc(mbedtls_aria_context *ctx,
 {
     unsigned char temp[MBEDTLS_ARIA_BLOCKSIZE];
 
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
-                      mode == MBEDTLS_ARIA_DECRYPT);
-    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
-    ARIA_VALIDATE_RET(length == 0 || output != NULL);
-    ARIA_VALIDATE_RET(iv != NULL);
+    if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {
+        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+    }
 
     if (length % MBEDTLS_ARIA_BLOCKSIZE) {
         return MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH;
@@ -598,19 +571,14 @@ int mbedtls_aria_crypt_cfb128(mbedtls_aria_context *ctx,
     unsigned char c;
     size_t n;
 
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(mode == MBEDTLS_ARIA_ENCRYPT ||
-                      mode == MBEDTLS_ARIA_DECRYPT);
-    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
-    ARIA_VALIDATE_RET(length == 0 || output != NULL);
-    ARIA_VALIDATE_RET(iv != NULL);
-    ARIA_VALIDATE_RET(iv_off != NULL);
+    if ((mode != MBEDTLS_ARIA_ENCRYPT) && (mode != MBEDTLS_ARIA_DECRYPT)) {
+        return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
+    }
 
     n = *iv_off;
 
     /* An overly large value of n can lead to an unlimited
-     * buffer overflow. Therefore, guard against this
-     * outside of parameter validation. */
+     * buffer overflow. */
     if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
         return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
     }
@@ -660,17 +628,9 @@ int mbedtls_aria_crypt_ctr(mbedtls_aria_context *ctx,
     int c, i;
     size_t n;
 
-    ARIA_VALIDATE_RET(ctx != NULL);
-    ARIA_VALIDATE_RET(length == 0 || input  != NULL);
-    ARIA_VALIDATE_RET(length == 0 || output != NULL);
-    ARIA_VALIDATE_RET(nonce_counter != NULL);
-    ARIA_VALIDATE_RET(stream_block  != NULL);
-    ARIA_VALIDATE_RET(nc_off != NULL);
-
     n = *nc_off;
     /* An overly large value of n can lead to an unlimited
-     * buffer overflow. Therefore, guard against this
-     * outside of parameter validation. */
+     * buffer overflow. */
     if (n >= MBEDTLS_ARIA_BLOCKSIZE) {
         return MBEDTLS_ERR_ARIA_BAD_INPUT_DATA;
     }
@@ -884,12 +844,18 @@ int mbedtls_aria_self_test(int verbose)
         /* test ECB decryption */
         if (verbose) {
             mbedtls_printf("  ARIA-ECB-%d (dec): ", 128 + 64 * i);
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+            mbedtls_printf("skipped\n");
+#endif
         }
+
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
         mbedtls_aria_setkey_dec(&ctx, aria_test1_ecb_key, 128 + 64 * i);
         mbedtls_aria_crypt_ecb(&ctx, aria_test1_ecb_ct[i], blk);
         ARIA_SELF_TEST_ASSERT(
             memcmp(blk, aria_test1_ecb_pt, MBEDTLS_ARIA_BLOCKSIZE)
             != 0);
+#endif
     }
     if (verbose) {
         mbedtls_printf("\n");
diff --git a/lib/libmbedtls/mbedtls/library/asn1parse.c b/lib/libmbedtls/mbedtls/library/asn1parse.c
index d257ef43830d7a86586a458149bc2ee43b19365a..e33fdf71da65e2733fd9c7e3ed2607e2bf91f2dc 100644
--- a/lib/libmbedtls/mbedtls/library/asn1parse.c
+++ b/lib/libmbedtls/mbedtls/library/asn1parse.c
@@ -2,24 +2,13 @@
  *  Generic ASN.1 parsing
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
-#if defined(MBEDTLS_ASN1_PARSE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_X509_CREATE_C) || \
+    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 
 #include "mbedtls/asn1.h"
 #include "mbedtls/platform_util.h"
@@ -47,47 +36,18 @@ int mbedtls_asn1_get_len(unsigned char **p,
     if ((**p & 0x80) == 0) {
         *len = *(*p)++;
     } else {
-        switch (**p & 0x7F) {
-            case 1:
-                if ((end - *p) < 2) {
-                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-                }
-
-                *len = (*p)[1];
-                (*p) += 2;
-                break;
-
-            case 2:
-                if ((end - *p) < 3) {
-                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-                }
-
-                *len = ((size_t) (*p)[1] << 8) | (*p)[2];
-                (*p) += 3;
-                break;
-
-            case 3:
-                if ((end - *p) < 4) {
-                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-                }
-
-                *len = ((size_t) (*p)[1] << 16) |
-                       ((size_t) (*p)[2] << 8) | (*p)[3];
-                (*p) += 4;
-                break;
-
-            case 4:
-                if ((end - *p) < 5) {
-                    return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
-                }
-
-                *len = ((size_t) (*p)[1] << 24) | ((size_t) (*p)[2] << 16) |
-                       ((size_t) (*p)[3] << 8) |           (*p)[4];
-                (*p) += 5;
-                break;
-
-            default:
-                return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+        int n = (**p) & 0x7F;
+        if (n == 0 || n > 4) {
+            return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+        }
+        if ((end - *p) <= n) {
+            return MBEDTLS_ERR_ASN1_OUT_OF_DATA;
+        }
+        *len = 0;
+        (*p)++;
+        while (n--) {
+            *len = (*len << 8) | **p;
+            (*p)++;
         }
     }
 
@@ -114,7 +74,9 @@ int mbedtls_asn1_get_tag(unsigned char **p,
 
     return mbedtls_asn1_get_len(p, end, len);
 }
+#endif /* MBEDTLS_ASN1_PARSE_C || MBEDTLS_X509_CREATE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
 
+#if defined(MBEDTLS_ASN1_PARSE_C)
 int mbedtls_asn1_get_bool(unsigned char **p,
                           const unsigned char *end,
                           int *val)
diff --git a/lib/libmbedtls/mbedtls/library/asn1write.c b/lib/libmbedtls/mbedtls/library/asn1write.c
index b9d586aef4affbcb3f83c6cf2bf7cba97e925921..775a9ef530fb469a01c50f06059794fdebc8b58b 100644
--- a/lib/libmbedtls/mbedtls/library/asn1write.c
+++ b/lib/libmbedtls/mbedtls/library/asn1write.c
@@ -2,24 +2,13 @@
  * ASN.1 buffer writing functionality
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
-#if defined(MBEDTLS_ASN1_WRITE_C)
+#if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
+    defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
 
 #include "mbedtls/asn1write.h"
 #include "mbedtls/error.h"
@@ -28,68 +17,40 @@
 
 #include "mbedtls/platform.h"
 
+#if defined(MBEDTLS_ASN1_PARSE_C)
+#include "mbedtls/asn1.h"
+#endif
+
 int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len)
 {
-    if (len < 0x80) {
-        if (*p - start < 1) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-        }
-
-        *--(*p) = (unsigned char) len;
-        return 1;
+#if SIZE_MAX > 0xFFFFFFFF
+    if (len > 0xFFFFFFFF) {
+        return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
     }
+#endif
 
-    if (len <= 0xFF) {
-        if (*p - start < 2) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-        }
-
-        *--(*p) = (unsigned char) len;
-        *--(*p) = 0x81;
-        return 2;
-    }
+    int required = 1;
 
-    if (len <= 0xFFFF) {
-        if (*p - start < 3) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    if (len >= 0x80) {
+        for (size_t l = len; l != 0; l >>= 8) {
+            required++;
         }
-
-        *--(*p) = MBEDTLS_BYTE_0(len);
-        *--(*p) = MBEDTLS_BYTE_1(len);
-        *--(*p) = 0x82;
-        return 3;
     }
 
-    if (len <= 0xFFFFFF) {
-        if (*p - start < 4) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-        }
-
-        *--(*p) = MBEDTLS_BYTE_0(len);
-        *--(*p) = MBEDTLS_BYTE_1(len);
-        *--(*p) = MBEDTLS_BYTE_2(len);
-        *--(*p) = 0x83;
-        return 4;
+    if (required > (*p - start)) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     }
 
-    int len_is_valid = 1;
-#if SIZE_MAX > 0xFFFFFFFF
-    len_is_valid = (len <= 0xFFFFFFFF);
-#endif
-    if (len_is_valid) {
-        if (*p - start < 5) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-        }
-
+    do {
         *--(*p) = MBEDTLS_BYTE_0(len);
-        *--(*p) = MBEDTLS_BYTE_1(len);
-        *--(*p) = MBEDTLS_BYTE_2(len);
-        *--(*p) = MBEDTLS_BYTE_3(len);
-        *--(*p) = 0x84;
-        return 5;
+        len >>= 8;
+    } while (len);
+
+    if (required > 1) {
+        *--(*p) = (unsigned char) (0x80 + required - 1);
     }
 
-    return MBEDTLS_ERR_ASN1_INVALID_LENGTH;
+    return required;
 }
 
 int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsigned char tag)
@@ -102,6 +63,21 @@ int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start, unsign
 
     return 1;
 }
+#endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA */
+
+#if defined(MBEDTLS_ASN1_WRITE_C)
+static int mbedtls_asn1_write_len_and_tag(unsigned char **p,
+                                          const unsigned char *start,
+                                          size_t len,
+                                          unsigned char tag)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
+
+    return (int) len;
+}
 
 int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
                                   const unsigned char *buf, size_t size)
@@ -154,10 +130,7 @@ int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start, const
         len += 1;
     }
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_INTEGER));
-
-    ret = (int) len;
+    ret = mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_INTEGER);
 
 cleanup:
     return ret;
@@ -166,15 +139,9 @@ cleanup:
 
 int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-
     // Write NULL
     //
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, 0));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_NULL));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, 0, MBEDTLS_ASN1_NULL);
 }
 
 int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
@@ -185,38 +152,39 @@ int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
 
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start,
                                                             (const unsigned char *) oid, oid_len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OID));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OID);
 }
 
 int mbedtls_asn1_write_algorithm_identifier(unsigned char **p, const unsigned char *start,
                                             const char *oid, size_t oid_len,
                                             size_t par_len)
+{
+    return mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len, par_len, 1);
+}
+
+int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p, const unsigned char *start,
+                                                const char *oid, size_t oid_len,
+                                                size_t par_len, int has_par)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
-    if (par_len == 0) {
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
-    } else {
-        len += par_len;
+    if (has_par) {
+        if (par_len == 0) {
+            MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_null(p, start));
+        } else {
+            len += par_len;
+        }
     }
 
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_oid(p, start, oid, oid_len));
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
-                                                     MBEDTLS_ASN1_CONSTRUCTED |
-                                                     MBEDTLS_ASN1_SEQUENCE));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len,
+                                          MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
 }
 
 int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int boolean)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     if (*p - start < 1) {
@@ -226,15 +194,11 @@ int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start, int b
     *--(*p) = (boolean) ? 255 : 0;
     len++;
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BOOLEAN));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BOOLEAN);
 }
 
 static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start, int val, int tag)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
 
     do {
@@ -254,10 +218,7 @@ static int asn1_write_tagged_int(unsigned char **p, const unsigned char *start,
         len += 1;
     }
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
 }
 
 int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val)
@@ -280,10 +241,7 @@ int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *sta
                                                             (const unsigned char *) text,
                                                             text_len));
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, tag));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, tag);
 }
 
 int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
@@ -352,7 +310,6 @@ int mbedtls_asn1_write_named_bitstring(unsigned char **p,
 int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
                                  const unsigned char *buf, size_t bits)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     size_t unused_bits, byte_len;
 
@@ -376,10 +333,7 @@ int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
     /* Write unused bits */
     *--(*p) = (unsigned char) unused_bits;
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_BIT_STRING));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_BIT_STRING);
 }
 
 int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
@@ -390,13 +344,11 @@ int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *star
 
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_raw_buffer(p, start, buf, size));
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_OCTET_STRING));
-
-    return (int) len;
+    return mbedtls_asn1_write_len_and_tag(p, start, len, MBEDTLS_ASN1_OCTET_STRING);
 }
 
 
+#if !defined(MBEDTLS_ASN1_PARSE_C)
 /* This is a copy of the ASN.1 parsing function mbedtls_asn1_find_named_data(),
  * which is replicated to avoid a dependency ASN1_WRITE_C on ASN1_PARSE_C. */
 static mbedtls_asn1_named_data *asn1_find_named_data(
@@ -414,6 +366,10 @@ static mbedtls_asn1_named_data *asn1_find_named_data(
 
     return list;
 }
+#else
+#define asn1_find_named_data(list, oid, len) \
+    ((mbedtls_asn1_named_data *) mbedtls_asn1_find_named_data(list, oid, len))
+#endif
 
 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(
     mbedtls_asn1_named_data **head,
diff --git a/lib/libmbedtls/mbedtls/library/base64.c b/lib/libmbedtls/mbedtls/library/base64.c
index 41706106424697d5b41ce96f3848a7f4f1aa42f5..9677dee5b29577b0decaa2c55ffa2036fe78e2d8 100644
--- a/lib/libmbedtls/mbedtls/library/base64.c
+++ b/lib/libmbedtls/mbedtls/library/base64.c
@@ -2,26 +2,17 @@
  *  RFC 1521 base64 encoding/decoding
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
+#include <limits.h>
+
 #include "common.h"
 
 #if defined(MBEDTLS_BASE64_C)
 
 #include "mbedtls/base64.h"
+#include "base64_internal.h"
 #include "constant_time_internal.h"
 
 #include <stdint.h>
@@ -31,7 +22,38 @@
 #include "mbedtls/platform.h"
 #endif /* MBEDTLS_SELF_TEST */
 
-#define BASE64_SIZE_T_MAX   ((size_t) -1)   /* SIZE_T_MAX is not standard */
+MBEDTLS_STATIC_TESTABLE
+unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
+{
+    unsigned char digit = 0;
+    /* For each range of values, if value is in that range, mask digit with
+     * the corresponding value. Since value can only be in a single range,
+     * only at most one masking will change digit. */
+    digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
+    digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
+    digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
+    digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
+    digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
+    return digit;
+}
+
+MBEDTLS_STATIC_TESTABLE
+signed char mbedtls_ct_base64_dec_value(unsigned char c)
+{
+    unsigned char val = 0;
+    /* For each range of digits, if c is in that range, mask val with
+     * the corresponding value. Since c can only be in a single range,
+     * only at most one masking will change val. Set val to one plus
+     * the desired value so that it stays 0 if c is in none of the ranges. */
+    val |= mbedtls_ct_uchar_in_range_if('A', 'Z', c, c - 'A' +  0 + 1);
+    val |= mbedtls_ct_uchar_in_range_if('a', 'z', c, c - 'a' + 26 + 1);
+    val |= mbedtls_ct_uchar_in_range_if('0', '9', c, c - '0' + 52 + 1);
+    val |= mbedtls_ct_uchar_in_range_if('+', '+', c, c - '+' + 62 + 1);
+    val |= mbedtls_ct_uchar_in_range_if('/', '/', c, c - '/' + 63 + 1);
+    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
+     * a digit with the value v. */
+    return val - 1;
+}
 
 /*
  * Encode a buffer into base64 format
@@ -50,8 +72,8 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
 
     n = slen / 3 + (slen % 3 != 0);
 
-    if (n > (BASE64_SIZE_T_MAX - 1) / 4) {
-        *olen = BASE64_SIZE_T_MAX;
+    if (n > (SIZE_MAX - 1) / 4) {
+        *olen = SIZE_MAX;
         return MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL;
     }
 
@@ -94,7 +116,7 @@ int mbedtls_base64_encode(unsigned char *dst, size_t dlen, size_t *olen,
         *p++ = '=';
     }
 
-    *olen = p - dst;
+    *olen = (size_t) (p - dst);
     *p = 0;
 
     return 0;
@@ -203,7 +225,7 @@ int mbedtls_base64_decode(unsigned char *dst, size_t dlen, size_t *olen,
         }
     }
 
-    *olen = p - dst;
+    *olen = (size_t) (p - dst);
 
     return 0;
 }
diff --git a/lib/libmbedtls/mbedtls/library/base64_internal.h b/lib/libmbedtls/mbedtls/library/base64_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..a09bd2377714a334ac8c411ee8404e6c2e4e1b8f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/base64_internal.h
@@ -0,0 +1,45 @@
+/**
+ * \file base64_internal.h
+ *
+ * \brief RFC 1521 base64 encoding/decoding: interfaces for invasive testing
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_BASE64_INTERNAL
+#define MBEDTLS_BASE64_INTERNAL
+
+#include "common.h"
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+/** Given a value in the range 0..63, return the corresponding Base64 digit.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * \param value     A value in the range 0..63.
+ *
+ * \return          A base64 digit converted from \p value.
+ */
+unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
+
+/** Given a Base64 digit, return its value.
+ *
+ * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
+ * return -1.
+ *
+ * The implementation assumes that letters are consecutive (e.g. ASCII
+ * but not EBCDIC).
+ *
+ * \param c     A base64 digit.
+ *
+ * \return      The value of the base64 digit \p c.
+ */
+signed char mbedtls_ct_base64_dec_value(unsigned char c);
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* MBEDTLS_BASE64_INTERNAL */
diff --git a/lib/libmbedtls/mbedtls/library/bignum.c b/lib/libmbedtls/mbedtls/library/bignum.c
index b6733b7d86080bdf2e2c226a1ddc5030ab7e664e..107a3972af13a94d1d60ad562640a2d61fbef6ac 100644
--- a/lib/libmbedtls/mbedtls/library/bignum.c
+++ b/lib/libmbedtls/mbedtls/library/bignum.c
@@ -2,19 +2,7 @@
  *  Multi-precision integer library
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -39,6 +27,7 @@
 
 #include "mbedtls/bignum.h"
 #include "bignum_core.h"
+#include "bignum_internal.h"
 #include "bn_mul.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
@@ -50,30 +39,156 @@
 #include "mbedtls/platform.h"
 
 #include <mempool.h>
-#include <util.h>
 
-#define MPI_VALIDATE_RET(cond)                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
-#define MPI_VALIDATE(cond)                                           \
-    MBEDTLS_INTERNAL_VALIDATE(cond)
+void *mbedtls_mpi_mempool;
 
-#define MPI_SIZE_T_MAX  ((size_t) -1)   /* SIZE_T_MAX is not standard */
 
-void *mbedtls_mpi_mempool;
+/*
+ * Conditionally select an MPI sign in constant time.
+ * (MPI sign is the field s in mbedtls_mpi. It is unsigned short and only 1 and -1 are valid
+ * values.)
+ */
+static inline signed short mbedtls_ct_mpi_sign_if(mbedtls_ct_condition_t cond,
+                                                  signed short sign1, signed short sign2)
+{
+    return (signed short) mbedtls_ct_uint_if(cond, sign1 + 1, sign2 + 1) - 1;
+}
 
-/* Implementation that should never be optimized out by the compiler */
-static void mbedtls_mpi_zeroize(mbedtls_mpi_uint *v, size_t n)
+/*
+ * Compare signed values in constant time
+ */
+int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
+                          const mbedtls_mpi *Y,
+                          unsigned *ret)
 {
-    mbedtls_platform_zeroize(v, ciL * n);
+    mbedtls_ct_condition_t different_sign, X_is_negative, Y_is_negative, result;
+
+    if (X->n != Y->n) {
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
+    }
+
+    /*
+     * Set N_is_negative to MBEDTLS_CT_FALSE if N >= 0, MBEDTLS_CT_TRUE if N < 0.
+     * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
+     */
+    X_is_negative = mbedtls_ct_bool((X->s & 2) >> 1);
+    Y_is_negative = mbedtls_ct_bool((Y->s & 2) >> 1);
+
+    /*
+     * If the signs are different, then the positive operand is the bigger.
+     * That is if X is negative (X_is_negative == 1), then X < Y is true and it
+     * is false if X is positive (X_is_negative == 0).
+     */
+    different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign
+    result = mbedtls_ct_bool_and(different_sign, X_is_negative);
+
+    /*
+     * Assuming signs are the same, compare X and Y. We switch the comparison
+     * order if they are negative so that we get the right result, regardles of
+     * sign.
+     */
+
+    /* This array is used to conditionally swap the pointers in const time */
+    void * const p[2] = { X->p, Y->p };
+    size_t i = mbedtls_ct_size_if_else_0(X_is_negative, 1);
+    mbedtls_ct_condition_t lt = mbedtls_mpi_core_lt_ct(p[i], p[i ^ 1], X->n);
+
+    /*
+     * Store in result iff the signs are the same (i.e., iff different_sign == false). If
+     * the signs differ, result has already been set, so we don't change it.
+     */
+    result = mbedtls_ct_bool_or(result,
+                                mbedtls_ct_bool_and(mbedtls_ct_bool_not(different_sign), lt));
+
+    *ret = mbedtls_ct_uint_if_else_0(result, 1);
+
+    return 0;
+}
+
+/*
+ * Conditionally assign X = Y, without leaking information
+ * about whether the assignment was made or not.
+ * (Leaking information about the respective sizes of X and Y is ok however.)
+ */
+#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \
+    (_MSC_FULL_VER < 193131103)
+/*
+ * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
+ * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
+ */
+__declspec(noinline)
+#endif
+int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
+                                 const mbedtls_mpi *Y,
+                                 unsigned char assign)
+{
+    int ret = 0;
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
+
+    {
+        mbedtls_ct_condition_t do_assign = mbedtls_ct_bool(assign);
+
+        X->s = mbedtls_ct_mpi_sign_if(do_assign, Y->s, X->s);
+
+        mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, do_assign);
+
+        mbedtls_ct_condition_t do_not_assign = mbedtls_ct_bool_not(do_assign);
+        for (size_t i = Y->n; i < X->n; i++) {
+            X->p[i] = mbedtls_ct_mpi_uint_if_else_0(do_not_assign, X->p[i]);
+        }
+    }
+
+cleanup:
+    return ret;
+}
+
+/*
+ * Conditionally swap X and Y, without leaking information
+ * about whether the swap was made or not.
+ * Here it is not ok to simply swap the pointers, which would lead to
+ * different memory access patterns when X and Y are used afterwards.
+ */
+int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
+                               mbedtls_mpi *Y,
+                               unsigned char swap)
+{
+    int ret = 0;
+    int s;
+
+    if (X == Y) {
+        return 0;
+    }
+
+    mbedtls_ct_condition_t do_swap = mbedtls_ct_bool(swap);
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
+
+    s = X->s;
+    X->s = mbedtls_ct_mpi_sign_if(do_swap, Y->s, X->s);
+    Y->s = mbedtls_ct_mpi_sign_if(do_swap, s, Y->s);
+
+    mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, do_swap);
+
+cleanup:
+    return ret;
 }
 
+/* Implementation that should never be optimized out by the compiler */
+#define mbedtls_mpi_zeroize_and_free(v, n) mbedtls_zeroize_and_free(v, ciL * (n))
+
+/*
+ * Implementation that should never be optimized out by the compiler.
+ * Reintroduced to allow use of mempool.
+ */
+#define mbedtls_mpi_zeroize(v, n) mbedtls_platform_zeroize(v, ciL * (n))
+
 /*
  * Initialize one MPI
  */
 static void mpi_init(mbedtls_mpi *X, short use_mempool)
 {
-    MPI_VALIDATE(X != NULL);
-
     X->s = 1;
     X->use_mempool = use_mempool;
     X->n = 0;
@@ -100,11 +215,12 @@ void mbedtls_mpi_free(mbedtls_mpi *X)
     }
 
     if (X->p != NULL) {
-        mbedtls_mpi_zeroize(X->p, X->n);
-        if(X->use_mempool)
+        if(X->use_mempool) {
+            mbedtls_mpi_zeroize(X->p, X->n);
             mempool_free(mbedtls_mpi_mempool, X->p);
-        else
-        mbedtls_free(X->p);
+        } else {
+            mbedtls_mpi_zeroize_and_free(X->p, X->n);
+        }
     }
 
     X->s = 1;
@@ -118,7 +234,6 @@ void mbedtls_mpi_free(mbedtls_mpi *X)
 int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
 {
     mbedtls_mpi_uint *p;
-    MPI_VALIDATE_RET(X != NULL);
 
     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
@@ -138,14 +253,18 @@ int mbedtls_mpi_grow(mbedtls_mpi *X, size_t nblimbs)
 
         if (X->p != NULL) {
             memcpy(p, X->p, X->n * ciL);
-            mbedtls_mpi_zeroize(X->p, X->n);
-            if (X->use_mempool)
+
+            if (X->use_mempool) {
+                mbedtls_mpi_zeroize(X->p, X->n);
                 mempool_free(mbedtls_mpi_mempool, X->p);
-            else
-                mbedtls_free(X->p);
+            } else {
+                mbedtls_mpi_zeroize_and_free(X->p, X->n);
+            }
         }
 
-        X->n = nblimbs;
+        /* nblimbs fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
+         * fits, and we've checked that nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
+        X->n = (unsigned short) nblimbs;
         X->p = p;
     }
 
@@ -160,7 +279,6 @@ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
 {
     mbedtls_mpi_uint *p;
     size_t i;
-    MPI_VALIDATE_RET(X != NULL);
 
     if (nblimbs > MBEDTLS_MPI_MAX_LIMBS) {
         return MBEDTLS_ERR_MPI_ALLOC_FAILED;
@@ -195,14 +313,19 @@ int mbedtls_mpi_shrink(mbedtls_mpi *X, size_t nblimbs)
 
     if (X->p != NULL) {
         memcpy(p, X->p, i * ciL);
-        mbedtls_mpi_zeroize(X->p, X->n);
-        if (X->use_mempool)
+
+        if (X->use_mempool) {
+            mbedtls_mpi_zeroize(X->p, X->n);
             mempool_free(mbedtls_mpi_mempool, X->p);
-        else
-            mbedtls_free(X->p);
+        }
+        else {
+            mbedtls_mpi_zeroize_and_free(X->p, X->n);
+        }
     }
 
-    X->n = i;
+    /* i fits in n because we ensure that MBEDTLS_MPI_MAX_LIMBS
+     * fits, and we've checked that i <= nblimbs <= MBEDTLS_MPI_MAX_LIMBS. */
+    X->n = (unsigned short) i;
     X->p = p;
 
     return 0;
@@ -230,15 +353,12 @@ static int mbedtls_mpi_resize_clear(mbedtls_mpi *X, size_t limbs)
  * This function is not constant-time. Leading zeros in Y may be removed.
  *
  * Ensure that X does not shrink. This is not guaranteed by the public API,
- * but some code in the bignum module relies on this property, for example
- * in mbedtls_mpi_exp_mod().
+ * but some code in the bignum module might still rely on this property.
  */
 int mbedtls_mpi_copy(mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     int ret = 0;
     size_t i;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
 
     if (X == Y) {
         return 0;
@@ -280,8 +400,6 @@ cleanup:
 void mbedtls_mpi_swap(mbedtls_mpi *X, mbedtls_mpi *Y)
 {
     mbedtls_mpi T;
-    MPI_VALIDATE(X != NULL);
-    MPI_VALIDATE(Y != NULL);
 
     memcpy(&T,  X, sizeof(mbedtls_mpi));
     memcpy(X,  Y, sizeof(mbedtls_mpi));
@@ -300,19 +418,22 @@ static inline mbedtls_mpi_uint mpi_sint_abs(mbedtls_mpi_sint z)
     return (mbedtls_mpi_uint) 0 - (mbedtls_mpi_uint) z;
 }
 
+/* Convert x to a sign, i.e. to 1, if x is positive, or -1, if x is negative.
+ * This looks awkward but generates smaller code than (x < 0 ? -1 : 1) */
+#define TO_SIGN(x) ((mbedtls_mpi_sint) (((mbedtls_mpi_uint) x) >> (biL - 1)) * -2 + 1)
+
 /*
  * Set value from integer
  */
 int mbedtls_mpi_lset(mbedtls_mpi *X, mbedtls_mpi_sint z)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MPI_VALIDATE_RET(X != NULL);
 
     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, 1));
     memset(X->p, 0, X->n * ciL);
 
     X->p[0] = mpi_sint_abs(z);
-    X->s    = (z < 0) ? -1 : 1;
+    X->s    = TO_SIGN(z);
 
 cleanup:
 
@@ -324,8 +445,6 @@ cleanup:
  */
 int mbedtls_mpi_get_bit(const mbedtls_mpi *X, size_t pos)
 {
-    MPI_VALIDATE_RET(X != NULL);
-
     if (X->n * biL <= pos) {
         return 0;
     }
@@ -341,7 +460,6 @@ int mbedtls_mpi_set_bit(mbedtls_mpi *X, size_t pos, unsigned char val)
     int ret = 0;
     size_t off = pos / biL;
     size_t idx = pos % biL;
-    MPI_VALIDATE_RET(X != NULL);
 
     if (val != 0 && val != 1) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -368,16 +486,34 @@ cleanup:
  */
 size_t mbedtls_mpi_lsb(const mbedtls_mpi *X)
 {
-    size_t i, j, count = 0;
-    MBEDTLS_INTERNAL_VALIDATE_RET(X != NULL, 0);
+    size_t i;
+
+#if defined(__has_builtin)
+#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_ctz)
+    #define mbedtls_mpi_uint_ctz __builtin_ctz
+#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_ctzl)
+    #define mbedtls_mpi_uint_ctz __builtin_ctzl
+#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_ctzll)
+    #define mbedtls_mpi_uint_ctz __builtin_ctzll
+#endif
+#endif
 
+#if defined(mbedtls_mpi_uint_ctz)
     for (i = 0; i < X->n; i++) {
-        for (j = 0; j < biL; j++, count++) {
+        if (X->p[i] != 0) {
+            return i * biL + mbedtls_mpi_uint_ctz(X->p[i]);
+        }
+    }
+#else
+    size_t count = 0;
+    for (i = 0; i < X->n; i++) {
+        for (size_t j = 0; j < biL; j++, count++) {
             if (((X->p[i] >> j) & 1) != 0) {
                 return count;
             }
         }
     }
+#endif
 
     return 0;
 }
@@ -432,8 +568,6 @@ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
     int sign = 1;
     mbedtls_mpi_uint d;
     mbedtls_mpi T;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(s != NULL);
 
     if (radix < 2 || radix > 16) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -454,7 +588,7 @@ int mbedtls_mpi_read_string(mbedtls_mpi *X, int radix, const char *s)
     slen = strlen(s);
 
     if (radix == 16) {
-        if (slen > MPI_SIZE_T_MAX >> 2) {
+        if (slen > SIZE_MAX >> 2) {
             return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
         }
 
@@ -536,9 +670,6 @@ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
     size_t n;
     char *p;
     mbedtls_mpi T;
-    MPI_VALIDATE_RET(X    != NULL);
-    MPI_VALIDATE_RET(olen != NULL);
-    MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
 
     if (radix < 2 || radix > 16) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -604,7 +735,7 @@ int mbedtls_mpi_write_string(const mbedtls_mpi *X, int radix,
     }
 
     *p++ = '\0';
-    *olen = p - buf;
+    *olen = (size_t) (p - buf);
 
 cleanup:
 
@@ -628,9 +759,6 @@ int mbedtls_mpi_read_file(mbedtls_mpi *X, int radix, FILE *fin)
      */
     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
 
-    MPI_VALIDATE_RET(X   != NULL);
-    MPI_VALIDATE_RET(fin != NULL);
-
     if (radix < 2 || radix > 16) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
@@ -674,7 +802,6 @@ int mbedtls_mpi_write_file(const char *p, const mbedtls_mpi *X, int radix, FILE
      * newline characters and '\0'
      */
     char s[MBEDTLS_MPI_RW_BUFFER_SIZE];
-    MPI_VALIDATE_RET(X != NULL);
 
     if (radix < 2 || radix > 16) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -746,9 +873,6 @@ int mbedtls_mpi_read_binary(mbedtls_mpi *X, const unsigned char *buf, size_t buf
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const size_t limbs = CHARS_TO_LIMBS(buflen);
 
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(buflen == 0 || buf != NULL);
-
     /* Ensure that target MPI has exactly the necessary number of limbs */
     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
 
@@ -788,12 +912,7 @@ int mbedtls_mpi_write_binary(const mbedtls_mpi *X,
 int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, v0, t1;
-    mbedtls_mpi_uint r0 = 0, r1;
-    MPI_VALIDATE_RET(X != NULL);
-
-    v0 = count / (biL);
-    t1 = count & (biL - 1);
+    size_t i;
 
     i = mbedtls_mpi_bitlen(X) + count;
 
@@ -803,31 +922,7 @@ int mbedtls_mpi_shift_l(mbedtls_mpi *X, size_t count)
 
     ret = 0;
 
-    /*
-     * shift by count / limb_size
-     */
-    if (v0 > 0) {
-        for (i = X->n; i > v0; i--) {
-            X->p[i - 1] = X->p[i - v0 - 1];
-        }
-
-        for (; i > 0; i--) {
-            X->p[i - 1] = 0;
-        }
-    }
-
-    /*
-     * shift by count % limb_size
-     */
-    if (t1 > 0) {
-        for (i = v0; i < X->n; i++) {
-            r1 = X->p[i] >> (biL - t1);
-            X->p[i] <<= t1;
-            X->p[i] |= r0;
-            r0 = r1;
-        }
-    }
-
+    mbedtls_mpi_core_shift_l(X->p, X->n, count);
 cleanup:
 
     return ret;
@@ -838,7 +933,6 @@ cleanup:
  */
 int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
 {
-    MPI_VALIDATE_RET(X != NULL);
     if (X->n != 0) {
         mbedtls_mpi_core_shift_r(X->p, X->n, count);
     }
@@ -851,8 +945,6 @@ int mbedtls_mpi_shift_r(mbedtls_mpi *X, size_t count)
 int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     size_t i, j;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
 
     for (i = X->n; i > 0; i--) {
         if (X->p[i - 1] != 0) {
@@ -866,9 +958,8 @@ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
         }
     }
 
-    if (i == 0 && j == 0) {
-        return 0;
-    }
+    /* If i == j == 0, i.e. abs(X) == abs(Y),
+     * we end up returning 0 at the end of the function. */
 
     if (i > j) {
         return 1;
@@ -895,8 +986,6 @@ int mbedtls_mpi_cmp_abs(const mbedtls_mpi *X, const mbedtls_mpi *Y)
 int mbedtls_mpi_cmp_mpi(const mbedtls_mpi *X, const mbedtls_mpi *Y)
 {
     size_t i, j;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
 
     for (i = X->n; i > 0; i--) {
         if (X->p[i - 1] != 0) {
@@ -947,10 +1036,9 @@ int mbedtls_mpi_cmp_int(const mbedtls_mpi *X, mbedtls_mpi_sint z)
 {
     mbedtls_mpi Y;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET(X != NULL);
 
     *p  = mpi_sint_abs(z);
-    Y.s = (z < 0) ? -1 : 1;
+    Y.s = TO_SIGN(z);
     Y.n = 1;
     Y.p = p;
 
@@ -964,9 +1052,8 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t j;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
+    mbedtls_mpi_uint *p;
+    mbedtls_mpi_uint c;
 
     if (X == B) {
         const mbedtls_mpi *T = A; A = X; B = T;
@@ -997,9 +1084,9 @@ int mbedtls_mpi_add_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
 
     /* j is the number of non-zero limbs of B. Add those to X. */
 
-    mbedtls_mpi_uint *p = X->p;
+    p = X->p;
 
-    mbedtls_mpi_uint c = mbedtls_mpi_core_add(p, p, B->p, j);
+    c = mbedtls_mpi_core_add(p, p, B->p, j);
 
     p += j;
 
@@ -1027,9 +1114,6 @@ int mbedtls_mpi_sub_abs(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t n;
     mbedtls_mpi_uint carry;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
 
     for (n = B->n; n > 0; n--) {
         if (B->p[n - 1] != 0) {
@@ -1081,9 +1165,6 @@ static int add_sub_mpi(mbedtls_mpi *X,
                        int flip_B)
 {
     int ret, s;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
 
     s = A->s;
     if (A->s * B->s * flip_B < 0) {
@@ -1132,11 +1213,9 @@ int mbedtls_mpi_add_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
 
     p[0] = mpi_sint_abs(b);
-    B.s = (b < 0) ? -1 : 1;
+    B.s = TO_SIGN(b);
     B.n = 1;
     B.p = p;
 
@@ -1150,11 +1229,9 @@ int mbedtls_mpi_sub_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
 
     p[0] = mpi_sint_abs(b);
-    B.s = (b < 0) ? -1 : 1;
+    B.s = TO_SIGN(b);
     B.n = 1;
     B.p = p;
 
@@ -1170,11 +1247,9 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
     size_t i, j;
     mbedtls_mpi TA, TB;
     int result_is_zero = 0;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
 
-    mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
+    mbedtls_mpi_init_mempool(&TA);
+    mbedtls_mpi_init_mempool(&TB);
 
     if (X == A) {
         MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A)); A = &TA;
@@ -1204,13 +1279,7 @@ int mbedtls_mpi_mul_mpi(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
     MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, i + j));
     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(X, 0));
 
-    for (size_t k = 0; k < j; k++) {
-        /* We know that there cannot be any carry-out since we're
-         * iterating from bottom to top. */
-        (void) mbedtls_mpi_core_mla(X->p + k, i + 1,
-                                    A->p, i,
-                                    B->p[k]);
-    }
+    mbedtls_mpi_core_mul(X->p, A->p, i, B->p, j);
 
     /* If the result is 0, we don't shortcut the operation, which reduces
      * but does not eliminate side channels leaking the zero-ness. We do
@@ -1234,9 +1303,6 @@ cleanup:
  */
 int mbedtls_mpi_mul_int(mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b)
 {
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-
     size_t n = A->n;
     while (n > 0 && A->p[n - 1] == 0) {
         --n;
@@ -1382,8 +1448,6 @@ int mbedtls_mpi_div_mpi(mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A,
     size_t i, n, t, k;
     mbedtls_mpi X, Y, Z, T1, T2;
     mbedtls_mpi_uint TP2[3];
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
 
     if (mbedtls_mpi_cmp_int(B, 0) == 0) {
         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
@@ -1506,10 +1570,9 @@ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
 {
     mbedtls_mpi B;
     mbedtls_mpi_uint p[1];
-    MPI_VALIDATE_RET(A != NULL);
 
     p[0] = mpi_sint_abs(b);
-    B.s = (b < 0) ? -1 : 1;
+    B.s = TO_SIGN(b);
     B.n = 1;
     B.p = p;
 
@@ -1522,9 +1585,6 @@ int mbedtls_mpi_div_int(mbedtls_mpi *Q, mbedtls_mpi *R,
 int mbedtls_mpi_mod_mpi(mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    MPI_VALIDATE_RET(R != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
 
     if (mbedtls_mpi_cmp_int(B, 0) < 0) {
         return MBEDTLS_ERR_MPI_NEGATIVE_VALUE;
@@ -1552,8 +1612,6 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_s
 {
     size_t i;
     mbedtls_mpi_uint x, y, z;
-    MPI_VALIDATE_RET(r != NULL);
-    MPI_VALIDATE_RET(A != NULL);
 
     if (b == 0) {
         return MBEDTLS_ERR_MPI_DIVISION_BY_ZERO;
@@ -1604,16 +1662,15 @@ int mbedtls_mpi_mod_int(mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_s
     return 0;
 }
 
-static void mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
+/**
+ * \remark Replaced by our own because the original has been removed since
+ *         mbedtls v3.6.0.
+*/
+void mbedtls_mpi_montg_init(mbedtls_mpi_uint *mm, const mbedtls_mpi *N)
 {
     *mm = mbedtls_mpi_core_montmul_init(N->p);
 }
 
-void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
-{
-	mpi_montg_init( mm, N );
-}
-
 /** Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
  *
  * \param[in,out]   A   One of the numbers to multiply.
@@ -1634,27 +1691,25 @@ void mbedtls_mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N )
  *                      Its initial content is unused and
  *                      its final content is indeterminate.
  *                      It does not get reallocated.
+ * \remark Replaced by our own because the original has been removed since
+ *         mbedtls v3.6.0.
  */
-static void mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
+void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
                         const mbedtls_mpi *N, mbedtls_mpi_uint mm,
                         mbedtls_mpi *T)
 {
     mbedtls_mpi_core_montmul(A->p, A->p, B->p, B->n, N->p, N->n, mm, T->p);
 }
 
-void mbedtls_mpi_montmul(mbedtls_mpi *A, const mbedtls_mpi *B,
-                         const mbedtls_mpi *N, mbedtls_mpi_uint mm,
-                         mbedtls_mpi *T )
-{
-    mpi_montmul( A, B, N, mm, T);
-}
-
-/*
+/**
  * Montgomery reduction: A = A * R^-1 mod N
  *
- * See mpi_montmul() regarding constraints and guarantees on the parameters.
+ * See mbedtls_mpi_montmul() regarding constraints and guarantees on the parameters.
+ *
+ * \remark Replaced by our own because the original has been removed since
+ *         mbedtls v3.6.0.
  */
-static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
+void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
                         mbedtls_mpi_uint mm, mbedtls_mpi *T)
 {
     mbedtls_mpi_uint z = 1;
@@ -1663,66 +1718,18 @@ static void mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
     U.n = U.s = (int) z;
     U.p = &z;
 
-    mpi_montmul(A, &U, N, mm, T);
-}
-
-void mbedtls_mpi_montred(mbedtls_mpi *A, const mbedtls_mpi *N,
-                         mbedtls_mpi_uint mm, mbedtls_mpi *T)
-{
-    mpi_montred(A, N, mm, T);
-}
-
-/**
- * Select an MPI from a table without leaking the index.
- *
- * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it
- * reads the entire table in order to avoid leaking the value of idx to an
- * attacker able to observe memory access patterns.
- *
- * \param[out] R        Where to write the selected MPI.
- * \param[in] T         The table to read from.
- * \param[in] T_size    The number of elements in the table.
- * \param[in] idx       The index of the element to select;
- *                      this must satisfy 0 <= idx < T_size.
- *
- * \return \c 0 on success, or a negative error code.
- */
-static int mpi_select(mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    for (size_t i = 0; i < T_size; i++) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_safe_cond_assign(R, &T[i],
-                                                     (unsigned char) mbedtls_ct_size_bool_eq(i,
-                                                                                             idx)));
-    }
-
-cleanup:
-    return ret;
+    mbedtls_mpi_montmul(A, &U, N, mm, T);
 }
 
 /*
- * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
+ * this function is not constant time with respect to the exponent (parameter E).
  */
-int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
-                        const mbedtls_mpi *E, const mbedtls_mpi *N,
-                        mbedtls_mpi *prec_RR)
+static int mbedtls_mpi_exp_mod_optionally_safe(mbedtls_mpi *X, const mbedtls_mpi *A,
+                                               const mbedtls_mpi *E, int E_public,
+                                               const mbedtls_mpi *N, mbedtls_mpi *prec_RR)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t window_bitsize;
-    size_t i, j, nblimbs;
-    size_t bufsize, nbits;
-    size_t exponent_bits_in_window = 0;
-    mbedtls_mpi_uint ei, mm, state;
-    mbedtls_mpi RR, T, WW, Apos;
-    mbedtls_mpi *W;
-    const size_t array_size_W = 2 << MBEDTLS_MPI_WINDOW_SIZE;
-    int neg;
-
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(E != NULL);
-    MPI_VALIDATE_RET(N != NULL);
 
     if (mbedtls_mpi_cmp_int(N, 0) <= 0 || (N->p[0] & 1) == 0) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -1738,268 +1745,94 @@ int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
     }
 
     /*
-     * Init temps and window size
+     * Ensure that the exponent that we are passing to the core is not NULL.
      */
-    mpi_montg_init(&mm, N);
-    mbedtls_mpi_init_mempool(&RR); mbedtls_mpi_init(&T);
-    mbedtls_mpi_init_mempool(&Apos);
-    mbedtls_mpi_init_mempool(&WW);
-
-    i = mbedtls_mpi_bitlen(E);
-
-    window_bitsize = (i > 671) ? 6 : (i > 239) ? 5 :
-                     (i >  79) ? 4 : (i >  23) ? 3 : 1;
-
-#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
-    if (window_bitsize > MBEDTLS_MPI_WINDOW_SIZE) {
-        window_bitsize = MBEDTLS_MPI_WINDOW_SIZE;
+    if (E->n == 0) {
+        ret = mbedtls_mpi_lset(X, 1);
+        return ret;
     }
-#endif
 
-    const size_t w_table_used_size = (size_t) 1 << window_bitsize;
-
-    W = mempool_alloc(mbedtls_mpi_mempool,
-                      sizeof( mbedtls_mpi ) * array_size_W);
-    if (W == NULL) {
-        ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
-        goto cleanup;
-    }
-    for (i = 0; i < array_size_W; i++)
-        mbedtls_mpi_init_mempool(W + i);
     /*
-     * This function is not constant-trace: its memory accesses depend on the
-     * exponent value. To defend against timing attacks, callers (such as RSA
-     * and DHM) should use exponent blinding. However this is not enough if the
-     * adversary can find the exponent in a single trace, so this function
-     * takes extra precautions against adversaries who can observe memory
-     * access patterns.
-     *
-     * This function performs a series of multiplications by table elements and
-     * squarings, and we want the prevent the adversary from finding out which
-     * table element was used, and from distinguishing between multiplications
-     * and squarings. Firstly, when multiplying by an element of the window
-     * W[i], we do a constant-trace table lookup to obfuscate i. This leaves
-     * squarings as having a different memory access patterns from other
-     * multiplications. So secondly, we put the accumulator X in the table as
-     * well, and also do a constant-trace table lookup to multiply by X.
-     *
-     * This way, all multiplications take the form of a lookup-and-multiply.
-     * The number of lookup-and-multiply operations inside each iteration of
-     * the main loop still depends on the bits of the exponent, but since the
-     * other operations in the loop don't have an easily recognizable memory
-     * trace, an adversary is unlikely to be able to observe the exact
-     * patterns.
-     *
-     * An adversary may still be able to recover the exponent if they can
-     * observe both memory accesses and branches. However, branch prediction
-     * exploitation typically requires many traces of execution over the same
-     * data, which is defeated by randomized blinding.
-     *
-     * To achieve this, we make a copy of X and we use the table entry in each
-     * calculation from this point on.
-     */
-    const size_t x_index = 0;
-    mbedtls_mpi_copy(&W[x_index], X);
-
-    j = N->n + 1;
-    /* All W[i] and X must have at least N->n limbs for the mpi_montmul()
-     * and mpi_montred() calls later. Here we ensure that W[1] and X are
-     * large enough, and later we'll grow other W[i] to the same length.
-     * They must not be shrunk midway through this function!
-     */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[x_index], j));
-
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&T, j * 2));
-
-    /*
-     * Compensate for negative A (and correct at the end)
+     * Allocate working memory for mbedtls_mpi_core_exp_mod()
      */
-    neg = (A->s == -1);
-    if (neg) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&Apos, A));
-        Apos.s = 1;
-        A = &Apos;
+    size_t T_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N->n, E->n);
+    mbedtls_mpi_uint *T = mempool_calloc(mbedtls_mpi_mempool, T_limbs,
+                                         sizeof(mbedtls_mpi_uint));
+    if (T == NULL) {
+        return MBEDTLS_ERR_MPI_ALLOC_FAILED;
     }
 
+    mbedtls_mpi RR;
+    mbedtls_mpi_init_mempool(&RR);
+
     /*
      * If 1st call, pre-compute R^2 mod N
      */
     if (prec_RR == NULL || prec_RR->p == NULL) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&RR, 1));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&RR, N->n * 2 * biL));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&RR, &RR, N));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
 
         if (prec_RR != NULL) {
-            memcpy(prec_RR, &RR, sizeof(mbedtls_mpi));
+            *prec_RR = RR;
         }
     } else {
-        memcpy(&RR, prec_RR, sizeof(mbedtls_mpi));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(prec_RR, N->n));
+        RR = *prec_RR;
     }
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1],  j));
-
     /*
-     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
+     * To preserve constness we need to make a copy of A. Using X for this to
+     * save memory.
      */
-    if (mbedtls_mpi_cmp_mpi(A, N) >= 0) {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&W[1], A, N));
-        /* This should be a no-op because W[1] is already that large before
-         * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow
-         * in mpi_montmul() below, so let's make sure. */
-        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[1], N->n + 1));
-    } else {
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[1], A));
-    }
-
-    /* Note that this is safe because W[1] always has at least N->n limbs
-     * (it grew above and was preserved by mbedtls_mpi_copy()). */
-    mpi_montmul(&W[1], &RR, N, mm, &T);
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(X, A));
 
     /*
-     * W[x_index] = R^2 * R^-1 mod N = R mod N
+     * Compensate for negative A (and correct at the end).
      */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[x_index], &RR));
-    mpi_montred(&W[x_index], N, mm, &T);
-
-
-    if (window_bitsize > 1) {
-        /*
-         * W[i] = W[1] ^ i
-         *
-         * The first bit of the sliding window is always 1 and therefore we
-         * only need to store the second half of the table.
-         *
-         * (There are two special elements in the table: W[0] for the
-         * accumulator/result and W[1] for A in Montgomery form. Both of these
-         * are already set at this point.)
-         */
-        j = w_table_used_size / 2;
-
-        MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[j], N->n + 1));
-        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[j], &W[1]));
-
-        for (i = 0; i < window_bitsize - 1; i++) {
-            mpi_montmul(&W[j], &W[j], N, mm, &T);
-        }
-
-        /*
-         * W[i] = W[i - 1] * W[1]
-         */
-        for (i = j + 1; i < w_table_used_size; i++) {
-            MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&W[i], N->n + 1));
-            MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&W[i], &W[i - 1]));
-
-            mpi_montmul(&W[i], &W[1], N, mm, &T);
-        }
-    }
-
-    nblimbs = E->n;
-    bufsize = 0;
-    nbits   = 0;
-    state   = 0;
-
-    while (1) {
-        if (bufsize == 0) {
-            if (nblimbs == 0) {
-                break;
-            }
-
-            nblimbs--;
-
-            bufsize = sizeof(mbedtls_mpi_uint) << 3;
-        }
-
-        bufsize--;
-
-        ei = (E->p[nblimbs] >> bufsize) & 1;
-
-        /*
-         * skip leading 0s
-         */
-        if (ei == 0 && state == 0) {
-            continue;
-        }
-
-        if (ei == 0 && state == 1) {
-            /*
-             * out of window, square W[x_index]
-             */
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
-            continue;
-        }
-
-        /*
-         * add ei to current window
-         */
-        state = 2;
-
-        nbits++;
-        exponent_bits_in_window |= (ei << (window_bitsize - nbits));
-
-        if (nbits == window_bitsize) {
-            /*
-             * W[x_index] = W[x_index]^window_bitsize R^-1 mod N
-             */
-            for (i = 0; i < window_bitsize; i++) {
-                MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
-                                           x_index));
-                mpi_montmul(&W[x_index], &WW, N, mm, &T);
-            }
-
-            /*
-             * W[x_index] = W[x_index] * W[exponent_bits_in_window] R^-1 mod N
-             */
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size,
-                                       exponent_bits_in_window));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
+    X->s = 1;
 
-            state--;
-            nbits = 0;
-            exponent_bits_in_window = 0;
-        }
+    /*
+     * Make sure that X is in a form that is safe for consumption by
+     * the core functions.
+     *
+     * - The core functions will not touch the limbs of X above N->n. The
+     *   result will be correct if those limbs are 0, which the mod call
+     *   ensures.
+     * - Also, X must have at least as many limbs as N for the calls to the
+     *   core functions.
+     */
+    if (mbedtls_mpi_cmp_mpi(X, N) >= 0) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(X, X, N));
     }
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, N->n));
 
     /*
-     * process the remaining bits
+     * Convert to and from Montgomery around mbedtls_mpi_core_exp_mod().
      */
-    for (i = 0; i < nbits; i++) {
-        MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, x_index));
-        mpi_montmul(&W[x_index], &WW, N, mm, &T);
-
-        exponent_bits_in_window <<= 1;
-
-        if ((exponent_bits_in_window & ((size_t) 1 << window_bitsize)) != 0) {
-            MBEDTLS_MPI_CHK(mpi_select(&WW, W, w_table_used_size, 1));
-            mpi_montmul(&W[x_index], &WW, N, mm, &T);
+    {
+        mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
+        mbedtls_mpi_core_to_mont_rep(X->p, X->p, N->p, N->n, mm, RR.p, T);
+        if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
+            mbedtls_mpi_core_exp_mod_unsafe(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
+        } else {
+            mbedtls_mpi_core_exp_mod(X->p, X->p, N->p, N->n, E->p, E->n, RR.p, T);
         }
+        mbedtls_mpi_core_from_mont_rep(X->p, X->p, N->p, N->n, mm, T);
     }
 
     /*
-     * W[x_index] = A^E * R * R^-1 mod N = A^E mod N
+     * Correct for negative A.
      */
-    mpi_montred(&W[x_index], N, mm, &T);
+    if (A->s == -1 && (E->p[0] & 1) != 0) {
+        mbedtls_ct_condition_t is_x_non_zero = mbedtls_mpi_core_check_zero_ct(X->p, X->n);
+        X->s = mbedtls_ct_mpi_sign_if(is_x_non_zero, -1, 1);
 
-    if (neg && E->n != 0 && (E->p[0] & 1) != 0) {
-        W[x_index].s = -1;
-        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&W[x_index], N, &W[x_index]));
+        MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(X, N, X));
     }
 
-    /*
-     * Load the result in the output variable.
-     */
-    mbedtls_mpi_copy(X, &W[x_index]);
-
 cleanup:
 
-    if (W)
-        for (i = 0; i < array_size_W; i++)
-            mbedtls_mpi_free(W + i);
-    mempool_free(mbedtls_mpi_mempool , W);
-
-    mbedtls_mpi_free(&T);
-    mbedtls_mpi_free(&Apos);
-    mbedtls_mpi_free(&WW);
+    mbedtls_mpi_zeroize(T, T_limbs);
+    mempool_free(mbedtls_mpi_mempool, T);
 
     if (prec_RR == NULL || prec_RR->p == NULL) {
         mbedtls_mpi_free(&RR);
@@ -2008,6 +1841,29 @@ cleanup:
     return ret;
 }
 
+int mbedtls_mpi_exp_mod(mbedtls_mpi *X, const mbedtls_mpi *A,
+                        const mbedtls_mpi *E, const mbedtls_mpi *N,
+                        mbedtls_mpi *prec_RR)
+{
+#if (defined(__KERNEL__) && defined(CFG_CORE_UNSAFE_MODEXP)) || \
+    (!defined(__KERNEL__) && defined(CFG_TA_MEBDTLS_UNSAFE_MODEXP))
+    return mbedtls_mpi_exp_mod_unsafe(X, A, E, N, prec_RR);
+#else
+    return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_SECRET, N, prec_RR);
+#endif
+}
+
+
+/*
+ * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
+ */
+int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
+                               const mbedtls_mpi *E, const mbedtls_mpi *N,
+                               mbedtls_mpi *prec_RR)
+{
+    return mbedtls_mpi_exp_mod_optionally_safe(X, A, E, MBEDTLS_MPI_IS_PUBLIC, N, prec_RR);
+}
+
 /*
  * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
  */
@@ -2017,10 +1873,6 @@ int mbedtls_mpi_gcd(mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B)
     size_t lz, lzt;
     mbedtls_mpi TA, TB;
 
-    MPI_VALIDATE_RET(G != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(B != NULL);
-
     mbedtls_mpi_init_mempool(&TA); mbedtls_mpi_init_mempool(&TB);
 
     MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&TA, A));
@@ -2131,9 +1983,6 @@ int mbedtls_mpi_fill_random(mbedtls_mpi *X, size_t size,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const size_t limbs = CHARS_TO_LIMBS(size);
 
-    MPI_VALIDATE_RET(X     != NULL);
-    MPI_VALIDATE_RET(f_rng != NULL);
-
     /* Ensure that target MPI has exactly the necessary number of limbs */
     MBEDTLS_MPI_CHK(mbedtls_mpi_resize_clear(X, limbs));
     if (size == 0) {
@@ -2177,9 +2026,6 @@ int mbedtls_mpi_inv_mod(mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(A != NULL);
-    MPI_VALIDATE_RET(N != NULL);
 
     if (mbedtls_mpi_cmp_int(N, 1) <= 0) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
@@ -2265,29 +2111,30 @@ cleanup:
 
 #if defined(MBEDTLS_GENPRIME)
 
-static const int small_prime[] =
-{
-    3,    5,    7,   11,   13,   17,   19,   23,
-    29,   31,   37,   41,   43,   47,   53,   59,
-    61,   67,   71,   73,   79,   83,   89,   97,
-    101,  103,  107,  109,  113,  127,  131,  137,
-    139,  149,  151,  157,  163,  167,  173,  179,
-    181,  191,  193,  197,  199,  211,  223,  227,
-    229,  233,  239,  241,  251,  257,  263,  269,
-    271,  277,  281,  283,  293,  307,  311,  313,
-    317,  331,  337,  347,  349,  353,  359,  367,
-    373,  379,  383,  389,  397,  401,  409,  419,
-    421,  431,  433,  439,  443,  449,  457,  461,
-    463,  467,  479,  487,  491,  499,  503,  509,
-    521,  523,  541,  547,  557,  563,  569,  571,
-    577,  587,  593,  599,  601,  607,  613,  617,
-    619,  631,  641,  643,  647,  653,  659,  661,
-    673,  677,  683,  691,  701,  709,  719,  727,
-    733,  739,  743,  751,  757,  761,  769,  773,
-    787,  797,  809,  811,  821,  823,  827,  829,
-    839,  853,  857,  859,  863,  877,  881,  883,
-    887,  907,  911,  919,  929,  937,  941,  947,
-    953,  967,  971,  977,  983,  991,  997, -103
+/* Gaps between primes, starting at 3. https://oeis.org/A001223 */
+static const unsigned char small_prime_gaps[] = {
+    2, 2, 4, 2, 4, 2, 4, 6,
+    2, 6, 4, 2, 4, 6, 6, 2,
+    6, 4, 2, 6, 4, 6, 8, 4,
+    2, 4, 2, 4, 14, 4, 6, 2,
+    10, 2, 6, 6, 4, 6, 6, 2,
+    10, 2, 4, 2, 12, 12, 4, 2,
+    4, 6, 2, 10, 6, 6, 6, 2,
+    6, 4, 2, 10, 14, 4, 2, 4,
+    14, 6, 10, 2, 4, 6, 8, 6,
+    6, 4, 6, 8, 4, 8, 10, 2,
+    10, 2, 6, 4, 6, 8, 4, 2,
+    4, 12, 8, 4, 8, 4, 6, 12,
+    2, 18, 6, 10, 6, 6, 2, 6,
+    10, 6, 6, 2, 6, 6, 4, 2,
+    12, 10, 2, 4, 6, 6, 2, 12,
+    4, 6, 8, 10, 8, 10, 8, 6,
+    6, 4, 8, 6, 4, 8, 4, 14,
+    10, 12, 2, 10, 2, 4, 2, 10,
+    14, 4, 2, 4, 14, 4, 2, 4,
+    20, 4, 8, 10, 8, 4, 6, 6,
+    14, 4, 6, 6, 8, 6, /*reaches 997*/
+    0 /* the last entry is effectively unused */
 };
 
 /*
@@ -2304,20 +2151,20 @@ static int mpi_check_small_factors(const mbedtls_mpi *X)
     int ret = 0;
     size_t i;
     mbedtls_mpi_uint r;
+    unsigned p = 3; /* The first odd prime */
 
     if ((X->p[0] & 1) == 0) {
         return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
     }
 
-    for (i = 0; small_prime[i] > 0; i++) {
-        if (mbedtls_mpi_cmp_int(X, small_prime[i]) <= 0) {
-            return 1;
-        }
-
-        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, small_prime[i]));
-
+    for (i = 0; i < sizeof(small_prime_gaps); p += small_prime_gaps[i], i++) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_mod_int(&r, X, p));
         if (r == 0) {
-            return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            if (mbedtls_mpi_cmp_int(X, p) == 0) {
+                return 1;
+            } else {
+                return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
+            }
         }
     }
 
@@ -2336,9 +2183,6 @@ static int mpi_miller_rabin(const mbedtls_mpi *X, size_t rounds,
     size_t i, j, k, s;
     mbedtls_mpi W, R, T, A, RR;
 
-    MPI_VALIDATE_RET(X     != NULL);
-    MPI_VALIDATE_RET(f_rng != NULL);
-
     mbedtls_mpi_init_mempool(&W); mbedtls_mpi_init_mempool(&R);
     mbedtls_mpi_init_mempool(&T); mbedtls_mpi_init_mempool(&A);
     mbedtls_mpi_init_mempool(&RR);
@@ -2426,8 +2270,6 @@ int mbedtls_mpi_is_prime_ext(const mbedtls_mpi *X, int rounds,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_mpi XX;
-    MPI_VALIDATE_RET(X     != NULL);
-    MPI_VALIDATE_RET(f_rng != NULL);
 
     XX.s = 1;
     XX.n = X->n;
@@ -2477,9 +2319,6 @@ int mbedtls_mpi_gen_prime(mbedtls_mpi *X, size_t nbits, int flags,
     mbedtls_mpi_uint r;
     mbedtls_mpi Y;
 
-    MPI_VALIDATE_RET(X     != NULL);
-    MPI_VALIDATE_RET(f_rng != NULL);
-
     if (nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS) {
         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
diff --git a/lib/libmbedtls/mbedtls/library/bignum_core.c b/lib/libmbedtls/mbedtls/library/bignum_core.c
index e50f043c510332849502b33464440fe09687f70e..4231554b84175102cb609fa4fd6a8ca2fcd65e85 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_core.c
+++ b/lib/libmbedtls/mbedtls/library/bignum_core.c
@@ -2,19 +2,7 @@
  *  Core bignum functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -35,6 +23,18 @@
 
 size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)
 {
+#if defined(__has_builtin)
+#if (MBEDTLS_MPI_UINT_MAX == UINT_MAX) && __has_builtin(__builtin_clz)
+    #define core_clz __builtin_clz
+#elif (MBEDTLS_MPI_UINT_MAX == ULONG_MAX) && __has_builtin(__builtin_clzl)
+    #define core_clz __builtin_clzl
+#elif (MBEDTLS_MPI_UINT_MAX == ULLONG_MAX) && __has_builtin(__builtin_clzll)
+    #define core_clz __builtin_clzll
+#endif
+#endif
+#if defined(core_clz)
+    return (size_t) core_clz(a);
+#else
     size_t j;
     mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1);
 
@@ -47,41 +47,22 @@ size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a)
     }
 
     return j;
+#endif
 }
 
 size_t mbedtls_mpi_core_bitlen(const mbedtls_mpi_uint *A, size_t A_limbs)
 {
-    size_t i, j;
-
-    if (A_limbs == 0) {
-        return 0;
-    }
+    int i;
+    size_t j;
 
-    for (i = A_limbs - 1; i > 0; i--) {
+    for (i = ((int) A_limbs) - 1; i >= 0; i--) {
         if (A[i] != 0) {
-            break;
+            j = biL - mbedtls_mpi_core_clz(A[i]);
+            return (i * biL) + j;
         }
     }
 
-    j = biL - mbedtls_mpi_core_clz(A[i]);
-
-    return (i * biL) + j;
-}
-
-/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint
- * into the storage form used by mbedtls_mpi. */
-static mbedtls_mpi_uint mpi_bigendian_to_host_c(mbedtls_mpi_uint a)
-{
-    uint8_t i;
-    unsigned char *a_ptr;
-    mbedtls_mpi_uint tmp = 0;
-
-    for (i = 0, a_ptr = (unsigned char *) &a; i < ciL; i++, a_ptr++) {
-        tmp <<= CHAR_BIT;
-        tmp |= (mbedtls_mpi_uint) *a_ptr;
-    }
-
-    return tmp;
+    return 0;
 }
 
 static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a)
@@ -90,16 +71,11 @@ static mbedtls_mpi_uint mpi_bigendian_to_host(mbedtls_mpi_uint a)
         /* Nothing to do on bigendian systems. */
         return a;
     } else {
-        switch (sizeof(mbedtls_mpi_uint)) {
-            case 4:
-                return (mbedtls_mpi_uint) MBEDTLS_BSWAP32((uint32_t) a);
-            case 8:
-                return (mbedtls_mpi_uint) MBEDTLS_BSWAP64((uint64_t) a);
-        }
-
-        /* Fall back to C-based reordering if we don't know the byte order
-         * or we couldn't use a compiler-specific builtin. */
-        return mpi_bigendian_to_host_c(a);
+#if defined(MBEDTLS_HAVE_INT32)
+        return (mbedtls_mpi_uint) MBEDTLS_BSWAP32(a);
+#elif defined(MBEDTLS_HAVE_INT64)
+        return (mbedtls_mpi_uint) MBEDTLS_BSWAP64(a);
+#endif
     }
 }
 
@@ -135,54 +111,92 @@ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
 
 /* Whether min <= A, in constant time.
  * A_limbs must be at least 1. */
-unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
-                                      const mbedtls_mpi_uint *A,
-                                      size_t A_limbs)
+mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
+                                                    const mbedtls_mpi_uint *A,
+                                                    size_t A_limbs)
 {
     /* min <= least significant limb? */
-    unsigned min_le_lsl = 1 ^ mbedtls_ct_mpi_uint_lt(A[0], min);
+    mbedtls_ct_condition_t min_le_lsl = mbedtls_ct_uint_ge(A[0], min);
 
     /* limbs other than the least significant one are all zero? */
-    mbedtls_mpi_uint msll_mask = 0;
+    mbedtls_ct_condition_t msll_mask = MBEDTLS_CT_FALSE;
     for (size_t i = 1; i < A_limbs; i++) {
-        msll_mask |= A[i];
+        msll_mask = mbedtls_ct_bool_or(msll_mask, mbedtls_ct_bool(A[i]));
     }
-    /* The most significant limbs of A are not all zero iff msll_mask != 0. */
-    unsigned msll_nonzero = mbedtls_ct_mpi_uint_mask(msll_mask) & 1;
 
     /* min <= A iff the lowest limb of A is >= min or the other limbs
      * are not all zero. */
-    return min_le_lsl | msll_nonzero;
+    return mbedtls_ct_bool_or(msll_mask, min_le_lsl);
+}
+
+mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
+                                              const mbedtls_mpi_uint *B,
+                                              size_t limbs)
+{
+    mbedtls_ct_condition_t ret = MBEDTLS_CT_FALSE, cond = MBEDTLS_CT_FALSE, done = MBEDTLS_CT_FALSE;
+
+    for (size_t i = limbs; i > 0; i--) {
+        /*
+         * If B[i - 1] < A[i - 1] then A < B is false and the result must
+         * remain 0.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = mbedtls_ct_uint_lt(B[i - 1], A[i - 1]);
+        done = mbedtls_ct_bool_or(done, cond);
+
+        /*
+         * If A[i - 1] < B[i - 1] then A < B is true.
+         *
+         * Again even if we can make a decision, we just mark the result and
+         * the fact that we are done and continue looping.
+         */
+        cond = mbedtls_ct_uint_lt(A[i - 1], B[i - 1]);
+        ret  = mbedtls_ct_bool_or(ret, mbedtls_ct_bool_and(cond, mbedtls_ct_bool_not(done)));
+        done = mbedtls_ct_bool_or(done, cond);
+    }
+
+    /*
+     * If all the limbs were equal, then the numbers are equal, A < B is false
+     * and leaving the result 0 is correct.
+     */
+
+    return ret;
 }
 
 void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
                                   const mbedtls_mpi_uint *A,
                                   size_t limbs,
-                                  unsigned char assign)
+                                  mbedtls_ct_condition_t assign)
 {
     if (X == A) {
         return;
     }
 
-    mbedtls_ct_mpi_uint_cond_assign(limbs, X, A, assign);
+    /* This function is very performance-sensitive for RSA. For this reason
+     * we have the loop below, instead of calling mbedtls_ct_memcpy_if
+     * (this is more optimal since here we don't have to handle the case where
+     * we copy awkwardly sized data).
+     */
+    for (size_t i = 0; i < limbs; i++) {
+        X[i] = mbedtls_ct_mpi_uint_if(assign, A[i], X[i]);
+    }
 }
 
 void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
                                 mbedtls_mpi_uint *Y,
                                 size_t limbs,
-                                unsigned char swap)
+                                mbedtls_ct_condition_t swap)
 {
     if (X == Y) {
         return;
     }
 
-    /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */
-    mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(swap);
-
     for (size_t i = 0; i < limbs; i++) {
         mbedtls_mpi_uint tmp = X[i];
-        X[i] = (X[i] & ~limb_mask) | (Y[i] & limb_mask);
-        Y[i] = (Y[i] & ~limb_mask) | (tmp & limb_mask);
+        X[i] = mbedtls_ct_mpi_uint_if(swap, Y[i], X[i]);
+        Y[i] = mbedtls_ct_mpi_uint_if(swap, tmp, Y[i]);
     }
 }
 
@@ -353,6 +367,41 @@ void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,
     }
 }
 
+void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs,
+                              size_t count)
+{
+    size_t i, v0, v1;
+    mbedtls_mpi_uint r0 = 0, r1;
+
+    v0 = count / (biL);
+    v1 = count & (biL - 1);
+
+    /*
+     * shift by count / limb_size
+     */
+    if (v0 > 0) {
+        for (i = limbs; i > v0; i--) {
+            X[i - 1] = X[i - v0 - 1];
+        }
+
+        for (; i > 0; i--) {
+            X[i - 1] = 0;
+        }
+    }
+
+    /*
+     * shift by count % limb_size
+     */
+    if (v1 > 0) {
+        for (i = v0; i < limbs; i++) {
+            r1 = X[i] >> (biL - v1);
+            X[i] <<= v1;
+            X[i] |= r0;
+            r0 = r1;
+        }
+    }
+}
+
 mbedtls_mpi_uint mbedtls_mpi_core_add(mbedtls_mpi_uint *X,
                                       const mbedtls_mpi_uint *A,
                                       const mbedtls_mpi_uint *B,
@@ -378,11 +427,10 @@ mbedtls_mpi_uint mbedtls_mpi_core_add_if(mbedtls_mpi_uint *X,
 {
     mbedtls_mpi_uint c = 0;
 
-    /* all-bits 0 if cond is 0, all-bits 1 if cond is non-0 */
-    const mbedtls_mpi_uint mask = mbedtls_ct_mpi_uint_mask(cond);
+    mbedtls_ct_condition_t do_add = mbedtls_ct_bool(cond);
 
     for (size_t i = 0; i < limbs; i++) {
-        mbedtls_mpi_uint add = mask & A[i];
+        mbedtls_mpi_uint add = mbedtls_ct_mpi_uint_if_else_0(do_add, A[i]);
         mbedtls_mpi_uint t = c + X[i];
         c = (t < X[i]);
         t += add;
@@ -448,6 +496,17 @@ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *d, size_t d_len,
     return c;
 }
 
+void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,
+                          const mbedtls_mpi_uint *A, size_t A_limbs,
+                          const mbedtls_mpi_uint *B, size_t B_limbs)
+{
+    memset(X, 0, (A_limbs + B_limbs) * ciL);
+
+    for (size_t i = 0; i < B_limbs; i++) {
+        (void) mbedtls_mpi_core_mla(X + i, A_limbs + 1, A, A_limbs, B[i]);
+    }
+}
+
 /*
  * Fast Montgomery initialization (thanks to Tom St Denis).
  */
@@ -513,7 +572,11 @@ void mbedtls_mpi_core_montmul(mbedtls_mpi_uint *X,
      * So the correct return value is already in X if (carry ^ borrow) = 0,
      * but is in (the lower AN_limbs limbs of) T if (carry ^ borrow) = 1.
      */
-    mbedtls_ct_mpi_uint_cond_assign(AN_limbs, X, T, (unsigned char) (carry ^ borrow));
+    mbedtls_ct_memcpy_if(mbedtls_ct_bool(carry ^ borrow),
+                         (unsigned char *) X,
+                         (unsigned char *) T,
+                         NULL,
+                         AN_limbs * sizeof(mbedtls_mpi_uint));
 }
 
 int mbedtls_mpi_core_get_mont_r2_unsafe(mbedtls_mpi *X,
@@ -538,7 +601,7 @@ void mbedtls_mpi_core_ct_uint_table_lookup(mbedtls_mpi_uint *dest,
                                            size_t index)
 {
     for (size_t i = 0; i < count; i++, table += limbs) {
-        unsigned char assign = mbedtls_ct_size_bool_eq(i, index);
+        mbedtls_ct_condition_t assign = mbedtls_ct_uint_eq(i, index);
         mbedtls_mpi_core_cond_assign(dest, table, limbs, assign);
     }
 }
@@ -578,7 +641,7 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
                             int (*f_rng)(void *, unsigned char *, size_t),
                             void *p_rng)
 {
-    unsigned ge_lower = 1, lt_upper = 0;
+    mbedtls_ct_condition_t ge_lower = MBEDTLS_CT_TRUE, lt_upper = MBEDTLS_CT_FALSE;
     size_t n_bits = mbedtls_mpi_core_bitlen(N, limbs);
     size_t n_bytes = (n_bits + 7) / 8;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -623,26 +686,24 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
 
         ge_lower = mbedtls_mpi_core_uint_le_mpi(min, X, limbs);
         lt_upper = mbedtls_mpi_core_lt_ct(X, N, limbs);
-    } while (ge_lower == 0 || lt_upper == 0);
+    } while (mbedtls_ct_bool_and(ge_lower, lt_upper) == MBEDTLS_CT_FALSE);
 
 cleanup:
     return ret;
 }
 
-/* BEGIN MERGE SLOT 1 */
-
 static size_t exp_mod_get_window_size(size_t Ebits)
 {
-    size_t wsize = (Ebits > 671) ? 6 : (Ebits > 239) ? 5 :
-                   (Ebits >  79) ? 4 : 1;
-
-#if (MBEDTLS_MPI_WINDOW_SIZE < 6)
-    if (wsize > MBEDTLS_MPI_WINDOW_SIZE) {
-        wsize = MBEDTLS_MPI_WINDOW_SIZE;
-    }
+#if MBEDTLS_MPI_WINDOW_SIZE >= 6
+    return (Ebits > 671) ? 6 : (Ebits > 239) ? 5 : (Ebits >  79) ? 4 : 1;
+#elif MBEDTLS_MPI_WINDOW_SIZE == 5
+    return (Ebits > 239) ? 5 : (Ebits >  79) ? 4 : 1;
+#elif MBEDTLS_MPI_WINDOW_SIZE > 1
+    return (Ebits >  79) ? MBEDTLS_MPI_WINDOW_SIZE : 1;
+#else
+    (void) Ebits;
+    return 1;
 #endif
-
-    return wsize;
 }
 
 size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs)
@@ -685,7 +746,93 @@ static void exp_mod_precompute_window(const mbedtls_mpi_uint *A,
     }
 }
 
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+// Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET
+int mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1;
+#endif
+
+/*
+ * This function calculates the indices of the exponent where the exponentiation algorithm should
+ * start processing.
+ *
+ * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
+ * this function is not constant time with respect to the exponent (parameter E).
+ */
+static inline void exp_mod_calc_first_bit_optionally_safe(const mbedtls_mpi_uint *E,
+                                                          size_t E_limbs,
+                                                          int E_public,
+                                                          size_t *E_limb_index,
+                                                          size_t *E_bit_index)
+{
+    if (E_public == MBEDTLS_MPI_IS_PUBLIC) {
+        /*
+         * Skip leading zero bits.
+         */
+        size_t E_bits = mbedtls_mpi_core_bitlen(E, E_limbs);
+        if (E_bits == 0) {
+            /*
+             * If E is 0 mbedtls_mpi_core_bitlen() returns 0. Even if that is the case, we will want
+             * to represent it as a single 0 bit and as such the bitlength will be 1.
+             */
+            E_bits = 1;
+        }
+
+        *E_limb_index = E_bits / biL;
+        *E_bit_index = E_bits % biL;
+
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+        mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC;
+#endif
+    } else {
+        /*
+         * Here we need to be constant time with respect to E and can't do anything better than
+         * start at the first allocated bit.
+         */
+        *E_limb_index = E_limbs;
+        *E_bit_index = 0;
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+        // Only mark the codepath safe if there wasn't an unsafe codepath before
+        if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) {
+            mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET;
+        }
+#endif
+    }
+}
+
+/*
+ * Warning! If the parameter window_public has MBEDTLS_MPI_IS_PUBLIC as its value, this function is
+ * not constant time with respect to the window parameter and consequently the exponent of the
+ * exponentiation (parameter E of mbedtls_mpi_core_exp_mod_optionally_safe).
+ */
+static inline void exp_mod_table_lookup_optionally_safe(mbedtls_mpi_uint *Wselect,
+                                                        mbedtls_mpi_uint *Wtable,
+                                                        size_t AN_limbs, size_t welem,
+                                                        mbedtls_mpi_uint window,
+                                                        int window_public)
+{
+    if (window_public == MBEDTLS_MPI_IS_PUBLIC) {
+        memcpy(Wselect, Wtable + window * AN_limbs, AN_limbs * ciL);
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+        mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC;
+#endif
+    } else {
+        /* Select Wtable[window] without leaking window through
+         * memory access patterns. */
+        mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,
+                                              AN_limbs, welem, window);
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+        // Only mark the codepath safe if there wasn't an unsafe codepath before
+        if (mbedtls_mpi_optionally_safe_codepath != MBEDTLS_MPI_IS_PUBLIC) {
+            mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_SECRET;
+        }
+#endif
+    }
+}
+
 /* Exponentiation: X := A^E mod N.
+ *
+ * Warning! If the parameter E_public has MBEDTLS_MPI_IS_PUBLIC as its value,
+ * this function is not constant time with respect to the exponent (parameter E).
  *
  * A must already be in Montgomery form.
  *
@@ -697,16 +844,25 @@ static void exp_mod_precompute_window(const mbedtls_mpi_uint *A,
  * (The difference is that the body in our loop processes a single bit instead
  * of a full window.)
  */
-void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
-                              const mbedtls_mpi_uint *A,
-                              const mbedtls_mpi_uint *N,
-                              size_t AN_limbs,
-                              const mbedtls_mpi_uint *E,
-                              size_t E_limbs,
-                              const mbedtls_mpi_uint *RR,
-                              mbedtls_mpi_uint *T)
+static void mbedtls_mpi_core_exp_mod_optionally_safe(mbedtls_mpi_uint *X,
+                                                     const mbedtls_mpi_uint *A,
+                                                     const mbedtls_mpi_uint *N,
+                                                     size_t AN_limbs,
+                                                     const mbedtls_mpi_uint *E,
+                                                     size_t E_limbs,
+                                                     int E_public,
+                                                     const mbedtls_mpi_uint *RR,
+                                                     mbedtls_mpi_uint *T)
 {
-    const size_t wsize = exp_mod_get_window_size(E_limbs * biL);
+    /* We'll process the bits of E from most significant
+     * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
+     * (limb_index=0, E_bit_index=0). */
+    size_t E_limb_index;
+    size_t E_bit_index;
+    exp_mod_calc_first_bit_optionally_safe(E, E_limbs, E_public,
+                                           &E_limb_index, &E_bit_index);
+
+    const size_t wsize = exp_mod_get_window_size(E_limb_index * biL);
     const size_t welem = ((size_t) 1) << wsize;
 
     /* This is how we will use the temporary storage T, which must have space
@@ -725,7 +881,7 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
 
     const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N);
 
-    /* Set Wtable[i] = A^(2^i) (in Montgomery representation) */
+    /* Set Wtable[i] = A^i (in Montgomery representation) */
     exp_mod_precompute_window(A, N, AN_limbs,
                               mm, RR,
                               welem, Wtable, temp);
@@ -737,11 +893,6 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
     /* X = 1 (in Montgomery presentation) initially */
     memcpy(X, Wtable, AN_limbs * ciL);
 
-    /* We'll process the bits of E from most significant
-     * (limb_index=E_limbs-1, E_bit_index=biL-1) to least significant
-     * (limb_index=0, E_bit_index=0). */
-    size_t E_limb_index = E_limbs;
-    size_t E_bit_index = 0;
     /* At any given time, window contains window_bits bits from E.
      * window_bits can go up to wsize. */
     size_t window_bits = 0;
@@ -767,10 +918,9 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
          * when we've finished processing the exponent. */
         if (window_bits == wsize ||
             (E_bit_index == 0 && E_limb_index == 0)) {
-            /* Select Wtable[window] without leaking window through
-             * memory access patterns. */
-            mbedtls_mpi_core_ct_uint_table_lookup(Wselect, Wtable,
-                                                  AN_limbs, welem, window);
+
+            exp_mod_table_lookup_optionally_safe(Wselect, Wtable, AN_limbs, welem,
+                                                 window, E_public);
             /* Multiply X by the selected element. */
             mbedtls_mpi_core_montmul(X, X, Wselect, AN_limbs, N, AN_limbs, mm,
                                      temp);
@@ -780,13 +930,41 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
     } while (!(E_bit_index == 0 && E_limb_index == 0));
 }
 
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
-
-/* END MERGE SLOT 2 */
+void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
+                              const mbedtls_mpi_uint *A,
+                              const mbedtls_mpi_uint *N, size_t AN_limbs,
+                              const mbedtls_mpi_uint *E, size_t E_limbs,
+                              const mbedtls_mpi_uint *RR,
+                              mbedtls_mpi_uint *T)
+{
+    mbedtls_mpi_core_exp_mod_optionally_safe(X,
+                                             A,
+                                             N,
+                                             AN_limbs,
+                                             E,
+                                             E_limbs,
+                                             MBEDTLS_MPI_IS_SECRET,
+                                             RR,
+                                             T);
+}
 
-/* BEGIN MERGE SLOT 3 */
+void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,
+                                     const mbedtls_mpi_uint *A,
+                                     const mbedtls_mpi_uint *N, size_t AN_limbs,
+                                     const mbedtls_mpi_uint *E, size_t E_limbs,
+                                     const mbedtls_mpi_uint *RR,
+                                     mbedtls_mpi_uint *T)
+{
+    mbedtls_mpi_core_exp_mod_optionally_safe(X,
+                                             A,
+                                             N,
+                                             AN_limbs,
+                                             E,
+                                             E_limbs,
+                                             MBEDTLS_MPI_IS_PUBLIC,
+                                             RR,
+                                             T);
+}
 
 mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
                                           const mbedtls_mpi_uint *A,
@@ -803,16 +981,17 @@ mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
     return c;
 }
 
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
-                                                size_t limbs)
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                      size_t limbs)
 {
+    volatile const mbedtls_mpi_uint *force_read_A = A;
     mbedtls_mpi_uint bits = 0;
 
     for (size_t i = 0; i < limbs; i++) {
-        bits |= A[i];
+        bits |= force_read_A[i];
     }
 
-    return bits;
+    return mbedtls_ct_bool(bits);
 }
 
 void mbedtls_mpi_core_to_mont_rep(mbedtls_mpi_uint *X,
@@ -838,34 +1017,4 @@ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
     mbedtls_mpi_core_montmul(X, A, &Rinv, 1, N, AN_limbs, mm, T);
 }
 
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
-
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
-
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
-
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
-
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
-
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
-
-/* END MERGE SLOT 9 */
-
-/* BEGIN MERGE SLOT 10 */
-
-/* END MERGE SLOT 10 */
-
 #endif /* MBEDTLS_BIGNUM_C */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_core.h b/lib/libmbedtls/mbedtls/library/bignum_core.h
index 05bc923d27e365ca318f99701e692e9051e6a397..cf6485a1480b0980af23dfa62d4b44571a01b85a 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_core.h
+++ b/lib/libmbedtls/mbedtls/library/bignum_core.h
@@ -62,19 +62,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_BIGNUM_CORE_H
@@ -86,6 +74,8 @@
 #include "mbedtls/bignum.h"
 #endif
 
+#include "constant_time_internal.h"
+
 #define ciL    (sizeof(mbedtls_mpi_uint))     /** chars in limb  */
 #define biL    (ciL << 3)                     /** bits  in limb  */
 #define biH    (ciL << 2)                     /** half limb size */
@@ -100,11 +90,35 @@
 #define GET_BYTE(X, i)                                \
     (((X)[(i) / ciL] >> (((i) % ciL) * 8)) & 0xff)
 
+/* Constants to identify whether a value is public or secret. If a parameter is marked as secret by
+ * this constant, the function must be constant time with respect to the parameter.
+ *
+ * This is only needed for functions with the _optionally_safe postfix. All other functions have
+ * fixed behavior that can't be changed at runtime and are constant time with respect to their
+ * parameters as prescribed by their documentation or by conventions in their module's documentation.
+ *
+ * Parameters should be named X_public where X is the name of the
+ * corresponding input parameter.
+ *
+ * Implementation should always check using
+ *  if (X_public == MBEDTLS_MPI_IS_PUBLIC) {
+ *      // unsafe path
+ *  } else {
+ *      // safe path
+ *  }
+ * not the other way round, in order to prevent misuse. (This is, if a value
+ * other than the two below is passed, default to the safe path.) */
+#define MBEDTLS_MPI_IS_PUBLIC  0x2a2a2a2a
+#define MBEDTLS_MPI_IS_SECRET  0
+
 /** Count leading zero bits in a given integer.
+ *
+ * \warning     The result is undefined if \p a == 0
  *
  * \param a     Integer to count leading zero bits.
  *
- * \return      The number of leading zero bits in \p a.
+ * \return      The number of leading zero bits in \p a, if \p a != 0.
+ *              If \p a == 0, the result is undefined.
  */
 size_t mbedtls_mpi_core_clz(mbedtls_mpi_uint a);
 
@@ -139,11 +153,29 @@ void mbedtls_mpi_core_bigendian_to_host(mbedtls_mpi_uint *A,
  * \param A_limbs  The number of limbs of \p A.
  *                 This must be at least 1.
  *
- * \return         1 if \p min is less than or equal to \p A, otherwise 0.
+ * \return         MBEDTLS_CT_TRUE if \p min is less than or equal to \p A, otherwise MBEDTLS_CT_FALSE.
  */
-unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
-                                      const mbedtls_mpi_uint *A,
-                                      size_t A_limbs);
+mbedtls_ct_condition_t mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
+                                                    const mbedtls_mpi_uint *A,
+                                                    size_t A_limbs);
+
+/**
+ * \brief          Check if one unsigned MPI is less than another in constant
+ *                 time.
+ *
+ * \param A        The left-hand MPI. This must point to an array of limbs
+ *                 with the same allocated length as \p B.
+ * \param B        The right-hand MPI. This must point to an array of limbs
+ *                 with the same allocated length as \p A.
+ * \param limbs    The number of limbs in \p A and \p B.
+ *                 This must not be 0.
+ *
+ * \return         MBEDTLS_CT_TRUE  if \p A is less than \p B.
+ *                 MBEDTLS_CT_FALSE if \p A is greater than or equal to \p B.
+ */
+mbedtls_ct_condition_t mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
+                                              const mbedtls_mpi_uint *B,
+                                              size_t limbs);
 
 /**
  * \brief   Perform a safe conditional copy of an MPI which doesn't reveal
@@ -155,21 +187,17 @@ unsigned mbedtls_mpi_core_uint_le_mpi(mbedtls_mpi_uint min,
  * \param[in]  A        The address of the source MPI. This must be initialized.
  * \param      limbs    The number of limbs of \p A.
  * \param      assign   The condition deciding whether to perform the
- *                      assignment or not. Must be either 0 or 1:
- *                      * \c 1: Perform the assignment `X = A`.
- *                      * \c 0: Keep the original value of \p X.
+ *                      assignment or not. Callers will need to use
+ *                      the constant time interface (e.g. `mbedtls_ct_bool()`)
+ *                      to construct this argument.
  *
  * \note           This function avoids leaking any information about whether
  *                 the assignment was done or not.
- *
- * \warning        If \p assign is neither 0 nor 1, the result of this function
- *                 is indeterminate, and the resulting value in \p X might be
- *                 neither its original value nor the value in \p A.
  */
 void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
                                   const mbedtls_mpi_uint *A,
                                   size_t limbs,
-                                  unsigned char assign);
+                                  mbedtls_ct_condition_t assign);
 
 /**
  * \brief   Perform a safe conditional swap of two MPIs which doesn't reveal
@@ -181,21 +209,15 @@ void mbedtls_mpi_core_cond_assign(mbedtls_mpi_uint *X,
  *                          This must be initialized.
  * \param         limbs     The number of limbs of \p X and \p Y.
  * \param         swap      The condition deciding whether to perform
- *                          the swap or not. Must be either 0 or 1:
- *                          * \c 1: Swap the values of \p X and \p Y.
- *                          * \c 0: Keep the original values of \p X and \p Y.
+ *                          the swap or not.
  *
  * \note           This function avoids leaking any information about whether
  *                 the swap was done or not.
- *
- * \warning        If \p swap is neither 0 nor 1, the result of this function
- *                 is indeterminate, and both \p X and \p Y might end up with
- *                 values different to either of the original ones.
  */
 void mbedtls_mpi_core_cond_swap(mbedtls_mpi_uint *X,
                                 mbedtls_mpi_uint *Y,
                                 size_t limbs,
-                                unsigned char swap);
+                                mbedtls_ct_condition_t swap);
 
 /** Import X from unsigned binary data, little-endian.
  *
@@ -278,7 +300,7 @@ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A,
                               unsigned char *output,
                               size_t output_length);
 
-/** \brief              Shift an MPI right in place by a number of bits.
+/** \brief              Shift an MPI in-place right by a number of bits.
  *
  *                      Shifting by more bits than there are bit positions
  *                      in \p X is valid and results in setting \p X to 0.
@@ -293,6 +315,21 @@ int mbedtls_mpi_core_write_be(const mbedtls_mpi_uint *A,
 void mbedtls_mpi_core_shift_r(mbedtls_mpi_uint *X, size_t limbs,
                               size_t count);
 
+/**
+ * \brief               Shift an MPI in-place left by a number of bits.
+ *
+ *                      Shifting by more bits than there are bit positions
+ *                      in \p X will produce an unspecified result.
+ *
+ *                      This function's execution time depends on the value
+ *                      of \p count (and of course \p limbs).
+ * \param[in,out] X     The number to shift.
+ * \param limbs         The number of limbs of \p X. This must be at least 1.
+ * \param count         The number of bits to shift by.
+ */
+void mbedtls_mpi_core_shift_l(mbedtls_mpi_uint *X, size_t limbs,
+                              size_t count);
+
 /**
  * \brief Add two fixed-size large unsigned integers, returning the carry.
  *
@@ -398,6 +435,26 @@ mbedtls_mpi_uint mbedtls_mpi_core_mla(mbedtls_mpi_uint *X, size_t X_limbs,
                                       const mbedtls_mpi_uint *A, size_t A_limbs,
                                       mbedtls_mpi_uint b);
 
+/**
+ * \brief Perform a known-size multiplication
+ *
+ * \p X may not be aliased to any of the inputs for this function.
+ * \p A may be aliased to \p B.
+ *
+ * \param[out] X     The pointer to the (little-endian) array to receive
+ *                   the product of \p A_limbs and \p B_limbs.
+ *                   This must be of length \p A_limbs + \p B_limbs.
+ * \param[in] A      The pointer to the (little-endian) array
+ *                   representing the first factor.
+ * \param A_limbs    The number of limbs in \p A.
+ * \param[in] B      The pointer to the (little-endian) array
+ *                   representing the second factor.
+ * \param B_limbs    The number of limbs in \p B.
+ */
+void mbedtls_mpi_core_mul(mbedtls_mpi_uint *X,
+                          const mbedtls_mpi_uint *A, size_t A_limbs,
+                          const mbedtls_mpi_uint *B, size_t B_limbs);
+
 /**
  * \brief Calculate initialisation value for fast Montgomery modular
  *        multiplication
@@ -549,8 +606,6 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
                             int (*f_rng)(void *, unsigned char *, size_t),
                             void *p_rng);
 
-/* BEGIN MERGE SLOT 1 */
-
 /**
  * \brief          Returns the number of limbs of working memory required for
  *                 a call to `mbedtls_mpi_core_exp_mod()`.
@@ -570,6 +625,42 @@ int mbedtls_mpi_core_random(mbedtls_mpi_uint *X,
  */
 size_t mbedtls_mpi_core_exp_mod_working_limbs(size_t AN_limbs, size_t E_limbs);
 
+/**
+ * \brief            Perform a modular exponentiation with public or secret exponent:
+ *                   X = A^E mod N, where \p A is already in Montgomery form.
+ *
+ * \warning          This function is not constant time with respect to \p E (the exponent).
+ *
+ * \p X may be aliased to \p A, but not to \p RR or \p E, even if \p E_limbs ==
+ * \p AN_limbs.
+ *
+ * \param[out] X     The destination MPI, as a little endian array of length
+ *                   \p AN_limbs.
+ * \param[in] A      The base MPI, as a little endian array of length \p AN_limbs.
+ *                   Must be in Montgomery form.
+ * \param[in] N      The modulus, as a little endian array of length \p AN_limbs.
+ * \param AN_limbs   The number of limbs in \p X, \p A, \p N, \p RR.
+ * \param[in] E      The exponent, as a little endian array of length \p E_limbs.
+ * \param E_limbs    The number of limbs in \p E.
+ * \param[in] RR     The precomputed residue of 2^{2*biL} modulo N, as a little
+ *                   endian array of length \p AN_limbs.
+ * \param[in,out] T  Temporary storage of at least the number of limbs returned
+ *                   by `mbedtls_mpi_core_exp_mod_working_limbs()`.
+ *                   Its initial content is unused and its final content is
+ *                   indeterminate.
+ *                   It must not alias or otherwise overlap any of the other
+ *                   parameters.
+ *                   It is up to the caller to zeroize \p T when it is no
+ *                   longer needed, and before freeing it if it was dynamically
+ *                   allocated.
+ */
+void mbedtls_mpi_core_exp_mod_unsafe(mbedtls_mpi_uint *X,
+                                     const mbedtls_mpi_uint *A,
+                                     const mbedtls_mpi_uint *N, size_t AN_limbs,
+                                     const mbedtls_mpi_uint *E, size_t E_limbs,
+                                     const mbedtls_mpi_uint *RR,
+                                     mbedtls_mpi_uint *T);
+
 /**
  * \brief            Perform a modular exponentiation with secret exponent:
  *                   X = A^E mod N, where \p A is already in Montgomery form.
@@ -604,14 +695,6 @@ void mbedtls_mpi_core_exp_mod(mbedtls_mpi_uint *X,
                               const mbedtls_mpi_uint *RR,
                               mbedtls_mpi_uint *T);
 
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
-
-/* END MERGE SLOT 2 */
-
-/* BEGIN MERGE SLOT 3 */
-
 /**
  * \brief Subtract unsigned integer from known-size large unsigned integers.
  *        Return the borrow.
@@ -636,11 +719,11 @@ mbedtls_mpi_uint mbedtls_mpi_core_sub_int(mbedtls_mpi_uint *X,
  * \param[in] A   The MPI to test.
  * \param limbs   Number of limbs in \p A.
  *
- * \return        0 if `A == 0`
- *                non-0 (may be any value) if `A != 0`.
+ * \return        MBEDTLS_CT_FALSE if `A == 0`
+ *                MBEDTLS_CT_TRUE  if `A != 0`.
  */
-mbedtls_mpi_uint mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
-                                                size_t limbs);
+mbedtls_ct_condition_t mbedtls_mpi_core_check_zero_ct(const mbedtls_mpi_uint *A,
+                                                      size_t limbs);
 
 /**
  * \brief          Returns the number of limbs of working memory required for
@@ -734,34 +817,17 @@ void mbedtls_mpi_core_from_mont_rep(mbedtls_mpi_uint *X,
                                     mbedtls_mpi_uint mm,
                                     mbedtls_mpi_uint *T);
 
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
-
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
-
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
-
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
-
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
-
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
-
-/* END MERGE SLOT 9 */
-
-/* BEGIN MERGE SLOT 10 */
+/*
+ * Can't define thread local variables with our abstraction layer: do nothing if threading is on.
+ */
+#if defined(MBEDTLS_TEST_HOOKS) && !defined(MBEDTLS_THREADING_C)
+extern int mbedtls_mpi_optionally_safe_codepath;
 
-/* END MERGE SLOT 10 */
+static inline void mbedtls_mpi_optionally_safe_codepath_reset(void)
+{
+    // Set to a default that is neither MBEDTLS_MPI_IS_PUBLIC nor MBEDTLS_MPI_IS_SECRET
+    mbedtls_mpi_optionally_safe_codepath = MBEDTLS_MPI_IS_PUBLIC + MBEDTLS_MPI_IS_SECRET + 1;
+}
+#endif
 
 #endif /* MBEDTLS_BIGNUM_CORE_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_internal.h b/lib/libmbedtls/mbedtls/library/bignum_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..aceaf55ea2b8a39cc3c2bd1b25f33c79aa6d89e8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/bignum_internal.h
@@ -0,0 +1,50 @@
+/**
+ * \file bignum_internal.h
+ *
+ * \brief Internal-only bignum public-key cryptosystem API.
+ *
+ * This file declares bignum-related functions that are to be used
+ * only from within the Mbed TLS library itself.
+ *
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_BIGNUM_INTERNAL_H
+#define MBEDTLS_BIGNUM_INTERNAL_H
+
+/**
+ * \brief          Perform a modular exponentiation: X = A^E mod N
+ *
+ * \warning        This function is not constant time with respect to \p E (the exponent).
+ *
+ * \param X        The destination MPI. This must point to an initialized MPI.
+ *                 This must not alias E or N.
+ * \param A        The base of the exponentiation.
+ *                 This must point to an initialized MPI.
+ * \param E        The exponent MPI. This must point to an initialized MPI.
+ * \param N        The base for the modular reduction. This must point to an
+ *                 initialized MPI.
+ * \param prec_RR  A helper MPI depending solely on \p N which can be used to
+ *                 speed-up multiple modular exponentiations for the same value
+ *                 of \p N. This may be \c NULL. If it is not \c NULL, it must
+ *                 point to an initialized MPI. If it hasn't been used after
+ *                 the call to mbedtls_mpi_init(), this function will compute
+ *                 the helper value and store it in \p prec_RR for reuse on
+ *                 subsequent calls to this function. Otherwise, the function
+ *                 will assume that \p prec_RR holds the helper value set by a
+ *                 previous call to mbedtls_mpi_exp_mod(), and reuse it.
+ *
+ * \return         \c 0 if successful.
+ * \return         #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed.
+ * \return         #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or
+ *                 even, or if \c E is negative.
+ * \return         Another negative error code on different kinds of failures.
+ *
+ */
+int mbedtls_mpi_exp_mod_unsafe(mbedtls_mpi *X, const mbedtls_mpi *A,
+                               const mbedtls_mpi *E, const mbedtls_mpi *N,
+                               mbedtls_mpi *prec_RR);
+
+#endif /* bignum_internal.h */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod.c b/lib/libmbedtls/mbedtls/library/bignum_mod.c
index e986865a1baf6796cfbccd0e11e4babcbea4c851..dfd332a703413e45e9455a8b3f75289f1aa8d9aa 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_mod.c
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod.c
@@ -2,24 +2,12 @@
  *  Modular bignum functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
-#if defined(MBEDTLS_BIGNUM_C)
+#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
 
 #include <string.h>
 
@@ -80,15 +68,14 @@ void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N)
     switch (N->int_rep) {
         case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
             if (N->rep.mont.rr != NULL) {
-                mbedtls_platform_zeroize((mbedtls_mpi_uint *) N->rep.mont.rr,
+                mbedtls_zeroize_and_free((mbedtls_mpi_uint *) N->rep.mont.rr,
                                          N->limbs * sizeof(mbedtls_mpi_uint));
-                mbedtls_free((mbedtls_mpi_uint *) N->rep.mont.rr);
                 N->rep.mont.rr = NULL;
             }
             N->rep.mont.mm = 0;
             break;
         case MBEDTLS_MPI_MOD_REP_OPT_RED:
-            mbedtls_free(N->rep.ored);
+            N->rep.ored.modp = NULL;
             break;
         case MBEDTLS_MPI_MOD_REP_INVALID:
             break;
@@ -136,33 +123,25 @@ cleanup:
     return ret;
 }
 
-int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
-                                  const mbedtls_mpi_uint *p,
-                                  size_t p_limbs,
-                                  mbedtls_mpi_mod_rep_selector int_rep)
+static inline void standard_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                          const mbedtls_mpi_uint *p,
+                                          size_t p_limbs,
+                                          mbedtls_mpi_mod_rep_selector int_rep)
 {
-    int ret = 0;
-
     N->p = p;
     N->limbs = p_limbs;
     N->bits = mbedtls_mpi_core_bitlen(p, p_limbs);
+    N->int_rep = int_rep;
+}
 
-    switch (int_rep) {
-        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
-            N->int_rep = int_rep;
-            N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
-            ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
-            break;
-        case MBEDTLS_MPI_MOD_REP_OPT_RED:
-            N->int_rep = int_rep;
-            N->rep.ored = NULL;
-            break;
-        default:
-            ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-            goto exit;
-    }
-
-exit:
+int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                  const mbedtls_mpi_uint *p,
+                                  size_t p_limbs)
+{
+    int ret = 0;
+    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_MONTGOMERY);
+    N->rep.mont.mm = mbedtls_mpi_core_montmul_init(N->p);
+    ret = set_mont_const_square(&N->rep.mont.rr, N->p, N->limbs);
 
     if (ret != 0) {
         mbedtls_mpi_mod_modulus_free(N);
@@ -171,11 +150,15 @@ exit:
     return ret;
 }
 
-/* BEGIN MERGE SLOT 1 */
-
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
+int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                         const mbedtls_mpi_uint *p,
+                                         size_t p_limbs,
+                                         mbedtls_mpi_modp_fn modp)
+{
+    standard_modulus_setup(N, p, p_limbs, MBEDTLS_MPI_MOD_REP_OPT_RED);
+    N->rep.ored.modp = modp;
+    return 0;
+}
 
 int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
@@ -202,9 +185,6 @@ int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
     return 0;
 }
 
-/* END MERGE SLOT 2 */
-
-/* BEGIN MERGE SLOT 3 */
 int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
                         const mbedtls_mpi_mod_residue *B,
@@ -244,8 +224,7 @@ static int mbedtls_mpi_mod_inv_non_mont(mbedtls_mpi_mod_residue *X,
     mbedtls_mpi_mod_modulus Nmont;
     mbedtls_mpi_mod_modulus_init(&Nmont);
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs,
-                                                  MBEDTLS_MPI_MOD_REP_MONTGOMERY));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_modulus_setup(&Nmont, N->p, N->limbs));
 
     /* We'll use X->p to hold the Montgomery form of the input A->p */
     mbedtls_mpi_core_to_mont_rep(X->p, A->p, Nmont.p, Nmont.limbs,
@@ -303,19 +282,12 @@ int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
             break;
     }
 
-    mbedtls_platform_zeroize(working_memory,
+    mbedtls_zeroize_and_free(working_memory,
                              working_limbs * sizeof(mbedtls_mpi_uint));
-    mbedtls_free(working_memory);
 
     return ret;
 }
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
 
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
 int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
                         const mbedtls_mpi_mod_residue *B,
@@ -329,9 +301,6 @@ int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
 
     return 0;
 }
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
 
 int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
                            mbedtls_mpi_uint min,
@@ -345,9 +314,6 @@ int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
     return mbedtls_mpi_mod_raw_random(X->p, min, N, f_rng, p_rng);
 }
 
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
 int mbedtls_mpi_mod_read(mbedtls_mpi_mod_residue *r,
                          const mbedtls_mpi_mod_modulus *N,
                          const unsigned char *buf,
@@ -383,52 +349,46 @@ int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
                           size_t buflen,
                           mbedtls_mpi_mod_ext_rep ext_rep)
 {
-    int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-
     /* Do our best to check if r and m have been set up */
     if (r->limbs == 0 || N->limbs == 0) {
-        goto cleanup;
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
     if (r->limbs != N->limbs) {
-        goto cleanup;
+        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     }
 
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi_uint *working_memory = r->p;
+    size_t working_memory_len = sizeof(mbedtls_mpi_uint) * r->limbs;
+
     if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
-        ret = mbedtls_mpi_mod_raw_from_mont_rep(r->p, N);
-        if (ret != 0) {
+
+        working_memory = mbedtls_calloc(r->limbs, sizeof(mbedtls_mpi_uint));
+
+        if (working_memory == NULL) {
+            ret = MBEDTLS_ERR_MPI_ALLOC_FAILED;
             goto cleanup;
         }
-    }
 
-    ret = mbedtls_mpi_mod_raw_write(r->p, N, buf, buflen, ext_rep);
+        memcpy(working_memory, r->p, working_memory_len);
 
-    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY) {
-        /* If this fails, the value of r is corrupted and we want to return
-         * this error (as opposed to the error code from the write above) to
-         * let the caller know. If it succeeds, we want to return the error
-         * code from write above. */
-        int conv_ret = mbedtls_mpi_mod_raw_to_mont_rep(r->p, N);
-        if (ret == 0) {
-            ret = conv_ret;
+        ret = mbedtls_mpi_mod_raw_from_mont_rep(working_memory, N);
+        if (ret != 0) {
+            goto cleanup;
         }
     }
 
-cleanup:
-
-    return ret;
-}
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
+    ret = mbedtls_mpi_mod_raw_write(working_memory, N, buf, buflen, ext_rep);
 
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
+cleanup:
 
-/* END MERGE SLOT 9 */
+    if (N->int_rep == MBEDTLS_MPI_MOD_REP_MONTGOMERY &&
+        working_memory != NULL) {
 
-/* BEGIN MERGE SLOT 10 */
+        mbedtls_zeroize_and_free(working_memory, working_memory_len);
+    }
 
-/* END MERGE SLOT 10 */
+    return ret;
+}
 
-#endif /* MBEDTLS_BIGNUM_C */
+#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod.h b/lib/libmbedtls/mbedtls/library/bignum_mod.h
index d4c1d5d67574f24c9e0e0c4af8072d6db8a52cb4..963d8881ace57b188ccd26c303b4ea3935bb0dc4 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_mod.h
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod.h
@@ -63,19 +63,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_BIGNUM_MOD_H
@@ -98,10 +86,11 @@ typedef enum {
     /* Skip 1 as it is slightly easier to accidentally pass to functions. */
     /** Montgomery representation. */
     MBEDTLS_MPI_MOD_REP_MONTGOMERY = 2,
-    /** TODO: document this.
-     *
-     * Residues are in canonical representation.
-     */
+    /* Optimised reduction available. This indicates a coordinate modulus (P)
+     * and one or more of the following have been configured:
+     * - A nist curve (MBEDTLS_ECP_DP_SECPXXXR1_ENABLED) & MBEDTLS_ECP_NIST_OPTIM.
+     * - A Kobliz Curve.
+     * - A Fast Reduction Curve CURVE25519 or CURVE448. */
     MBEDTLS_MPI_MOD_REP_OPT_RED,
 } mbedtls_mpi_mod_rep_selector;
 
@@ -123,7 +112,11 @@ typedef struct {
     mbedtls_mpi_uint mm;         /* Montgomery const for -N^{-1} mod 2^{ciL} */
 } mbedtls_mpi_mont_struct;
 
-typedef void *mbedtls_mpi_opt_red_struct;
+typedef int (*mbedtls_mpi_modp_fn)(mbedtls_mpi_uint *X, size_t X_limbs);
+
+typedef struct {
+    mbedtls_mpi_modp_fn modp;    /* The optimised reduction function pointer */
+} mbedtls_mpi_opt_red_struct;
 
 typedef struct {
     const mbedtls_mpi_uint *p;
@@ -197,16 +190,29 @@ void mbedtls_mpi_mod_modulus_init(mbedtls_mpi_mod_modulus *N);
  *                  not be modified in any way until after
  *                  mbedtls_mpi_mod_modulus_free() is called.
  * \param p_limbs   The number of limbs of \p p.
- * \param int_rep   The internal representation to be used for residues
- *                  associated with \p N (see #mbedtls_mpi_mod_rep_selector).
  *
  * \return      \c 0 if successful.
- * \return      #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p int_rep is invalid.
  */
 int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
                                   const mbedtls_mpi_uint *p,
-                                  size_t p_limbs,
-                                  mbedtls_mpi_mod_rep_selector int_rep);
+                                  size_t p_limbs);
+
+/** Setup an optimised-reduction compatible modulus structure.
+ *
+ * \param[out] N    The address of the modulus structure to populate.
+ * \param[in] p     The address of the limb array storing the value of \p N.
+ *                  The memory pointed to by \p p will be used by \p N and must
+ *                  not be modified in any way until after
+ *                  mbedtls_mpi_mod_modulus_free() is called.
+ * \param p_limbs   The number of limbs of \p p.
+ * \param modp      A pointer to the optimised reduction function to use. \p p.
+ *
+ * \return      \c 0 if successful.
+ */
+int mbedtls_mpi_mod_optred_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                                         const mbedtls_mpi_uint *p,
+                                         size_t p_limbs,
+                                         mbedtls_mpi_modp_fn modp);
 
 /** Free elements of a modulus structure.
  *
@@ -220,12 +226,6 @@ int mbedtls_mpi_mod_modulus_setup(mbedtls_mpi_mod_modulus *N,
  */
 void mbedtls_mpi_mod_modulus_free(mbedtls_mpi_mod_modulus *N);
 
-/* BEGIN MERGE SLOT 1 */
-
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
-
 /** \brief  Multiply two residues, returning the residue modulo the specified
  *          modulus.
  *
@@ -260,9 +260,6 @@ int mbedtls_mpi_mod_mul(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *B,
                         const mbedtls_mpi_mod_modulus *N);
 
-/* END MERGE SLOT 2 */
-
-/* BEGIN MERGE SLOT 3 */
 /**
  * \brief Perform a fixed-size modular subtraction.
  *
@@ -321,13 +318,6 @@ int mbedtls_mpi_mod_sub(mbedtls_mpi_mod_residue *X,
 int mbedtls_mpi_mod_inv(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
                         const mbedtls_mpi_mod_modulus *N);
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
-
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
 /**
  * \brief Perform a fixed-size modular addition.
  *
@@ -358,9 +348,6 @@ int mbedtls_mpi_mod_add(mbedtls_mpi_mod_residue *X,
                         const mbedtls_mpi_mod_residue *A,
                         const mbedtls_mpi_mod_residue *B,
                         const mbedtls_mpi_mod_modulus *N);
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
 
 /** Generate a random number uniformly in a range.
  *
@@ -395,9 +382,6 @@ int mbedtls_mpi_mod_random(mbedtls_mpi_mod_residue *X,
                            int (*f_rng)(void *, unsigned char *, size_t),
                            void *p_rng);
 
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
 /** Read a residue from a byte buffer.
  *
  * The residue will be automatically converted to the internal representation
@@ -464,18 +448,5 @@ int mbedtls_mpi_mod_write(const mbedtls_mpi_mod_residue *r,
                           unsigned char *buf,
                           size_t buflen,
                           mbedtls_mpi_mod_ext_rep ext_rep);
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
-
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
-
-/* END MERGE SLOT 9 */
-
-/* BEGIN MERGE SLOT 10 */
-
-/* END MERGE SLOT 10 */
 
 #endif /* MBEDTLS_BIGNUM_MOD_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c
index bf0cb2524522521ebf4e91aa94e48764dd2a2e6f..5343bc650d1621d2f6fe4ace70ae69d5a9dc1145 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.c
@@ -2,24 +2,12 @@
  *  Low-level modular bignum functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
-#if defined(MBEDTLS_BIGNUM_C)
+#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ECP_WITH_MPI_UINT)
 
 #include <string.h>
 
@@ -40,7 +28,7 @@ void mbedtls_mpi_mod_raw_cond_assign(mbedtls_mpi_uint *X,
                                      const mbedtls_mpi_mod_modulus *N,
                                      unsigned char assign)
 {
-    mbedtls_mpi_core_cond_assign(X, A, N->limbs, assign);
+    mbedtls_mpi_core_cond_assign(X, A, N->limbs, mbedtls_ct_bool(assign));
 }
 
 void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
@@ -48,7 +36,7 @@ void mbedtls_mpi_mod_raw_cond_swap(mbedtls_mpi_uint *X,
                                    const mbedtls_mpi_mod_modulus *N,
                                    unsigned char swap)
 {
-    mbedtls_mpi_core_cond_swap(X, Y, N->limbs, swap);
+    mbedtls_mpi_core_cond_swap(X, Y, N->limbs, mbedtls_ct_bool(swap));
 }
 
 int mbedtls_mpi_mod_raw_read(mbedtls_mpi_uint *X,
@@ -104,12 +92,6 @@ int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
     }
 }
 
-/* BEGIN MERGE SLOT 1 */
-
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
-
 void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
                              const mbedtls_mpi_uint *B,
@@ -120,8 +102,6 @@ void mbedtls_mpi_mod_raw_sub(mbedtls_mpi_uint *X,
     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
 }
 
-#if defined(MBEDTLS_TEST_HOOKS)
-
 MBEDTLS_STATIC_TESTABLE
 void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
                                              const mbedtls_mpi_mod_modulus *N)
@@ -131,7 +111,6 @@ void mbedtls_mpi_mod_raw_fix_quasi_reduction(mbedtls_mpi_uint *X,
     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) c);
 }
 
-#endif /* MBEDTLS_TEST_HOOKS */
 
 void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
@@ -139,13 +118,32 @@ void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_mod_modulus *N,
                              mbedtls_mpi_uint *T)
 {
-    mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
-                             N->rep.mont.mm, T);
-}
+    /* Standard (A * B) multiplication stored into pre-allocated T
+     * buffer of fixed limb size of (2N + 1).
+     *
+     * The space may not not fully filled by when
+     * MBEDTLS_MPI_MOD_REP_OPT_RED is used. */
+    const size_t T_limbs = BITS_TO_LIMBS(N->bits) * 2;
+    switch (N->int_rep) {
+        case MBEDTLS_MPI_MOD_REP_MONTGOMERY:
+            mbedtls_mpi_core_montmul(X, A, B, N->limbs, N->p, N->limbs,
+                                     N->rep.mont.mm, T);
+            break;
+        case MBEDTLS_MPI_MOD_REP_OPT_RED:
+            mbedtls_mpi_core_mul(T, A, N->limbs, B, N->limbs);
 
-/* END MERGE SLOT 2 */
+            /* Optimised Reduction */
+            (*N->rep.ored.modp)(T, T_limbs);
 
-/* BEGIN MERGE SLOT 3 */
+            /* Convert back to canonical representation */
+            mbedtls_mpi_mod_raw_fix_quasi_reduction(T, N);
+            memcpy(X, T, N->limbs * sizeof(mbedtls_mpi_uint));
+            break;
+        default:
+            break;
+    }
+
+}
 
 size_t mbedtls_mpi_mod_raw_inv_prime_working_limbs(size_t AN_limbs)
 {
@@ -178,13 +176,6 @@ void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
                              RR, T + AN_limbs);
 }
 
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
-
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
 void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
                              const mbedtls_mpi_uint *B,
@@ -195,9 +186,6 @@ void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
     borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) (carry ^ borrow));
 }
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
 
 int mbedtls_mpi_mod_raw_canonical_to_modulus_rep(
     mbedtls_mpi_uint *X,
@@ -240,9 +228,6 @@ int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
     return mbedtls_mpi_mod_raw_canonical_to_modulus_rep(X, N);
 }
 
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
 int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
                                     const mbedtls_mpi_mod_modulus *N)
 {
@@ -256,8 +241,7 @@ int mbedtls_mpi_mod_raw_to_mont_rep(mbedtls_mpi_uint *X,
     mbedtls_mpi_core_to_mont_rep(X, X, N->p, N->limbs,
                                  N->rep.mont.mm, N->rep.mont.rr, T);
 
-    mbedtls_platform_zeroize(T, t_limbs * ciL);
-    mbedtls_free(T);
+    mbedtls_zeroize_and_free(T, t_limbs * ciL);
     return 0;
 }
 
@@ -273,8 +257,7 @@ int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
 
     mbedtls_mpi_core_from_mont_rep(X, X, N->p, N->limbs, N->rep.mont.mm, T);
 
-    mbedtls_platform_zeroize(T, t_limbs * ciL);
-    mbedtls_free(T);
+    mbedtls_zeroize_and_free(T, t_limbs * ciL);
     return 0;
 }
 
@@ -289,18 +272,5 @@ void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
     mbedtls_mpi_uint borrow = mbedtls_mpi_core_sub(X, X, N->p, N->limbs);
     (void) mbedtls_mpi_core_add_if(X, N->p, N->limbs, (unsigned) borrow);
 }
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
-
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
-
-/* END MERGE SLOT 9 */
-
-/* BEGIN MERGE SLOT 10 */
-
-/* END MERGE SLOT 10 */
 
-#endif /* MBEDTLS_BIGNUM_C */
+#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ECP_WITH_MPI_UINT */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h
index a32500fe81d752e7ae493ed728b74b3e74a2cdca..7bb4ca3cf528a0ac0ac4bbd5ae96bb47fb0d465f 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw.h
@@ -60,19 +60,7 @@
 
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_BIGNUM_MOD_RAW_H
@@ -187,12 +175,6 @@ int mbedtls_mpi_mod_raw_write(const mbedtls_mpi_uint *A,
                               size_t output_length,
                               mbedtls_mpi_mod_ext_rep ext_rep);
 
-/* BEGIN MERGE SLOT 1 */
-
-/* END MERGE SLOT 1 */
-
-/* BEGIN MERGE SLOT 2 */
-
 /** \brief  Subtract two MPIs, returning the residue modulo the specified
  *          modulus.
  *
@@ -250,10 +232,6 @@ void mbedtls_mpi_mod_raw_mul(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_mod_modulus *N,
                              mbedtls_mpi_uint *T);
 
-/* END MERGE SLOT 2 */
-
-/* BEGIN MERGE SLOT 3 */
-
 /**
  * \brief          Returns the number of limbs of working memory required for
  *                 a call to `mbedtls_mpi_mod_raw_inv_prime()`.
@@ -303,13 +281,6 @@ void mbedtls_mpi_mod_raw_inv_prime(mbedtls_mpi_uint *X,
                                    const mbedtls_mpi_uint *RR,
                                    mbedtls_mpi_uint *T);
 
-/* END MERGE SLOT 3 */
-
-/* BEGIN MERGE SLOT 4 */
-
-/* END MERGE SLOT 4 */
-
-/* BEGIN MERGE SLOT 5 */
 /**
  * \brief Perform a known-size modular addition.
  *
@@ -332,9 +303,6 @@ void mbedtls_mpi_mod_raw_add(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
                              const mbedtls_mpi_uint *B,
                              const mbedtls_mpi_mod_modulus *N);
-/* END MERGE SLOT 5 */
-
-/* BEGIN MERGE SLOT 6 */
 
 /** Convert an MPI from canonical representation (little-endian limb array)
  * to the representation associated with the modulus.
@@ -404,9 +372,6 @@ int mbedtls_mpi_mod_raw_random(mbedtls_mpi_uint *X,
                                int (*f_rng)(void *, unsigned char *, size_t),
                                void *p_rng);
 
-/* END MERGE SLOT 6 */
-
-/* BEGIN MERGE SLOT 7 */
 /** Convert an MPI into Montgomery form.
  *
  * \param X      The address of the MPI.
@@ -447,18 +412,5 @@ int mbedtls_mpi_mod_raw_from_mont_rep(mbedtls_mpi_uint *X,
 void mbedtls_mpi_mod_raw_neg(mbedtls_mpi_uint *X,
                              const mbedtls_mpi_uint *A,
                              const mbedtls_mpi_mod_modulus *N);
-/* END MERGE SLOT 7 */
-
-/* BEGIN MERGE SLOT 8 */
-
-/* END MERGE SLOT 8 */
-
-/* BEGIN MERGE SLOT 9 */
-
-/* END MERGE SLOT 9 */
-
-/* BEGIN MERGE SLOT 10 */
-
-/* END MERGE SLOT 10 */
 
 #endif /* MBEDTLS_BIGNUM_MOD_RAW_H */
diff --git a/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h b/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h
index ead83942c6059903ab18b3e5c436bb3126de5661..94a0d06cf0f86e799b72144b2db3d82278dd2c74 100644
--- a/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h
+++ b/lib/libmbedtls/mbedtls/library/bignum_mod_raw_invasive.h
@@ -6,19 +6,7 @@
  */
 /**
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_BIGNUM_MOD_RAW_INVASIVE_H
diff --git a/lib/libmbedtls/mbedtls/library/block_cipher.c b/lib/libmbedtls/mbedtls/library/block_cipher.c
new file mode 100644
index 0000000000000000000000000000000000000000..51cdcdf46bc9b902adaa90d44cebcedc1554ed39
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/block_cipher.c
@@ -0,0 +1,207 @@
+/**
+ * \file block_cipher.c
+ *
+ * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
+ * for use by the GCM and CCM modules.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "psa_util_internal.h"
+#endif
+
+#include "block_cipher_internal.h"
+
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+static psa_key_type_t psa_key_type_from_block_cipher_id(mbedtls_block_cipher_id_t cipher_id)
+{
+    switch (cipher_id) {
+#if defined(MBEDTLS_BLOCK_CIPHER_AES_VIA_PSA)
+        case MBEDTLS_BLOCK_CIPHER_ID_AES:
+            return PSA_KEY_TYPE_AES;
+#endif
+#if defined(MBEDTLS_BLOCK_CIPHER_ARIA_VIA_PSA)
+        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
+            return PSA_KEY_TYPE_ARIA;
+#endif
+#if defined(MBEDTLS_BLOCK_CIPHER_CAMELLIA_VIA_PSA)
+        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
+            return PSA_KEY_TYPE_CAMELLIA;
+#endif
+        default:
+            return PSA_KEY_TYPE_NONE;
+    }
+}
+
+static int mbedtls_cipher_error_from_psa(psa_status_t status)
+{
+    return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_cipher_errors,
+                                   psa_generic_status_to_mbedtls);
+}
+#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
+
+void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
+        psa_destroy_key(ctx->psa_key_id);
+        return;
+    }
+#endif
+    switch (ctx->id) {
+#if defined(MBEDTLS_AES_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_AES:
+            mbedtls_aes_free(&ctx->ctx.aes);
+            break;
+#endif
+#if defined(MBEDTLS_ARIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
+            mbedtls_aria_free(&ctx->ctx.aria);
+            break;
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
+            mbedtls_camellia_free(&ctx->ctx.camellia);
+            break;
+#endif
+        default:
+            break;
+    }
+    ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
+}
+
+int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
+                               mbedtls_cipher_id_t cipher_id)
+{
+    ctx->id = (cipher_id == MBEDTLS_CIPHER_ID_AES) ? MBEDTLS_BLOCK_CIPHER_ID_AES :
+              (cipher_id == MBEDTLS_CIPHER_ID_ARIA) ? MBEDTLS_BLOCK_CIPHER_ID_ARIA :
+              (cipher_id == MBEDTLS_CIPHER_ID_CAMELLIA) ? MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA :
+              MBEDTLS_BLOCK_CIPHER_ID_NONE;
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+    psa_key_type_t psa_key_type = psa_key_type_from_block_cipher_id(ctx->id);
+    if (psa_key_type != PSA_KEY_TYPE_NONE &&
+        psa_can_do_cipher(psa_key_type, PSA_ALG_ECB_NO_PADDING)) {
+        ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_PSA;
+        return 0;
+    }
+    ctx->engine = MBEDTLS_BLOCK_CIPHER_ENGINE_LEGACY;
+#endif
+
+    switch (ctx->id) {
+#if defined(MBEDTLS_AES_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_AES:
+            mbedtls_aes_init(&ctx->ctx.aes);
+            return 0;
+#endif
+#if defined(MBEDTLS_ARIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
+            mbedtls_aria_init(&ctx->ctx.aria);
+            return 0;
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
+            mbedtls_camellia_init(&ctx->ctx.camellia);
+            return 0;
+#endif
+        default:
+            ctx->id = MBEDTLS_BLOCK_CIPHER_ID_NONE;
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+    }
+}
+
+int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
+                                const unsigned char *key,
+                                unsigned key_bitlen)
+{
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
+        psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+        psa_status_t status;
+
+        psa_set_key_type(&key_attr, psa_key_type_from_block_cipher_id(ctx->id));
+        psa_set_key_bits(&key_attr, key_bitlen);
+        psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
+        psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
+
+        status = psa_import_key(&key_attr, key, PSA_BITS_TO_BYTES(key_bitlen), &ctx->psa_key_id);
+        if (status != PSA_SUCCESS) {
+            return mbedtls_cipher_error_from_psa(status);
+        }
+        psa_reset_key_attributes(&key_attr);
+
+        return 0;
+    }
+#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
+
+    switch (ctx->id) {
+#if defined(MBEDTLS_AES_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_AES:
+            return mbedtls_aes_setkey_enc(&ctx->ctx.aes, key, key_bitlen);
+#endif
+#if defined(MBEDTLS_ARIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
+            return mbedtls_aria_setkey_enc(&ctx->ctx.aria, key, key_bitlen);
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
+            return mbedtls_camellia_setkey_enc(&ctx->ctx.camellia, key, key_bitlen);
+#endif
+        default:
+            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+    }
+}
+
+int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
+                                 const unsigned char input[16],
+                                 unsigned char output[16])
+{
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+    if (ctx->engine == MBEDTLS_BLOCK_CIPHER_ENGINE_PSA) {
+        psa_status_t status;
+        size_t olen;
+
+        status = psa_cipher_encrypt(ctx->psa_key_id, PSA_ALG_ECB_NO_PADDING,
+                                    input, 16, output, 16, &olen);
+        if (status != PSA_SUCCESS) {
+            return mbedtls_cipher_error_from_psa(status);
+        }
+        return 0;
+    }
+#endif /* MBEDTLS_BLOCK_CIPHER_SOME_PSA */
+
+    switch (ctx->id) {
+#if defined(MBEDTLS_AES_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_AES:
+            return mbedtls_aes_crypt_ecb(&ctx->ctx.aes, MBEDTLS_AES_ENCRYPT,
+                                         input, output);
+#endif
+#if defined(MBEDTLS_ARIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_ARIA:
+            return mbedtls_aria_crypt_ecb(&ctx->ctx.aria, input, output);
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+        case MBEDTLS_BLOCK_CIPHER_ID_CAMELLIA:
+            return mbedtls_camellia_crypt_ecb(&ctx->ctx.camellia,
+                                              MBEDTLS_CAMELLIA_ENCRYPT,
+                                              input, output);
+#endif
+        default:
+            return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
+    }
+}
+
+#endif /* MBEDTLS_BLOCK_CIPHER_C */
diff --git a/lib/libmbedtls/mbedtls/library/block_cipher_internal.h b/lib/libmbedtls/mbedtls/library/block_cipher_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..c57338b751e0ecc84653239669f8698f8680a287
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/block_cipher_internal.h
@@ -0,0 +1,99 @@
+/**
+ * \file block_cipher_internal.h
+ *
+ * \brief Lightweight abstraction layer for block ciphers with 128 bit blocks,
+ * for use by the GCM and CCM modules.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_BLOCK_CIPHER_INTERNAL_H
+#define MBEDTLS_BLOCK_CIPHER_INTERNAL_H
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/cipher.h"
+
+#include "mbedtls/block_cipher.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief           Initialize the context.
+ *                  This must be the first API call before using the context.
+ *
+ * \param ctx       The context to initialize.
+ */
+static inline void mbedtls_block_cipher_init(mbedtls_block_cipher_context_t *ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+}
+
+/**
+ * \brief           Set the block cipher to use with this context.
+ *                  This must be called after mbedtls_block_cipher_init().
+ *
+ * \param ctx       The context to set up.
+ * \param cipher_id The identifier of the cipher to use.
+ *                  This must be either AES, ARIA or Camellia.
+ *                  Warning: this is a ::mbedtls_cipher_id_t,
+ *                  not a ::mbedtls_block_cipher_id_t!
+ *
+ * \retval          \c 0 on success.
+ * \retval          #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if \p cipher_id was
+ *                  invalid.
+ */
+int mbedtls_block_cipher_setup(mbedtls_block_cipher_context_t *ctx,
+                               mbedtls_cipher_id_t cipher_id);
+
+/**
+ * \brief           Set the key into the context.
+ *
+ * \param ctx       The context to configure.
+ * \param key       The buffer holding the key material.
+ * \param key_bitlen    The size of the key in bits.
+ *
+ * \retval          \c 0 on success.
+ * \retval          #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not
+ *                  properly set up before calling this function.
+ * \retval          One of #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH,
+ *                  #MBEDTLS_ERR_ARIA_BAD_INPUT_DATA,
+ *                  #MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA if \p key_bitlen is
+ *                  invalid.
+ */
+int mbedtls_block_cipher_setkey(mbedtls_block_cipher_context_t *ctx,
+                                const unsigned char *key,
+                                unsigned key_bitlen);
+
+/**
+ * \brief           Encrypt one block (16 bytes) with the configured key.
+ *
+ * \param ctx       The context holding the key.
+ * \param input     The buffer holding the input block. Must be 16 bytes.
+ * \param output    The buffer to which the output block will be written.
+ *                  Must be writable and 16 bytes long.
+ *                  This must either not overlap with \p input, or be equal.
+ *
+ * \retval          \c 0 on success.
+ * \retval          #MBEDTLS_ERR_CIPHER_INVALID_CONTEXT if the context was not
+ *                  properly set up before calling this function.
+ * \retval          Another negative value if encryption failed.
+ */
+int mbedtls_block_cipher_encrypt(mbedtls_block_cipher_context_t *ctx,
+                                 const unsigned char input[16],
+                                 unsigned char output[16]);
+/**
+ * \brief           Clear the context.
+ *
+ * \param ctx       The context to clear.
+ */
+void mbedtls_block_cipher_free(mbedtls_block_cipher_context_t *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MBEDTLS_BLOCK_CIPHER_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/bn_mul.h b/lib/libmbedtls/mbedtls/library/bn_mul.h
index ab59fbd64f2f2af641e8a66cd22b4c746f0858e9..0738469db4f0a194d2444b3439ec7b7240619386 100644
--- a/lib/libmbedtls/mbedtls/library/bn_mul.h
+++ b/lib/libmbedtls/mbedtls/library/bn_mul.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *      Multiply source vector [s] with b, add result
@@ -248,27 +236,39 @@
 
 #endif /* AMD64 */
 
-#if defined(__aarch64__)
+// The following assembly code assumes that a pointer will fit in a 64-bit register
+// (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1)
+#if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful)
 
+/*
+ * There are some issues around different compilers requiring different constraint
+ * syntax for updating pointers from assembly code (see notes for
+ * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32).
+ *
+ * For this reason we cast the pointers to/from uintptr_t here.
+ */
 #define MULADDC_X1_INIT             \
-    asm(
+    do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm(
 
 #define MULADDC_X1_CORE             \
-        "ldr x4, [%2], #8   \n\t"   \
-        "ldr x5, [%1]       \n\t"   \
+        "ldr x4, [%x2], #8  \n\t"   \
+        "ldr x5, [%x1]      \n\t"   \
         "mul x6, x4, %4     \n\t"   \
         "umulh x7, x4, %4   \n\t"   \
         "adds x5, x5, x6    \n\t"   \
         "adc x7, x7, xzr    \n\t"   \
         "adds x5, x5, %0    \n\t"   \
         "adc %0, x7, xzr    \n\t"   \
-        "str x5, [%1], #8   \n\t"
+        "str x5, [%x1], #8  \n\t"
 
 #define MULADDC_X1_STOP                                                 \
-         : "+r" (c),  "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d)  \
+         : "+r" (c),                                                    \
+           "+r" (muladdc_d),                                            \
+           "+r" (muladdc_s),                                            \
+           "+m" (*(uint64_t (*)[16]) d)                                 \
          : "r" (b), "m" (*(const uint64_t (*)[16]) s)                   \
          : "x4", "x5", "x6", "x7", "cc"                                 \
-    );
+    ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0);
 
 #endif /* Aarch64 */
 
@@ -658,6 +658,16 @@
 
 #endif /* TriCore */
 
+#if defined(__arm__)
+
+#if defined(__thumb__) && !defined(__thumb2__)
+#if defined(MBEDTLS_COMPILER_IS_GCC)
+/*
+ * Thumb 1 ISA. This code path has only been tested successfully on gcc;
+ * it does not compile on clang or armclang.
+ */
+
+#if !defined(__OPTIMIZE__) && defined(__GNUC__)
 /*
  * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about
  * our use of r7 below, unless -fomit-frame-pointer is passed.
@@ -666,32 +676,39 @@
  * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by
  * clang and armcc5 under the same conditions).
  *
- * So, only use the optimized assembly below for optimized build, which avoids
- * the build error and is pretty reasonable anyway.
+ * If gcc needs to use r7, we use r1 as a scratch register and have a few extra
+ * instructions to preserve/restore it; otherwise, we can use r7 and avoid
+ * the preserve/restore overhead.
  */
-#if defined(__GNUC__) && !defined(__OPTIMIZE__)
-#define MULADDC_CANNOT_USE_R7
-#endif
-
-#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7)
-
-#if defined(__thumb__) && !defined(__thumb2__)
+#define MULADDC_SCRATCH              "RS .req r1         \n\t"
+#define MULADDC_PRESERVE_SCRATCH     "mov    r10, r1     \n\t"
+#define MULADDC_RESTORE_SCRATCH      "mov    r1, r10     \n\t"
+#define MULADDC_SCRATCH_CLOBBER      "r10"
+#else /* !defined(__OPTIMIZE__) && defined(__GNUC__) */
+#define MULADDC_SCRATCH              "RS .req r7         \n\t"
+#define MULADDC_PRESERVE_SCRATCH     ""
+#define MULADDC_RESTORE_SCRATCH      ""
+#define MULADDC_SCRATCH_CLOBBER      "r7"
+#endif /* !defined(__OPTIMIZE__) && defined(__GNUC__) */
 
 #define MULADDC_X1_INIT                                 \
     asm(                                                \
+    MULADDC_SCRATCH                                     \
             "ldr    r0, %3                      \n\t"   \
             "ldr    r1, %4                      \n\t"   \
             "ldr    r2, %5                      \n\t"   \
             "ldr    r3, %6                      \n\t"   \
-            "lsr    r7, r3, #16                 \n\t"   \
-            "mov    r9, r7                      \n\t"   \
-            "lsl    r7, r3, #16                 \n\t"   \
-            "lsr    r7, r7, #16                 \n\t"   \
-            "mov    r8, r7                      \n\t"
+            "lsr    r4, r3, #16                 \n\t"   \
+            "mov    r9, r4                      \n\t"   \
+            "lsl    r4, r3, #16                 \n\t"   \
+            "lsr    r4, r4, #16                 \n\t"   \
+            "mov    r8, r4                      \n\t"   \
+
 
 #define MULADDC_X1_CORE                                 \
+            MULADDC_PRESERVE_SCRATCH                    \
             "ldmia  r0!, {r6}                   \n\t"   \
-            "lsr    r7, r6, #16                 \n\t"   \
+            "lsr    RS, r6, #16                 \n\t"   \
             "lsl    r6, r6, #16                 \n\t"   \
             "lsr    r6, r6, #16                 \n\t"   \
             "mov    r4, r8                      \n\t"   \
@@ -699,12 +716,12 @@
             "mov    r3, r9                      \n\t"   \
             "mul    r6, r3                      \n\t"   \
             "mov    r5, r9                      \n\t"   \
-            "mul    r5, r7                      \n\t"   \
+            "mul    r5, RS                      \n\t"   \
             "mov    r3, r8                      \n\t"   \
-            "mul    r7, r3                      \n\t"   \
+            "mul    RS, r3                      \n\t"   \
             "lsr    r3, r6, #16                 \n\t"   \
             "add    r5, r5, r3                  \n\t"   \
-            "lsr    r3, r7, #16                 \n\t"   \
+            "lsr    r3, RS, #16                 \n\t"   \
             "add    r5, r5, r3                  \n\t"   \
             "add    r4, r4, r2                  \n\t"   \
             "mov    r2, #0                      \n\t"   \
@@ -712,9 +729,10 @@
             "lsl    r3, r6, #16                 \n\t"   \
             "add    r4, r4, r3                  \n\t"   \
             "adc    r5, r2                      \n\t"   \
-            "lsl    r3, r7, #16                 \n\t"   \
+            "lsl    r3, RS, #16                 \n\t"   \
             "add    r4, r4, r3                  \n\t"   \
             "adc    r5, r2                      \n\t"   \
+            MULADDC_RESTORE_SCRATCH                     \
             "ldr    r3, [r1]                    \n\t"   \
             "add    r4, r4, r3                  \n\t"   \
             "adc    r2, r5                      \n\t"   \
@@ -727,11 +745,15 @@
          : "=m" (c),  "=m" (d), "=m" (s)        \
          : "m" (s), "m" (d), "m" (c), "m" (b)   \
          : "r0", "r1", "r2", "r3", "r4", "r5",  \
-           "r6", "r7", "r8", "r9", "cc"         \
+           "r6", MULADDC_SCRATCH_CLOBBER, "r8", "r9", "cc" \
          );
+#endif /* !defined(__ARMCC_VERSION) && !defined(__clang__) */
 
 #elif (__ARM_ARCH >= 6) && \
     defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1)
+/* Armv6-M (or later) with DSP Instruction Set Extensions.
+ * Requires support for either Thumb 2 or Arm ISA.
+ */
 
 #define MULADDC_X1_INIT                            \
     {                                              \
@@ -796,7 +818,7 @@
         );                                                   \
     }
 
-#else
+#else /* Thumb 2 or Arm ISA, without DSP extensions */
 
 #define MULADDC_X1_INIT                                 \
     asm(                                                \
@@ -810,9 +832,9 @@
             "mov    r5, #0                      \n\t"   \
             "ldr    r6, [r1]                    \n\t"   \
             "umlal  r2, r5, r3, r4              \n\t"   \
-            "adds   r7, r6, r2                  \n\t"   \
+            "adds   r4, r6, r2                  \n\t"   \
             "adc    r2, r5, #0                  \n\t"   \
-            "str    r7, [r1], #4                \n\t"
+            "str    r4, [r1], #4                \n\t"
 
 #define MULADDC_X1_STOP                                 \
             "str    r2, %0                      \n\t"   \
@@ -821,12 +843,12 @@
          : "=m" (c),  "=m" (d), "=m" (s)        \
          : "m" (s), "m" (d), "m" (c), "m" (b)   \
          : "r0", "r1", "r2", "r3", "r4", "r5",  \
-           "r6", "r7", "cc"                     \
+           "r6", "cc"                     \
          );
 
-#endif /* Thumb */
+#endif /* ISA codepath selection */
 
-#endif /* ARMv3 */
+#endif /* defined(__arm__) */
 
 #if defined(__alpha__)
 
diff --git a/lib/libmbedtls/mbedtls/library/camellia.c b/lib/libmbedtls/mbedtls/library/camellia.c
index 409727d04258410dd85b86ed70a2a29f69be1806..b1c0a08ca23ab020e37e91c1c2f7cebf8dab0fda 100644
--- a/lib/libmbedtls/mbedtls/library/camellia.c
+++ b/lib/libmbedtls/mbedtls/library/camellia.c
@@ -2,19 +2,7 @@
  *  Camellia implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The Camellia block cipher was designed by NTT and Mitsubishi Electric
@@ -411,6 +399,7 @@ int mbedtls_camellia_setkey_enc(mbedtls_camellia_context *ctx,
 /*
  * Camellia key schedule (decryption)
  */
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 int mbedtls_camellia_setkey_dec(mbedtls_camellia_context *ctx,
                                 const unsigned char *key,
                                 unsigned int keybits)
@@ -456,6 +445,7 @@ exit:
 
     return ret;
 }
+#endif /* !MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 
 /*
  * Camellia-ECB block encryption/decryption
@@ -900,14 +890,26 @@ int mbedtls_camellia_self_test(int verbose)
                            (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc");
         }
 
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+        if (v == MBEDTLS_CAMELLIA_DECRYPT) {
+            if (verbose != 0) {
+                mbedtls_printf("skipped\n");
+            }
+            continue;
+        }
+#endif
+
         for (i = 0; i < CAMELLIA_TESTS_ECB; i++) {
             memcpy(key, camellia_test_ecb_key[u][i], 16 + 8 * u);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
             if (v == MBEDTLS_CAMELLIA_DECRYPT) {
                 mbedtls_camellia_setkey_dec(&ctx, key, 128 + u * 64);
                 memcpy(src, camellia_test_ecb_cipher[u][i], 16);
                 memcpy(dst, camellia_test_ecb_plain[i], 16);
-            } else { /* MBEDTLS_CAMELLIA_ENCRYPT */
+            } else
+#endif
+            { /* MBEDTLS_CAMELLIA_ENCRYPT */
                 mbedtls_camellia_setkey_enc(&ctx, key, 128 + u * 64);
                 memcpy(src, camellia_test_ecb_plain[i], 16);
                 memcpy(dst, camellia_test_ecb_cipher[u][i], 16);
diff --git a/lib/libmbedtls/mbedtls/library/ccm.c b/lib/libmbedtls/mbedtls/library/ccm.c
index 36c999e7d73c9bf1ce1cefef5889252a9f4dfb0b..45ed697dd32164969b3d76b09d8ca08a72752055 100644
--- a/lib/libmbedtls/mbedtls/library/ccm.c
+++ b/lib/libmbedtls/mbedtls/library/ccm.c
@@ -2,19 +2,7 @@
  *  NIST SP800-38C compliant CCM implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -33,6 +21,11 @@
 #include "mbedtls/ccm.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
+
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+#include "block_cipher_internal.h"
+#endif
 
 #include <string.h>
 
@@ -62,6 +55,18 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
                        unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
+
+    if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+
+    if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
+        return MBEDTLS_ERR_CCM_BAD_INPUT;
+    }
+#else
     const mbedtls_cipher_info_t *cipher_info;
 
     cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
@@ -70,7 +75,7 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
         return MBEDTLS_ERR_CCM_BAD_INPUT;
     }
 
-    if (cipher_info->block_size != 16) {
+    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
         return MBEDTLS_ERR_CCM_BAD_INPUT;
     }
 
@@ -84,8 +89,9 @@ int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx,
                                      MBEDTLS_ENCRYPT)) != 0) {
         return ret;
     }
+#endif
 
-    return 0;
+    return ret;
 }
 
 /*
@@ -96,7 +102,11 @@ void mbedtls_ccm_free(mbedtls_ccm_context *ctx)
     if (ctx == NULL) {
         return;
     }
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
+#else
     mbedtls_cipher_free(&ctx->cipher_ctx);
+#endif
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ccm_context));
 }
 
@@ -115,12 +125,16 @@ static int mbedtls_ccm_crypt(mbedtls_ccm_context *ctx,
                              const unsigned char *input,
                              unsigned char *output)
 {
-    size_t olen = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char tmp_buf[16] = { 0 };
 
-    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf,
-                                     &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->ctr, tmp_buf);
+#else
+    size_t olen = 0;
+    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->ctr, 16, tmp_buf, &olen);
+#endif
+    if (ret != 0) {
         ctx->state |= CCM_STATE__ERROR;
         mbedtls_platform_zeroize(tmp_buf, sizeof(tmp_buf));
         return ret;
@@ -143,7 +157,10 @@ static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char i;
-    size_t len_left, olen;
+    size_t len_left;
+#if !defined(MBEDTLS_BLOCK_CIPHER_C)
+    size_t olen;
+#endif
 
     /* length calculation can be done only after both
      * mbedtls_ccm_starts() and mbedtls_ccm_set_lengths() have been executed
@@ -189,7 +206,12 @@ static int ccm_calculate_first_block_if_ready(mbedtls_ccm_context *ctx)
     }
 
     /* Start CBC-MAC with first block*/
-    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
+#else
+    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
+#endif
+    if (ret != 0) {
         ctx->state |= CCM_STATE__ERROR;
         return ret;
     }
@@ -269,7 +291,10 @@ int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,
                           size_t add_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t olen, use_len, offset;
+    size_t use_len, offset;
+#if !defined(MBEDTLS_BLOCK_CIPHER_C)
+    size_t olen;
+#endif
 
     if (ctx->state & CCM_STATE__ERROR) {
         return MBEDTLS_ERR_CCM_BAD_INPUT;
@@ -309,8 +334,12 @@ int mbedtls_ccm_update_ad(mbedtls_ccm_context *ctx,
             add += use_len;
 
             if (use_len + offset == 16 || ctx->processed == ctx->add_len) {
-                if ((ret =
-                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
+#else
+                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
+#endif
+                if (ret != 0) {
                     ctx->state |= CCM_STATE__ERROR;
                     return ret;
                 }
@@ -333,7 +362,10 @@ int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char i;
-    size_t use_len, offset, olen;
+    size_t use_len, offset;
+#if !defined(MBEDTLS_BLOCK_CIPHER_C)
+    size_t olen;
+#endif
 
     unsigned char local_output[16];
 
@@ -371,8 +403,12 @@ int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
             mbedtls_xor(ctx->y + offset, ctx->y + offset, input, use_len);
 
             if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
-                if ((ret =
-                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
+#else
+                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
+#endif
+                if (ret != 0) {
                     ctx->state |= CCM_STATE__ERROR;
                     goto exit;
                 }
@@ -400,11 +436,14 @@ int mbedtls_ccm_update(mbedtls_ccm_context *ctx,
             mbedtls_xor(ctx->y + offset, ctx->y + offset, local_output, use_len);
 
             memcpy(output, local_output, use_len);
-            mbedtls_platform_zeroize(local_output, 16);
 
             if (use_len + offset == 16 || ctx->processed == ctx->plaintext_len) {
-                if ((ret =
-                         mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+                ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->y);
+#else
+                ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->y, &olen);
+#endif
+                if (ret != 0) {
                     ctx->state |= CCM_STATE__ERROR;
                     goto exit;
                 }
@@ -533,13 +572,8 @@ static int mbedtls_ccm_compare_tags(const unsigned char *tag1,
                                     const unsigned char *tag2,
                                     size_t tag_len)
 {
-    unsigned char i;
-    int diff;
-
     /* Check tag in "constant-time" */
-    for (diff = 0, i = 0; i < tag_len; i++) {
-        diff |= tag1[i] ^ tag2[i];
-    }
+    int diff = mbedtls_ct_memcmp(tag1, tag2, tag_len);
 
     if (diff != 0) {
         return MBEDTLS_ERR_CCM_AUTH_FAILED;
@@ -594,7 +628,7 @@ int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length,
 }
 #endif /* !MBEDTLS_CCM_ALT */
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
 /*
  * Examples 1 to 3 from SP800-38C Appendix C
  */
diff --git a/lib/libmbedtls/mbedtls/library/chacha20.c b/lib/libmbedtls/mbedtls/library/chacha20.c
index cbb01f4adf733e409f6ea97006ef434766d4041e..acaae5b2e98d279c18cdedcd62a31efe8172584a 100644
--- a/lib/libmbedtls/mbedtls/library/chacha20.c
+++ b/lib/libmbedtls/mbedtls/library/chacha20.c
@@ -6,19 +6,7 @@
  * \author Daniel King <damaki.gh@gmail.com>
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
diff --git a/lib/libmbedtls/mbedtls/library/chachapoly.c b/lib/libmbedtls/mbedtls/library/chachapoly.c
index 0124d757016bbf83c20ea0ad14c743ff017088c6..a1314eab6dfba44204dfef4cf5a10e135fd09875 100644
--- a/lib/libmbedtls/mbedtls/library/chachapoly.c
+++ b/lib/libmbedtls/mbedtls/library/chachapoly.c
@@ -4,19 +4,7 @@
  * \brief ChaCha20-Poly1305 AEAD construction based on RFC 7539.
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #include "common.h"
 
@@ -25,6 +13,7 @@
 #include "mbedtls/chachapoly.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
 
 #include <string.h>
 
@@ -310,7 +299,6 @@ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char check_tag[16];
-    size_t i;
     int diff;
 
     if ((ret = chachapoly_crypt_and_tag(ctx,
@@ -320,9 +308,7 @@ int mbedtls_chachapoly_auth_decrypt(mbedtls_chachapoly_context *ctx,
     }
 
     /* Check tag in "constant-time" */
-    for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
-        diff |= tag[i] ^ check_tag[i];
-    }
+    diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
 
     if (diff != 0) {
         mbedtls_platform_zeroize(output, length);
diff --git a/lib/libmbedtls/mbedtls/library/check_crypto_config.h b/lib/libmbedtls/mbedtls/library/check_crypto_config.h
index 58175e374df1c6caea1835569fac8f65b2d3c489..6469e9f43939302af4d8e66656d24dde1e0bf13b 100644
--- a/lib/libmbedtls/mbedtls/library/check_crypto_config.h
+++ b/lib/libmbedtls/mbedtls/library/check_crypto_config.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -42,13 +30,13 @@
 #endif
 
 #if defined(PSA_WANT_ALG_DETERMINISTIC_ECDSA) && \
-    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
 #error "PSA_WANT_ALG_DETERMINISTIC_ECDSA defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_ECDSA) && \
-    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY))
 #error "PSA_WANT_ALG_ECDSA defined, but not all prerequisites"
 #endif
@@ -60,32 +48,84 @@
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) && \
-    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PKCS1V15_SIGN) && \
-    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PKCS1V15_SIGN defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_OAEP) && \
-    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_OAEP defined, but not all prerequisites"
 #endif
 
 #if defined(PSA_WANT_ALG_RSA_PSS) && \
-    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR) || \
+    !(defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
     defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY))
 #error "PSA_WANT_ALG_RSA_PSS defined, but not all prerequisites"
 #endif
 
-#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR) && \
+#if (defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) || \
+    defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)) && \
     !defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR defined, but not all prerequisites"
+#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx defined, but not all prerequisites"
+#endif
+
+#if (defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)) && \
+    !defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY)
+#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx defined, but not all prerequisites"
+#endif
+
+#if (defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)) && \
+    !defined(PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY)
+#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_xxx defined, but not all prerequisites"
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR)
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \
+    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \
+    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR is deprecated and will be removed in a \
+    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_xxx \
+    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
+#endif /* MBEDTLS_DEPRECATED_WARNING */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
+#if defined(MBEDTLS_DEPRECATED_REMOVED)
+#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \
+    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \
+    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
+#elif defined(MBEDTLS_DEPRECATED_WARNING)
+#warning "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR is deprecated and will be removed in a \
+    future version of Mbed TLS. Please switch to new PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_xxx \
+    symbols, where xxx can be: USE, IMPORT, EXPORT, GENERATE, DERIVE"
+#endif /* MBEDTLS_DEPRECATED_WARNING */
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE)
+#error "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_DERIVE defined, but feature is not supported"
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE)
+#error "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_DERIVE defined, but feature is not supported"
 #endif
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_USE_PSA_CRYPTO) && \
diff --git a/lib/libmbedtls/mbedtls/library/cipher.c b/lib/libmbedtls/mbedtls/library/cipher.c
index 2f57f95529cbba9266444712401f68ca46d9978a..a09540e9087d11204e8e6fabfbc62fa77ff38aa0 100644
--- a/lib/libmbedtls/mbedtls/library/cipher.c
+++ b/lib/libmbedtls/mbedtls/library/cipher.c
@@ -1,24 +1,12 @@
 /**
  * \file cipher.c
  *
- * \brief Generic cipher wrapper for mbed TLS
+ * \brief Generic cipher wrapper for Mbed TLS
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -30,6 +18,7 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "mbedtls/constant_time.h"
+#include "constant_time_internal.h"
 
 #include <stdlib.h>
 #include <string.h>
@@ -54,10 +43,9 @@
 #include "mbedtls/cmac.h"
 #endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_NIST_KW_C)
 #include "mbedtls/nist_kw.h"
@@ -67,6 +55,12 @@
 
 static int supported_init = 0;
 
+static inline const mbedtls_cipher_base_t *mbedtls_cipher_get_base(
+    const mbedtls_cipher_info_t *info)
+{
+    return mbedtls_cipher_base_lookup_table[info->base_idx];
+}
+
 const int *mbedtls_cipher_list(void)
 {
     const mbedtls_cipher_definition_t *def;
@@ -128,8 +122,8 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
     const mbedtls_cipher_definition_t *def;
 
     for (def = mbedtls_cipher_definitions; def->info != NULL; def++) {
-        if (def->info->base->cipher == cipher_id &&
-            def->info->key_bitlen == (unsigned) key_bitlen &&
+        if (mbedtls_cipher_get_base(def->info)->cipher == cipher_id &&
+            mbedtls_cipher_info_get_key_bitlen(def->info) == (unsigned) key_bitlen &&
             def->info->mode == mode) {
             return def->info;
         }
@@ -138,6 +132,72 @@ const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values(
     return NULL;
 }
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+static inline psa_key_type_t mbedtls_psa_translate_cipher_type(
+    mbedtls_cipher_type_t cipher)
+{
+    switch (cipher) {
+        case MBEDTLS_CIPHER_AES_128_CCM:
+        case MBEDTLS_CIPHER_AES_192_CCM:
+        case MBEDTLS_CIPHER_AES_256_CCM:
+        case MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG:
+        case MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG:
+        case MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG:
+        case MBEDTLS_CIPHER_AES_128_GCM:
+        case MBEDTLS_CIPHER_AES_192_GCM:
+        case MBEDTLS_CIPHER_AES_256_GCM:
+        case MBEDTLS_CIPHER_AES_128_CBC:
+        case MBEDTLS_CIPHER_AES_192_CBC:
+        case MBEDTLS_CIPHER_AES_256_CBC:
+        case MBEDTLS_CIPHER_AES_128_ECB:
+        case MBEDTLS_CIPHER_AES_192_ECB:
+        case MBEDTLS_CIPHER_AES_256_ECB:
+            return PSA_KEY_TYPE_AES;
+
+        /* ARIA not yet supported in PSA. */
+        /* case MBEDTLS_CIPHER_ARIA_128_CCM:
+           case MBEDTLS_CIPHER_ARIA_192_CCM:
+           case MBEDTLS_CIPHER_ARIA_256_CCM:
+           case MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG:
+           case MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG:
+           case MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG:
+           case MBEDTLS_CIPHER_ARIA_128_GCM:
+           case MBEDTLS_CIPHER_ARIA_192_GCM:
+           case MBEDTLS_CIPHER_ARIA_256_GCM:
+           case MBEDTLS_CIPHER_ARIA_128_CBC:
+           case MBEDTLS_CIPHER_ARIA_192_CBC:
+           case MBEDTLS_CIPHER_ARIA_256_CBC:
+               return( PSA_KEY_TYPE_ARIA ); */
+
+        default:
+            return 0;
+    }
+}
+
+static inline psa_algorithm_t mbedtls_psa_translate_cipher_mode(
+    mbedtls_cipher_mode_t mode, size_t taglen)
+{
+    switch (mode) {
+        case MBEDTLS_MODE_ECB:
+            return PSA_ALG_ECB_NO_PADDING;
+        case MBEDTLS_MODE_GCM:
+            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, taglen);
+        case MBEDTLS_MODE_CCM:
+            return PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen);
+        case MBEDTLS_MODE_CCM_STAR_NO_TAG:
+            return PSA_ALG_CCM_STAR_NO_TAG;
+        case MBEDTLS_MODE_CBC:
+            if (taglen == 0) {
+                return PSA_ALG_CBC_NO_PADDING;
+            } else {
+                return 0;
+            }
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
+
 void mbedtls_cipher_init(mbedtls_cipher_context_t *ctx)
 {
     memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
@@ -149,7 +209,7 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx)
         return;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         if (ctx->cipher_ctx != NULL) {
             mbedtls_cipher_context_psa * const cipher_psa =
@@ -160,25 +220,23 @@ void mbedtls_cipher_free(mbedtls_cipher_context_t *ctx)
                 (void) psa_destroy_key(cipher_psa->slot);
             }
 
-            mbedtls_platform_zeroize(cipher_psa, sizeof(*cipher_psa));
-            mbedtls_free(cipher_psa);
+            mbedtls_zeroize_and_free(cipher_psa, sizeof(*cipher_psa));
         }
 
         mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
         return;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_CMAC_C)
     if (ctx->cmac_ctx) {
-        mbedtls_platform_zeroize(ctx->cmac_ctx,
+        mbedtls_zeroize_and_free(ctx->cmac_ctx,
                                  sizeof(mbedtls_cmac_context_t));
-        mbedtls_free(ctx->cmac_ctx);
     }
 #endif
 
     if (ctx->cipher_ctx) {
-        ctx->cipher_info->base->ctx_free_func(ctx->cipher_ctx);
+        mbedtls_cipher_get_base(ctx->cipher_info)->ctx_free_func(ctx->cipher_ctx);
     }
 
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_cipher_context_t));
@@ -203,8 +261,8 @@ int mbedtls_cipher_clone(mbedtls_cipher_context_t *dst,
     dst->unprocessed_len = src->unprocessed_len;
     memcpy(dst->iv, src->iv, MBEDTLS_MAX_IV_LENGTH);
     dst->iv_size = src->iv_size;
-    if (dst->cipher_info->base->ctx_clone_func)
-        dst->cipher_info->base->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx);
+    if (mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func)
+        mbedtls_cipher_get_base(dst->cipher_info)->ctx_clone_func(dst->cipher_ctx, src->cipher_ctx);
 
 #if defined(MBEDTLS_CMAC_C)
     if (dst->cmac_ctx != NULL && src->cmac_ctx != NULL)
@@ -222,28 +280,19 @@ int mbedtls_cipher_setup(mbedtls_cipher_context_t *ctx,
 
     memset(ctx, 0, sizeof(mbedtls_cipher_context_t));
 
-    if (NULL == (ctx->cipher_ctx = cipher_info->base->ctx_alloc_func())) {
-        return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+    if (mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func != NULL) {
+        ctx->cipher_ctx = mbedtls_cipher_get_base(cipher_info)->ctx_alloc_func();
+        if (ctx->cipher_ctx == NULL) {
+            return MBEDTLS_ERR_CIPHER_ALLOC_FAILED;
+        }
     }
 
     ctx->cipher_info = cipher_info;
 
-#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
-    /*
-     * Ignore possible errors caused by a cipher mode that doesn't use padding
-     */
-#if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
-    (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_PKCS7);
-#else
-    (void) mbedtls_cipher_set_padding_mode(ctx, MBEDTLS_PADDING_NONE);
-#endif
-#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
-
     return 0;
 }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,
                              const mbedtls_cipher_info_t *cipher_info,
                              size_t taglen)
@@ -257,11 +306,11 @@ int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,
 
     /* Check that the underlying cipher mode and cipher type are
      * supported by the underlying PSA Crypto implementation. */
-    alg = mbedtls_psa_translate_cipher_mode(cipher_info->mode, taglen);
+    alg = mbedtls_psa_translate_cipher_mode(((mbedtls_cipher_mode_t) cipher_info->mode), taglen);
     if (alg == 0) {
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-    if (mbedtls_psa_translate_cipher_type(cipher_info->type) == 0) {
+    if (mbedtls_psa_translate_cipher_type(((mbedtls_cipher_type_t) cipher_info->type)) == 0) {
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
 
@@ -277,8 +326,7 @@ int mbedtls_cipher_setup_psa(mbedtls_cipher_context_t *ctx,
     ctx->psa_enabled = 1;
     return 0;
 }
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 int mbedtls_cipher_setup_info(mbedtls_cipher_context_t *ctx,
                               const mbedtls_cipher_info_t *cipher_info )
@@ -301,8 +349,14 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
     if (ctx->cipher_info == NULL) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+    if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) &&
+        MBEDTLS_DECRYPT == operation) {
+        return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
+    }
+#endif
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         mbedtls_cipher_context_psa * const cipher_psa =
             (mbedtls_cipher_context_psa *) ctx->cipher_ctx;
@@ -324,7 +378,7 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
         }
 
         key_type = mbedtls_psa_translate_cipher_type(
-            ctx->cipher_info->type);
+            ((mbedtls_cipher_type_t) ctx->cipher_info->type));
         if (key_type == 0) {
             return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         }
@@ -335,7 +389,6 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
          * and use it for AEAD decryption. Until tests relying on this
          * are changed, allow any usage in PSA. */
         psa_set_key_usage_flags(&attributes,
-                                /* mbedtls_psa_translate_cipher_operation( operation ); */
                                 PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
         psa_set_key_algorithm(&attributes, cipher_psa->alg);
 
@@ -359,31 +412,38 @@ int mbedtls_cipher_setkey(mbedtls_cipher_context_t *ctx,
         ctx->operation = operation;
         return 0;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN) == 0 &&
-        (int) ctx->cipher_info->key_bitlen != key_bitlen) {
+        (int) mbedtls_cipher_info_get_key_bitlen(ctx->cipher_info) != key_bitlen) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
     ctx->key_bitlen = key_bitlen;
     ctx->operation = operation;
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     /*
      * For OFB, CFB and CTR mode always use the encryption key schedule
      */
     if (MBEDTLS_ENCRYPT == operation ||
-        MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_CTR == ctx->cipher_info->mode) {
-        return ctx->cipher_info->base->setkey_enc_func(ctx->cipher_ctx, key,
-                                                       ctx->key_bitlen);
+        MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
+        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,
+                                                                          ctx->key_bitlen);
     }
 
     if (MBEDTLS_DECRYPT == operation) {
-        return ctx->cipher_info->base->setkey_dec_func(ctx->cipher_ctx, key,
-                                                       ctx->key_bitlen);
+        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_dec_func(ctx->cipher_ctx, key,
+                                                                          ctx->key_bitlen);
+    }
+#else
+    if (operation == MBEDTLS_ENCRYPT || operation == MBEDTLS_DECRYPT) {
+        return mbedtls_cipher_get_base(ctx->cipher_info)->setkey_enc_func(ctx->cipher_ctx, key,
+                                                                          ctx->key_bitlen);
     }
+#endif
 
     return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
 }
@@ -397,14 +457,14 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
     if (ctx->cipher_info == NULL) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     /* avoid buffer overflow in ctx->iv */
     if (iv_len > MBEDTLS_MAX_IV_LENGTH) {
@@ -414,7 +474,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
     if ((ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN) != 0) {
         actual_iv_size = iv_len;
     } else {
-        actual_iv_size = ctx->cipher_info->iv_size;
+        actual_iv_size = mbedtls_cipher_info_get_iv_size(ctx->cipher_info);
 
         /* avoid reading past the end of input buffer */
         if (actual_iv_size > iv_len) {
@@ -423,7 +483,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
     }
 
 #if defined(MBEDTLS_CHACHA20_C)
-    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20) {
+    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20) {
         /* Even though the actual_iv_size is overwritten with a correct value
          * of 12 from the cipher info, return an error to indicate that
          * the input iv_len is wrong. */
@@ -438,7 +498,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
         }
     }
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
+    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305 &&
         iv_len != 12) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
@@ -446,7 +506,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
 #endif
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         return mbedtls_gcm_starts((mbedtls_gcm_context *) ctx->cipher_ctx,
                                   ctx->operation,
                                   iv, iv_len);
@@ -454,7 +514,7 @@ int mbedtls_cipher_set_iv(mbedtls_cipher_context_t *ctx,
 #endif
 
 #if defined(MBEDTLS_CCM_C)
-    if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         int set_lengths_result;
         int ccm_star_mode;
 
@@ -493,13 +553,13 @@ int mbedtls_cipher_reset(mbedtls_cipher_context_t *ctx)
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* We don't support resetting PSA-based
          * cipher contexts, yet. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     ctx->unprocessed_len = 0;
 
@@ -514,24 +574,24 @@ int mbedtls_cipher_update_ad(mbedtls_cipher_context_t *ctx,
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         return mbedtls_gcm_update_ad((mbedtls_gcm_context *) ctx->cipher_ctx,
                                      ad, ad_len);
     }
 #endif
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
         int result;
         mbedtls_chachapoly_mode_t mode;
 
@@ -565,14 +625,14 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     *olen = 0;
     block_size = mbedtls_cipher_get_block_size(ctx);
@@ -580,15 +640,16 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
         return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT;
     }
 
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_ECB) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_ECB) {
         if (ilen != block_size) {
             return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
         }
 
         *olen = ilen;
 
-        if (0 != (ret = ctx->cipher_info->base->ecb_func(ctx->cipher_ctx,
-                                                         ctx->operation, input, output))) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ecb_func(ctx->cipher_ctx,
+                                                                            ctx->operation, input,
+                                                                            output))) {
             return ret;
         }
 
@@ -596,7 +657,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
     }
 
 #if defined(MBEDTLS_GCM_C)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_GCM) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_GCM) {
         return mbedtls_gcm_update((mbedtls_gcm_context *) ctx->cipher_ctx,
                                   input, ilen,
                                   output, ilen, olen);
@@ -604,7 +665,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif
 
 #if defined(MBEDTLS_CCM_C)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_CCM_STAR_NO_TAG) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CCM_STAR_NO_TAG) {
         return mbedtls_ccm_update((mbedtls_ccm_context *) ctx->cipher_ctx,
                                   input, ilen,
                                   output, ilen, olen);
@@ -612,7 +673,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305) {
+    if (((mbedtls_cipher_type_t) ctx->cipher_info->type) == MBEDTLS_CIPHER_CHACHA20_POLY1305) {
         *olen = ilen;
         return mbedtls_chachapoly_update((mbedtls_chachapoly_context *) ctx->cipher_ctx,
                                          ilen, input, output);
@@ -625,7 +686,7 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_CBC) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CBC) {
         size_t copy_len = 0;
 
         /*
@@ -653,9 +714,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
             memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]), input,
                    copy_len);
 
-            if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
-                                                             ctx->operation, block_size, ctx->iv,
-                                                             ctx->unprocessed_data, output))) {
+            if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
+                                                                                ctx->operation,
+                                                                                block_size, ctx->iv,
+                                                                                ctx->
+                                                                                unprocessed_data,
+                                                                                output))) {
                 return ret;
             }
 
@@ -693,9 +757,11 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
          * Process remaining full blocks
          */
         if (ilen) {
-            if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
-                                                             ctx->operation, ilen, ctx->iv, input,
-                                                             output))) {
+            if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
+                                                                                ctx->operation,
+                                                                                ilen, ctx->iv,
+                                                                                input,
+                                                                                output))) {
                 return ret;
             }
 
@@ -707,11 +773,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_CFB) {
-        if (0 != (ret = ctx->cipher_info->base->cfb_func(ctx->cipher_ctx,
-                                                         ctx->operation, ilen,
-                                                         &ctx->unprocessed_len, ctx->iv,
-                                                         input, output))) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CFB) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cfb_func(ctx->cipher_ctx,
+                                                                            ctx->operation, ilen,
+                                                                            &ctx->unprocessed_len,
+                                                                            ctx->iv,
+                                                                            input, output))) {
             return ret;
         }
 
@@ -722,10 +789,12 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_OFB) {
-        if (0 != (ret = ctx->cipher_info->base->ofb_func(ctx->cipher_ctx,
-                                                         ilen, &ctx->unprocessed_len, ctx->iv,
-                                                         input, output))) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_OFB) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ofb_func(ctx->cipher_ctx,
+                                                                            ilen,
+                                                                            &ctx->unprocessed_len,
+                                                                            ctx->iv,
+                                                                            input, output))) {
             return ret;
         }
 
@@ -736,10 +805,13 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_CTR) {
-        if (0 != (ret = ctx->cipher_info->base->ctr_func(ctx->cipher_ctx,
-                                                         ilen, &ctx->unprocessed_len, ctx->iv,
-                                                         ctx->unprocessed_data, input, output))) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_CTR) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->ctr_func(ctx->cipher_ctx,
+                                                                            ilen,
+                                                                            &ctx->unprocessed_len,
+                                                                            ctx->iv,
+                                                                            ctx->unprocessed_data,
+                                                                            input, output))) {
             return ret;
         }
 
@@ -750,14 +822,18 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_XTS) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_XTS) {
         if (ctx->unprocessed_len > 0) {
             /* We can only process an entire data unit at a time. */
             return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
         }
 
-        ret = ctx->cipher_info->base->xts_func(ctx->cipher_ctx,
-                                               ctx->operation, ilen, ctx->iv, input, output);
+        ret = mbedtls_cipher_get_base(ctx->cipher_info)->xts_func(ctx->cipher_ctx,
+                                                                  ctx->operation,
+                                                                  ilen,
+                                                                  ctx->iv,
+                                                                  input,
+                                                                  output);
         if (ret != 0) {
             return ret;
         }
@@ -769,9 +845,10 @@ int mbedtls_cipher_update(mbedtls_cipher_context_t *ctx, const unsigned char *in
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
-    if (ctx->cipher_info->mode == MBEDTLS_MODE_STREAM) {
-        if (0 != (ret = ctx->cipher_info->base->stream_func(ctx->cipher_ctx,
-                                                            ilen, input, output))) {
+    if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) == MBEDTLS_MODE_STREAM) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->stream_func(ctx->cipher_ctx,
+                                                                               ilen, input,
+                                                                               output))) {
             return ret;
         }
 
@@ -804,27 +881,31 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len,
                             size_t *data_len)
 {
     size_t i, pad_idx;
-    unsigned char padding_len, bad = 0;
+    unsigned char padding_len;
 
     if (NULL == input || NULL == data_len) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
     padding_len = input[input_len - 1];
+    if (padding_len == 0 || padding_len > input_len) {
+        return MBEDTLS_ERR_CIPHER_INVALID_PADDING;
+    }
     *data_len = input_len - padding_len;
 
-    /* Avoid logical || since it results in a branch */
-    bad |= padding_len > input_len;
-    bad |= padding_len == 0;
+    mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
 
     /* The number of bytes checked must be independent of padding_len,
      * so pick input_len, which is usually 8 or 16 (one block) */
     pad_idx = input_len - padding_len;
     for (i = 0; i < input_len; i++) {
-        bad |= (input[i] ^ padding_len) * (i >= pad_idx);
+        mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx);
+        mbedtls_ct_condition_t different  = mbedtls_ct_uint_ne(input[i], padding_len);
+        bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));
     }
 
-    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
 
@@ -847,24 +928,28 @@ static void add_one_and_zeros_padding(unsigned char *output,
 static int get_one_and_zeros_padding(unsigned char *input, size_t input_len,
                                      size_t *data_len)
 {
-    size_t i;
-    unsigned char done = 0, prev_done, bad;
-
     if (NULL == input || NULL == data_len) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    bad = 0x80;
+    mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE;
+    mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE;
+
     *data_len = 0;
-    for (i = input_len; i > 0; i--) {
-        prev_done = done;
-        done |= (input[i - 1] != 0);
-        *data_len |= (i - 1) * (done != prev_done);
-        bad ^= input[i - 1] * (done != prev_done);
-    }
 
-    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) {
+        mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]);
+
+        mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding);
+
+        *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len);
+
+        bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad);
 
+        in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero));
+    }
+
+    return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
 
@@ -888,7 +973,8 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
                                      size_t *data_len)
 {
     size_t i, pad_idx;
-    unsigned char padding_len, bad = 0;
+    unsigned char padding_len;
+    mbedtls_ct_condition_t bad;
 
     if (NULL == input || NULL == data_len) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
@@ -898,16 +984,19 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
     *data_len = input_len - padding_len;
 
     /* Avoid logical || since it results in a branch */
-    bad |= padding_len > input_len;
-    bad |= padding_len == 0;
+    bad = mbedtls_ct_uint_gt(padding_len, input_len);
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
 
     /* The number of bytes checked must be independent of padding_len */
     pad_idx = input_len - padding_len;
     for (i = 0; i < input_len - 1; i++) {
-        bad |= input[i] * (i >= pad_idx);
+        mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx);
+        mbedtls_ct_condition_t nonzero_pad_byte;
+        nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i]));
+        bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte);
     }
 
-    return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+    return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
 
@@ -918,18 +1007,14 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len,
 static void add_zeros_padding(unsigned char *output,
                               size_t output_len, size_t data_len)
 {
-    size_t i;
-
-    for (i = data_len; i < output_len; i++) {
-        output[i] = 0x00;
-    }
+    memset(output + data_len, 0, output_len - data_len);
 }
 
 static int get_zeros_padding(unsigned char *input, size_t input_len,
                              size_t *data_len)
 {
     size_t i;
-    unsigned char done = 0, prev_done;
+    mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done;
 
     if (NULL == input || NULL == data_len) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
@@ -938,8 +1023,8 @@ static int get_zeros_padding(unsigned char *input, size_t input_len,
     *data_len = 0;
     for (i = input_len; i > 0; i--) {
         prev_done = done;
-        done |= (input[i-1] != 0);
-        *data_len |= i * (done != prev_done);
+        done = mbedtls_ct_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0));
+        *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len);
     }
 
     return 0;
@@ -972,33 +1057,43 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     *olen = 0;
 
-    if (MBEDTLS_MODE_CFB == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_OFB == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_CTR == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_GCM == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_CCM_STAR_NO_TAG == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_XTS == ctx->cipher_info->mode ||
-        MBEDTLS_MODE_STREAM == ctx->cipher_info->mode) {
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    /* CBC mode requires padding so we make sure a call to
+     * mbedtls_cipher_set_padding_mode has been done successfully. */
+    if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
+        if (ctx->get_padding == NULL) {
+            return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
+        }
+    }
+#endif
+
+    if (MBEDTLS_MODE_CFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_OFB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_CTR == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_CCM_STAR_NO_TAG == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_XTS == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+        MBEDTLS_MODE_STREAM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         return 0;
     }
 
-    if ((MBEDTLS_CIPHER_CHACHA20          == ctx->cipher_info->type) ||
-        (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type)) {
+    if ((MBEDTLS_CIPHER_CHACHA20          == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) ||
+        (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type))) {
         return 0;
     }
 
-    if (MBEDTLS_MODE_ECB == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_ECB == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         if (ctx->unprocessed_len != 0) {
             return MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED;
         }
@@ -1007,7 +1102,7 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
     }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if (MBEDTLS_MODE_CBC == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_CBC == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         int ret = 0;
 
         if (MBEDTLS_ENCRYPT == ctx->operation) {
@@ -1035,11 +1130,13 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
         }
 
         /* cipher block */
-        if (0 != (ret = ctx->cipher_info->base->cbc_func(ctx->cipher_ctx,
-                                                         ctx->operation,
-                                                         mbedtls_cipher_get_block_size(ctx),
-                                                         ctx->iv,
-                                                         ctx->unprocessed_data, output))) {
+        if (0 != (ret = mbedtls_cipher_get_base(ctx->cipher_info)->cbc_func(ctx->cipher_ctx,
+                                                                            ctx->operation,
+                                                                            mbedtls_cipher_get_block_size(
+                                                                                ctx),
+                                                                            ctx->iv,
+                                                                            ctx->unprocessed_data,
+                                                                            output))) {
             return ret;
         }
 
@@ -1064,11 +1161,12 @@ int mbedtls_cipher_finish(mbedtls_cipher_context_t *ctx,
 int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,
                                     mbedtls_cipher_padding_t mode)
 {
-    if (NULL == ctx->cipher_info || MBEDTLS_MODE_CBC != ctx->cipher_info->mode) {
+    if (NULL == ctx->cipher_info ||
+        MBEDTLS_MODE_CBC != ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto knows about CBC padding
          * schemes, we currently don't make them
@@ -1079,7 +1177,7 @@ int mbedtls_cipher_set_padding_mode(mbedtls_cipher_context_t *ctx,
 
         return 0;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     switch (mode) {
 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
@@ -1131,17 +1229,17 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         size_t output_length;
         /* The code here doesn't yet support alternative implementations
          * that can delay up to a block of output. */
@@ -1152,7 +1250,7 @@ int mbedtls_cipher_write_tag(mbedtls_cipher_context_t *ctx,
 #endif
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
         /* Don't allow truncated MAC for Poly1305 */
         if (tag_len != 16U) {
             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
@@ -1180,20 +1278,20 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* While PSA Crypto has an API for multipart
          * operations, we currently don't make it
          * accessible through the cipher layer. */
         return MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     /* Status to return on a non-authenticated algorithm. */
     ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE;
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         size_t output_length;
         /* The code here doesn't yet support alternative implementations
          * that can delay up to a block of output. */
@@ -1218,7 +1316,7 @@ int mbedtls_cipher_check_tag(mbedtls_cipher_context_t *ctx,
 #endif /* MBEDTLS_GCM_C */
 
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
         /* Don't allow truncated MAC for Poly1305 */
         if (tag_len != sizeof(check_tag)) {
             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
@@ -1255,7 +1353,7 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t finish_olen;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
@@ -1289,7 +1387,7 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,
             return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
         }
 
-        if (ctx->cipher_info->mode != MBEDTLS_MODE_ECB) {
+        if (((mbedtls_cipher_mode_t) ctx->cipher_info->mode) != MBEDTLS_MODE_ECB) {
             status = psa_cipher_set_iv(&cipher_op, iv, iv_len);
             if (status != PSA_SUCCESS) {
                 return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
@@ -1313,7 +1411,7 @@ int mbedtls_cipher_crypt(mbedtls_cipher_context_t *ctx,
         *olen += part_len;
         return 0;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
     if ((ret = mbedtls_cipher_set_iv(ctx, iv, iv_len)) != 0) {
         return ret;
@@ -1350,7 +1448,7 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
                                        unsigned char *output, size_t *olen,
                                        unsigned char *tag, size_t tag_len)
 {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
@@ -1381,10 +1479,10 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
         *olen -= tag_len;
         return 0;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         *olen = ilen;
         return mbedtls_gcm_crypt_and_tag(ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT,
                                          ilen, iv, iv_len, ad, ad_len,
@@ -1392,7 +1490,7 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
     }
 #endif /* MBEDTLS_GCM_C */
 #if defined(MBEDTLS_CCM_C)
-    if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         *olen = ilen;
         return mbedtls_ccm_encrypt_and_tag(ctx->cipher_ctx, ilen,
                                            iv, iv_len, ad, ad_len, input, output,
@@ -1400,9 +1498,9 @@ static int mbedtls_cipher_aead_encrypt(mbedtls_cipher_context_t *ctx,
     }
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
         /* ChachaPoly has fixed length nonce and MAC (tag) */
-        if ((iv_len != ctx->cipher_info->iv_size) ||
+        if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||
             (tag_len != 16U)) {
             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
@@ -1427,7 +1525,7 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
                                        unsigned char *output, size_t *olen,
                                        const unsigned char *tag, size_t tag_len)
 {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
     if (ctx->psa_enabled == 1) {
         /* As in the non-PSA case, we don't check that
          * a key has been set. If not, the key slot will
@@ -1459,10 +1557,10 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
 
         return 0;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_USE_PSA_CRYPTO && !MBEDTLS_DEPRECATED_REMOVED */
 
 #if defined(MBEDTLS_GCM_C)
-    if (MBEDTLS_MODE_GCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_GCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         *olen = ilen;
@@ -1478,7 +1576,7 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
     }
 #endif /* MBEDTLS_GCM_C */
 #if defined(MBEDTLS_CCM_C)
-    if (MBEDTLS_MODE_CCM == ctx->cipher_info->mode) {
+    if (MBEDTLS_MODE_CCM == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         *olen = ilen;
@@ -1494,11 +1592,11 @@ static int mbedtls_cipher_aead_decrypt(mbedtls_cipher_context_t *ctx,
     }
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type) {
+    if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ((mbedtls_cipher_type_t) ctx->cipher_info->type)) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
         /* ChachaPoly has fixed length nonce and MAC (tag) */
-        if ((iv_len != ctx->cipher_info->iv_size) ||
+        if ((iv_len != mbedtls_cipher_info_get_iv_size(ctx->cipher_info)) ||
             (tag_len != 16U)) {
             return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
         }
@@ -1532,13 +1630,14 @@ int mbedtls_cipher_auth_encrypt_ext(mbedtls_cipher_context_t *ctx,
 {
 #if defined(MBEDTLS_NIST_KW_C)
     if (
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
         ctx->psa_enabled == 0 &&
 #endif
-        (MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
-         MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) {
-        mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ?
-                                      MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+        (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+         MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {
+        mbedtls_nist_kw_mode_t mode =
+            (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?
+            MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
 
         /* There is no iv, tag or ad associated with KW and KWP,
          * so these length should be 0 as documented. */
@@ -1582,13 +1681,14 @@ int mbedtls_cipher_auth_decrypt_ext(mbedtls_cipher_context_t *ctx,
 {
 #if defined(MBEDTLS_NIST_KW_C)
     if (
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_DEPRECATED_REMOVED)
         ctx->psa_enabled == 0 &&
 #endif
-        (MBEDTLS_MODE_KW == ctx->cipher_info->mode ||
-         MBEDTLS_MODE_KWP == ctx->cipher_info->mode)) {
-        mbedtls_nist_kw_mode_t mode = (MBEDTLS_MODE_KW == ctx->cipher_info->mode) ?
-                                      MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
+        (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode) ||
+         MBEDTLS_MODE_KWP == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode))) {
+        mbedtls_nist_kw_mode_t mode =
+            (MBEDTLS_MODE_KW == ((mbedtls_cipher_mode_t) ctx->cipher_info->mode)) ?
+            MBEDTLS_KW_MODE_KW : MBEDTLS_KW_MODE_KWP;
 
         /* There is no iv, tag or ad associated with KW and KWP,
          * so these length should be 0 as documented. */
diff --git a/lib/libmbedtls/mbedtls/library/cipher_wrap.c b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
index fb363145c5fe2e3b10fd146ce401376de9a85cdb..b570241af81a6ce37c825f7a72af85591bcc2c8e 100644
--- a/lib/libmbedtls/mbedtls/library/cipher_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/cipher_wrap.c
@@ -1,24 +1,12 @@
 /**
  * \file cipher_wrap.c
  *
- * \brief Generic cipher wrapper for mbed TLS
+ * \brief Generic cipher wrapper for Mbed TLS
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -72,7 +60,65 @@
 
 #include "mbedtls/platform.h"
 
-#if defined(MBEDTLS_GCM_C)
+enum mbedtls_cipher_base_index {
+#if defined(MBEDTLS_AES_C)
+    MBEDTLS_CIPHER_BASE_INDEX_AES,
+#endif
+#if defined(MBEDTLS_ARIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA,
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA,
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES,
+#endif
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA,
+#endif
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA,
+#endif
+#if defined(MBEDTLS_CHACHA20_C)
+    MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE,
+#endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE,
+#endif
+#if defined(MBEDTLS_DES_C)
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3,
+#endif
+#if defined(MBEDTLS_DES_C)
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE,
+#endif
+#if defined(MBEDTLS_DES_C)
+    MBEDTLS_CIPHER_BASE_INDEX_DES,
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES,
+#endif
+#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA,
+#endif
+#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C)
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA,
+#endif
+#if defined(MBEDTLS_NIST_KW_C)
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES,
+#endif
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+    MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C)
+    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES,
+#endif
+    /* Prevent compile failure due to empty enum */
+    MBEDTLS_CIPHER_BASE_PREVENT_EMPTY_ENUM
+};
+
+#if defined(MBEDTLS_GCM_C) && \
+    (defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA) || \
+    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C))
 /* shared by all GCM ciphers */
 static void *gcm_ctx_alloc(void)
 {
@@ -97,7 +143,9 @@ static void gcm_ctx_free(void *ctx)
 }
 #endif /* MBEDTLS_GCM_C */
 
-#if defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_CCM_C) && \
+    (defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA) || \
+    defined(MBEDTLS_ARIA_C) || defined(MBEDTLS_CAMELLIA_C))
 /* shared by all CCM ciphers */
 static void *ccm_ctx_alloc(void)
 {
@@ -194,11 +242,13 @@ static int aes_crypt_xts_wrap(void *ctx, mbedtls_operation_t operation,
 }
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 static int aes_setkey_dec_wrap(void *ctx, const unsigned char *key,
                                unsigned int key_bitlen)
 {
     return mbedtls_aes_setkey_dec((mbedtls_aes_context *) ctx, key, key_bitlen);
 }
+#endif
 
 static int aes_setkey_enc_wrap(void *ctx, const unsigned char *key,
                                unsigned int key_bitlen)
@@ -252,183 +302,195 @@ static const mbedtls_cipher_base_t aes_info = {
     NULL,
 #endif
     aes_setkey_enc_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     aes_setkey_dec_wrap,
+#endif
     aes_ctx_alloc,
     aes_ctx_clone,
     aes_ctx_free
 };
 
 static const mbedtls_cipher_info_t aes_128_ecb_info = {
-    MBEDTLS_CIPHER_AES_128_ECB,
-    MBEDTLS_MODE_ECB,
-    128,
     "AES-128-ECB",
-    0,
-    0,
     16,
-    &aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_AES_128_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_ecb_info = {
-    MBEDTLS_CIPHER_AES_192_ECB,
-    MBEDTLS_MODE_ECB,
-    192,
     "AES-192-ECB",
-    0,
-    0,
     16,
-    &aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_AES_192_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_ecb_info = {
-    MBEDTLS_CIPHER_AES_256_ECB,
-    MBEDTLS_MODE_ECB,
-    256,
     "AES-256-ECB",
-    0,
-    0,
     16,
-    &aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_AES_256_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
+#endif
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t aes_128_cbc_info = {
-    MBEDTLS_CIPHER_AES_128_CBC,
-    MBEDTLS_MODE_CBC,
-    128,
     "AES-128-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_AES_128_CBC,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_cbc_info = {
-    MBEDTLS_CIPHER_AES_192_CBC,
-    MBEDTLS_MODE_CBC,
-    192,
     "AES-192-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_AES_192_CBC,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_cbc_info = {
-    MBEDTLS_CIPHER_AES_256_CBC,
-    MBEDTLS_MODE_CBC,
-    256,
     "AES-256-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_AES_256_CBC,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
+#endif
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
 static const mbedtls_cipher_info_t aes_128_cfb128_info = {
-    MBEDTLS_CIPHER_AES_128_CFB128,
-    MBEDTLS_MODE_CFB,
-    128,
     "AES-128-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_AES_128_CFB128,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_cfb128_info = {
-    MBEDTLS_CIPHER_AES_192_CFB128,
-    MBEDTLS_MODE_CFB,
-    192,
     "AES-192-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_AES_192_CFB128,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_cfb128_info = {
-    MBEDTLS_CIPHER_AES_256_CFB128,
-    MBEDTLS_MODE_CFB,
-    256,
     "AES-256-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_AES_256_CFB128,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
+#endif
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
 static const mbedtls_cipher_info_t aes_128_ofb_info = {
-    MBEDTLS_CIPHER_AES_128_OFB,
-    MBEDTLS_MODE_OFB,
-    128,
     "AES-128-OFB",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_OFB,
+    MBEDTLS_CIPHER_AES_128_OFB,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_ofb_info = {
-    MBEDTLS_CIPHER_AES_192_OFB,
-    MBEDTLS_MODE_OFB,
-    192,
     "AES-192-OFB",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_OFB,
+    MBEDTLS_CIPHER_AES_192_OFB,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_ofb_info = {
-    MBEDTLS_CIPHER_AES_256_OFB,
-    MBEDTLS_MODE_OFB,
-    256,
     "AES-256-OFB",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_OFB,
+    MBEDTLS_CIPHER_AES_256_OFB,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
+#endif
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static const mbedtls_cipher_info_t aes_128_ctr_info = {
-    MBEDTLS_CIPHER_AES_128_CTR,
-    MBEDTLS_MODE_CTR,
-    128,
     "AES-128-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_AES_128_CTR,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_ctr_info = {
-    MBEDTLS_CIPHER_AES_192_CTR,
-    MBEDTLS_MODE_CTR,
-    192,
     "AES-192-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_AES_192_CTR,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_ctr_info = {
-    MBEDTLS_CIPHER_AES_256_CTR,
-    MBEDTLS_MODE_CTR,
-    256,
     "AES-256-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_AES_256_CTR,
     0,
-    16,
-    &aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_AES
 };
+#endif
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
@@ -497,36 +559,41 @@ static const mbedtls_cipher_base_t xts_aes_info = {
 };
 
 static const mbedtls_cipher_info_t aes_128_xts_info = {
-    MBEDTLS_CIPHER_AES_128_XTS,
-    MBEDTLS_MODE_XTS,
-    256,
     "AES-128-XTS",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_XTS,
+    MBEDTLS_CIPHER_AES_128_XTS,
     0,
-    16,
-    &xts_aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_256_xts_info = {
-    MBEDTLS_CIPHER_AES_256_XTS,
-    MBEDTLS_MODE_XTS,
-    512,
     "AES-256-XTS",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    512 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_XTS,
+    MBEDTLS_CIPHER_AES_256_XTS,
     0,
-    16,
-    &xts_aes_info
+    MBEDTLS_CIPHER_BASE_INDEX_XTS_AES
 };
+#endif
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
+#endif /* MBEDTLS_AES_C */
 
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES)
 static int gcm_aes_setkey_wrap(void *ctx, const unsigned char *key,
                                unsigned int key_bitlen)
 {
     return mbedtls_gcm_setkey((mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
                               key, key_bitlen);
 }
+#endif /* MBEDTLS_GCM_C && MBEDTLS_CCM_GCM_CAN_AES */
 
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)
 static const mbedtls_cipher_base_t gcm_aes_info = {
     MBEDTLS_CIPHER_ID_AES,
     NULL,
@@ -548,55 +615,70 @@ static const mbedtls_cipher_base_t gcm_aes_info = {
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
+#if defined(MBEDTLS_GCM_C)
     gcm_aes_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     gcm_aes_setkey_wrap,
+#endif
     gcm_ctx_alloc,
     gcm_ctx_clone,
     gcm_ctx_free,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif /* MBEDTLS_GCM_C */
 };
+#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */
 
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)
 static const mbedtls_cipher_info_t aes_128_gcm_info = {
-    MBEDTLS_CIPHER_AES_128_GCM,
-    MBEDTLS_MODE_GCM,
-    128,
     "AES-128-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_AES_128_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_gcm_info = {
-    MBEDTLS_CIPHER_AES_192_GCM,
-    MBEDTLS_MODE_GCM,
-    192,
     "AES-192-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_AES_192_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_gcm_info = {
-    MBEDTLS_CIPHER_AES_256_GCM,
-    MBEDTLS_MODE_GCM,
-    256,
     "AES-256-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_AES_256_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_AES
 };
-#endif /* MBEDTLS_GCM_C */
+#endif
+#endif /* MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA */
 
-#if defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CCM_GCM_CAN_AES)
 static int ccm_aes_setkey_wrap(void *ctx, const unsigned char *key,
                                unsigned int key_bitlen)
 {
     return mbedtls_ccm_setkey((mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES,
                               key, key_bitlen);
 }
+#endif /* MBEDTLS_CCM_C && MBEDTLS_CCM_GCM_CAN_AES */
 
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)
 static const mbedtls_cipher_base_t ccm_aes_info = {
     MBEDTLS_CIPHER_ID_AES,
     NULL,
@@ -618,81 +700,97 @@ static const mbedtls_cipher_base_t ccm_aes_info = {
 #if defined(MBEDTLS_CIPHER_MODE_STREAM)
     NULL,
 #endif
+#if defined(MBEDTLS_CCM_C)
     ccm_aes_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     ccm_aes_setkey_wrap,
+#endif
     ccm_ctx_alloc,
     ccm_ctx_clone,
     ccm_ctx_free,
+#else
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+#endif
 };
+#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */
 
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)
 static const mbedtls_cipher_info_t aes_128_ccm_info = {
-    MBEDTLS_CIPHER_AES_128_CCM,
-    MBEDTLS_MODE_CCM,
-    128,
     "AES-128-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_AES_128_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_ccm_info = {
-    MBEDTLS_CIPHER_AES_192_CCM,
-    MBEDTLS_MODE_CCM,
-    192,
     "AES-192-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_AES_192_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_ccm_info = {
-    MBEDTLS_CIPHER_AES_256_CCM,
-    MBEDTLS_MODE_CCM,
-    256,
     "AES-256-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_AES_256_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
+#endif
+#endif /* MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA */
 
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA)
 static const mbedtls_cipher_info_t aes_128_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    128,
     "AES-128-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    192,
     "AES-192-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    256,
     "AES-256-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aes_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_AES
 };
-#endif /* MBEDTLS_CCM_C */
+#endif
+#endif /* MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA */
 
-#endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_CAMELLIA_C)
 
@@ -733,11 +831,13 @@ static int camellia_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 static int camellia_setkey_dec_wrap(void *ctx, const unsigned char *key,
                                     unsigned int key_bitlen)
 {
     return mbedtls_camellia_setkey_dec((mbedtls_camellia_context *) ctx, key, key_bitlen);
 }
+#endif
 
 static int camellia_setkey_enc_wrap(void *ctx, const unsigned char *key,
                                     unsigned int key_bitlen)
@@ -792,147 +892,149 @@ static const mbedtls_cipher_base_t camellia_info = {
     NULL,
 #endif
     camellia_setkey_enc_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     camellia_setkey_dec_wrap,
+#endif
     camellia_ctx_alloc,
     camellia_ctx_clone,
     camellia_ctx_free
 };
 
 static const mbedtls_cipher_info_t camellia_128_ecb_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_ECB,
-    MBEDTLS_MODE_ECB,
-    128,
     "CAMELLIA-128-ECB",
-    0,
-    0,
     16,
-    &camellia_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_128_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_ecb_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_ECB,
-    MBEDTLS_MODE_ECB,
-    192,
     "CAMELLIA-192-ECB",
-    0,
-    0,
     16,
-    &camellia_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_192_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_ecb_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_ECB,
-    MBEDTLS_MODE_ECB,
-    256,
     "CAMELLIA-256-ECB",
-    0,
-    0,
     16,
-    &camellia_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_CAMELLIA_256_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t camellia_128_cbc_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_CBC,
-    MBEDTLS_MODE_CBC,
-    128,
     "CAMELLIA-128-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_128_CBC,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_cbc_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_CBC,
-    MBEDTLS_MODE_CBC,
-    192,
     "CAMELLIA-192-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_192_CBC,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_cbc_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_CBC,
-    MBEDTLS_MODE_CBC,
-    256,
     "CAMELLIA-256-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_CAMELLIA_256_CBC,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
 static const mbedtls_cipher_info_t camellia_128_cfb128_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,
-    MBEDTLS_MODE_CFB,
-    128,
     "CAMELLIA-128-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_CAMELLIA_128_CFB128,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_cfb128_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,
-    MBEDTLS_MODE_CFB,
-    192,
     "CAMELLIA-192-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_CAMELLIA_192_CFB128,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_cfb128_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,
-    MBEDTLS_MODE_CFB,
-    256,
     "CAMELLIA-256-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_CAMELLIA_256_CFB128,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static const mbedtls_cipher_info_t camellia_128_ctr_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_CTR,
-    MBEDTLS_MODE_CTR,
-    128,
     "CAMELLIA-128-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_128_CTR,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_ctr_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_CTR,
-    MBEDTLS_MODE_CTR,
-    192,
     "CAMELLIA-192-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_192_CTR,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_ctr_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_CTR,
-    MBEDTLS_MODE_CTR,
-    256,
     "CAMELLIA-256-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_CAMELLIA_256_CTR,
     0,
-    16,
-    &camellia_info
+    MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
@@ -966,43 +1068,45 @@ static const mbedtls_cipher_base_t gcm_camellia_info = {
     NULL,
 #endif
     gcm_camellia_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     gcm_camellia_setkey_wrap,
+#endif
     gcm_ctx_alloc,
     gcm_ctx_clone,
     gcm_ctx_free,
 };
 
 static const mbedtls_cipher_info_t camellia_128_gcm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_GCM,
-    MBEDTLS_MODE_GCM,
-    128,
     "CAMELLIA-128-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_128_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_gcm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_GCM,
-    MBEDTLS_MODE_GCM,
-    192,
     "CAMELLIA-192-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_192_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_gcm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_GCM,
-    MBEDTLS_MODE_GCM,
-    256,
     "CAMELLIA-256-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_CAMELLIA_256_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA
 };
 #endif /* MBEDTLS_GCM_C */
 
@@ -1036,76 +1140,78 @@ static const mbedtls_cipher_base_t ccm_camellia_info = {
     NULL,
 #endif
     ccm_camellia_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     ccm_camellia_setkey_wrap,
+#endif
     ccm_ctx_alloc,
     ccm_ctx_clone,
     ccm_ctx_free,
 };
 
 static const mbedtls_cipher_info_t camellia_128_ccm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_CCM,
-    MBEDTLS_MODE_CCM,
-    128,
     "CAMELLIA-128-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_128_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_ccm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_CCM,
-    MBEDTLS_MODE_CCM,
-    192,
     "CAMELLIA-192-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_192_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_ccm_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_CCM,
-    MBEDTLS_MODE_CCM,
-    256,
     "CAMELLIA-256-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_CAMELLIA_256_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_128_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    128,
     "CAMELLIA-128-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_192_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    192,
     "CAMELLIA-192-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 
 static const mbedtls_cipher_info_t camellia_256_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    256,
     "CAMELLIA-256-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_camellia_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA
 };
 #endif /* MBEDTLS_CCM_C */
 
@@ -1151,11 +1257,13 @@ static int aria_crypt_ctr_wrap(void *ctx, size_t length, size_t *nc_off,
 }
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
 static int aria_setkey_dec_wrap(void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen)
 {
     return mbedtls_aria_setkey_dec((mbedtls_aria_context *) ctx, key, key_bitlen);
 }
+#endif
 
 static int aria_setkey_enc_wrap(void *ctx, const unsigned char *key,
                                 unsigned int key_bitlen)
@@ -1205,146 +1313,148 @@ static const mbedtls_cipher_base_t aria_info = {
     NULL,
 #endif
     aria_setkey_enc_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     aria_setkey_dec_wrap,
+#endif
     aria_ctx_alloc,
     aria_ctx_free
 };
 
 static const mbedtls_cipher_info_t aria_128_ecb_info = {
-    MBEDTLS_CIPHER_ARIA_128_ECB,
-    MBEDTLS_MODE_ECB,
-    128,
     "ARIA-128-ECB",
-    0,
-    0,
     16,
-    &aria_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_ARIA_128_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_ecb_info = {
-    MBEDTLS_CIPHER_ARIA_192_ECB,
-    MBEDTLS_MODE_ECB,
-    192,
     "ARIA-192-ECB",
-    0,
-    0,
     16,
-    &aria_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_ARIA_192_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_ecb_info = {
-    MBEDTLS_CIPHER_ARIA_256_ECB,
-    MBEDTLS_MODE_ECB,
-    256,
     "ARIA-256-ECB",
-    0,
-    0,
     16,
-    &aria_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_ARIA_256_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t aria_128_cbc_info = {
-    MBEDTLS_CIPHER_ARIA_128_CBC,
-    MBEDTLS_MODE_CBC,
-    128,
     "ARIA-128-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_ARIA_128_CBC,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_cbc_info = {
-    MBEDTLS_CIPHER_ARIA_192_CBC,
-    MBEDTLS_MODE_CBC,
-    192,
     "ARIA-192-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_ARIA_192_CBC,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_cbc_info = {
-    MBEDTLS_CIPHER_ARIA_256_CBC,
-    MBEDTLS_MODE_CBC,
-    256,
     "ARIA-256-CBC",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_ARIA_256_CBC,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
 static const mbedtls_cipher_info_t aria_128_cfb128_info = {
-    MBEDTLS_CIPHER_ARIA_128_CFB128,
-    MBEDTLS_MODE_CFB,
-    128,
     "ARIA-128-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_ARIA_128_CFB128,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_cfb128_info = {
-    MBEDTLS_CIPHER_ARIA_192_CFB128,
-    MBEDTLS_MODE_CFB,
-    192,
     "ARIA-192-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_ARIA_192_CFB128,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_cfb128_info = {
-    MBEDTLS_CIPHER_ARIA_256_CFB128,
-    MBEDTLS_MODE_CFB,
-    256,
     "ARIA-256-CFB128",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CFB,
+    MBEDTLS_CIPHER_ARIA_256_CFB128,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
 static const mbedtls_cipher_info_t aria_128_ctr_info = {
-    MBEDTLS_CIPHER_ARIA_128_CTR,
-    MBEDTLS_MODE_CTR,
-    128,
     "ARIA-128-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_ARIA_128_CTR,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_ctr_info = {
-    MBEDTLS_CIPHER_ARIA_192_CTR,
-    MBEDTLS_MODE_CTR,
-    192,
     "ARIA-192-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_ARIA_192_CTR,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_ctr_info = {
-    MBEDTLS_CIPHER_ARIA_256_CTR,
-    MBEDTLS_MODE_CTR,
-    256,
     "ARIA-256-CTR",
     16,
+    16 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CTR,
+    MBEDTLS_CIPHER_ARIA_256_CTR,
     0,
-    16,
-    &aria_info
+    MBEDTLS_CIPHER_BASE_INDEX_ARIA
 };
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 
@@ -1378,42 +1488,44 @@ static const mbedtls_cipher_base_t gcm_aria_info = {
     NULL,
 #endif
     gcm_aria_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     gcm_aria_setkey_wrap,
+#endif
     gcm_ctx_alloc,
     gcm_ctx_free,
 };
 
 static const mbedtls_cipher_info_t aria_128_gcm_info = {
-    MBEDTLS_CIPHER_ARIA_128_GCM,
-    MBEDTLS_MODE_GCM,
-    128,
     "ARIA-128-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_ARIA_128_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_gcm_info = {
-    MBEDTLS_CIPHER_ARIA_192_GCM,
-    MBEDTLS_MODE_GCM,
-    192,
     "ARIA-192-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_ARIA_192_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_gcm_info = {
-    MBEDTLS_CIPHER_ARIA_256_GCM,
-    MBEDTLS_MODE_GCM,
-    256,
     "ARIA-256-GCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &gcm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_GCM,
+    MBEDTLS_CIPHER_ARIA_256_GCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA
 };
 #endif /* MBEDTLS_GCM_C */
 
@@ -1447,75 +1559,77 @@ static const mbedtls_cipher_base_t ccm_aria_info = {
     NULL,
 #endif
     ccm_aria_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     ccm_aria_setkey_wrap,
+#endif
     ccm_ctx_alloc,
     ccm_ctx_free,
 };
 
 static const mbedtls_cipher_info_t aria_128_ccm_info = {
-    MBEDTLS_CIPHER_ARIA_128_CCM,
-    MBEDTLS_MODE_CCM,
-    128,
     "ARIA-128-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_ARIA_128_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_ccm_info = {
-    MBEDTLS_CIPHER_ARIA_192_CCM,
-    MBEDTLS_MODE_CCM,
-    192,
     "ARIA-192-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_ARIA_192_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_ccm_info = {
-    MBEDTLS_CIPHER_ARIA_256_CCM,
-    MBEDTLS_MODE_CCM,
-    256,
     "ARIA-256-CCM",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM,
+    MBEDTLS_CIPHER_ARIA_256_CCM,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_128_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    128,
     "ARIA-128-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_192_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    192,
     "ARIA-192-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 
 static const mbedtls_cipher_info_t aria_256_ccm_star_no_tag_info = {
-    MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,
-    MBEDTLS_MODE_CCM_STAR_NO_TAG,
-    256,
     "ARIA-256-CCM*-NO-TAG",
-    12,
-    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
     16,
-    &ccm_aria_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG,
+    MBEDTLS_CIPHER_VARIABLE_IV_LEN,
+    MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA
 };
 #endif /* MBEDTLS_CCM_C */
 
@@ -1681,26 +1795,26 @@ static const mbedtls_cipher_base_t des_info = {
 };
 
 static const mbedtls_cipher_info_t des_ecb_info = {
-    MBEDTLS_CIPHER_DES_ECB,
-    MBEDTLS_MODE_ECB,
-    MBEDTLS_KEY_LENGTH_DES,
     "DES-ECB",
-    0,
-    0,
     8,
-    &des_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_DES_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_DES
 };
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t des_cbc_info = {
-    MBEDTLS_CIPHER_DES_CBC,
-    MBEDTLS_MODE_CBC,
-    MBEDTLS_KEY_LENGTH_DES,
     "DES-CBC",
     8,
+    8 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_DES_CBC,
     0,
-    8,
-    &des_info
+    MBEDTLS_CIPHER_BASE_INDEX_DES
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1733,26 +1847,26 @@ static const mbedtls_cipher_base_t des_ede_info = {
 };
 
 static const mbedtls_cipher_info_t des_ede_ecb_info = {
-    MBEDTLS_CIPHER_DES_EDE_ECB,
-    MBEDTLS_MODE_ECB,
-    MBEDTLS_KEY_LENGTH_DES_EDE,
     "DES-EDE-ECB",
-    0,
-    0,
     8,
-    &des_ede_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_DES_EDE_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE
 };
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t des_ede_cbc_info = {
-    MBEDTLS_CIPHER_DES_EDE_CBC,
-    MBEDTLS_MODE_CBC,
-    MBEDTLS_KEY_LENGTH_DES_EDE,
     "DES-EDE-CBC",
     8,
+    8 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES_EDE >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_DES_EDE_CBC,
     0,
-    8,
-    &des_ede_info
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 
@@ -1785,25 +1899,25 @@ static const mbedtls_cipher_base_t des_ede3_info = {
 };
 
 static const mbedtls_cipher_info_t des_ede3_ecb_info = {
-    MBEDTLS_CIPHER_DES_EDE3_ECB,
-    MBEDTLS_MODE_ECB,
-    MBEDTLS_KEY_LENGTH_DES_EDE3,
     "DES-EDE3-ECB",
-    0,
-    0,
     8,
-    &des_ede3_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_ECB,
+    MBEDTLS_CIPHER_DES_EDE3_ECB,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3
 };
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
 static const mbedtls_cipher_info_t des_ede3_cbc_info = {
-    MBEDTLS_CIPHER_DES_EDE3_CBC,
-    MBEDTLS_MODE_CBC,
-    MBEDTLS_KEY_LENGTH_DES_EDE3,
     "DES-EDE3-CBC",
     8,
+    8 >> MBEDTLS_IV_SIZE_SHIFT,
+    MBEDTLS_KEY_LENGTH_DES_EDE3 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CBC,
+    MBEDTLS_CIPHER_DES_EDE3_CBC,
     0,
-    8,
-    &des_ede3_info
+    MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3
 };
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #endif /* MBEDTLS_DES_C */
@@ -1885,20 +1999,22 @@ static const mbedtls_cipher_base_t chacha20_base_info = {
     chacha20_stream_wrap,
 #endif
     chacha20_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     chacha20_setkey_wrap,
+#endif
     chacha20_ctx_alloc,
     chacha20_ctx_clone,
     chacha20_ctx_free
 };
 static const mbedtls_cipher_info_t chacha20_info = {
-    MBEDTLS_CIPHER_CHACHA20,
-    MBEDTLS_MODE_STREAM,
-    256,
     "CHACHA20",
-    12,
-    0,
     1,
-    &chacha20_base_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_STREAM,
+    MBEDTLS_CIPHER_CHACHA20,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE
 };
 #endif /* MBEDTLS_CHACHA20_C */
 
@@ -1966,20 +2082,22 @@ static const mbedtls_cipher_base_t chachapoly_base_info = {
     NULL,
 #endif
     chachapoly_setkey_wrap,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     chachapoly_setkey_wrap,
+#endif
     chachapoly_ctx_alloc,
     chachapoly_ctx_clone,
     chachapoly_ctx_free
 };
 static const mbedtls_cipher_info_t chachapoly_info = {
-    MBEDTLS_CIPHER_CHACHA20_POLY1305,
-    MBEDTLS_MODE_CHACHAPOLY,
-    256,
     "CHACHA20-POLY1305",
-    12,
-    0,
     1,
-    &chachapoly_base_info
+    12 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_CHACHAPOLY,
+    MBEDTLS_CIPHER_CHACHA20_POLY1305,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE
 };
 #endif /* MBEDTLS_CHACHAPOLY_C */
 
@@ -2041,21 +2159,23 @@ static const mbedtls_cipher_base_t null_base_info = {
     null_crypt_stream,
 #endif
     null_setkey,
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     null_setkey,
+#endif
     null_ctx_alloc,
     null_ctx_clone,
     null_ctx_free
 };
 
 static const mbedtls_cipher_info_t null_cipher_info = {
-    MBEDTLS_CIPHER_NULL,
-    MBEDTLS_MODE_STREAM,
-    0,
     "NULL",
-    0,
-    0,
     1,
-    &null_base_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    0 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_STREAM,
+    MBEDTLS_CIPHER_NULL,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE
 };
 #endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */
 
@@ -2125,116 +2245,140 @@ static const mbedtls_cipher_base_t kw_aes_info = {
 };
 
 static const mbedtls_cipher_info_t aes_128_nist_kw_info = {
-    MBEDTLS_CIPHER_AES_128_KW,
-    MBEDTLS_MODE_KW,
-    128,
     "AES-128-KW",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KW,
+    MBEDTLS_CIPHER_AES_128_KW,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_nist_kw_info = {
-    MBEDTLS_CIPHER_AES_192_KW,
-    MBEDTLS_MODE_KW,
-    192,
     "AES-192-KW",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KW,
+    MBEDTLS_CIPHER_AES_192_KW,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_nist_kw_info = {
-    MBEDTLS_CIPHER_AES_256_KW,
-    MBEDTLS_MODE_KW,
-    256,
     "AES-256-KW",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KW,
+    MBEDTLS_CIPHER_AES_256_KW,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
+#endif
 
 static const mbedtls_cipher_info_t aes_128_nist_kwp_info = {
-    MBEDTLS_CIPHER_AES_128_KWP,
-    MBEDTLS_MODE_KWP,
-    128,
     "AES-128-KWP",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    128 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KWP,
+    MBEDTLS_CIPHER_AES_128_KWP,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
 
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const mbedtls_cipher_info_t aes_192_nist_kwp_info = {
-    MBEDTLS_CIPHER_AES_192_KWP,
-    MBEDTLS_MODE_KWP,
-    192,
     "AES-192-KWP",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    192 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KWP,
+    MBEDTLS_CIPHER_AES_192_KWP,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
 
 static const mbedtls_cipher_info_t aes_256_nist_kwp_info = {
-    MBEDTLS_CIPHER_AES_256_KWP,
-    MBEDTLS_MODE_KWP,
-    256,
     "AES-256-KWP",
-    0,
-    0,
     16,
-    &kw_aes_info
+    0 >> MBEDTLS_IV_SIZE_SHIFT,
+    256 >> MBEDTLS_KEY_BITLEN_SHIFT,
+    MBEDTLS_MODE_KWP,
+    MBEDTLS_CIPHER_AES_256_KWP,
+    0,
+    MBEDTLS_CIPHER_BASE_INDEX_KW_AES
 };
+#endif
 #endif /* MBEDTLS_NIST_KW_C */
 
 const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
 {
 #if defined(MBEDTLS_AES_C)
     { MBEDTLS_CIPHER_AES_128_ECB,          &aes_128_ecb_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_ECB,          &aes_192_ecb_info },
     { MBEDTLS_CIPHER_AES_256_ECB,          &aes_256_ecb_info },
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
     { MBEDTLS_CIPHER_AES_128_CBC,          &aes_128_cbc_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_CBC,          &aes_192_cbc_info },
     { MBEDTLS_CIPHER_AES_256_CBC,          &aes_256_cbc_info },
 #endif
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
     { MBEDTLS_CIPHER_AES_128_CFB128,       &aes_128_cfb128_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_CFB128,       &aes_192_cfb128_info },
     { MBEDTLS_CIPHER_AES_256_CFB128,       &aes_256_cfb128_info },
 #endif
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
     { MBEDTLS_CIPHER_AES_128_OFB,          &aes_128_ofb_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_OFB,          &aes_192_ofb_info },
     { MBEDTLS_CIPHER_AES_256_OFB,          &aes_256_ofb_info },
 #endif
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
     { MBEDTLS_CIPHER_AES_128_CTR,          &aes_128_ctr_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_CTR,          &aes_192_ctr_info },
     { MBEDTLS_CIPHER_AES_256_CTR,          &aes_256_ctr_info },
 #endif
+#endif
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
     { MBEDTLS_CIPHER_AES_128_XTS,          &aes_128_xts_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_256_XTS,          &aes_256_xts_info },
 #endif
-#if defined(MBEDTLS_GCM_C)
+#endif
+#endif /* MBEDTLS_AES_C */
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)
     { MBEDTLS_CIPHER_AES_128_GCM,          &aes_128_gcm_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_GCM,          &aes_192_gcm_info },
     { MBEDTLS_CIPHER_AES_256_GCM,          &aes_256_gcm_info },
 #endif
-#if defined(MBEDTLS_CCM_C)
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)
     { MBEDTLS_CIPHER_AES_128_CCM,          &aes_128_ccm_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_CCM,          &aes_192_ccm_info },
     { MBEDTLS_CIPHER_AES_256_CCM,          &aes_256_ccm_info },
+#endif
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA)
     { MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG,          &aes_128_ccm_star_no_tag_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG,          &aes_192_ccm_star_no_tag_info },
     { MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG,          &aes_256_ccm_star_no_tag_info },
 #endif
-#endif /* MBEDTLS_AES_C */
+#endif
 
 #if defined(MBEDTLS_CAMELLIA_C)
     { MBEDTLS_CIPHER_CAMELLIA_128_ECB,     &camellia_128_ecb_info },
@@ -2325,12 +2469,16 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
 
 #if defined(MBEDTLS_NIST_KW_C)
     { MBEDTLS_CIPHER_AES_128_KW,          &aes_128_nist_kw_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_KW,          &aes_192_nist_kw_info },
     { MBEDTLS_CIPHER_AES_256_KW,          &aes_256_nist_kw_info },
+#endif
     { MBEDTLS_CIPHER_AES_128_KWP,         &aes_128_nist_kwp_info },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { MBEDTLS_CIPHER_AES_192_KWP,         &aes_192_nist_kwp_info },
     { MBEDTLS_CIPHER_AES_256_KWP,         &aes_256_nist_kwp_info },
 #endif
+#endif
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
     { MBEDTLS_CIPHER_NULL,                 &null_cipher_info },
@@ -2343,4 +2491,58 @@ const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] =
                      sizeof(mbedtls_cipher_definitions[0]))
 int mbedtls_cipher_supported[NUM_CIPHERS];
 
+const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[] = {
+#if defined(MBEDTLS_AES_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_AES] = &aes_info,
+#endif
+#if defined(MBEDTLS_ARIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_ARIA] = &aria_info,
+#endif
+#if defined(MBEDTLS_CAMELLIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_CAMELLIA] = &camellia_info,
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA)
+    [MBEDTLS_CIPHER_BASE_INDEX_CCM_AES] = &ccm_aes_info,
+#endif
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_ARIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_CCM_ARIA] = &ccm_aria_info,
+#endif
+#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_CAMELLIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_CCM_CAMELLIA] = &ccm_camellia_info,
+#endif
+#if defined(MBEDTLS_CHACHA20_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_CHACHA20_BASE] = &chacha20_base_info,
+#endif
+#if defined(MBEDTLS_CHACHAPOLY_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_CHACHAPOLY_BASE] = &chachapoly_base_info,
+#endif
+#if defined(MBEDTLS_DES_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE3] = &des_ede3_info,
+#endif
+#if defined(MBEDTLS_DES_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_DES_EDE] = &des_ede_info,
+#endif
+#if defined(MBEDTLS_DES_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_DES] = &des_info,
+#endif
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA)
+    [MBEDTLS_CIPHER_BASE_INDEX_GCM_AES] = &gcm_aes_info,
+#endif
+#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_ARIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_GCM_ARIA] = &gcm_aria_info,
+#endif
+#if defined(MBEDTLS_GCM_C) && defined(MBEDTLS_CAMELLIA_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_GCM_CAMELLIA] = &gcm_camellia_info,
+#endif
+#if defined(MBEDTLS_NIST_KW_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_KW_AES] = &kw_aes_info,
+#endif
+#if defined(MBEDTLS_CIPHER_NULL_CIPHER)
+    [MBEDTLS_CIPHER_BASE_INDEX_NULL_BASE] = &null_base_info,
+#endif
+#if defined(MBEDTLS_CIPHER_MODE_XTS) && defined(MBEDTLS_AES_C)
+    [MBEDTLS_CIPHER_BASE_INDEX_XTS_AES] = &xts_aes_info
+#endif
+};
+
 #endif /* MBEDTLS_CIPHER_C */
diff --git a/lib/libmbedtls/mbedtls/library/cipher_wrap.h b/lib/libmbedtls/mbedtls/library/cipher_wrap.h
index 49f5ff149305483c946c3d1376e61558f3338284..aa742892042316a39403a5662ef0560bf6a33431 100644
--- a/lib/libmbedtls/mbedtls/library/cipher_wrap.h
+++ b/lib/libmbedtls/mbedtls/library/cipher_wrap.h
@@ -7,19 +7,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_CIPHER_WRAP_H
 #define MBEDTLS_CIPHER_WRAP_H
@@ -36,6 +24,50 @@
 extern "C" {
 #endif
 
+/* Support for GCM either through Mbed TLS SW implementation or PSA */
+#if defined(MBEDTLS_GCM_C) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM))
+#define MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_AES_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_GCM) && defined(PSA_WANT_KEY_TYPE_AES))
+#define MBEDTLS_CIPHER_HAVE_GCM_AES_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if defined(MBEDTLS_CCM_C) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM))
+#define MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM) && defined(PSA_WANT_KEY_TYPE_AES))
+#define MBEDTLS_CIPHER_HAVE_CCM_AES_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if defined(MBEDTLS_CCM_C) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG))
+#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if (defined(MBEDTLS_CCM_C) && defined(MBEDTLS_AES_C)) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CCM_STAR_NO_TAG) && \
+    defined(PSA_WANT_KEY_TYPE_AES))
+#define MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_AES_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C) || \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) && defined(PSA_WANT_ALG_CHACHA20_POLY1305))
+#define MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA
+#endif
+
+#if defined(MBEDTLS_CIPHER_HAVE_GCM_VIA_LEGACY_OR_USE_PSA) || \
+    defined(MBEDTLS_CIPHER_HAVE_CCM_VIA_LEGACY_OR_USE_PSA) || \
+    defined(MBEDTLS_CIPHER_HAVE_CCM_STAR_NO_TAG_VIA_LEGACY_OR_USE_PSA) || \
+    defined(MBEDTLS_CIPHER_HAVE_CHACHAPOLY_VIA_LEGACY_OR_USE_PSA)
+#define MBEDTLS_CIPHER_HAVE_SOME_AEAD_VIA_LEGACY_OR_USE_PSA
+#endif
+
 /**
  * Base cipher information. The non-mode specific functions and values.
  */
@@ -93,9 +125,11 @@ struct mbedtls_cipher_base_t {
     int (*setkey_enc_func)(void *ctx, const unsigned char *key,
                            unsigned int key_bitlen);
 
+#if !defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
     /** Set key for decryption purposes */
     int (*setkey_dec_func)(void *ctx, const unsigned char *key,
                            unsigned int key_bitlen);
+#endif
 
     /** Allocate a new context */
     void * (*ctx_alloc_func)(void);
@@ -138,6 +172,8 @@ extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[];
 
 extern int mbedtls_cipher_supported[];
 
+extern const mbedtls_cipher_base_t *mbedtls_cipher_base_lookup_table[];
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/libmbedtls/mbedtls/library/cmac.c b/lib/libmbedtls/mbedtls/library/cmac.c
index 17c7e49c1904d5fc034c9f4680dbf64d76b3bcd8..a1ef9475968975c9a010ad3990c38dd0eea288a6 100644
--- a/lib/libmbedtls/mbedtls/library/cmac.c
+++ b/lib/libmbedtls/mbedtls/library/cmac.c
@@ -4,19 +4,7 @@
  * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -46,6 +34,7 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
+#include "constant_time_internal.h"
 
 #include <string.h>
 
@@ -68,39 +57,33 @@ static int cmac_multiply_by_u(unsigned char *output,
                               size_t blocksize)
 {
     const unsigned char R_128 = 0x87;
-    const unsigned char R_64 = 0x1B;
-    unsigned char R_n, mask;
-    unsigned char overflow = 0x00;
+    unsigned char R_n;
+    uint32_t overflow = 0x00;
     int i;
 
     if (blocksize == MBEDTLS_AES_BLOCK_SIZE) {
         R_n = R_128;
-    } else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
+    }
+#if defined(MBEDTLS_DES_C)
+    else if (blocksize == MBEDTLS_DES3_BLOCK_SIZE) {
+        const unsigned char R_64 = 0x1B;
         R_n = R_64;
-    } else {
+    }
+#endif
+    else {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    for (i = (int) blocksize - 1; i >= 0; i--) {
-        output[i] = input[i] << 1 | overflow;
-        overflow = input[i] >> 7;
+    for (i = (int) blocksize - 4; i >= 0; i -= 4) {
+        uint32_t i32 = MBEDTLS_GET_UINT32_BE(&input[i], 0);
+        uint32_t new_overflow = i32 >> 31;
+        i32 = (i32 << 1) | overflow;
+        MBEDTLS_PUT_UINT32_BE(i32, &output[i], 0);
+        overflow = new_overflow;
     }
 
-    /* mask = ( input[0] >> 7 ) ? 0xff : 0x00
-     * using bit operations to avoid branches */
-
-    /* MSVC has a warning about unary minus on unsigned, but this is
-     * well-defined and precisely what we want to do here */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-    mask = -(input[0] >> 7);
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    output[blocksize - 1] ^= R_n & mask;
+    R_n = (unsigned char) mbedtls_ct_uint_if_else_0(mbedtls_ct_bool(input[0] >> 7), R_n);
+    output[blocksize - 1] ^= R_n;
 
     return 0;
 }
@@ -114,12 +97,12 @@ static int cmac_generate_subkeys(mbedtls_cipher_context_t *ctx,
                                  unsigned char *K1, unsigned char *K2)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char L[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
     size_t olen, block_size;
 
     mbedtls_platform_zeroize(L, sizeof(L));
 
-    block_size = ctx->cipher_info->block_size;
+    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
 
     /* Calculate Ek(0) */
     if ((ret = mbedtls_cipher_update(ctx, L, block_size, L, &olen)) != 0) {
@@ -152,7 +135,7 @@ exit:
  * We can't use the padding option from the cipher layer, as it only works for
  * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition.
  */
-static void cmac_pad(unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX],
+static void cmac_pad(unsigned char padded_block[MBEDTLS_CMAC_MAX_BLOCK_SIZE],
                      size_t padded_block_len,
                      const unsigned char *last_block,
                      size_t last_block_len)
@@ -201,7 +184,7 @@ int mbedtls_cipher_cmac_starts(mbedtls_cipher_context_t *ctx,
         return retval;
     }
 
-    type = ctx->cipher_info->type;
+    type = mbedtls_cipher_info_get_type(ctx->cipher_info);
 
     switch (type) {
         case MBEDTLS_CIPHER_AES_128_ECB:
@@ -234,9 +217,13 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
     }
 
     cmac_ctx = ctx->cmac_ctx;
-    block_size = ctx->cipher_info->block_size;
+    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
     state = ctx->cmac_ctx->state;
 
+    /* Without the MBEDTLS_ASSUME below, gcc -O3 will generate a warning of the form
+     * error: writing 16 bytes into a region of size 0 [-Werror=stringop-overflow=] */
+    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE);
+
     /* Is there data still to process from the last call, that's greater in
      * size than a block? */
     if (cmac_ctx->unprocessed_len > 0 &&
@@ -245,7 +232,7 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
                input,
                block_size - cmac_ctx->unprocessed_len);
 
-        mbedtls_xor(state, cmac_ctx->unprocessed_block, state, block_size);
+        mbedtls_xor_no_simd(state, cmac_ctx->unprocessed_block, state, block_size);
 
         if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
                                          &olen)) != 0) {
@@ -263,7 +250,7 @@ int mbedtls_cipher_cmac_update(mbedtls_cipher_context_t *ctx,
     /* Iterate across the input data in block sized chunks, excluding any
      * final partial or complete block */
     for (j = 1; j < n; j++) {
-        mbedtls_xor(state, input, state, block_size);
+        mbedtls_xor_no_simd(state, input, state, block_size);
 
         if ((ret = mbedtls_cipher_update(ctx, state, block_size, state,
                                          &olen)) != 0) {
@@ -291,9 +278,9 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
 {
     mbedtls_cmac_context_t *cmac_ctx;
     unsigned char *state, *last_block;
-    unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
-    unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
-    unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
+    unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
+    unsigned char M_last[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t olen, block_size;
 
@@ -303,7 +290,8 @@ int mbedtls_cipher_cmac_finish(mbedtls_cipher_context_t *ctx,
     }
 
     cmac_ctx = ctx->cmac_ctx;
-    block_size = ctx->cipher_info->block_size;
+    block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
+    MBEDTLS_ASSUME(block_size <= MBEDTLS_CMAC_MAX_BLOCK_SIZE); // silence GCC warning
     state = cmac_ctx->state;
 
     mbedtls_platform_zeroize(K1, sizeof(K1));
@@ -340,7 +328,7 @@ exit:
     mbedtls_platform_zeroize(cmac_ctx->unprocessed_block,
                              sizeof(cmac_ctx->unprocessed_block));
 
-    mbedtls_platform_zeroize(state, MBEDTLS_CIPHER_BLKSIZE_MAX);
+    mbedtls_platform_zeroize(state, MBEDTLS_CMAC_MAX_BLOCK_SIZE);
     return ret;
 }
 
@@ -529,6 +517,7 @@ static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL
 };
 
 /* CMAC-AES192 Test Data */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const unsigned char aes_192_key[24] = {
     0x8e, 0x73, 0xb0, 0xf7,     0xda, 0x0e, 0x64, 0x52,
     0xc8, 0x10, 0xf3, 0x2b,     0x80, 0x90, 0x79, 0xe5,
@@ -569,8 +558,10 @@ static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL
         0x4d, 0x77, 0x58, 0x96,     0x59, 0xf3, 0x9a, 0x11
     }
 };
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 
 /* CMAC-AES256 Test Data */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
 static const unsigned char aes_256_key[32] = {
     0x60, 0x3d, 0xeb, 0x10,     0x15, 0xca, 0x71, 0xbe,
     0x2b, 0x73, 0xae, 0xf0,     0x85, 0x7d, 0x77, 0x81,
@@ -612,6 +603,7 @@ static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTL
         0x69, 0x6a, 0x2c, 0x05,     0x6c, 0x31, 0x54, 0x10
     }
 };
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_DES_C)
@@ -754,8 +746,8 @@ static int cmac_test_subkeys(int verbose,
     int i, ret = 0;
     mbedtls_cipher_context_t ctx;
     const mbedtls_cipher_info_t *cipher_info;
-    unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX];
-    unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char K1[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
+    unsigned char K2[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
 
     cipher_info = mbedtls_cipher_info_from_type(cipher_type);
     if (cipher_info == NULL) {
@@ -849,7 +841,7 @@ static int cmac_test_wth_cipher(int verbose,
 {
     const mbedtls_cipher_info_t *cipher_info;
     int i, ret = 0;
-    unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX];
+    unsigned char output[MBEDTLS_CMAC_MAX_BLOCK_SIZE];
 
     cipher_info = mbedtls_cipher_info_from_type(cipher_type);
     if (cipher_info == NULL) {
@@ -959,6 +951,7 @@ int mbedtls_cmac_self_test(int verbose)
     }
 
     /* AES-192 */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     if ((ret = cmac_test_subkeys(verbose,
                                  "AES 192",
                                  aes_192_key,
@@ -982,8 +975,10 @@ int mbedtls_cmac_self_test(int verbose)
                                     NB_CMAC_TESTS_PER_KEY)) != 0) {
         return ret;
     }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 
     /* AES-256 */
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     if ((ret = cmac_test_subkeys(verbose,
                                  "AES 256",
                                  aes_256_key,
@@ -1007,6 +1002,7 @@ int mbedtls_cmac_self_test(int verbose)
                                     NB_CMAC_TESTS_PER_KEY)) != 0) {
         return ret;
     }
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 #endif /* MBEDTLS_AES_C */
 
 #if defined(MBEDTLS_DES_C)
diff --git a/lib/libmbedtls/mbedtls/library/common.h b/lib/libmbedtls/mbedtls/library/common.h
index eb159a7c48755798633a6c61de0a8fd14f95a2d0..17a4dc970746e97cc121046be45de6b873f90195 100644
--- a/lib/libmbedtls/mbedtls/library/common.h
+++ b/lib/libmbedtls/mbedtls/library/common.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_LIBRARY_COMMON_H
@@ -31,6 +19,24 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#if defined(__ARM_NEON)
+/*
+ * Undefine and restore __section and __data from compiler.h to prevent
+ * collision with arm_neon.h
+ */
+#pragma push_macro("__section")
+#pragma push_macro("__data")
+#undef __section
+#undef __data
+#include <arm_neon.h>
+#pragma pop_macro("__data")
+#pragma pop_macro("__section")
+#define MBEDTLS_HAVE_NEON_INTRINSICS
+#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
+#include <arm64_neon.h>
+#define MBEDTLS_HAVE_NEON_INTRINSICS
+#endif
+
 /** Helper to define a function as static except when building invasive tests.
  *
  * If a function is only used inside its own source file and should be
@@ -65,6 +71,44 @@ extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const cha
 #define MBEDTLS_TEST_HOOK_TEST_ASSERT(TEST)
 #endif /* defined(MBEDTLS_TEST_HOOKS) */
 
+/** \def ARRAY_LENGTH
+ * Return the number of elements of a static or stack array.
+ *
+ * \param array         A value of array (not pointer) type.
+ *
+ * \return The number of elements of the array.
+ */
+/* A correct implementation of ARRAY_LENGTH, but which silently gives
+ * a nonsensical result if called with a pointer rather than an array. */
+#define ARRAY_LENGTH_UNSAFE(array)            \
+    (sizeof(array) / sizeof(*(array)))
+
+#if defined(__GNUC__)
+/* Test if arg and &(arg)[0] have the same type. This is true if arg is
+ * an array but not if it's a pointer. */
+#define IS_ARRAY_NOT_POINTER(arg)                                     \
+    (!__builtin_types_compatible_p(__typeof__(arg),                \
+                                   __typeof__(&(arg)[0])))
+/* A compile-time constant with the value 0. If `const_expr` is not a
+ * compile-time constant with a nonzero value, cause a compile-time error. */
+#define STATIC_ASSERT_EXPR(const_expr)                                \
+    (0 && sizeof(struct { unsigned int STATIC_ASSERT : 1 - 2 * !(const_expr); }))
+
+/* Return the scalar value `value` (possibly promoted). This is a compile-time
+ * constant if `value` is. `condition` must be a compile-time constant.
+ * If `condition` is false, arrange to cause a compile-time error. */
+#define STATIC_ASSERT_THEN_RETURN(condition, value)   \
+    (STATIC_ASSERT_EXPR(condition) ? 0 : (value))
+
+#define ARRAY_LENGTH(array)                                           \
+    (STATIC_ASSERT_THEN_RETURN(IS_ARRAY_NOT_POINTER(array),         \
+                               ARRAY_LENGTH_UNSAFE(array)))
+
+#else
+/* If we aren't sure the compiler supports our non-standard tricks,
+ * fall back to the unsafe implementation. */
+#define ARRAY_LENGTH(array) ARRAY_LENGTH_UNSAFE(array)
+#endif
 /** Allow library to access its structs' private members.
  *
  * Although structs defined in header files are publicly available,
@@ -72,6 +116,20 @@ extern void (*mbedtls_test_hook_test_fail)(const char *test, int line, const cha
  */
 #define MBEDTLS_ALLOW_PRIVATE_ACCESS
 
+/**
+ * \brief       Securely zeroize a buffer then free it.
+ *
+ *              Similar to making consecutive calls to
+ *              \c mbedtls_platform_zeroize() and \c mbedtls_free(), but has
+ *              code size savings, and potential for optimisation in the future.
+ *
+ *              Guaranteed to be a no-op if \p buf is \c NULL and \p len is 0.
+ *
+ * \param buf   Buffer to be zeroized then freed.
+ * \param len   Length of the buffer in bytes
+ */
+void mbedtls_zeroize_and_free(void *buf, size_t len);
+
 /** Return an offset into a buffer.
  *
  * This is just the addition of an offset to a pointer, except that this
@@ -110,25 +168,146 @@ static inline const unsigned char *mbedtls_buffer_offset_const(
     return p == NULL ? NULL : p + n;
 }
 
+/* Always inline mbedtls_xor() for similar reasons as mbedtls_xor_no_simd(). */
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
+/**
+ * Perform a fast block XOR operation, such that
+ * r[i] = a[i] ^ b[i] where 0 <= i < n
+ *
+ * \param   r Pointer to result (buffer of at least \p n bytes). \p r
+ *            may be equal to either \p a or \p b, but behaviour when
+ *            it overlaps in other ways is undefined.
+ * \param   a Pointer to input (buffer of at least \p n bytes)
+ * \param   b Pointer to input (buffer of at least \p n bytes)
+ * \param   n Number of bytes to process.
+ *
+ * \note      Depending on the situation, it may be faster to use either mbedtls_xor() or
+ *            mbedtls_xor_no_simd() (these are functionally equivalent).
+ *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in
+ *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
+ *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
+ *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
+ *            For targets without SIMD support, they will behave the same.
+ */
+static inline void mbedtls_xor(unsigned char *r,
+                               const unsigned char *a,
+                               const unsigned char *b,
+                               size_t n)
+{
+    size_t i = 0;
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
+#if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \
+    (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300))
+    /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */
+    for (; (i + 16) <= n; i += 16) {
+        uint8x16_t v1 = vld1q_u8(a + i);
+        uint8x16_t v2 = vld1q_u8(b + i);
+        uint8x16_t x = veorq_u8(v1, v2);
+        vst1q_u8(r + i, x);
+    }
+#if defined(__IAR_SYSTEMS_ICC__)
+    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
+     * where n is a constant multiple of 16.
+     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
+     * constant, and is a very small perf regression if n is not a compile-time constant. */
+    if (n % 16 == 0) {
+        return;
+    }
+#endif
+#elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
+    /* This codepath probably only makes sense on architectures with 64-bit registers */
+    for (; (i + 8) <= n; i += 8) {
+        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
+        mbedtls_put_unaligned_uint64(r + i, x);
+    }
+#if defined(__IAR_SYSTEMS_ICC__)
+    if (n % 8 == 0) {
+        return;
+    }
+#endif
+#else
+    for (; (i + 4) <= n; i += 4) {
+        uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
+        mbedtls_put_unaligned_uint32(r + i, x);
+    }
+#if defined(__IAR_SYSTEMS_ICC__)
+    if (n % 4 == 0) {
+        return;
+    }
+#endif
+#endif
+#endif
+    for (; i < n; i++) {
+        r[i] = a[i] ^ b[i];
+    }
+}
+
+/* Always inline mbedtls_xor_no_simd() as we see significant perf regressions when it does not get
+ * inlined (e.g., observed about 3x perf difference in gcm_mult_largetable with gcc 7 - 12) */
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma inline = forced
+#elif defined(__GNUC__)
+__attribute__((always_inline))
+#endif
 /**
  * Perform a fast block XOR operation, such that
  * r[i] = a[i] ^ b[i] where 0 <= i < n
  *
+ * In some situations, this can perform better than mbedtls_xor() (e.g., it's about 5%
+ * better in AES-CBC).
+ *
  * \param   r Pointer to result (buffer of at least \p n bytes). \p r
  *            may be equal to either \p a or \p b, but behaviour when
  *            it overlaps in other ways is undefined.
  * \param   a Pointer to input (buffer of at least \p n bytes)
  * \param   b Pointer to input (buffer of at least \p n bytes)
  * \param   n Number of bytes to process.
+ *
+ * \note      Depending on the situation, it may be faster to use either mbedtls_xor() or
+ *            mbedtls_xor_no_simd() (these are functionally equivalent).
+ *            If the result is used immediately after the xor operation in non-SIMD code (e.g, in
+ *            AES-CBC), there may be additional latency to transfer the data from SIMD to scalar
+ *            registers, and in this case, mbedtls_xor_no_simd() may be faster. In other cases where
+ *            the result is not used immediately (e.g., in AES-CTR), mbedtls_xor() may be faster.
+ *            For targets without SIMD support, they will behave the same.
  */
-inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned char *b, size_t n)
+static inline void mbedtls_xor_no_simd(unsigned char *r,
+                                       const unsigned char *a,
+                                       const unsigned char *b,
+                                       size_t n)
 {
     size_t i = 0;
 #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
+#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64)
+    /* This codepath probably only makes sense on architectures with 64-bit registers */
+    for (; (i + 8) <= n; i += 8) {
+        uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i);
+        mbedtls_put_unaligned_uint64(r + i, x);
+    }
+#if defined(__IAR_SYSTEMS_ICC__)
+    /* This if statement helps some compilers (e.g., IAR) optimise out the byte-by-byte tail case
+     * where n is a constant multiple of 8.
+     * For other compilers (e.g. recent gcc and clang) it makes no difference if n is a compile-time
+     * constant, and is a very small perf regression if n is not a compile-time constant. */
+    if (n % 8 == 0) {
+        return;
+    }
+#endif
+#else
     for (; (i + 4) <= n; i += 4) {
         uint32_t x = mbedtls_get_unaligned_uint32(a + i) ^ mbedtls_get_unaligned_uint32(b + i);
         mbedtls_put_unaligned_uint32(r + i, x);
     }
+#if defined(__IAR_SYSTEMS_ICC__)
+    if (n % 4 == 0) {
+        return;
+    }
+#endif
+#endif
 #endif
     for (; i < n; i++) {
         r[i] = a[i] ^ b[i];
@@ -146,22 +325,123 @@ inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned
 /* Define `asm` for compilers which don't define it. */
 /* *INDENT-OFF* */
 #ifndef asm
+#if defined(__IAR_SYSTEMS_ICC__)
+#define asm __asm
+#else
 #define asm __asm__
 #endif
+#endif
 /* *INDENT-ON* */
 
+/*
+ * Define the constraint used for read-only pointer operands to aarch64 asm.
+ *
+ * This is normally the usual "r", but for aarch64_32 (aka ILP32,
+ * as found in watchos), "p" is required to avoid warnings from clang.
+ *
+ * Note that clang does not recognise '+p' or '=p', and armclang
+ * does not recognise 'p' at all. Therefore, to update a pointer from
+ * aarch64 assembly, it is necessary to use something like:
+ *
+ * uintptr_t uptr = (uintptr_t) ptr;
+ * asm( "ldr x4, [%x0], #8" ... : "+r" (uptr) : : )
+ * ptr = (void*) uptr;
+ *
+ * Note that the "x" in "%x0" is neccessary; writing "%0" will cause warnings.
+ */
+#if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM)
+#if UINTPTR_MAX == 0xfffffffful
+/* ILP32: Specify the pointer operand slightly differently, as per #7787. */
+#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p"
+#elif UINTPTR_MAX == 0xfffffffffffffffful
+/* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */
+#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r"
+#else
+#error "Unrecognised pointer size for aarch64"
+#endif
+#endif
+
 /* Always provide a static assert macro, so it can be used unconditionally.
- * It will expand to nothing on some systems.
- * Can be used outside functions (but don't add a trailing ';' in that case:
- * the semicolon is included here to avoid triggering -Wextra-semi when
- * MBEDTLS_STATIC_ASSERT() expands to nothing).
- * Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
+ * It does nothing on systems where we don't know how to define a static assert.
+ */
+/* Can't use the C11-style `defined(static_assert)` on FreeBSD, since it
  * defines static_assert even with -std=c99, but then complains about it.
  */
 #if defined(static_assert) && !defined(__FreeBSD__)
-#define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg);
+#define MBEDTLS_STATIC_ASSERT(expr, msg)    static_assert(expr, msg)
+#else
+/* Make sure `MBEDTLS_STATIC_ASSERT(expr, msg);` is valid both inside and
+ * outside a function. We choose a struct declaration, which can be repeated
+ * any number of times and does not need a matching definition. */
+#define MBEDTLS_STATIC_ASSERT(expr, msg)                                \
+    struct ISO_C_does_not_allow_extra_semicolon_outside_of_a_function
+#endif
+
+#if defined(__has_builtin)
+#define MBEDTLS_HAS_BUILTIN(x) __has_builtin(x)
+#else
+#define MBEDTLS_HAS_BUILTIN(x) 0
+#endif
+
+/* Define compiler branch hints */
+#if MBEDTLS_HAS_BUILTIN(__builtin_expect)
+#define MBEDTLS_LIKELY(x)       __builtin_expect(!!(x), 1)
+#define MBEDTLS_UNLIKELY(x)     __builtin_expect(!!(x), 0)
+#else
+#define MBEDTLS_LIKELY(x)       x
+#define MBEDTLS_UNLIKELY(x)     x
+#endif
+
+/* MBEDTLS_ASSUME may be used to provide additional information to the compiler
+ * which can result in smaller code-size. */
+#if MBEDTLS_HAS_BUILTIN(__builtin_assume)
+/* clang provides __builtin_assume */
+#define MBEDTLS_ASSUME(x)       __builtin_assume(x)
+#elif MBEDTLS_HAS_BUILTIN(__builtin_unreachable)
+/* gcc and IAR can use __builtin_unreachable */
+#define MBEDTLS_ASSUME(x)       do { if (!(x)) __builtin_unreachable(); } while (0)
+#elif defined(_MSC_VER)
+/* Supported by MSVC since VS 2005 */
+#define MBEDTLS_ASSUME(x)       __assume(x)
 #else
-#define MBEDTLS_STATIC_ASSERT(expr, msg)
+#define MBEDTLS_ASSUME(x)       do { } while (0)
+#endif
+
+/* For gcc -Os, override with -O2 for a given function.
+ *
+ * This will not affect behaviour for other optimisation settings, e.g. -O0.
+ */
+#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__OPTIMIZE_SIZE__)
+#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE __attribute__((optimize("-O2")))
+#else
+#define MBEDTLS_OPTIMIZE_FOR_PERFORMANCE
+#endif
+
+/* Suppress compiler warnings for unused functions and variables. */
+#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__has_attribute)
+#    if __has_attribute(unused)
+#        define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
+#    endif
+#endif
+#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__GNUC__)
+#    define MBEDTLS_MAYBE_UNUSED __attribute__((unused))
+#endif
+#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(__IAR_SYSTEMS_ICC__) && defined(__VER__)
+/* IAR does support __attribute__((unused)), but only if the -e flag (extended language support)
+ * is given; the pragma always works.
+ * Unfortunately the pragma affects the rest of the file where it is used, but this is harmless.
+ * Check for version 5.2 or later - this pragma may be supported by earlier versions, but I wasn't
+ * able to find documentation).
+ */
+#    if (__VER__ >= 5020000)
+#        define MBEDTLS_MAYBE_UNUSED _Pragma("diag_suppress=Pe177")
+#    endif
+#endif
+#if !defined(MBEDTLS_MAYBE_UNUSED) && defined(_MSC_VER)
+#    define MBEDTLS_MAYBE_UNUSED __pragma(warning(suppress:4189))
+#endif
+#if !defined(MBEDTLS_MAYBE_UNUSED)
+#    define MBEDTLS_MAYBE_UNUSED
 #endif
 
 #endif /* MBEDTLS_LIBRARY_COMMON_H */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time.c b/lib/libmbedtls/mbedtls/library/constant_time.c
index 552a918f43abae01e556fe1a33596d14ca033861..d212ddfd8104eb0ff08efea35a3387d7c4347008 100644
--- a/lib/libmbedtls/mbedtls/library/constant_time.c
+++ b/lib/libmbedtls/mbedtls/library/constant_time.c
@@ -2,19 +2,7 @@
  *  Constant-time functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -22,34 +10,24 @@
  * might be translated to branches by some compilers on some platforms.
  */
 
+#include <stdint.h>
+#include <limits.h>
+
 #include "common.h"
 #include "constant_time_internal.h"
 #include "mbedtls/constant_time.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
-#if defined(MBEDTLS_BIGNUM_C)
-#include "mbedtls/bignum.h"
-#include "bignum_core.h"
-#endif
-
-#if defined(MBEDTLS_SSL_TLS_C)
-#include "ssl_misc.h"
-#endif
-
-#if defined(MBEDTLS_RSA_C)
-#include "mbedtls/rsa.h"
-#endif
-
-#if defined(MBEDTLS_BASE64_C)
-#include "constant_time_invasive.h"
-#endif
-
 #include <string.h>
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,    \
-                                                           psa_to_ssl_errors,              \
-                                                           psa_generic_status_to_mbedtls)
+
+#if !defined(MBEDTLS_CT_ASM)
+/*
+ * Define an object with the value zero, such that the compiler cannot prove that it
+ * has the value zero (because it is volatile, it "may be modified in ways unknown to
+ * the implementation").
+ */
+volatile mbedtls_ct_uint_t mbedtls_ct_zero = 0;
 #endif
 
 /*
@@ -62,13 +40,12 @@
  * Some of these definitions could be moved into alignment.h but for now they are
  * only used here.
  */
-#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && defined(MBEDTLS_HAVE_ASM)
-#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(__aarch64__)
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && \
+    ((defined(MBEDTLS_CT_ARM_ASM) && (UINTPTR_MAX == 0xfffffffful)) || \
+    defined(MBEDTLS_CT_AARCH64_ASM))
+/* We check pointer sizes to avoid issues with them not matching register size requirements */
 #define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS
-#endif
-#endif
 
-#if defined(MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS)
 static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsigned char *p)
 {
     /* This is UB, even where it's safe:
@@ -76,14 +53,17 @@ static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsi
      * so instead the same thing is expressed in assembly below.
      */
     uint32_t r;
-#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__)
+#if defined(MBEDTLS_CT_ARM_ASM)
     asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :);
-#elif defined(__aarch64__)
-    asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :);
+#elif defined(MBEDTLS_CT_AARCH64_ASM)
+    asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :);
+#else
+#error "No assembly defined for mbedtls_get_unaligned_volatile_uint32"
 #endif
     return r;
 }
-#endif /* MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS */
+#endif /* defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) &&
+          (defined(MBEDTLS_CT_ARM_ASM) || defined(MBEDTLS_CT_AARCH64_ASM)) */
 
 int mbedtls_ct_memcmp(const void *a,
                       const void *b,
@@ -116,373 +96,119 @@ int mbedtls_ct_memcmp(const void *a,
         diff |= x ^ y;
     }
 
-    return (int) diff;
-}
-
-unsigned mbedtls_ct_uint_mask(unsigned value)
-{
-    /* MSVC has a warning about unary minus on unsigned, but this is
-     * well-defined and precisely what we want to do here */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-    return -((value | -value) >> (sizeof(value) * 8 - 1));
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-}
-
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-
-size_t mbedtls_ct_size_mask(size_t value)
-{
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-    return -((value | -value) >> (sizeof(value) * 8 - 1));
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-}
-
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
-#if defined(MBEDTLS_BIGNUM_C)
-
-mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value)
-{
-    /* MSVC has a warning about unary minus on unsigned, but this is
-     * well-defined and precisely what we want to do here */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-    return -((value | -value) >> (sizeof(value) * 8 - 1));
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-}
-
-#endif /* MBEDTLS_BIGNUM_C */
-
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
-
-/** Constant-flow mask generation for "less than" comparison:
- * - if \p x < \p y, return all-bits 1, that is (size_t) -1
- * - otherwise, return all bits 0, that is 0
- *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
- *
- * \param x     The first value to analyze.
- * \param y     The second value to analyze.
- *
- * \return      All-bits-one if \p x is less than \p y, otherwise zero.
- */
-static size_t mbedtls_ct_size_mask_lt(size_t x,
-                                      size_t y)
-{
-    /* This has the most significant bit set if and only if x < y */
-    const size_t sub = x - y;
-
-    /* sub1 = (x < y) ? 1 : 0 */
-    const size_t sub1 = sub >> (sizeof(sub) * 8 - 1);
-
-    /* mask = (x < y) ? 0xff... : 0x00... */
-    const size_t mask = mbedtls_ct_size_mask(sub1);
-
-    return mask;
-}
-
-size_t mbedtls_ct_size_mask_ge(size_t x,
-                               size_t y)
-{
-    return ~mbedtls_ct_size_mask_lt(x, y);
-}
-
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
-
-#if defined(MBEDTLS_BASE64_C)
-
-/* Return 0xff if low <= c <= high, 0 otherwise.
- *
- * Constant flow with respect to c.
- */
-MBEDTLS_STATIC_TESTABLE
-unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
-                                             unsigned char high,
-                                             unsigned char c)
-{
-    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
-    unsigned low_mask = ((unsigned) c - low) >> 8;
-    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
-    unsigned high_mask = ((unsigned) high - c) >> 8;
-    return ~(low_mask | high_mask) & 0xff;
-}
-
-#endif /* MBEDTLS_BASE64_C */
-
-unsigned mbedtls_ct_size_bool_eq(size_t x,
-                                 size_t y)
-{
-    /* diff = 0 if x == y, non-zero otherwise */
-    const size_t diff = x ^ y;
-
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* diff_msb's most significant bit is equal to x != y */
-    const size_t diff_msb = (diff | (size_t) -diff);
-
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
-
-    /* diff1 = (x != y) ? 1 : 0 */
-    const unsigned diff1 = diff_msb >> (sizeof(diff_msb) * 8 - 1);
-
-    return 1 ^ diff1;
-}
-
-#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
-
-/** Constant-flow "greater than" comparison:
- * return x > y
- *
- * This is equivalent to \p x > \p y, but is likely to be compiled
- * to code using bitwise operation rather than a branch.
- *
- * \param x     The first value to analyze.
- * \param y     The second value to analyze.
- *
- * \return      1 if \p x greater than \p y, otherwise 0.
- */
-static unsigned mbedtls_ct_size_gt(size_t x,
-                                   size_t y)
-{
-    /* Return the sign bit (1 for negative) of (y - x). */
-    return (y - x) >> (sizeof(size_t) * 8 - 1);
-}
-
-#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
-
-#if defined(MBEDTLS_BIGNUM_C)
-
-unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
-                                const mbedtls_mpi_uint y)
-{
-    mbedtls_mpi_uint ret;
-    mbedtls_mpi_uint cond;
-
-    /*
-     * Check if the most significant bits (MSB) of the operands are different.
-     */
-    cond = (x ^ y);
-    /*
-     * If the MSB are the same then the difference x-y will be negative (and
-     * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
-     */
-    ret = (x - y) & ~cond;
-    /*
-     * If the MSB are different, then the operand with the MSB of 1 is the
-     * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
-     * the MSB of y is 0.)
+#if (INT_MAX < INT32_MAX)
+    /* We don't support int smaller than 32-bits, but if someone tried to build
+     * with this configuration, there is a risk that, for differing data, the
+     * only bits set in diff are in the top 16-bits, and would be lost by a
+     * simple cast from uint32 to int.
+     * This would have significant security implications, so protect against it. */
+#error "mbedtls_ct_memcmp() requires minimum 32-bit ints"
+#else
+    /* The bit-twiddling ensures that when we cast uint32_t to int, we are casting
+     * a value that is in the range 0..INT_MAX - a value larger than this would
+     * result in implementation defined behaviour.
+     *
+     * This ensures that the value returned by the function is non-zero iff
+     * diff is non-zero.
      */
-    ret |= y & cond;
-
-
-    ret = ret >> (sizeof(mbedtls_mpi_uint) * 8 - 1);
-
-    return (unsigned) ret;
-}
-
-#endif /* MBEDTLS_BIGNUM_C */
-
-unsigned mbedtls_ct_uint_if(unsigned condition,
-                            unsigned if1,
-                            unsigned if0)
-{
-    unsigned mask = mbedtls_ct_uint_mask(condition);
-    return (mask & if1) | (~mask & if0);
+    return (int) ((diff & 0xffff) | (diff >> 16));
+#endif
 }
 
-#if defined(MBEDTLS_BIGNUM_C)
-
-/** Select between two sign values without branches.
- *
- * This is functionally equivalent to `condition ? if1 : if0` but uses only bit
- * operations in order to avoid branches.
- *
- * \note if1 and if0 must be either 1 or -1, otherwise the result
- *       is undefined.
- *
- * \param condition     Condition to test; must be either 0 or 1.
- * \param if1           The first sign; must be either +1 or -1.
- * \param if0           The second sign; must be either +1 or -1.
- *
- * \return  \c if1 if \p condition is nonzero, otherwise \c if0.
- * */
-static int mbedtls_ct_cond_select_sign(unsigned char condition,
-                                       int if1,
-                                       int if0)
-{
-    /* In order to avoid questions about what we can reasonably assume about
-     * the representations of signed integers, move everything to unsigned
-     * by taking advantage of the fact that if1 and if0 are either +1 or -1. */
-    unsigned uif1 = if1 + 1;
-    unsigned uif0 = if0 + 1;
-
-    /* condition was 0 or 1, mask is 0 or 2 as are uif1 and uif0 */
-    const unsigned mask = condition << 1;
-
-    /* select uif1 or uif0 */
-    unsigned ur = (uif0 & ~mask) | (uif1 & mask);
+#if defined(MBEDTLS_NIST_KW_C)
 
-    /* ur is now 0 or 2, convert back to -1 or +1 */
-    return (int) ur - 1;
-}
-
-void mbedtls_ct_mpi_uint_cond_assign(size_t n,
-                                     mbedtls_mpi_uint *dest,
-                                     const mbedtls_mpi_uint *src,
-                                     unsigned char condition)
+int mbedtls_ct_memcmp_partial(const void *a,
+                              const void *b,
+                              size_t n,
+                              size_t skip_head,
+                              size_t skip_tail)
 {
-    size_t i;
+    unsigned int diff = 0;
 
-    /* MSVC has a warning about unary minus on unsigned integer types,
-     * but this is well-defined and precisely what we want to do here. */
-#if defined(_MSC_VER)
-#pragma warning( push )
-#pragma warning( disable : 4146 )
-#endif
-
-    /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */
-    const mbedtls_mpi_uint mask = -condition;
+    volatile const unsigned char *A = (volatile const unsigned char *) a;
+    volatile const unsigned char *B = (volatile const unsigned char *) b;
 
-#if defined(_MSC_VER)
-#pragma warning( pop )
-#endif
+    size_t valid_end = n - skip_tail;
 
-    for (i = 0; i < n; i++) {
-        dest[i] = (src[i] & mask) | (dest[i] & ~mask);
+    for (size_t i = 0; i < n; i++) {
+        unsigned char x = A[i], y = B[i];
+        unsigned int d = x ^ y;
+        mbedtls_ct_condition_t valid = mbedtls_ct_bool_and(mbedtls_ct_uint_ge(i, skip_head),
+                                                           mbedtls_ct_uint_lt(i, valid_end));
+        diff |= mbedtls_ct_uint_if_else_0(valid, d);
     }
-}
 
-#endif /* MBEDTLS_BIGNUM_C */
-
-#if defined(MBEDTLS_BASE64_C)
-
-unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
-{
-    unsigned char digit = 0;
-    /* For each range of values, if value is in that range, mask digit with
-     * the corresponding value. Since value can only be in a single range,
-     * only at most one masking will change digit. */
-    digit |= mbedtls_ct_uchar_mask_of_range(0, 25, value) & ('A' + value);
-    digit |= mbedtls_ct_uchar_mask_of_range(26, 51, value) & ('a' + value - 26);
-    digit |= mbedtls_ct_uchar_mask_of_range(52, 61, value) & ('0' + value - 52);
-    digit |= mbedtls_ct_uchar_mask_of_range(62, 62, value) & '+';
-    digit |= mbedtls_ct_uchar_mask_of_range(63, 63, value) & '/';
-    return digit;
-}
-
-signed char mbedtls_ct_base64_dec_value(unsigned char c)
-{
-    unsigned char val = 0;
-    /* For each range of digits, if c is in that range, mask val with
-     * the corresponding value. Since c can only be in a single range,
-     * only at most one masking will change val. Set val to one plus
-     * the desired value so that it stays 0 if c is in none of the ranges. */
-    val |= mbedtls_ct_uchar_mask_of_range('A', 'Z', c) & (c - 'A' +  0 + 1);
-    val |= mbedtls_ct_uchar_mask_of_range('a', 'z', c) & (c - 'a' + 26 + 1);
-    val |= mbedtls_ct_uchar_mask_of_range('0', '9', c) & (c - '0' + 52 + 1);
-    val |= mbedtls_ct_uchar_mask_of_range('+', '+', c) & (c - '+' + 62 + 1);
-    val |= mbedtls_ct_uchar_mask_of_range('/', '/', c) & (c - '/' + 63 + 1);
-    /* At this point, val is 0 if c is an invalid digit and v+1 if c is
-     * a digit with the value v. */
-    return val - 1;
+    /* Since we go byte-by-byte, the only bits set will be in the bottom 8 bits, so the
+     * cast from uint to int is safe. */
+    return (int) diff;
 }
 
-#endif /* MBEDTLS_BASE64_C */
+#endif
 
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
-/** Shift some data towards the left inside a buffer.
- *
- * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally
- * equivalent to
- * ```
- * memmove(start, start + offset, total - offset);
- * memset(start + offset, 0, total - offset);
- * ```
- * but it strives to use a memory access pattern (and thus total timing)
- * that does not depend on \p offset. This timing independence comes at
- * the expense of performance.
- *
- * \param start     Pointer to the start of the buffer.
- * \param total     Total size of the buffer.
- * \param offset    Offset from which to copy \p total - \p offset bytes.
- */
-static void mbedtls_ct_mem_move_to_left(void *start,
-                                        size_t total,
-                                        size_t offset)
+void mbedtls_ct_memmove_left(void *start, size_t total, size_t offset)
 {
     volatile unsigned char *buf = start;
-    size_t i, n;
-    if (total == 0) {
-        return;
-    }
-    for (i = 0; i < total; i++) {
-        unsigned no_op = mbedtls_ct_size_gt(total - offset, i);
+    for (size_t i = 0; i < total; i++) {
+        mbedtls_ct_condition_t no_op = mbedtls_ct_uint_gt(total - offset, i);
         /* The first `total - offset` passes are a no-op. The last
          * `offset` passes shift the data one byte to the left and
          * zero out the last byte. */
-        for (n = 0; n < total - 1; n++) {
+        for (size_t n = 0; n < total - 1; n++) {
             unsigned char current = buf[n];
-            unsigned char next = buf[n+1];
+            unsigned char next    = buf[n+1];
             buf[n] = mbedtls_ct_uint_if(no_op, current, next);
         }
-        buf[total-1] = mbedtls_ct_uint_if(no_op, buf[total-1], 0);
+        buf[total-1] = mbedtls_ct_uint_if_else_0(no_op, buf[total-1]);
     }
 }
 
 #endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-
-void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
-                             const unsigned char *src,
-                             size_t len,
-                             size_t c1,
-                             size_t c2)
+void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
+                          unsigned char *dest,
+                          const unsigned char *src1,
+                          const unsigned char *src2,
+                          size_t len)
 {
-    /* mask = c1 == c2 ? 0xff : 0x00 */
-    const size_t equal = mbedtls_ct_size_bool_eq(c1, c2);
+#if defined(MBEDTLS_CT_SIZE_64)
+    const uint64_t mask     = (uint64_t) condition;
+    const uint64_t not_mask = (uint64_t) ~mbedtls_ct_compiler_opaque(condition);
+#else
+    const uint32_t mask     = (uint32_t) condition;
+    const uint32_t not_mask = (uint32_t) ~mbedtls_ct_compiler_opaque(condition);
+#endif
+
+    /* If src2 is NULL, setup src2 so that we read from the destination address.
+     *
+     * This means that if src2 == NULL && condition is false, the result will be a
+     * no-op because we read from dest and write the same data back into dest.
+     */
+    if (src2 == NULL) {
+        src2 = dest;
+    }
 
     /* dest[i] = c1 == c2 ? src[i] : dest[i] */
     size_t i = 0;
 #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
-    const uint32_t mask32 = (uint32_t) mbedtls_ct_size_mask(equal);
-    const unsigned char mask = (unsigned char) mask32 & 0xff;
-
+#if defined(MBEDTLS_CT_SIZE_64)
+    for (; (i + 8) <= len; i += 8) {
+        uint64_t a = mbedtls_get_unaligned_uint64(src1 + i) & mask;
+        uint64_t b = mbedtls_get_unaligned_uint64(src2 + i) & not_mask;
+        mbedtls_put_unaligned_uint64(dest + i, a | b);
+    }
+#else
     for (; (i + 4) <= len; i += 4) {
-        uint32_t a = mbedtls_get_unaligned_uint32(src  + i) &  mask32;
-        uint32_t b = mbedtls_get_unaligned_uint32(dest + i) & ~mask32;
+        uint32_t a = mbedtls_get_unaligned_uint32(src1 + i) & mask;
+        uint32_t b = mbedtls_get_unaligned_uint32(src2 + i) & not_mask;
         mbedtls_put_unaligned_uint32(dest + i, a | b);
     }
-#else
-    const unsigned char mask = (unsigned char) mbedtls_ct_size_mask(equal);
+#endif /* defined(MBEDTLS_CT_SIZE_64) */
 #endif /* MBEDTLS_EFFICIENT_UNALIGNED_ACCESS */
     for (; i < len; i++) {
-        dest[i] = (src[i] & mask) | (dest[i] & ~mask);
+        dest[i] = (src1[i] & mask) | (src2[i] & not_mask);
     }
 }
 
@@ -496,547 +222,27 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest,
     size_t offsetval;
 
     for (offsetval = offset_min; offsetval <= offset_max; offsetval++) {
-        mbedtls_ct_memcpy_if_eq(dest, src + offsetval, len,
-                                offsetval, offset);
+        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offsetval, offset), dest, src + offsetval, NULL,
+                             len);
     }
 }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-#if defined(PSA_WANT_ALG_SHA_384)
-#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
-#elif defined(PSA_WANT_ALG_SHA_256)
-#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
-#else /* See check_config.h */
-#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
-#endif
-
-int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
-                    psa_algorithm_t mac_alg,
-                    const unsigned char *add_data,
-                    size_t add_data_len,
-                    const unsigned char *data,
-                    size_t data_len_secret,
-                    size_t min_data_len,
-                    size_t max_data_len,
-                    unsigned char *output)
-{
-    /*
-     * This function breaks the HMAC abstraction and uses psa_hash_clone()
-     * extension in order to get constant-flow behaviour.
-     *
-     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
-     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
-     * patterns (see RFC 2104, sec. 2).
-     *
-     * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
-     * hashing up to minlen, then cloning the context, and for each byte up
-     * to maxlen finishing up the hash computation, keeping only the
-     * correct result.
-     *
-     * Then we only need to compute HASH(okey + inner_hash) and we're done.
-     */
-    psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
-    const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
-    unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
-    const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
-    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
-    size_t hash_length;
-
-    unsigned char aux_out[PSA_HASH_MAX_SIZE];
-    psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
-    size_t offset;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-
-    size_t mac_key_length;
-    size_t i;
-
-#define PSA_CHK(func_call)        \
-    do {                            \
-        status = (func_call);       \
-        if (status != PSA_SUCCESS) \
-        goto cleanup;           \
-    } while (0)
-
-    /* Export MAC key
-     * We assume key length is always exactly the output size
-     * which is never more than the block size, thus we use block_size
-     * as the key buffer size.
-     */
-    PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
-
-    /* Calculate ikey */
-    for (i = 0; i < mac_key_length; i++) {
-        key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
-    }
-    for (; i < block_size; ++i) {
-        key_buf[i] = 0x36;
-    }
-
-    PSA_CHK(psa_hash_setup(&operation, hash_alg));
-
-    /* Now compute inner_hash = HASH(ikey + msg) */
-    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
-    PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
-    PSA_CHK(psa_hash_update(&operation, data, min_data_len));
-
-    /* Fill the hash buffer in advance with something that is
-     * not a valid hash (barring an attack on the hash and
-     * deliberately-crafted input), in case the caller doesn't
-     * check the return status properly. */
-    memset(output, '!', hash_size);
-
-    /* For each possible length, compute the hash up to that point */
-    for (offset = min_data_len; offset <= max_data_len; offset++) {
-        PSA_CHK(psa_hash_clone(&operation, &aux_operation));
-        PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
-                                PSA_HASH_MAX_SIZE, &hash_length));
-        /* Keep only the correct inner_hash in the output buffer */
-        mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
-                                offset, data_len_secret);
-
-        if (offset < max_data_len) {
-            PSA_CHK(psa_hash_update(&operation, data + offset, 1));
-        }
-    }
-
-    /* Abort current operation to prepare for final operation */
-    PSA_CHK(psa_hash_abort(&operation));
-
-    /* Calculate okey */
-    for (i = 0; i < mac_key_length; i++) {
-        key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
-    }
-    for (; i < block_size; ++i) {
-        key_buf[i] = 0x5C;
-    }
-
-    /* Now compute HASH(okey + inner_hash) */
-    PSA_CHK(psa_hash_setup(&operation, hash_alg));
-    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
-    PSA_CHK(psa_hash_update(&operation, output, hash_size));
-    PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
-
-#undef PSA_CHK
-
-cleanup:
-    mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
-    mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
-
-    psa_hash_abort(&operation);
-    psa_hash_abort(&aux_operation);
-    return PSA_TO_MBEDTLS_ERR(status);
-}
-
-#undef MAX_HASH_BLOCK_LENGTH
-
-#else
-int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
-                    const unsigned char *add_data,
-                    size_t add_data_len,
-                    const unsigned char *data,
-                    size_t data_len_secret,
-                    size_t min_data_len,
-                    size_t max_data_len,
-                    unsigned char *output)
-{
-    /*
-     * This function breaks the HMAC abstraction and uses the md_clone()
-     * extension to the MD API in order to get constant-flow behaviour.
-     *
-     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
-     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
-     * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
-     *
-     * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
-     * minlen, then cloning the context, and for each byte up to maxlen
-     * finishing up the hash computation, keeping only the correct result.
-     *
-     * Then we only need to compute HASH(okey + inner_hash) and we're done.
-     */
-    const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
-    /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
-     * all of which have the same block size except SHA-384. */
-    const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
-    const unsigned char * const ikey = ctx->hmac_ctx;
-    const unsigned char * const okey = ikey + block_size;
-    const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
-
-    unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
-    mbedtls_md_context_t aux;
-    size_t offset;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    mbedtls_md_init(&aux);
-
-#define MD_CHK(func_call) \
-    do {                    \
-        ret = (func_call);  \
-        if (ret != 0)      \
-        goto cleanup;   \
-    } while (0)
-
-    MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
-
-    /* After hmac_start() of hmac_reset(), ikey has already been hashed,
-     * so we can start directly with the message */
-    MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
-    MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
-
-    /* Fill the hash buffer in advance with something that is
-     * not a valid hash (barring an attack on the hash and
-     * deliberately-crafted input), in case the caller doesn't
-     * check the return status properly. */
-    memset(output, '!', hash_size);
-
-    /* For each possible length, compute the hash up to that point */
-    for (offset = min_data_len; offset <= max_data_len; offset++) {
-        MD_CHK(mbedtls_md_clone(&aux, ctx));
-        MD_CHK(mbedtls_md_finish(&aux, aux_out));
-        /* Keep only the correct inner_hash in the output buffer */
-        mbedtls_ct_memcpy_if_eq(output, aux_out, hash_size,
-                                offset, data_len_secret);
-
-        if (offset < max_data_len) {
-            MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
-        }
-    }
-
-    /* The context needs to finish() before it starts() again */
-    MD_CHK(mbedtls_md_finish(ctx, aux_out));
-
-    /* Now compute HASH(okey + inner_hash) */
-    MD_CHK(mbedtls_md_starts(ctx));
-    MD_CHK(mbedtls_md_update(ctx, okey, block_size));
-    MD_CHK(mbedtls_md_update(ctx, output, hash_size));
-    MD_CHK(mbedtls_md_finish(ctx, output));
-
-    /* Done, get ready for next time */
-    MD_CHK(mbedtls_md_hmac_reset(ctx));
-
-#undef MD_CHK
-
-cleanup:
-    mbedtls_md_free(&aux);
-    return ret;
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
-
-#if defined(MBEDTLS_BIGNUM_C)
-
-#define MPI_VALIDATE_RET(cond)                                       \
-    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA)
-
-/*
- * Conditionally assign X = Y, without leaking information
- * about whether the assignment was made or not.
- * (Leaking information about the respective sizes of X and Y is ok however.)
- */
-#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103)
-/*
- * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See:
- * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989
- */
-__declspec(noinline)
-#endif
-int mbedtls_mpi_safe_cond_assign(mbedtls_mpi *X,
-                                 const mbedtls_mpi *Y,
-                                 unsigned char assign)
-{
-    int ret = 0;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
-
-    /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */
-    mbedtls_mpi_uint limb_mask = mbedtls_ct_mpi_uint_mask(assign);
-
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
-
-    X->s = mbedtls_ct_cond_select_sign(assign, Y->s, X->s);
-
-    mbedtls_mpi_core_cond_assign(X->p, Y->p, Y->n, assign);
-
-    for (size_t i = Y->n; i < X->n; i++) {
-        X->p[i] &= ~limb_mask;
-    }
-
-cleanup:
-    return ret;
-}
-
-/*
- * Conditionally swap X and Y, without leaking information
- * about whether the swap was made or not.
- * Here it is not ok to simply swap the pointers, which would lead to
- * different memory access patterns when X and Y are used afterwards.
- */
-int mbedtls_mpi_safe_cond_swap(mbedtls_mpi *X,
-                               mbedtls_mpi *Y,
-                               unsigned char swap)
-{
-    int ret = 0;
-    int s;
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
-
-    if (X == Y) {
-        return 0;
-    }
-
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(X, Y->n));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Y, X->n));
-
-    s = X->s;
-    X->s = mbedtls_ct_cond_select_sign(swap, Y->s, X->s);
-    Y->s = mbedtls_ct_cond_select_sign(swap, s, Y->s);
-
-    mbedtls_mpi_core_cond_swap(X->p, Y->p, X->n, swap);
-
-cleanup:
-    return ret;
-}
-
-/*
- * Compare unsigned values in constant time
- */
-unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
-                                const mbedtls_mpi_uint *B,
-                                size_t limbs)
-{
-    unsigned ret, cond, done;
-
-    /* The value of any of these variables is either 0 or 1 for the rest of
-     * their scope. */
-    ret = cond = done = 0;
-
-    for (size_t i = limbs; i > 0; i--) {
-        /*
-         * If B[i - 1] < A[i - 1] then A < B is false and the result must
-         * remain 0.
-         *
-         * Again even if we can make a decision, we just mark the result and
-         * the fact that we are done and continue looping.
-         */
-        cond = mbedtls_ct_mpi_uint_lt(B[i - 1], A[i - 1]);
-        done |= cond;
-
-        /*
-         * If A[i - 1] < B[i - 1] then A < B is true.
-         *
-         * Again even if we can make a decision, we just mark the result and
-         * the fact that we are done and continue looping.
-         */
-        cond = mbedtls_ct_mpi_uint_lt(A[i - 1], B[i - 1]);
-        ret |= cond & (1 - done);
-        done |= cond;
-    }
-
-    /*
-     * If all the limbs were equal, then the numbers are equal, A < B is false
-     * and leaving the result 0 is correct.
-     */
-
-    return ret;
-}
-
-/*
- * Compare signed values in constant time
- */
-int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X,
-                          const mbedtls_mpi *Y,
-                          unsigned *ret)
-{
-    size_t i;
-    /* The value of any of these variables is either 0 or 1 at all times. */
-    unsigned cond, done, X_is_negative, Y_is_negative;
-
-    MPI_VALIDATE_RET(X != NULL);
-    MPI_VALIDATE_RET(Y != NULL);
-    MPI_VALIDATE_RET(ret != NULL);
-
-    if (X->n != Y->n) {
-        return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
-    }
-
-    /*
-     * Set sign_N to 1 if N >= 0, 0 if N < 0.
-     * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0.
-     */
-    X_is_negative = (X->s & 2) >> 1;
-    Y_is_negative = (Y->s & 2) >> 1;
-
-    /*
-     * If the signs are different, then the positive operand is the bigger.
-     * That is if X is negative (X_is_negative == 1), then X < Y is true and it
-     * is false if X is positive (X_is_negative == 0).
-     */
-    cond = (X_is_negative ^ Y_is_negative);
-    *ret = cond & X_is_negative;
-
-    /*
-     * This is a constant-time function. We might have the result, but we still
-     * need to go through the loop. Record if we have the result already.
-     */
-    done = cond;
-
-    for (i = X->n; i > 0; i--) {
-        /*
-         * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both
-         * X and Y are negative.
-         *
-         * Again even if we can make a decision, we just mark the result and
-         * the fact that we are done and continue looping.
-         */
-        cond = mbedtls_ct_mpi_uint_lt(Y->p[i - 1], X->p[i - 1]);
-        *ret |= cond & (1 - done) & X_is_negative;
-        done |= cond;
-
-        /*
-         * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both
-         * X and Y are positive.
-         *
-         * Again even if we can make a decision, we just mark the result and
-         * the fact that we are done and continue looping.
-         */
-        cond = mbedtls_ct_mpi_uint_lt(X->p[i - 1], Y->p[i - 1]);
-        *ret |= cond & (1 - done) & (1 - X_is_negative);
-        done |= cond;
-    }
-
-    return 0;
-}
-
-#endif /* MBEDTLS_BIGNUM_C */
-
 #if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
-int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
-                                         size_t ilen,
-                                         unsigned char *output,
-                                         size_t output_max_len,
-                                         size_t *olen)
+void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, plaintext_max_size;
-
-    /* The following variables take sensitive values: their value must
-     * not leak into the observable behavior of the function other than
-     * the designated outputs (output, olen, return value). Otherwise
-     * this would open the execution of the function to
-     * side-channel-based variants of the Bleichenbacher padding oracle
-     * attack. Potential side channels include overall timing, memory
-     * access patterns (especially visible to an adversary who has access
-     * to a shared memory cache), and branches (especially visible to
-     * an adversary who has access to a shared code cache or to a shared
-     * branch predictor). */
-    size_t pad_count = 0;
-    unsigned bad = 0;
-    unsigned char pad_done = 0;
-    size_t plaintext_size = 0;
-    unsigned output_too_large;
-
-    plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
-                                                        : output_max_len;
-
-    /* Check and get padding length in constant time and constant
-     * memory trace. The first byte must be 0. */
-    bad |= input[0];
-
-
-    /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
-     * where PS must be at least 8 nonzero bytes. */
-    bad |= input[1] ^ MBEDTLS_RSA_CRYPT;
-
-    /* Read the whole buffer. Set pad_done to nonzero if we find
-     * the 0x00 byte and remember the padding length in pad_count. */
-    for (i = 2; i < ilen; i++) {
-        pad_done  |= ((input[i] | (unsigned char) -input[i]) >> 7) ^ 1;
-        pad_count += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
-    }
-
-
-    /* If pad_done is still zero, there's no data, only unfinished padding. */
-    bad |= mbedtls_ct_uint_if(pad_done, 0, 1);
-
-    /* There must be at least 8 bytes of padding. */
-    bad |= mbedtls_ct_size_gt(8, pad_count);
-
-    /* If the padding is valid, set plaintext_size to the number of
-     * remaining bytes after stripping the padding. If the padding
-     * is invalid, avoid leaking this fact through the size of the
-     * output: use the maximum message size that fits in the output
-     * buffer. Do it without branches to avoid leaking the padding
-     * validity through timing. RSA keys are small enough that all the
-     * size_t values involved fit in unsigned int. */
-    plaintext_size = mbedtls_ct_uint_if(
-        bad, (unsigned) plaintext_max_size,
-        (unsigned) (ilen - pad_count - 3));
-
-    /* Set output_too_large to 0 if the plaintext fits in the output
-     * buffer and to 1 otherwise. */
-    output_too_large = mbedtls_ct_size_gt(plaintext_size,
-                                          plaintext_max_size);
-
-    /* Set ret without branches to avoid timing attacks. Return:
-     * - INVALID_PADDING if the padding is bad (bad != 0).
-     * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
-     *   plaintext does not fit in the output buffer.
-     * - 0 if the padding is correct. */
-    ret = -(int) mbedtls_ct_uint_if(
-        bad, -MBEDTLS_ERR_RSA_INVALID_PADDING,
-        mbedtls_ct_uint_if(output_too_large,
-                           -MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
-                           0));
-
-    /* If the padding is bad or the plaintext is too large, zero the
-     * data that we're about to copy to the output buffer.
-     * We need to copy the same amount of data
-     * from the same buffer whether the padding is good or not to
-     * avoid leaking the padding validity through overall timing or
-     * through memory or cache access patterns. */
-    bad = mbedtls_ct_uint_mask(bad | output_too_large);
-    for (i = 11; i < ilen; i++) {
-        input[i] &= ~bad;
+    uint32_t mask = (uint32_t) ~condition;
+    uint8_t *p = (uint8_t *) buf;
+    size_t i = 0;
+#if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS)
+    for (; (i + 4) <= len; i += 4) {
+        mbedtls_put_unaligned_uint32((void *) (p + i),
+                                     mbedtls_get_unaligned_uint32((void *) (p + i)) & mask);
     }
-
-    /* If the plaintext is too large, truncate it to the buffer size.
-     * Copy anyway to avoid revealing the length through timing, because
-     * revealing the length is as bad as revealing the padding validity
-     * for a Bleichenbacher attack. */
-    plaintext_size = mbedtls_ct_uint_if(output_too_large,
-                                        (unsigned) plaintext_max_size,
-                                        (unsigned) plaintext_size);
-
-    /* Move the plaintext to the leftmost position where it can start in
-     * the working buffer, i.e. make it start plaintext_max_size from
-     * the end of the buffer. Do this with a memory access trace that
-     * does not depend on the plaintext size. After this move, the
-     * starting location of the plaintext is no longer sensitive
-     * information. */
-    mbedtls_ct_mem_move_to_left(input + ilen - plaintext_max_size,
-                                plaintext_max_size,
-                                plaintext_max_size - plaintext_size);
-
-    /* Finally copy the decrypted plaintext plus trailing zeros into the output
-     * buffer. If output_max_len is 0, then output may be an invalid pointer
-     * and the result of memcpy() would be undefined; prevent undefined
-     * behavior making sure to depend only on output_max_len (the size of the
-     * user-provided output buffer), which is independent from plaintext
-     * length, validity of padding, success of the decryption, and other
-     * secrets. */
-    if (output_max_len != 0) {
-        memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
+#endif
+    for (; i < len; i++) {
+        p[i] = p[i] & mask;
     }
-
-    /* Report the amount of data we copied to the output buffer. In case
-     * of errors (bad padding or output too large), the value of *olen
-     * when this function returns is not specified. Making it equivalent
-     * to the good case limits the risks of leaking the padding validity. */
-    *olen = plaintext_size;
-
-    return ret;
 }
 
-#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
+#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time_impl.h b/lib/libmbedtls/mbedtls/library/constant_time_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..2a4574ba68f451557a5163f0c934a7b73842f30d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/constant_time_impl.h
@@ -0,0 +1,556 @@
+/**
+ *  Constant-time functions
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CONSTANT_TIME_IMPL_H
+#define MBEDTLS_CONSTANT_TIME_IMPL_H
+
+#include <stddef.h>
+
+#include "common.h"
+
+#if defined(MBEDTLS_BIGNUM_C)
+#include "mbedtls/bignum.h"
+#endif
+
+/*
+ * To improve readability of constant_time_internal.h, the static inline
+ * definitions are here, and constant_time_internal.h has only the declarations.
+ *
+ * This results in duplicate declarations of the form:
+ *     static inline void f();         // from constant_time_internal.h
+ *     static inline void f() { ... }  // from constant_time_impl.h
+ * when constant_time_internal.h is included.
+ *
+ * This appears to behave as if the declaration-without-definition was not present
+ * (except for warnings if gcc -Wredundant-decls or similar is used).
+ *
+ * Disable -Wredundant-decls so that gcc does not warn about this. This is re-enabled
+ * at the bottom of this file.
+ */
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)
+    #pragma GCC diagnostic push
+    #pragma GCC diagnostic ignored "-Wredundant-decls"
+#endif
+
+/* Disable asm under Memsan because it confuses Memsan and generates false errors.
+ *
+ * We also disable under Valgrind by default, because it's more useful
+ * for Valgrind to test the plain C implementation. MBEDTLS_TEST_CONSTANT_FLOW_ASM //no-check-names
+ * may be set to permit building asm under Valgrind.
+ */
+#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) || \
+    (defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND) && !defined(MBEDTLS_TEST_CONSTANT_FLOW_ASM)) //no-check-names
+#define MBEDTLS_CT_NO_ASM
+#elif defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+#define MBEDTLS_CT_NO_ASM
+#endif
+#endif
+
+/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */
+#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && (!defined(__ARMCC_VERSION) || \
+    __ARMCC_VERSION >= 6000000) && !defined(MBEDTLS_CT_NO_ASM)
+#define MBEDTLS_CT_ASM
+#if (defined(__arm__) || defined(__thumb__) || defined(__thumb2__))
+#define MBEDTLS_CT_ARM_ASM
+#elif defined(__aarch64__)
+#define MBEDTLS_CT_AARCH64_ASM
+#elif defined(__amd64__) || defined(__x86_64__)
+#define MBEDTLS_CT_X86_64_ASM
+#elif defined(__i386__)
+#define MBEDTLS_CT_X86_ASM
+#endif
+#endif
+
+#define MBEDTLS_CT_SIZE (sizeof(mbedtls_ct_uint_t) * 8)
+
+
+/* ============================================================================
+ * Core const-time primitives
+ */
+
+/* Ensure that the compiler cannot know the value of x (i.e., cannot optimise
+ * based on its value) after this function is called.
+ *
+ * If we are not using assembly, this will be fairly inefficient, so its use
+ * should be minimised.
+ */
+
+#if !defined(MBEDTLS_CT_ASM)
+extern volatile mbedtls_ct_uint_t mbedtls_ct_zero;
+#endif
+
+/**
+ * \brief   Ensure that a value cannot be known at compile time.
+ *
+ * \param x        The value to hide from the compiler.
+ * \return         The same value that was passed in, such that the compiler
+ *                 cannot prove its value (even for calls of the form
+ *                 x = mbedtls_ct_compiler_opaque(1), x will be unknown).
+ *
+ * \note           This is mainly used in constructing mbedtls_ct_condition_t
+ *                 values and performing operations over them, to ensure that
+ *                 there is no way for the compiler to ever know anything about
+ *                 the value of an mbedtls_ct_condition_t.
+ */
+static inline mbedtls_ct_uint_t mbedtls_ct_compiler_opaque(mbedtls_ct_uint_t x)
+{
+#if defined(MBEDTLS_CT_ASM)
+    asm volatile ("" : [x] "+r" (x) :);
+    return x;
+#else
+    return x ^ mbedtls_ct_zero;
+#endif
+}
+
+/*
+ * Selecting unified syntax is needed for gcc, and harmless on clang.
+ *
+ * This is needed because on Thumb 1, condition flags are always set, so
+ * e.g. "negs" is supported but "neg" is not (on Thumb 2, both exist).
+ *
+ * Under Thumb 1 unified syntax, only the "negs" form is accepted, and
+ * under divided syntax, only the "neg" form is accepted. clang only
+ * supports unified syntax.
+ *
+ * On Thumb 2 and Arm, both compilers are happy with the "s" suffix,
+ * although we don't actually care about setting the flags.
+ *
+ * For old versions of gcc (see #8516 for details), restore divided
+ * syntax afterwards - otherwise old versions of gcc seem to apply
+ * unified syntax globally, which breaks other asm code.
+ */
+#if defined(MBEDTLS_COMPILER_IS_GCC) && defined(__thumb__) && !defined(__thumb2__) && \
+    (__GNUC__ < 11) && !defined(__ARM_ARCH_2__)
+#define RESTORE_ASM_SYNTAX  ".syntax divided                      \n\t"
+#else
+#define RESTORE_ASM_SYNTAX
+#endif
+
+/* Convert a number into a condition in constant time. */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x)
+{
+    /*
+     * Define mask-generation code that, as far as possible, will not use branches or conditional instructions.
+     *
+     * For some platforms / type sizes, we define assembly to assure this.
+     *
+     * Otherwise, we define a plain C fallback which (in May 2023) does not get optimised into
+     * conditional instructions or branches by trunk clang, gcc, or MSVC v19.
+     */
+#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    mbedtls_ct_uint_t s;
+    asm volatile ("neg %x[s], %x[x]                               \n\t"
+                  "orr %x[x], %x[s], %x[x]                        \n\t"
+                  "asr %x[x], %x[x], 63                           \n\t"
+                  :
+                  [s] "=&r" (s),
+                  [x] "+&r" (x)
+                  :
+                  :
+                  );
+    return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    uint32_t s;
+    asm volatile (".syntax unified                                \n\t"
+                  "negs %[s], %[x]                                \n\t"
+                  "orrs %[x], %[x], %[s]                          \n\t"
+                  "asrs %[x], %[x], #31                           \n\t"
+                  RESTORE_ASM_SYNTAX
+                  :
+                  [s] "=&l" (s),
+                  [x] "+&l" (x)
+                  :
+                  :
+                  "cc" /* clobbers flag bits */
+                  );
+    return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    uint64_t s;
+    asm volatile ("mov  %[x], %[s]                                \n\t"
+                  "neg  %[s]                                      \n\t"
+                  "or   %[x], %[s]                                \n\t"
+                  "sar  $63, %[s]                                 \n\t"
+                  :
+                  [s] "=&a" (s)
+                  :
+                  [x] "D" (x)
+                  :
+                  );
+    return (mbedtls_ct_condition_t) s;
+#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    uint32_t s;
+    asm volatile ("mov %[x], %[s]                                 \n\t"
+                  "neg %[s]                                       \n\t"
+                  "or %[s], %[x]                                  \n\t"
+                  "sar $31, %[x]                                  \n\t"
+                  :
+                  [s] "=&c" (s),
+                  [x] "+&a" (x)
+                  :
+                  :
+                  );
+    return (mbedtls_ct_condition_t) x;
+#else
+    const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
+#if defined(_MSC_VER)
+    /* MSVC has a warning about unary minus on unsigned, but this is
+     * well-defined and precisely what we want to do here */
+#pragma warning( push )
+#pragma warning( disable : 4146 )
+#endif
+    // y is negative (i.e., top bit set) iff x is non-zero
+    mbedtls_ct_int_t y = (-xo) | -(xo >> 1);
+
+    // extract only the sign bit of y so that y == 1 (if x is non-zero) or 0 (if x is zero)
+    y = (((mbedtls_ct_uint_t) y) >> (MBEDTLS_CT_SIZE - 1));
+
+    // -y has all bits set (if x is non-zero), or all bits clear (if x is zero)
+    return (mbedtls_ct_condition_t) (-y);
+#if defined(_MSC_VER)
+#pragma warning( pop )
+#endif
+#endif
+}
+
+static inline mbedtls_ct_uint_t mbedtls_ct_if(mbedtls_ct_condition_t condition,
+                                              mbedtls_ct_uint_t if1,
+                                              mbedtls_ct_uint_t if0)
+{
+#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    asm volatile ("and %x[if1], %x[if1], %x[condition]            \n\t"
+                  "mvn %x[condition], %x[condition]               \n\t"
+                  "and %x[condition], %x[condition], %x[if0]      \n\t"
+                  "orr %x[condition], %x[if1], %x[condition]"
+                  :
+                  [condition] "+&r" (condition),
+                  [if1] "+&r" (if1)
+                  :
+                  [if0] "r" (if0)
+                  :
+                  );
+    return (mbedtls_ct_uint_t) condition;
+#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    asm volatile (".syntax unified                                \n\t"
+                  "ands %[if1], %[if1], %[condition]              \n\t"
+                  "mvns %[condition], %[condition]                \n\t"
+                  "ands %[condition], %[condition], %[if0]        \n\t"
+                  "orrs %[condition], %[if1], %[condition]        \n\t"
+                  RESTORE_ASM_SYNTAX
+                  :
+                  [condition] "+&l" (condition),
+                  [if1] "+&l" (if1)
+                  :
+                  [if0] "l" (if0)
+                  :
+                  "cc"
+                  );
+    return (mbedtls_ct_uint_t) condition;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    asm volatile ("and  %[condition], %[if1]                      \n\t"
+                  "not  %[condition]                              \n\t"
+                  "and  %[condition], %[if0]                      \n\t"
+                  "or   %[if1], %[if0]                            \n\t"
+                  :
+                  [condition] "+&D" (condition),
+                  [if1] "+&S" (if1),
+                  [if0] "+&a" (if0)
+                  :
+                  :
+                  );
+    return if0;
+#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    asm volatile ("and %[condition], %[if1]                       \n\t"
+                  "not %[condition]                               \n\t"
+                  "and %[if0], %[condition]                       \n\t"
+                  "or %[condition], %[if1]                        \n\t"
+                  :
+                  [condition] "+&c" (condition),
+                  [if1] "+&a" (if1)
+                  :
+                  [if0] "b" (if0)
+                  :
+                  );
+    return if1;
+#else
+    mbedtls_ct_condition_t not_cond =
+        (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition));
+    return (mbedtls_ct_uint_t) ((condition & if1) | (not_cond & if0));
+#endif
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
+{
+#if defined(MBEDTLS_CT_AARCH64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    uint64_t s1;
+    asm volatile ("eor     %x[s1], %x[y], %x[x]                   \n\t"
+                  "sub     %x[x], %x[x], %x[y]                    \n\t"
+                  "bic     %x[x], %x[x], %x[s1]                   \n\t"
+                  "and     %x[s1], %x[s1], %x[y]                  \n\t"
+                  "orr     %x[s1], %x[x], %x[s1]                  \n\t"
+                  "asr     %x[x], %x[s1], 63"
+                  :
+                  [s1] "=&r" (s1),
+                  [x] "+&r" (x)
+                  :
+                  [y] "r" (y)
+                  :
+                  );
+    return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_ARM_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    uint32_t s1;
+    asm volatile (
+        ".syntax unified                                          \n\t"
+#if defined(__thumb__) && !defined(__thumb2__)
+        "movs     %[s1], %[x]                                     \n\t"
+        "eors     %[s1], %[s1], %[y]                              \n\t"
+#else
+        "eors     %[s1], %[x], %[y]                               \n\t"
+#endif
+        "subs    %[x], %[x], %[y]                                 \n\t"
+        "bics    %[x], %[x], %[s1]                                \n\t"
+        "ands    %[y], %[s1], %[y]                                \n\t"
+        "orrs    %[x], %[x], %[y]                                 \n\t"
+        "asrs    %[x], %[x], #31                                  \n\t"
+        RESTORE_ASM_SYNTAX
+        :
+        [s1] "=&l" (s1),
+        [x] "+&l" (x),
+        [y] "+&l" (y)
+        :
+        :
+        "cc"
+        );
+    return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    uint64_t s;
+    asm volatile ("mov %[x], %[s]                                 \n\t"
+                  "xor %[y], %[s]                                 \n\t"
+                  "sub %[y], %[x]                                 \n\t"
+                  "and %[s], %[y]                                 \n\t"
+                  "not %[s]                                       \n\t"
+                  "and %[s], %[x]                                 \n\t"
+                  "or %[y], %[x]                                  \n\t"
+                  "sar $63, %[x]                                  \n\t"
+                  :
+                  [s] "=&a" (s),
+                  [x] "+&D" (x),
+                  [y] "+&S" (y)
+                  :
+                  :
+                  );
+    return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_X86_ASM) && defined(MBEDTLS_CT_SIZE_32)
+    uint32_t s;
+    asm volatile ("mov %[x], %[s]                                 \n\t"
+                  "xor %[y], %[s]                                 \n\t"
+                  "sub %[y], %[x]                                 \n\t"
+                  "and %[s], %[y]                                 \n\t"
+                  "not %[s]                                       \n\t"
+                  "and %[s], %[x]                                 \n\t"
+                  "or  %[y], %[x]                                 \n\t"
+                  "sar $31, %[x]                                  \n\t"
+                  :
+                  [s] "=&b" (s),
+                  [x] "+&a" (x),
+                  [y] "+&c" (y)
+                  :
+                  :
+                  );
+    return (mbedtls_ct_condition_t) x;
+#else
+    /* Ensure that the compiler cannot optimise the following operations over x and y,
+     * even if it knows the value of x and y.
+     */
+    const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
+    const mbedtls_ct_uint_t yo = mbedtls_ct_compiler_opaque(y);
+    /*
+     * Check if the most significant bits (MSB) of the operands are different.
+     * cond is true iff the MSBs differ.
+     */
+    mbedtls_ct_condition_t cond = mbedtls_ct_bool((xo ^ yo) >> (MBEDTLS_CT_SIZE - 1));
+
+    /*
+     * If the MSB are the same then the difference x-y will be negative (and
+     * have its MSB set to 1 during conversion to unsigned) if and only if x<y.
+     *
+     * If the MSB are different, then the operand with the MSB of 1 is the
+     * bigger. (That is if y has MSB of 1, then x<y is true and it is false if
+     * the MSB of y is 0.)
+     */
+
+    // Select either y, or x - y
+    mbedtls_ct_uint_t ret = mbedtls_ct_if(cond, yo, (mbedtls_ct_uint_t) (xo - yo));
+
+    // Extract only the MSB of ret
+    ret = ret >> (MBEDTLS_CT_SIZE - 1);
+
+    // Convert to a condition (i.e., all bits set iff non-zero)
+    return mbedtls_ct_bool(ret);
+#endif
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y)
+{
+    /* diff = 0 if x == y, non-zero otherwise */
+    const mbedtls_ct_uint_t diff = mbedtls_ct_compiler_opaque(x) ^ mbedtls_ct_compiler_opaque(y);
+
+    /* all ones if x != y, 0 otherwise */
+    return mbedtls_ct_bool(diff);
+}
+
+static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
+                                                         unsigned char high,
+                                                         unsigned char c,
+                                                         unsigned char t)
+{
+    const unsigned char co = (unsigned char) mbedtls_ct_compiler_opaque(c);
+    const unsigned char to = (unsigned char) mbedtls_ct_compiler_opaque(t);
+
+    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
+    unsigned low_mask = ((unsigned) co - low) >> 8;
+    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
+    unsigned high_mask = ((unsigned) high - co) >> 8;
+
+    return (unsigned char) (~(low_mask | high_mask)) & to;
+}
+
+/* ============================================================================
+ * Everything below here is trivial wrapper functions
+ */
+
+static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
+                                        size_t if1,
+                                        size_t if0)
+{
+    return (size_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
+}
+
+static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
+                                          unsigned if1,
+                                          unsigned if0)
+{
+    return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,
+                                                        mbedtls_ct_condition_t if1,
+                                                        mbedtls_ct_condition_t if0)
+{
+    return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1,
+                                                  (mbedtls_ct_uint_t) if0);
+}
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition,
+                                                      mbedtls_mpi_uint if1,
+                                                      mbedtls_mpi_uint if0)
+{
+    return (mbedtls_mpi_uint) mbedtls_ct_if(condition,
+                                            (mbedtls_ct_uint_t) if1,
+                                            (mbedtls_ct_uint_t) if0);
+}
+
+#endif
+
+static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1)
+{
+    return (size_t) (condition & if1);
+}
+
+static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1)
+{
+    return (unsigned) (condition & if1);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,
+                                                               mbedtls_ct_condition_t if1)
+{
+    return (mbedtls_ct_condition_t) (condition & if1);
+}
+
+#if defined(MBEDTLS_BIGNUM_C)
+
+static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
+                                                             mbedtls_mpi_uint if1)
+{
+    return (mbedtls_mpi_uint) (condition & if1);
+}
+
+#endif /* MBEDTLS_BIGNUM_C */
+
+static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0)
+{
+    /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be
+     * in the range -32767..0, and we require 32-bit int and uint types.
+     *
+     * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for
+     * converting back to int.
+     */
+    return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1),
+                                 (mbedtls_ct_uint_t) (-if0)));
+}
+
+static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1)
+{
+    return -((int) (condition & (-if1)));
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y)
+{
+    return ~mbedtls_ct_uint_ne(x, y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y)
+{
+    return mbedtls_ct_uint_lt(y, x);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y)
+{
+    return ~mbedtls_ct_uint_lt(x, y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y)
+{
+    return ~mbedtls_ct_uint_gt(x, y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
+                                                        mbedtls_ct_condition_t y)
+{
+    return (mbedtls_ct_condition_t) (x ^ y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
+                                                         mbedtls_ct_condition_t y)
+{
+    return (mbedtls_ct_condition_t) (x & y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
+                                                        mbedtls_ct_condition_t y)
+{
+    return (mbedtls_ct_condition_t) (x | y);
+}
+
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x)
+{
+    return (mbedtls_ct_condition_t) (~x);
+}
+
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (__GNUC__ > 4)
+/* Restore warnings for -Wredundant-decls on gcc */
+    #pragma GCC diagnostic pop
+#endif
+
+#endif /* MBEDTLS_CONSTANT_TIME_IMPL_H */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time_internal.h b/lib/libmbedtls/mbedtls/library/constant_time_internal.h
index c4a32c7f0279521a18fd4ebe397050c6ff1dc4fb..61a5c6d4e9525b6e7d7954caf78dfa6759f476d7 100644
--- a/lib/libmbedtls/mbedtls/library/constant_time_internal.h
+++ b/lib/libmbedtls/mbedtls/library/constant_time_internal.h
@@ -2,242 +2,512 @@
  *  Constant-time functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H
 #define MBEDTLS_CONSTANT_TIME_INTERNAL_H
 
+#include <stdint.h>
+#include <stddef.h>
+
 #include "common.h"
 
 #if defined(MBEDTLS_BIGNUM_C)
 #include "mbedtls/bignum.h"
 #endif
 
-#if defined(MBEDTLS_SSL_TLS_C)
-#include "ssl_misc.h"
-#endif
+/* The constant-time interface provides various operations that are likely
+ * to result in constant-time code that does not branch or use conditional
+ * instructions for secret data (for secret pointers, this also applies to
+ * the data pointed to).
+ *
+ * It has three main parts:
+ *
+ * - boolean operations
+ *   These are all named mbedtls_ct_<type>_<operation>.
+ *   They operate over <type> and return mbedtls_ct_condition_t.
+ *   All arguments are considered secret.
+ *   example: bool x = y | z          =>    x = mbedtls_ct_bool_or(y, z)
+ *   example: bool x = y == z         =>    x = mbedtls_ct_uint_eq(y, z)
+ *
+ * - conditional data selection
+ *   These are all named mbedtls_ct_<type>_if and mbedtls_ct_<type>_if_else_0
+ *   All arguments are considered secret.
+ *   example: size_t a = x ? b : c    =>    a = mbedtls_ct_size_if(x, b, c)
+ *   example: unsigned a = x ? b : 0  =>    a = mbedtls_ct_uint_if_else_0(x, b)
+ *
+ * - block memory operations
+ *   Only some arguments are considered secret, as documented for each
+ *   function.
+ *   example: if (x) memcpy(...)      =>    mbedtls_ct_memcpy_if(x, ...)
+ *
+ * mbedtls_ct_condition_t must be treated as opaque and only created and
+ * manipulated via the functions in this header. The compiler should never
+ * be able to prove anything about its value at compile-time.
+ *
+ * mbedtls_ct_uint_t is an unsigned integer type over which constant time
+ * operations may be performed via the functions in this header. It is as big
+ * as the larger of size_t and mbedtls_mpi_uint, i.e. it is safe to cast
+ * to/from "unsigned int", "size_t", and "mbedtls_mpi_uint" (and any other
+ * not-larger integer types).
+ *
+ * For Arm (32-bit, 64-bit and Thumb), x86 and x86-64, assembly implementations
+ * are used to ensure that the generated code is constant time. For other
+ * architectures, it uses a plain C fallback designed to yield constant-time code
+ * (this has been observed to be constant-time on latest gcc, clang and MSVC
+ * as of May 2023).
+ *
+ * For readability, the static inline definitions are separated out into
+ * constant_time_impl.h.
+ */
 
-#include <stddef.h>
+#if (SIZE_MAX > 0xffffffffffffffffULL)
+/* Pointer size > 64-bit */
+typedef size_t    mbedtls_ct_condition_t;
+typedef size_t    mbedtls_ct_uint_t;
+typedef ptrdiff_t mbedtls_ct_int_t;
+#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(SIZE_MAX))
+#elif (SIZE_MAX > 0xffffffff) || defined(MBEDTLS_HAVE_INT64)
+/* 32-bit < pointer size <= 64-bit, or 64-bit MPI */
+typedef uint64_t  mbedtls_ct_condition_t;
+typedef uint64_t  mbedtls_ct_uint_t;
+typedef int64_t   mbedtls_ct_int_t;
+#define MBEDTLS_CT_SIZE_64
+#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT64_MAX))
+#else
+/* Pointer size <= 32-bit, and no 64-bit MPIs */
+typedef uint32_t  mbedtls_ct_condition_t;
+typedef uint32_t  mbedtls_ct_uint_t;
+typedef int32_t   mbedtls_ct_int_t;
+#define MBEDTLS_CT_SIZE_32
+#define MBEDTLS_CT_TRUE  ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(UINT32_MAX))
+#endif
+#define MBEDTLS_CT_FALSE ((mbedtls_ct_condition_t) mbedtls_ct_compiler_opaque(0))
 
+/* ============================================================================
+ * Boolean operations
+ */
 
-/** Turn a value into a mask:
- * - if \p value == 0, return the all-bits 0 mask, aka 0
- * - otherwise, return the all-bits 1 mask, aka (unsigned) -1
+/** Convert a number into a mbedtls_ct_condition_t.
  *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
+ * \param x Number to convert.
  *
- * \param value     The value to analyze.
+ * \return MBEDTLS_CT_TRUE if \p x != 0, or MBEDTLS_CT_FALSE if \p x == 0
  *
- * \return          Zero if \p value is zero, otherwise all-bits-one.
  */
-unsigned mbedtls_ct_uint_mask(unsigned value);
-
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+static inline mbedtls_ct_condition_t mbedtls_ct_bool(mbedtls_ct_uint_t x);
 
-/** Turn a value into a mask:
- * - if \p value == 0, return the all-bits 0 mask, aka 0
- * - otherwise, return the all-bits 1 mask, aka (size_t) -1
+/** Boolean "not equal" operation.
+ *
+ * Functionally equivalent to:
  *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
+ * \p x != \p y
  *
- * \param value     The value to analyze.
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
  *
- * \return          Zero if \p value is zero, otherwise all-bits-one.
+ * \return      MBEDTLS_CT_TRUE if \p x != \p y, otherwise MBEDTLS_CT_FALSE.
  */
-size_t mbedtls_ct_size_mask(size_t value);
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_ne(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+/** Boolean "equals" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * \p x == \p y
+ *
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x == \p y, otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y);
 
-#if defined(MBEDTLS_BIGNUM_C)
+/** Boolean "less than" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * \p x < \p y
+ *
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x < \p y, otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_lt(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y);
 
-/** Turn a value into a mask:
- * - if \p value == 0, return the all-bits 0 mask, aka 0
- * - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1
+/** Boolean "greater than" operation.
+ *
+ * Functionally equivalent to:
  *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
+ * \p x > \p y
  *
- * \param value     The value to analyze.
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
  *
- * \return          Zero if \p value is zero, otherwise all-bits-one.
+ * \return      MBEDTLS_CT_TRUE if \p x > \p y, otherwise MBEDTLS_CT_FALSE.
  */
-mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask(mbedtls_mpi_uint value);
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_gt(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y);
 
-#endif /* MBEDTLS_BIGNUM_C */
+/** Boolean "greater or equal" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * \p x >= \p y
+ *
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x >= \p y,
+ *              otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y);
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+/** Boolean "less than or equal" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * \p x <= \p y
+ *
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x <= \p y,
+ *              otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x,
+                                                        mbedtls_ct_uint_t y);
 
-/** Constant-flow mask generation for "greater or equal" comparison:
- * - if \p x >= \p y, return all-bits 1, that is (size_t) -1
- * - otherwise, return all bits 0, that is 0
+/** Boolean not-equals operation.
+ *
+ * Functionally equivalent to:
  *
- * This function can be used to write constant-time code by replacing branches
- * with bit operations using masks.
+ * \p x != \p y
  *
  * \param x     The first value to analyze.
  * \param y     The second value to analyze.
  *
- * \return      All-bits-one if \p x is greater or equal than \p y,
- *              otherwise zero.
+ * \note        This is more efficient than mbedtls_ct_uint_ne if both arguments are
+ *              mbedtls_ct_condition_t.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x != \p y,
+ *              otherwise MBEDTLS_CT_FALSE.
  */
-size_t mbedtls_ct_size_mask_ge(size_t x,
-                               size_t y);
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x,
+                                                        mbedtls_ct_condition_t y);
 
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+/** Boolean "and" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * \p x && \p y
+ *
+ * \param x     The first value to analyze.
+ * \param y     The second value to analyze.
+ *
+ * \return      MBEDTLS_CT_TRUE if \p x && \p y,
+ *              otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_and(mbedtls_ct_condition_t x,
+                                                         mbedtls_ct_condition_t y);
 
-/** Constant-flow boolean "equal" comparison:
- * return x == y
+/** Boolean "or" operation.
+ *
+ * Functionally equivalent to:
  *
- * This is equivalent to \p x == \p y, but is likely to be compiled
- * to code using bitwise operation rather than a branch.
+ * \p x || \p y
  *
  * \param x     The first value to analyze.
  * \param y     The second value to analyze.
  *
- * \return      1 if \p x equals to \p y, otherwise 0.
+ * \return      MBEDTLS_CT_TRUE if \p x || \p y,
+ *              otherwise MBEDTLS_CT_FALSE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_or(mbedtls_ct_condition_t x,
+                                                        mbedtls_ct_condition_t y);
+
+/** Boolean "not" operation.
+ *
+ * Functionally equivalent to:
+ *
+ * ! \p x
+ *
+ * \param x     The value to invert
+ *
+ * \return      MBEDTLS_CT_FALSE if \p x, otherwise MBEDTLS_CT_TRUE.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_not(mbedtls_ct_condition_t x);
+
+
+/* ============================================================================
+ * Data selection operations
+ */
+
+/** Choose between two size_t values.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : if0.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ * \param if0           Value to use if \p condition == MBEDTLS_CT_FALSE.
+ *
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  */
-unsigned mbedtls_ct_size_bool_eq(size_t x,
-                                 size_t y);
+static inline size_t mbedtls_ct_size_if(mbedtls_ct_condition_t condition,
+                                        size_t if1,
+                                        size_t if0);
+
+/** Choose between two unsigned values.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : if0.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ * \param if0           Value to use if \p condition == MBEDTLS_CT_FALSE.
+ *
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
+ */
+static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition,
+                                          unsigned if1,
+                                          unsigned if0);
+
+/** Choose between two mbedtls_ct_condition_t values.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : if0.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ * \param if0           Value to use if \p condition == MBEDTLS_CT_FALSE.
+ *
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
+ */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition,
+                                                        mbedtls_ct_condition_t if1,
+                                                        mbedtls_ct_condition_t if0);
 
 #if defined(MBEDTLS_BIGNUM_C)
 
-/** Decide if an integer is less than the other, without branches.
+/** Choose between two mbedtls_mpi_uint values.
  *
- * This is equivalent to \p x < \p y, but is likely to be compiled
- * to code using bitwise operation rather than a branch.
+ * Functionally equivalent to:
  *
- * \param x     The first value to analyze.
- * \param y     The second value to analyze.
+ * condition ? if1 : if0.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ * \param if0           Value to use if \p condition == MBEDTLS_CT_FALSE.
  *
- * \return      1 if \p x is less than \p y, otherwise 0.
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  */
-unsigned mbedtls_ct_mpi_uint_lt(const mbedtls_mpi_uint x,
-                                const mbedtls_mpi_uint y);
+static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, \
+                                                      mbedtls_mpi_uint if1, \
+                                                      mbedtls_mpi_uint if0);
 
-/**
- * \brief          Check if one unsigned MPI is less than another in constant
- *                 time.
+#endif
+
+/** Choose between an unsigned value and 0.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : 0.
+ *
+ * Functionally equivalent to mbedtls_ct_uint_if(condition, if1, 0) but
+ * results in smaller code size.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ *
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
+ */
+static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1);
+
+/** Choose between an mbedtls_ct_condition_t and 0.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : 0.
  *
- * \param A        The left-hand MPI. This must point to an array of limbs
- *                 with the same allocated length as \p B.
- * \param B        The right-hand MPI. This must point to an array of limbs
- *                 with the same allocated length as \p A.
- * \param limbs    The number of limbs in \p A and \p B.
- *                 This must not be 0.
+ * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but
+ * results in smaller code size.
+ *
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
  *
- * \return         The result of the comparison:
- *                 \c 1 if \p A is less than \p B.
- *                 \c 0 if \p A is greater than or equal to \p B.
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  */
-unsigned mbedtls_mpi_core_lt_ct(const mbedtls_mpi_uint *A,
-                                const mbedtls_mpi_uint *B,
-                                size_t limbs);
-#endif /* MBEDTLS_BIGNUM_C */
+static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition,
+                                                               mbedtls_ct_condition_t if1);
 
-/** Choose between two integer values without branches.
+/** Choose between a size_t value and 0.
  *
- * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled
- * to code using bitwise operation rather than a branch.
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : 0.
+ *
+ * Functionally equivalent to mbedtls_ct_size_if(condition, if1, 0) but
+ * results in smaller code size.
  *
  * \param condition     Condition to test.
- * \param if1           Value to use if \p condition is nonzero.
- * \param if0           Value to use if \p condition is zero.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
  *
- * \return  \c if1 if \p condition is nonzero, otherwise \c if0.
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  */
-unsigned mbedtls_ct_uint_if(unsigned condition,
-                            unsigned if1,
-                            unsigned if0);
+static inline size_t mbedtls_ct_size_if_else_0(mbedtls_ct_condition_t condition, size_t if1);
 
 #if defined(MBEDTLS_BIGNUM_C)
 
-/** Conditionally assign a value without branches.
+/** Choose between an mbedtls_mpi_uint value and 0.
+ *
+ * Functionally equivalent to:
+ *
+ * condition ? if1 : 0.
  *
- * This is equivalent to `if ( condition ) dest = src`, but is likely
- * to be compiled to code using bitwise operation rather than a branch.
+ * Functionally equivalent to mbedtls_ct_mpi_uint_if(condition, if1, 0) but
+ * results in smaller code size.
  *
- * \param n             \p dest and \p src must be arrays of limbs of size n.
- * \param dest          The MPI to conditionally assign to. This must point
- *                      to an initialized MPI.
- * \param src           The MPI to be assigned from. This must point to an
- *                      initialized MPI.
- * \param condition     Condition to test, must be 0 or 1.
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ *
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  */
-void mbedtls_ct_mpi_uint_cond_assign(size_t n,
-                                     mbedtls_mpi_uint *dest,
-                                     const mbedtls_mpi_uint *src,
-                                     unsigned char condition);
+static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition,
+                                                             mbedtls_mpi_uint if1);
 
-#endif /* MBEDTLS_BIGNUM_C */
+#endif
 
-#if defined(MBEDTLS_BASE64_C)
+/** Constant-flow char selection
+ *
+ * \param low   Secret. Bottom of range
+ * \param high  Secret. Top of range
+ * \param c     Secret. Value to compare to range
+ * \param t     Secret. Value to return, if in range
+ *
+ * \return      \p t if \p low <= \p c <= \p high, 0 otherwise.
+ */
+static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
+                                                         unsigned char high,
+                                                         unsigned char c,
+                                                         unsigned char t);
 
-/** Given a value in the range 0..63, return the corresponding Base64 digit.
+/** Choose between two error values. The values must be in the range [-32767..0].
+ *
+ * Functionally equivalent to:
  *
- * The implementation assumes that letters are consecutive (e.g. ASCII
- * but not EBCDIC).
+ * condition ? if1 : if0.
  *
- * \param value     A value in the range 0..63.
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
+ * \param if0           Value to use if \p condition == MBEDTLS_CT_FALSE.
  *
- * \return          A base64 digit converted from \p value.
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0.
  */
-unsigned char mbedtls_ct_base64_enc_char(unsigned char value);
+static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0);
 
-/** Given a Base64 digit, return its value.
+/** Choose between an error value and 0. The error value must be in the range [-32767..0].
+ *
+ * Functionally equivalent to:
  *
- * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'),
- * return -1.
+ * condition ? if1 : 0.
  *
- * The implementation assumes that letters are consecutive (e.g. ASCII
- * but not EBCDIC).
+ * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but
+ * results in smaller code size.
  *
- * \param c     A base64 digit.
+ * \param condition     Condition to test.
+ * \param if1           Value to use if \p condition == MBEDTLS_CT_TRUE.
  *
- * \return      The value of the base64 digit \p c.
+ * \return  \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0.
  */
-signed char mbedtls_ct_base64_dec_value(unsigned char c);
+static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1);
 
-#endif /* MBEDTLS_BASE64_C */
+/* ============================================================================
+ * Block memory operations
+ */
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
 
-/** Conditional memcpy without branches.
+/** Conditionally set a block of memory to zero.
+ *
+ * Regardless of the condition, every byte will be read once and written to
+ * once.
+ *
+ * \param condition     Secret. Condition to test.
+ * \param buf           Secret. Pointer to the start of the buffer.
+ * \param len           Number of bytes to set to zero.
+ *
+ * \warning Unlike mbedtls_platform_zeroize, this does not have the same guarantees
+ * about not being optimised away if the memory is never read again.
+ */
+void mbedtls_ct_zeroize_if(mbedtls_ct_condition_t condition, void *buf, size_t len);
+
+/** Shift some data towards the left inside a buffer.
+ *
+ * Functionally equivalent to:
  *
- * This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely
- * to be compiled to code using bitwise operation rather than a branch.
+ * memmove(start, start + offset, total - offset);
+ * memset(start + (total - offset), 0, offset);
  *
- * \param dest      The pointer to conditionally copy to.
- * \param src       The pointer to copy from. Shouldn't overlap with \p dest.
- * \param len       The number of bytes to copy.
- * \param c1        The first value to analyze in the condition.
- * \param c2        The second value to analyze in the condition.
+ * Timing independence comes at the expense of performance.
+ *
+ * \param start     Secret. Pointer to the start of the buffer.
+ * \param total     Total size of the buffer.
+ * \param offset    Secret. Offset from which to copy \p total - \p offset bytes.
+ */
+void mbedtls_ct_memmove_left(void *start,
+                             size_t total,
+                             size_t offset);
+
+#endif /* defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) */
+
+/** Conditional memcpy.
+ *
+ * Functionally equivalent to:
+ *
+ * if (condition) {
+ *      memcpy(dest, src1, len);
+ * } else {
+ *      if (src2 != NULL)
+ *          memcpy(dest, src2, len);
+ * }
+ *
+ * It will always read len bytes from src1.
+ * If src2 != NULL, it will always read len bytes from src2.
+ * If src2 == NULL, it will instead read len bytes from dest (as if src2 == dest).
+ *
+ * \param condition The condition
+ * \param dest      Secret. Destination pointer.
+ * \param src1      Secret. Pointer to copy from (if \p condition == MBEDTLS_CT_TRUE).
+ *                  This may be equal to \p dest, but may not overlap in other ways.
+ * \param src2      Secret (contents only - may branch to determine if this parameter is NULL).
+ *                  Pointer to copy from (if \p condition == MBEDTLS_CT_FALSE and \p src2 is not NULL). May be NULL.
+ *                  This may be equal to \p dest, but may not overlap it in other ways. It may overlap with \p src1.
+ * \param len       Number of bytes to copy.
  */
-void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
-                             const unsigned char *src,
-                             size_t len,
-                             size_t c1, size_t c2);
+void mbedtls_ct_memcpy_if(mbedtls_ct_condition_t condition,
+                          unsigned char *dest,
+                          const unsigned char *src1,
+                          const unsigned char *src2,
+                          size_t len
+                          );
 
-/** Copy data from a secret position with constant flow.
+/** Copy data from a secret position.
+ *
+ * Functionally equivalent to:
  *
- * This function copies \p len bytes from \p src_base + \p offset_secret to \p
- * dst, with a code flow and memory access pattern that does not depend on \p
- * offset_secret, but only on \p offset_min, \p offset_max and \p len.
- * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`.
+ * memcpy(dst, src + offset, len)
+ *
+ * This function copies \p len bytes from \p src + \p offset to
+ * \p dst, with a code flow and memory access pattern that does not depend on
+ * \p offset, but only on \p offset_min, \p offset_max and \p len.
  *
  * \note                This function reads from \p dest, but the value that
  *                      is read does not influence the result and this
@@ -246,12 +516,12 @@ void mbedtls_ct_memcpy_if_eq(unsigned char *dest,
  *                      positives from static or dynamic analyzers, especially
  *                      if \p dest is not initialized.
  *
- * \param dest          The destination buffer. This must point to a writable
+ * \param dest          Secret. The destination buffer. This must point to a writable
  *                      buffer of at least \p len bytes.
- * \param src           The base of the source buffer. This must point to a
+ * \param src           Secret. The base of the source buffer. This must point to a
  *                      readable buffer of at least \p offset_max + \p len
- *                      bytes. Shouldn't overlap with \p dest.
- * \param offset        The offset in the source buffer from which to copy.
+ *                      bytes. Shouldn't overlap with \p dest
+ * \param offset        Secret. The offset in the source buffer from which to copy.
  *                      This must be no less than \p offset_min and no greater
  *                      than \p offset_max.
  * \param offset_min    The minimal value of \p offset.
@@ -265,99 +535,45 @@ void mbedtls_ct_memcpy_offset(unsigned char *dest,
                               size_t offset_max,
                               size_t len);
 
-/** Compute the HMAC of variable-length data with constant flow.
- *
- * This function computes the HMAC of the concatenation of \p add_data and \p
- * data, and does with a code flow and memory access pattern that does not
- * depend on \p data_len_secret, but only on \p min_data_len and \p
- * max_data_len. In particular, this function always reads exactly \p
- * max_data_len bytes from \p data.
- *
- * \param ctx               The HMAC context. It must have keys configured
- *                          with mbedtls_md_hmac_starts() and use one of the
- *                          following hashes: SHA-384, SHA-256, SHA-1 or MD-5.
- *                          It is reset using mbedtls_md_hmac_reset() after
- *                          the computation is complete to prepare for the
- *                          next computation.
- * \param add_data          The first part of the message whose HMAC is being
- *                          calculated. This must point to a readable buffer
- *                          of \p add_data_len bytes.
- * \param add_data_len      The length of \p add_data in bytes.
- * \param data              The buffer containing the second part of the
- *                          message. This must point to a readable buffer
- *                          of \p max_data_len bytes.
- * \param data_len_secret   The length of the data to process in \p data.
- *                          This must be no less than \p min_data_len and no
- *                          greater than \p max_data_len.
- * \param min_data_len      The minimal length of the second part of the
- *                          message, read from \p data.
- * \param max_data_len      The maximal length of the second part of the
- *                          message, read from \p data.
- * \param output            The HMAC will be written here. This must point to
- *                          a writable buffer of sufficient size to hold the
- *                          HMAC value.
- *
- * \retval 0 on success.
- * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
- *         The hardware accelerator failed.
- */
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
-                    psa_algorithm_t alg,
-                    const unsigned char *add_data,
-                    size_t add_data_len,
-                    const unsigned char *data,
-                    size_t data_len_secret,
-                    size_t min_data_len,
-                    size_t max_data_len,
-                    unsigned char *output);
-#else
-int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
-                    const unsigned char *add_data,
-                    size_t add_data_len,
-                    const unsigned char *data,
-                    size_t data_len_secret,
-                    size_t min_data_len,
-                    size_t max_data_len,
-                    unsigned char *output);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+/* Documented in include/mbedtls/constant_time.h. a and b are secret.
 
-#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
+   int mbedtls_ct_memcmp(const void *a,
+                         const void *b,
+                         size_t n);
+ */
+
+#if defined(MBEDTLS_NIST_KW_C)
+
+/** Constant-time buffer comparison without branches.
+ *
+ * Similar to mbedtls_ct_memcmp, except that the result only depends on part of
+ * the input data - differences in the head or tail are ignored. Functionally equivalent to:
+ *
+ * memcmp(a + skip_head, b + skip_head, size - skip_head - skip_tail)
+ *
+ * Time taken depends on \p n, but not on \p skip_head or \p skip_tail .
+ *
+ * Behaviour is undefined if ( \p skip_head + \p skip_tail) > \p n.
+ *
+ * \param a         Secret. Pointer to the first buffer, containing at least \p n bytes. May not be NULL.
+ * \param b         Secret. Pointer to the second buffer, containing at least \p n bytes. May not be NULL.
+ * \param n         The number of bytes to examine (total size of the buffers).
+ * \param skip_head Secret. The number of bytes to treat as non-significant at the start of the buffer.
+ *                  These bytes will still be read.
+ * \param skip_tail Secret. The number of bytes to treat as non-significant at the end of the buffer.
+ *                  These bytes will still be read.
+ *
+ * \return          Zero if the contents of the two buffers are the same, otherwise non-zero.
+ */
+int mbedtls_ct_memcmp_partial(const void *a,
+                              const void *b,
+                              size_t n,
+                              size_t skip_head,
+                              size_t skip_tail);
+
+#endif
 
-/** This function performs the unpadding part of a PKCS#1 v1.5 decryption
- *  operation (EME-PKCS1-v1_5 decoding).
- *
- * \note The return value from this function is a sensitive value
- *       (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen
- *       in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING
- *       is often a situation that an attacker can provoke and leaking which
- *       one is the result is precisely the information the attacker wants.
- *
- * \param input          The input buffer which is the payload inside PKCS#1v1.5
- *                       encryption padding, called the "encoded message EM"
- *                       by the terminology.
- * \param ilen           The length of the payload in the \p input buffer.
- * \param output         The buffer for the payload, called "message M" by the
- *                       PKCS#1 terminology. This must be a writable buffer of
- *                       length \p output_max_len bytes.
- * \param olen           The address at which to store the length of
- *                       the payload. This must not be \c NULL.
- * \param output_max_len The length in bytes of the output buffer \p output.
- *
- * \return      \c 0 on success.
- * \return      #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
- *              The output buffer is too small for the unpadded payload.
- * \return      #MBEDTLS_ERR_RSA_INVALID_PADDING
- *              The input doesn't contain properly formatted padding.
- */
-int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
-                                         size_t ilen,
-                                         unsigned char *output,
-                                         size_t output_max_len,
-                                         size_t *olen);
-
-#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
+/* Include the implementation of static inline functions above. */
+#include "constant_time_impl.h"
 
 #endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/constant_time_invasive.h b/lib/libmbedtls/mbedtls/library/constant_time_invasive.h
deleted file mode 100644
index c176b28ffdcec4030778747c7b0ef7a29751be2d..0000000000000000000000000000000000000000
--- a/lib/libmbedtls/mbedtls/library/constant_time_invasive.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * \file constant_time_invasive.h
- *
- * \brief Constant-time module: interfaces for invasive testing only.
- *
- * The interfaces in this file are intended for testing purposes only.
- * They SHOULD NOT be made available in library integrations except when
- * building the library for testing.
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H
-#define MBEDTLS_CONSTANT_TIME_INVASIVE_H
-
-#include "common.h"
-
-#if defined(MBEDTLS_TEST_HOOKS)
-
-/** Turn a value into a mask:
- * - if \p low <= \p c <= \p high,
- *   return the all-bits 1 mask, aka (unsigned) -1
- * - otherwise, return the all-bits 0 mask, aka 0
- *
- * \param low   The value to analyze.
- * \param high  The value to analyze.
- * \param c     The value to analyze.
- *
- * \return      All-bits-one if \p low <= \p c <= \p high, otherwise zero.
- */
-unsigned char mbedtls_ct_uchar_mask_of_range(unsigned char low,
-                                             unsigned char high,
-                                             unsigned char c);
-
-#endif /* MBEDTLS_TEST_HOOKS */
-
-#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */
diff --git a/lib/libmbedtls/mbedtls/library/ctr.h b/lib/libmbedtls/mbedtls/library/ctr.h
new file mode 100644
index 0000000000000000000000000000000000000000..aa48fb9e707adc4e2eb32a0cefd1d7d127a69946
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ctr.h
@@ -0,0 +1,35 @@
+/**
+ * \file ctr.h
+ *
+ * \brief    This file contains common functionality for counter algorithms.
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_CTR_H
+#define MBEDTLS_CTR_H
+
+#include "common.h"
+
+/**
+ * \brief               Increment a big-endian 16-byte value.
+ *                      This is quite performance-sensitive for AES-CTR and CTR-DRBG.
+ *
+ * \param n             A 16-byte value to be incremented.
+ */
+static inline void mbedtls_ctr_increment_counter(uint8_t n[16])
+{
+    // The 32-bit version seems to perform about the same as a 64-bit version
+    // on 64-bit architectures, so no need to define a 64-bit version.
+    for (int i = 3;; i--) {
+        uint32_t x = MBEDTLS_GET_UINT32_BE(n, i << 2);
+        x += 1;
+        MBEDTLS_PUT_UINT32_BE(x, n, i << 2);
+        if (x != 0 || i == 0) {
+            break;
+        }
+    }
+}
+
+#endif /* MBEDTLS_CTR_H */
diff --git a/lib/libmbedtls/mbedtls/library/ctr_drbg.c b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
index acc4208cc37b410741c33ad58f5fd74218715a6a..b82044eb7d26b986f86f6eb9b9f43d619e149a21 100644
--- a/lib/libmbedtls/mbedtls/library/ctr_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/ctr_drbg.c
@@ -2,30 +2,19 @@
  *  CTR_DRBG implementation based on AES-256 (NIST SP 800-90)
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The NIST SP 800-90 DRBGs are described in the following publication.
  *
- *  http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf
+ *  https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-90r.pdf
  */
 
 #include "common.h"
 
 #if defined(MBEDTLS_CTR_DRBG_C)
 
+#include "ctr.h"
 #include "mbedtls/ctr_drbg.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
@@ -36,15 +25,60 @@
 #include <stdio.h>
 #endif
 
+/* Using error translation functions from PSA to MbedTLS */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+#include "psa_util_internal.h"
+#endif
+
 #include "mbedtls/platform.h"
 
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+static psa_status_t ctr_drbg_setup_psa_context(mbedtls_ctr_drbg_psa_context *psa_ctx,
+                                               unsigned char *key, size_t key_len)
+{
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_status_t status;
+
+    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_ENCRYPT);
+    psa_set_key_algorithm(&key_attr, PSA_ALG_ECB_NO_PADDING);
+    psa_set_key_type(&key_attr, PSA_KEY_TYPE_AES);
+    status = psa_import_key(&key_attr, key, key_len, &psa_ctx->key_id);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_cipher_encrypt_setup(&psa_ctx->operation, psa_ctx->key_id, PSA_ALG_ECB_NO_PADDING);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    psa_reset_key_attributes(&key_attr);
+    return status;
+}
+
+static void ctr_drbg_destroy_psa_contex(mbedtls_ctr_drbg_psa_context *psa_ctx)
+{
+    psa_cipher_abort(&psa_ctx->operation);
+    psa_destroy_key(psa_ctx->key_id);
+
+    psa_ctx->operation = psa_cipher_operation_init();
+    psa_ctx->key_id = MBEDTLS_SVC_KEY_ID_INIT;
+}
+#endif
+
 /*
  * CTR_DRBG context initialization
  */
 void mbedtls_ctr_drbg_init(mbedtls_ctr_drbg_context *ctx)
 {
     memset(ctx, 0, sizeof(mbedtls_ctr_drbg_context));
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    ctx->psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    ctx->psa_ctx.operation = psa_cipher_operation_init();
+#else
     mbedtls_aes_init(&ctx->aes_ctx);
+#endif
     /* Indicate that the entropy nonce length is not set explicitly.
      * See mbedtls_ctr_drbg_set_nonce_len(). */
     ctx->reseed_counter = -1;
@@ -68,7 +102,11 @@ void mbedtls_ctr_drbg_free(mbedtls_ctr_drbg_context *ctx)
         mbedtls_mutex_free(&ctx->mutex);
     }
 #endif
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
+#else
     mbedtls_aes_free(&ctx->aes_ctx);
+#endif
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_ctr_drbg_context));
     ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL;
     ctx->reseed_counter = -1;
@@ -129,8 +167,17 @@ static int block_cipher_df(unsigned char *output,
     unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE];
     unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE];
     unsigned char *p, *iv;
-    mbedtls_aes_context aes_ctx;
     int ret = 0;
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    psa_status_t status;
+    size_t tmp_len;
+    mbedtls_ctr_drbg_psa_context psa_ctx;
+
+    psa_ctx.key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_ctx.operation = psa_cipher_operation_init();
+#else
+    mbedtls_aes_context aes_ctx;
+#endif
 
     int i, j;
     size_t buf_len, use_len;
@@ -141,7 +188,6 @@ static int block_cipher_df(unsigned char *output,
 
     memset(buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT +
            MBEDTLS_CTR_DRBG_BLOCKSIZE + 16);
-    mbedtls_aes_init(&aes_ctx);
 
     /*
      * Construct IV (16 bytes) and S in buffer
@@ -163,10 +209,20 @@ static int block_cipher_df(unsigned char *output,
         key[i] = i;
     }
 
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    status = ctr_drbg_setup_psa_context(&psa_ctx, key, sizeof(key));
+    if (status != PSA_SUCCESS) {
+        ret = psa_generic_status_to_mbedtls(status);
+        goto exit;
+    }
+#else
+    mbedtls_aes_init(&aes_ctx);
+
     if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, key,
                                       MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
+#endif
 
     /*
      * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data
@@ -182,10 +238,19 @@ static int block_cipher_df(unsigned char *output,
             use_len -= (use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE) ?
                        MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len;
 
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+            status = psa_cipher_update(&psa_ctx.operation, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE,
+                                       chain, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
+            if (status != PSA_SUCCESS) {
+                ret = psa_generic_status_to_mbedtls(status);
+                goto exit;
+            }
+#else
             if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
                                              chain, chain)) != 0) {
                 goto exit;
             }
+#endif
         }
 
         memcpy(tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE);
@@ -199,23 +264,46 @@ static int block_cipher_df(unsigned char *output,
     /*
      * Do final encryption with reduced data
      */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    ctr_drbg_destroy_psa_contex(&psa_ctx);
+
+    status = ctr_drbg_setup_psa_context(&psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
+    if (status != PSA_SUCCESS) {
+        ret = psa_generic_status_to_mbedtls(status);
+        goto exit;
+    }
+#else
     if ((ret = mbedtls_aes_setkey_enc(&aes_ctx, tmp,
                                       MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
+#endif
     iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE;
     p = output;
 
     for (j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE) {
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+        status = psa_cipher_update(&psa_ctx.operation, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE,
+                                   iv, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
+        if (status != PSA_SUCCESS) {
+            ret = psa_generic_status_to_mbedtls(status);
+            goto exit;
+        }
+#else
         if ((ret = mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT,
                                          iv, iv)) != 0) {
             goto exit;
         }
+#endif
         memcpy(p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE);
         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
     }
 exit:
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    ctr_drbg_destroy_psa_contex(&psa_ctx);
+#else
     mbedtls_aes_free(&aes_ctx);
+#endif
     /*
      * tidy up the stack
      */
@@ -246,8 +334,12 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
 {
     unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN];
     unsigned char *p = tmp;
-    int i, j;
+    int j;
     int ret = 0;
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    psa_status_t status;
+    size_t tmp_len;
+#endif
 
     memset(tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
 
@@ -255,34 +347,47 @@ static int ctr_drbg_update_internal(mbedtls_ctr_drbg_context *ctx,
         /*
          * Increase counter
          */
-        for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
-            if (++ctx->counter[i - 1] != 0) {
-                break;
-            }
-        }
+        mbedtls_ctr_increment_counter(ctx->counter);
 
         /*
          * Crypt counter block
          */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
+                                   p, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
+        if (status != PSA_SUCCESS) {
+            ret = psa_generic_status_to_mbedtls(status);
+            goto exit;
+        }
+#else
         if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
                                          ctx->counter, p)) != 0) {
             goto exit;
         }
+#endif
 
         p += MBEDTLS_CTR_DRBG_BLOCKSIZE;
     }
 
-    for (i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++) {
-        tmp[i] ^= data[i];
-    }
+    mbedtls_xor(tmp, tmp, data, MBEDTLS_CTR_DRBG_SEEDLEN);
 
     /*
      * Update key and counter
      */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    ctr_drbg_destroy_psa_contex(&ctx->psa_ctx);
+
+    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, tmp, MBEDTLS_CTR_DRBG_KEYSIZE);
+    if (status != PSA_SUCCESS) {
+        ret = psa_generic_status_to_mbedtls(status);
+        goto exit;
+    }
+#else
     if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, tmp,
                                       MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         goto exit;
     }
+#endif
     memcpy(ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE,
            MBEDTLS_CTR_DRBG_BLOCKSIZE);
 
@@ -459,10 +564,20 @@ int mbedtls_ctr_drbg_seed(mbedtls_ctr_drbg_context *ctx,
                  good_nonce_len(ctx->entropy_len));
 
     /* Initialize with an empty key. */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+    psa_status_t status;
+
+    status = ctr_drbg_setup_psa_context(&ctx->psa_ctx, key, MBEDTLS_CTR_DRBG_KEYSIZE);
+    if (status != PSA_SUCCESS) {
+        ret = psa_generic_status_to_mbedtls(status);
+        return status;
+    }
+#else
     if ((ret = mbedtls_aes_setkey_enc(&ctx->aes_ctx, key,
                                       MBEDTLS_CTR_DRBG_KEYBITS)) != 0) {
         return ret;
     }
+#endif
 
     /* Do the initial seeding. */
     if ((ret = mbedtls_ctr_drbg_reseed_internal(ctx, custom, len,
@@ -497,10 +612,11 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng,
 {
     int ret = 0;
     mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng;
-    unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
     unsigned char *p = output;
-    unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
-    int i;
+    struct {
+        unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN];
+        unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE];
+    } locals;
     size_t use_len;
 
     if (output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST) {
@@ -511,7 +627,7 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng,
         return MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG;
     }
 
-    memset(add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
+    memset(locals.add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN);
 
     if (ctx->reseed_counter > ctx->reseed_interval ||
         ctx->prediction_resistance) {
@@ -522,51 +638,58 @@ int mbedtls_ctr_drbg_random_with_add(void *p_rng,
     }
 
     if (add_len > 0) {
-        if ((ret = block_cipher_df(add_input, additional, add_len)) != 0) {
+        if ((ret = block_cipher_df(locals.add_input, additional, add_len)) != 0) {
             goto exit;
         }
-        if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
+        if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
             goto exit;
         }
     }
 
     while (output_len > 0) {
         /*
-         * Increase counter
+         * Increase counter (treat it as a 128-bit big-endian integer).
          */
-        for (i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i--) {
-            if (++ctx->counter[i - 1] != 0) {
-                break;
-            }
-        }
+        mbedtls_ctr_increment_counter(ctx->counter);
 
         /*
          * Crypt counter block
          */
+#if defined(MBEDTLS_CTR_DRBG_USE_PSA_CRYPTO)
+        psa_status_t status;
+        size_t tmp_len;
+
+        status = psa_cipher_update(&ctx->psa_ctx.operation, ctx->counter, sizeof(ctx->counter),
+                                   locals.tmp, MBEDTLS_CTR_DRBG_BLOCKSIZE, &tmp_len);
+        if (status != PSA_SUCCESS) {
+            ret = psa_generic_status_to_mbedtls(status);
+            goto exit;
+        }
+#else
         if ((ret = mbedtls_aes_crypt_ecb(&ctx->aes_ctx, MBEDTLS_AES_ENCRYPT,
-                                         ctx->counter, tmp)) != 0) {
+                                         ctx->counter, locals.tmp)) != 0) {
             goto exit;
         }
+#endif
 
         use_len = (output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE)
             ? MBEDTLS_CTR_DRBG_BLOCKSIZE : output_len;
         /*
          * Copy random block to destination
          */
-        memcpy(p, tmp, use_len);
+        memcpy(p, locals.tmp, use_len);
         p += use_len;
         output_len -= use_len;
     }
 
-    if ((ret = ctr_drbg_update_internal(ctx, add_input)) != 0) {
+    if ((ret = ctr_drbg_update_internal(ctx, locals.add_input)) != 0) {
         goto exit;
     }
 
     ctx->reseed_counter++;
 
 exit:
-    mbedtls_platform_zeroize(add_input, sizeof(add_input));
-    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    mbedtls_platform_zeroize(&locals, sizeof(locals));
     return ret;
 }
 
diff --git a/lib/libmbedtls/mbedtls/library/debug.c b/lib/libmbedtls/mbedtls/library/debug.c
index 12559afe345a3716195e2c9f6b369011e94f329e..c36ed3c5c21c4523a96fa75511d637026a68dbc4 100644
--- a/lib/libmbedtls/mbedtls/library/debug.c
+++ b/lib/libmbedtls/mbedtls/library/debug.c
@@ -2,19 +2,7 @@
  *  Debugging routines
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -23,13 +11,14 @@
 
 #include "mbedtls/platform.h"
 
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
+/* DEBUG_BUF_SIZE must be at least 2 */
 #define DEBUG_BUF_SIZE      512
 
 static int debug_threshold = 0;
@@ -69,6 +58,8 @@ void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
     char str[DEBUG_BUF_SIZE];
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
+    MBEDTLS_STATIC_ASSERT(DEBUG_BUF_SIZE >= 2, "DEBUG_BUF_SIZE too small");
+
     if (NULL == ssl              ||
         NULL == ssl->conf        ||
         NULL == ssl->conf->f_dbg ||
@@ -80,10 +71,15 @@ void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
     ret = mbedtls_vsnprintf(str, DEBUG_BUF_SIZE, format, argp);
     va_end(argp);
 
-    if (ret >= 0 && ret < DEBUG_BUF_SIZE - 1) {
-        str[ret]     = '\n';
-        str[ret + 1] = '\0';
+    if (ret < 0) {
+        ret = 0;
+    } else {
+        if (ret >= DEBUG_BUF_SIZE - 1) {
+            ret = DEBUG_BUF_SIZE - 2;
+        }
     }
+    str[ret]     = '\n';
+    str[ret + 1] = '\0';
 
     debug_send_line(ssl, level, file, line, str);
 }
@@ -136,7 +132,6 @@ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
 
     debug_send_line(ssl, level, file, line, str);
 
-    idx = 0;
     memset(txt, 0, sizeof(txt));
     for (i = 0; i < len; i++) {
         if (i >= 4096) {
@@ -172,7 +167,7 @@ void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
     }
 }
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_ECP_LIGHT)
 void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
                              const char *file, int line,
                              const char *text, const mbedtls_ecp_point *X)
@@ -192,7 +187,79 @@ void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
     mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
     mbedtls_debug_print_mpi(ssl, level, file, line, str, &X->Y);
 }
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_ECP_LIGHT */
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static void mbedtls_debug_print_ec_coord(const mbedtls_ssl_context *ssl, int level,
+                                         const char *file, int line, const char *text,
+                                         const unsigned char *buf, size_t len)
+{
+    char str[DEBUG_BUF_SIZE];
+    size_t i, idx = 0;
+
+    mbedtls_snprintf(str + idx, sizeof(str) - idx, "value of '%s' (%u bits) is:\n",
+                     text, (unsigned int) len * 8);
+
+    debug_send_line(ssl, level, file, line, str);
+
+    for (i = 0; i < len; i++) {
+        if (i >= 4096) {
+            break;
+        }
+
+        if (i % 16 == 0) {
+            if (i > 0) {
+                mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
+                debug_send_line(ssl, level, file, line, str);
+
+                idx = 0;
+            }
+        }
+
+        idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, " %02x",
+                                (unsigned int) buf[i]);
+    }
+
+    if (len > 0) {
+        for (/* i = i */; i % 16 != 0; i++) {
+            idx += mbedtls_snprintf(str + idx, sizeof(str) - idx, "   ");
+        }
+
+        mbedtls_snprintf(str + idx, sizeof(str) - idx, "\n");
+        debug_send_line(ssl, level, file, line, str);
+    }
+}
+
+void mbedtls_debug_print_psa_ec(const mbedtls_ssl_context *ssl, int level,
+                                const char *file, int line,
+                                const char *text, const mbedtls_pk_context *pk)
+{
+    char str[DEBUG_BUF_SIZE];
+    const uint8_t *coord_start;
+    size_t coord_len;
+
+    if (NULL == ssl              ||
+        NULL == ssl->conf        ||
+        NULL == ssl->conf->f_dbg ||
+        level > debug_threshold) {
+        return;
+    }
+
+    /* For the description of pk->pk_raw content please refer to the description
+     * psa_export_public_key() function. */
+    coord_len = (pk->pub_raw_len - 1)/2;
+
+    /* X coordinate */
+    coord_start = pk->pub_raw + 1;
+    mbedtls_snprintf(str, sizeof(str), "%s(X)", text);
+    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
+
+    /* Y coordinate */
+    coord_start = coord_start + coord_len;
+    mbedtls_snprintf(str, sizeof(str), "%s(Y)", text);
+    mbedtls_debug_print_ec_coord(ssl, level, file, line, str, coord_start, coord_len);
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 
 #if defined(MBEDTLS_BIGNUM_C)
 void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
@@ -270,14 +337,21 @@ static void debug_print_pk(const mbedtls_ssl_context *ssl, int level,
         mbedtls_snprintf(name, sizeof(name), "%s%s", text, items[i].name);
         name[sizeof(name) - 1] = '\0';
 
+#if defined(MBEDTLS_RSA_C)
         if (items[i].type == MBEDTLS_PK_DEBUG_MPI) {
             mbedtls_debug_print_mpi(ssl, level, file, line, name, items[i].value);
         } else
-#if defined(MBEDTLS_ECP_C)
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_ECP_LIGHT)
         if (items[i].type == MBEDTLS_PK_DEBUG_ECP) {
             mbedtls_debug_print_ecp(ssl, level, file, line, name, items[i].value);
         } else
-#endif
+#endif /* MBEDTLS_ECP_LIGHT */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        if (items[i].type == MBEDTLS_PK_DEBUG_PSA_EC) {
+            mbedtls_debug_print_psa_ec(ssl, level, file, line, name, items[i].value);
+        } else
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
         { debug_send_line(ssl, level, file, line,
                           "should not happen\n"); }
     }
@@ -292,7 +366,7 @@ static void debug_print_line_by_line(const mbedtls_ssl_context *ssl, int level,
     start = text;
     for (cur = text; *cur != '\0'; cur++) {
         if (*cur == '\n') {
-            size_t len = cur - start + 1;
+            size_t len = (size_t) (cur - start) + 1;
             if (len > DEBUG_BUF_SIZE - 1) {
                 len = DEBUG_BUF_SIZE - 1;
             }
@@ -338,7 +412,8 @@ void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
 }
 #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_X509_REMOVE_INFO */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
+    defined(MBEDTLS_ECDH_C)
 static void mbedtls_debug_printf_ecdh_internal(const mbedtls_ssl_context *ssl,
                                                int level, const char *file,
                                                int line,
@@ -384,6 +459,7 @@ void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
     }
 #endif
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
+          MBEDTLS_ECDH_C */
 
 #endif /* MBEDTLS_DEBUG_C */
diff --git a/lib/libmbedtls/mbedtls/library/debug_internal.h b/lib/libmbedtls/mbedtls/library/debug_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..4523b4633a2e6e11f57e6647bb3e824aee1ef7b5
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/debug_internal.h
@@ -0,0 +1,172 @@
+/**
+ * \file debug_internal.h
+ *
+ * \brief Internal part of the public "debug.h".
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_DEBUG_INTERNAL_H
+#define MBEDTLS_DEBUG_INTERNAL_H
+
+#include "mbedtls/debug.h"
+
+/**
+ * \brief    Print a message to the debug output. This function is always used
+ *          through the MBEDTLS_SSL_DEBUG_MSG() macro, which supplies the ssl
+ *          context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the message has occurred in
+ * \param line      line number the message has occurred at
+ * \param format    format specifier, in printf format
+ * \param ...       variables used by the format specifier
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_msg(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *format, ...) MBEDTLS_PRINTF_ATTRIBUTE(5, 6);
+
+/**
+ * \brief   Print the return value of a function to the debug output. This
+ *          function is always used through the MBEDTLS_SSL_DEBUG_RET() macro,
+ *          which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param text      the name of the function that returned the error
+ * \param ret       the return code value
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_ret(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, int ret);
+
+/**
+ * \brief   Output a buffer of size len bytes to the debug output. This function
+ *          is always used through the MBEDTLS_SSL_DEBUG_BUF() macro,
+ *          which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param text      a name or label for the buffer being dumped. Normally the
+ *                  variable or buffer name
+ * \param buf       the buffer to be outputted
+ * \param len       length of the buffer
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_buf(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line, const char *text,
+                             const unsigned char *buf, size_t len);
+
+#if defined(MBEDTLS_BIGNUM_C)
+/**
+ * \brief   Print a MPI variable to the debug output. This function is always
+ *          used through the MBEDTLS_SSL_DEBUG_MPI() macro, which supplies the
+ *          ssl context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param text      a name or label for the MPI being output. Normally the
+ *                  variable name
+ * \param X         the MPI variable
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_mpi(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_mpi *X);
+#endif
+
+#if defined(MBEDTLS_ECP_LIGHT)
+/**
+ * \brief   Print an ECP point to the debug output. This function is always
+ *          used through the MBEDTLS_SSL_DEBUG_ECP() macro, which supplies the
+ *          ssl context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param text      a name or label for the ECP point being output. Normally the
+ *                  variable name
+ * \param X         the ECP point
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_ecp(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_ecp_point *X);
+#endif
+
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && !defined(MBEDTLS_X509_REMOVE_INFO)
+/**
+ * \brief   Print a X.509 certificate structure to the debug output. This
+ *          function is always used through the MBEDTLS_SSL_DEBUG_CRT() macro,
+ *          which supplies the ssl context, file and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param text      a name or label for the certificate being output
+ * \param crt       X.509 certificate structure
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_print_crt(const mbedtls_ssl_context *ssl, int level,
+                             const char *file, int line,
+                             const char *text, const mbedtls_x509_crt *crt);
+#endif
+
+/* Note: the MBEDTLS_ECDH_C guard here is mandatory because this debug function
+         only works for the built-in implementation. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) && \
+    defined(MBEDTLS_ECDH_C)
+typedef enum {
+    MBEDTLS_DEBUG_ECDH_Q,
+    MBEDTLS_DEBUG_ECDH_QP,
+    MBEDTLS_DEBUG_ECDH_Z,
+} mbedtls_debug_ecdh_attr;
+
+/**
+ * \brief   Print a field of the ECDH structure in the SSL context to the debug
+ *          output. This function is always used through the
+ *          MBEDTLS_SSL_DEBUG_ECDH() macro, which supplies the ssl context, file
+ *          and line number parameters.
+ *
+ * \param ssl       SSL context
+ * \param level     error level of the debug message
+ * \param file      file the error has occurred in
+ * \param line      line number the error has occurred in
+ * \param ecdh      the ECDH context
+ * \param attr      the identifier of the attribute being output
+ *
+ * \attention       This function is intended for INTERNAL usage within the
+ *                  library only.
+ */
+void mbedtls_debug_printf_ecdh(const mbedtls_ssl_context *ssl, int level,
+                               const char *file, int line,
+                               const mbedtls_ecdh_context *ecdh,
+                               mbedtls_debug_ecdh_attr attr);
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED &&
+          MBEDTLS_ECDH_C */
+
+#endif /* MBEDTLS_DEBUG_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/des.c b/lib/libmbedtls/mbedtls/library/des.c
index eaddf282a9d48c806f6b419ce09305bd5755d45c..f0032b3b5699789389b289901031779b4f7d0bd3 100644
--- a/lib/libmbedtls/mbedtls/library/des.c
+++ b/lib/libmbedtls/mbedtls/library/des.c
@@ -2,19 +2,7 @@
  *  FIPS-46-3 compliant Triple-DES implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  DES, on which TDES is based, was originally designed by Horst Feistel
diff --git a/lib/libmbedtls/mbedtls/library/dhm.c b/lib/libmbedtls/mbedtls/library/dhm.c
index 94137a264d749d416d8ce54827c956d9b1b2bdc1..bcc07f544194e56185ceb3d4e90d02776d44b0c3 100644
--- a/lib/libmbedtls/mbedtls/library/dhm.c
+++ b/lib/libmbedtls/mbedtls/library/dhm.c
@@ -2,19 +2,7 @@
  *  Diffie-Hellman-Merkle key exchange
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The following sources were referenced in the design of this implementation
@@ -60,10 +48,10 @@ static int dhm_read_bignum(mbedtls_mpi *X,
         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
     }
 
-    n = ((*p)[0] << 8) | (*p)[1];
+    n = MBEDTLS_GET_UINT16_BE(*p, 0);
     (*p) += 2;
 
-    if ((int) (end - *p) < n) {
+    if ((size_t) (end - *p) < (size_t) n) {
         return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
     }
 
@@ -269,7 +257,7 @@ int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
     DHM_MPI_EXPORT(&ctx->G, n2);
     DHM_MPI_EXPORT(&ctx->GX, n3);
 
-    *olen = p - output;
+    *olen = (size_t) (p - output);
 
 cleanup:
     if (ret != 0 && ret > -128) {
@@ -617,8 +605,7 @@ static int load_file(const char *path, unsigned char **buf, size_t *n)
     if (fread(*buf, 1, *n, f) != *n) {
         fclose(f);
 
-        mbedtls_platform_zeroize(*buf, *n + 1);
-        mbedtls_free(*buf);
+        mbedtls_zeroize_and_free(*buf, *n + 1);
 
         return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
     }
@@ -649,8 +636,7 @@ int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
 
     ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
 
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
+    mbedtls_zeroize_and_free(buf, n);
 
     return ret;
 }
diff --git a/lib/libmbedtls/mbedtls/library/ecdh.c b/lib/libmbedtls/mbedtls/library/ecdh.c
index b529af59c9fbd04f273716bdf2001887ad95aca2..b276c6adadf4c4845950b540c831b2c8e0620f03 100644
--- a/lib/libmbedtls/mbedtls/library/ecdh.c
+++ b/lib/libmbedtls/mbedtls/library/ecdh.c
@@ -2,25 +2,13 @@
  *  Elliptic curve Diffie-Hellman
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
  * References:
  *
- * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * SEC1 https://www.secg.org/sec1-v2.pdf
  * RFC 4492
  */
 
@@ -156,6 +144,15 @@ static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
 #endif
 }
 
+mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
+{
+#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
+    return ctx->MBEDTLS_PRIVATE(grp).id;
+#else
+    return ctx->MBEDTLS_PRIVATE(grp_id);
+#endif
+}
+
 /*
  * Initialize context
  */
@@ -375,7 +372,7 @@ static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
                                      const unsigned char *end)
 {
     return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
-                                      end - *buf);
+                                      (size_t) (end - *buf));
 }
 
 /*
@@ -391,7 +388,7 @@ int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group_id grp_id;
-    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, end - *buf))
+    if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
         != 0) {
         return ret;
     }
diff --git a/lib/libmbedtls/mbedtls/library/ecdsa.c b/lib/libmbedtls/mbedtls/library/ecdsa.c
index eb3c3031972b349d196f314146e8c2769977e960..2f7a996a7e73383167737cd671fe4677f029326c 100644
--- a/lib/libmbedtls/mbedtls/library/ecdsa.c
+++ b/lib/libmbedtls/mbedtls/library/ecdsa.c
@@ -2,25 +2,13 @@
  *  Elliptic curve DSA
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
  * References:
  *
- * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * SEC1 https://www.secg.org/sec1-v2.pdf
  */
 
 #include "common.h"
@@ -234,6 +222,19 @@ cleanup:
 }
 #endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
 
+int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
+{
+    switch (gid) {
+#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
+        case MBEDTLS_ECP_DP_CURVE25519: return 0;
+#endif
+#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
+        case MBEDTLS_ECP_DP_CURVE448: return 0;
+#endif
+        default: return 1;
+    }
+}
+
 #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
 /*
  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
@@ -360,7 +361,7 @@ modn:
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     if (rs_ctx != NULL && rs_ctx->sig != NULL) {
-        mbedtls_mpi_copy(r, pr);
+        MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));
     }
 #endif
 
@@ -373,19 +374,6 @@ cleanup:
     return ret;
 }
 
-int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
-{
-    switch (gid) {
-#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
-        case MBEDTLS_ECP_DP_CURVE25519: return 0;
-#endif
-#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
-        case MBEDTLS_ECP_DP_CURVE448: return 0;
-#endif
-        default: return 1;
-    }
-}
-
 /*
  * Compute ECDSA signature of a hashed message
  */
@@ -447,7 +435,7 @@ int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
     MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
-    mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len);
+    MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
     if (rs_ctx != NULL && rs_ctx->det != NULL) {
diff --git a/lib/libmbedtls/mbedtls/library/ecjpake.c b/lib/libmbedtls/mbedtls/library/ecjpake.c
index 36c1327bd52b6e2d0b6e30932df952f98773d128..cdf5d7ea46e5dd2a3ac4ffd1ac677c49b852ec02 100644
--- a/lib/libmbedtls/mbedtls/library/ecjpake.c
+++ b/lib/libmbedtls/mbedtls/library/ecjpake.c
@@ -2,19 +2,7 @@
  *  Elliptic curve J-PAKE
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -30,20 +18,6 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
-/* We use MD first if it's available (for compatibility reasons)
- * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
-#if !defined(MBEDTLS_MD_C)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#if !defined(MBEDTLS_ECJPAKE_ALT)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_md_errors,              \
-                                                           psa_generic_status_to_mbedtls)
-#endif /* !MBEDTLS_ECJPAKE_ALT */
-#endif /* !MBEDTLS_MD_C */
-
-#include "hash_info.h"
-
 #include <string.h>
 
 #if !defined(MBEDTLS_ECJPAKE_ALT)
@@ -66,19 +40,8 @@ static int mbedtls_ecjpake_compute_hash(mbedtls_md_type_t md_type,
                                         const unsigned char *input, size_t ilen,
                                         unsigned char *output)
 {
-#if defined(MBEDTLS_MD_C)
     return mbedtls_md(mbedtls_md_info_from_type(md_type),
                       input, ilen, output);
-#else
-    psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
-    psa_status_t status;
-    size_t out_size = PSA_HASH_LENGTH(alg);
-    size_t out_len;
-
-    status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
-
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif /* !MBEDTLS_MD_C */
 }
 
 /*
@@ -142,15 +105,9 @@ int mbedtls_ecjpake_setup(mbedtls_ecjpake_context *ctx,
 
     ctx->role = role;
 
-#if defined(MBEDTLS_MD_C)
     if ((mbedtls_md_info_from_type(hash)) == NULL) {
         return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
     }
-#else
-    if (mbedtls_psa_translate_md(hash) == MBEDTLS_MD_NONE) {
-        return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
-    }
-#endif
 
     ctx->md_type = hash;
 
@@ -211,7 +168,7 @@ static int ecjpake_write_len_point(unsigned char **p,
     }
 
     ret = mbedtls_ecp_point_write_binary(grp, P, pf,
-                                         &len, *p + 4, end - (*p + 4));
+                                         &len, *p + 4, (size_t) (end - (*p + 4)));
     if (ret != 0) {
         return ret;
     }
@@ -246,7 +203,7 @@ static int ecjpake_hash(const mbedtls_md_type_t md_type,
     unsigned char *p = buf;
     const unsigned char *end = buf + sizeof(buf);
     const size_t id_len = strlen(id);
-    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 
     /* Write things to temporary buffer */
     MBEDTLS_MPI_CHK(ecjpake_write_len_point(&p, end, grp, pf, G));
@@ -269,11 +226,11 @@ static int ecjpake_hash(const mbedtls_md_type_t md_type,
 
     /* Compute hash */
     MBEDTLS_MPI_CHK(mbedtls_ecjpake_compute_hash(md_type,
-                                                 buf, p - buf, hash));
+                                                 buf, (size_t) (p - buf), hash));
 
     /* Turn it into an integer mod n */
     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(h, hash,
-                                            mbedtls_hash_info_get_size(md_type)));
+                                            mbedtls_md_get_size_from_type(md_type)));
     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(h, h, &grp->N));
 
 cleanup:
@@ -312,7 +269,7 @@ static int ecjpake_zkp_read(const mbedtls_md_type_t md_type,
         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, end - *p));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, &V, p, (size_t) (end - *p)));
 
     if (end < *p || (size_t) (end - *p) < 1) {
         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
@@ -389,7 +346,7 @@ static int ecjpake_zkp_write(const mbedtls_md_type_t md_type,
 
     /* Write it out */
     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, &V,
-                                                pf, &len, *p, end - *p));
+                                                pf, &len, *p, (size_t) (end - *p)));
     *p += len;
 
     len = mbedtls_mpi_size(&h);   /* actually r */
@@ -435,7 +392,7 @@ static int ecjpake_kkp_read(const mbedtls_md_type_t md_type,
      *     ECSchnorrZKP zkp;
      * } ECJPAKEKeyKP;
      */
-    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, end - *p));
+    MBEDTLS_MPI_CHK(mbedtls_ecp_tls_read_point(grp, X, p, (size_t) (end - *p)));
     if (mbedtls_ecp_is_zero(X)) {
         ret = MBEDTLS_ERR_ECP_INVALID_KEY;
         goto cleanup;
@@ -474,7 +431,7 @@ static int ecjpake_kkp_write(const mbedtls_md_type_t md_type,
     MBEDTLS_MPI_CHK(mbedtls_ecp_gen_keypair_base((mbedtls_ecp_group *) grp, G, x, X,
                                                  f_rng, p_rng));
     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(grp, X,
-                                                pf, &len, *p, end - *p));
+                                                pf, &len, *p, (size_t) (end - *p)));
     *p += len;
 
     /* Generate and write proof */
@@ -547,7 +504,7 @@ static int ecjpake_kkpp_write(const mbedtls_md_type_t md_type,
     MBEDTLS_MPI_CHK(ecjpake_kkp_write(md_type, grp, pf, G, xm2, Xb, id,
                                       &p, end, f_rng, p_rng));
 
-    *olen = p - buf;
+    *olen = (size_t) (p - buf);
 
 cleanup:
     return ret;
@@ -736,7 +693,7 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
             goto cleanup;
         }
         MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_group(&ctx->grp, &ec_len,
-                                                    p, end - p));
+                                                    p, (size_t) (end - p)));
         p += ec_len;
     }
 
@@ -745,7 +702,7 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
         goto cleanup;
     }
     MBEDTLS_MPI_CHK(mbedtls_ecp_tls_write_point(&ctx->grp, &Xm,
-                                                ctx->point_format, &ec_len, p, end - p));
+                                                ctx->point_format, &ec_len, p, (size_t) (end - p)));
     p += ec_len;
 
     MBEDTLS_MPI_CHK(ecjpake_zkp_write(ctx->md_type, &ctx->grp,
@@ -753,7 +710,7 @@ int mbedtls_ecjpake_write_round_two(mbedtls_ecjpake_context *ctx,
                                       &G, &xm, &Xm, ID_MINE,
                                       &p, end, f_rng, p_rng));
 
-    *olen = p - buf;
+    *olen = (size_t) (p - buf);
 
 cleanup:
     mbedtls_ecp_point_free(&G);
@@ -809,7 +766,7 @@ int mbedtls_ecjpake_derive_secret(mbedtls_ecjpake_context *ctx,
     unsigned char kx[MBEDTLS_ECP_MAX_BYTES];
     size_t x_bytes;
 
-    *olen = mbedtls_hash_info_get_size(ctx->md_type);
+    *olen = mbedtls_md_get_size_from_type(ctx->md_type);
     if (len < *olen) {
         return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
     }
@@ -870,7 +827,7 @@ cleanup:
 #include "mbedtls/platform.h"
 
 #if !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \
-    !defined(MBEDTLS_SHA256_C)
+    !defined(MBEDTLS_MD_CAN_SHA256)
 int mbedtls_ecjpake_self_test(int verbose)
 {
     (void) verbose;
@@ -1162,7 +1119,7 @@ int mbedtls_ecjpake_self_test(int verbose)
 #if !defined(MBEDTLS_ECJPAKE_ALT)
     /* 'reference handshake' tests can only be run against implementations
      * for which we have 100% control over how the random ephemeral keys
-     * are generated. This is only the case for the internal mbed TLS
+     * are generated. This is only the case for the internal Mbed TLS
      * implementation, so these tests are skipped in case the internal
      * implementation is swapped out for an alternative one. */
     if (verbose != 0) {
@@ -1252,7 +1209,7 @@ cleanup:
 
 #undef TEST_ASSERT
 
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_SHA256_C */
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_MD_CAN_SHA256 */
 
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/ecp.c b/lib/libmbedtls/mbedtls/library/ecp.c
index 607d753f3417ae297683cea4d2795701a8e5e2db..ab50a476bd2345f04b7e688abdfce186ca2aa583 100644
--- a/lib/libmbedtls/mbedtls/library/ecp.c
+++ b/lib/libmbedtls/mbedtls/library/ecp.c
@@ -2,31 +2,21 @@
  *  Elliptic curves over GF(p): generic functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
  * References:
  *
- * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
+ * SEC1 https://www.secg.org/sec1-v2.pdf
  * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone
  * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf
  * RFC 4492 for the related TLS structures and constants
+ * - https://www.rfc-editor.org/rfc/rfc4492
  * RFC 7748 for the Curve448 and Curve25519 curve definitions
+ * - https://www.rfc-editor.org/rfc/rfc7748
  *
- * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf
+ * [Curve25519] https://cr.yp.to/ecdh/curve25519-20060209.pdf
  *
  * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis
  *     for elliptic curve cryptosystems. In : Cryptographic Hardware and
@@ -70,7 +60,7 @@
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
 #endif
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_ECP_LIGHT)
 
 #include "mbedtls/ecp.h"
 #include "mbedtls/threading.h"
@@ -93,7 +83,10 @@
  * Counts of point addition and doubling, and field multiplications.
  * Used to test resistance of point multiplication to simple timing attacks.
  */
-static unsigned long add_count, dbl_count, mul_count;
+#if defined(MBEDTLS_ECP_C)
+static unsigned long add_count, dbl_count;
+#endif /* MBEDTLS_ECP_C */
+static unsigned long mul_count;
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
@@ -320,6 +313,7 @@ int mbedtls_ecp_check_budget(const mbedtls_ecp_group *grp,
 
 #endif /* MBEDTLS_ECP_RESTARTABLE */
 
+#if defined(MBEDTLS_ECP_C)
 static void mpi_init_many(mbedtls_mpi *arr, size_t size)
 {
     while (size--) {
@@ -333,6 +327,7 @@ static void mpi_free_many(mbedtls_mpi *arr, size_t size)
         mbedtls_mpi_free(arr++);
     }
 }
+#endif /* MBEDTLS_ECP_C */
 
 /*
  * List of supported curves:
@@ -589,6 +584,11 @@ void mbedtls_ecp_group_free(mbedtls_ecp_group *grp)
         mbedtls_mpi_free(&grp->A);
         mbedtls_mpi_free(&grp->B);
         mbedtls_ecp_point_free(&grp->G);
+
+#if !defined(MBEDTLS_ECP_WITH_MPI_UINT)
+        mbedtls_mpi_free(&grp->N);
+        mbedtls_mpi_free(&grp->P);
+#endif
     }
 
     if (!ecp_group_is_static_comb_table(grp) && grp->T != NULL) {
@@ -950,9 +950,8 @@ int mbedtls_ecp_tls_read_group_id(mbedtls_ecp_group_id *grp,
     /*
      * Next two bytes are the namedcurve value
      */
-    tls_id = *(*buf)++;
-    tls_id <<= 8;
-    tls_id |= *(*buf)++;
+    tls_id = MBEDTLS_GET_UINT16_BE(*buf, 0);
+    *buf += 2;
 
     if ((curve_info = mbedtls_ecp_curve_info_from_tls_id(tls_id)) == NULL) {
         return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
@@ -1079,13 +1078,7 @@ cleanup:
         MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi((N), (N), &grp->P));      \
     } while (0)
 
-#if (defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
-    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
-    defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
-    defined(MBEDTLS_ECP_ADD_MIXED_ALT))) || \
-    (defined(MBEDTLS_ECP_MONTGOMERY_ENABLED) && \
-    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
-    defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)))
+MBEDTLS_MAYBE_UNUSED
 static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp,
                                       mbedtls_mpi *X,
                                       const mbedtls_mpi *A,
@@ -1097,7 +1090,6 @@ static inline int mbedtls_mpi_sub_mod(const mbedtls_ecp_group *grp,
 cleanup:
     return ret;
 }
-#endif /* All functions referencing mbedtls_mpi_sub_mod() are alt-implemented without fallback */
 
 /*
  * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int.
@@ -1120,6 +1112,7 @@ cleanup:
     return ret;
 }
 
+MBEDTLS_MAYBE_UNUSED
 static inline int mbedtls_mpi_mul_int_mod(const mbedtls_ecp_group *grp,
                                           mbedtls_mpi *X,
                                           const mbedtls_mpi *A,
@@ -1133,6 +1126,7 @@ cleanup:
     return ret;
 }
 
+MBEDTLS_MAYBE_UNUSED
 static inline int mbedtls_mpi_sub_int_mod(const mbedtls_ecp_group *grp,
                                           mbedtls_mpi *X,
                                           const mbedtls_mpi *A,
@@ -1149,10 +1143,7 @@ cleanup:
 #define MPI_ECP_SUB_INT(X, A, c)             \
     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int_mod(grp, X, A, c))
 
-#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED) && \
-    !(defined(MBEDTLS_ECP_NO_FALLBACK) && \
-    defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && \
-    defined(MBEDTLS_ECP_ADD_MIXED_ALT))
+MBEDTLS_MAYBE_UNUSED
 static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp,
                                           mbedtls_mpi *X,
                                           size_t count)
@@ -1163,8 +1154,6 @@ static inline int mbedtls_mpi_shift_l_mod(const mbedtls_ecp_group *grp,
 cleanup:
     return ret;
 }
-#endif \
-    /* All functions referencing mbedtls_mpi_shift_l_mod() are alt-implemented without fallback */
 
 /*
  * Macro wrappers around ECP modular arithmetic
@@ -1247,7 +1236,7 @@ static int ecp_sw_rhs(const mbedtls_ecp_group *grp,
     MPI_ECP_SQR(rhs, X);
 
     /* Special case for A = -3 */
-    if (grp->A.p == NULL) {
+    if (mbedtls_ecp_group_a_is_minus_3(grp)) {
         MPI_ECP_SUB_INT(rhs, rhs, 3);
     } else {
         MPI_ECP_ADD(rhs, rhs, &grp->A);
@@ -1310,7 +1299,10 @@ cleanup:
     mbedtls_mpi_free(&exp);
     return ret;
 }
+#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
+#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
  * For curves in short Weierstrass form, we do all the internal operations in
  * Jacobian coordinates.
@@ -1515,7 +1507,7 @@ static int ecp_double_jac(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /* Special case for A = -3 */
-    if (grp->A.p == NULL) {
+    if (mbedtls_ecp_group_a_is_minus_3(grp)) {
         /* tmp[0] <- M = 3(X + Z^2)(X - Z^2) */
         MPI_ECP_SQR(&tmp[1],  &P->Z);
         MPI_ECP_ADD(&tmp[2],  &P->X,  &tmp[1]);
@@ -2727,6 +2719,7 @@ int mbedtls_ecp_mul(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
 {
     return mbedtls_ecp_mul_restartable(grp, R, m, P, f_rng, p_rng, NULL);
 }
+#endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
@@ -2767,6 +2760,7 @@ cleanup:
 }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
 
+#if defined(MBEDTLS_ECP_C)
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
 /*
  * R = m * P with shortcuts for m == 0, m == 1 and m == -1
@@ -2918,12 +2912,13 @@ int mbedtls_ecp_muladd(mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
     return mbedtls_ecp_muladd_restartable(grp, R, m, P, n, Q, NULL);
 }
 #endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
+#endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-#define ECP_MPI_INIT(s, n, p) {s, (n), (mbedtls_mpi_uint *)(p), 0}
+#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n), .use_mempool = 0 }
 #define ECP_MPI_INIT_ARRAY(x)   \
-    ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
+    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))
 /*
  * Constants for the two points other than 0, 1, -1 (mod p) in
  * https://cr.yp.to/ecdh.html#validate
@@ -3163,6 +3158,7 @@ int mbedtls_ecp_gen_privkey(const mbedtls_ecp_group *grp,
     return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
 }
 
+#if defined(MBEDTLS_ECP_C)
 /*
  * Generate a keypair with configurable base point
  */
@@ -3204,6 +3200,26 @@ int mbedtls_ecp_gen_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
 
     return mbedtls_ecp_gen_keypair(&key->grp, &key->d, &key->Q, f_rng, p_rng);
 }
+#endif /* MBEDTLS_ECP_C */
+
+int mbedtls_ecp_set_public_key(mbedtls_ecp_group_id grp_id,
+                               mbedtls_ecp_keypair *key,
+                               const mbedtls_ecp_point *Q)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (key->grp.id == MBEDTLS_ECP_DP_NONE) {
+        /* Group not set yet */
+        if ((ret = mbedtls_ecp_group_load(&key->grp, grp_id)) != 0) {
+            return ret;
+        }
+    } else if (key->grp.id != grp_id) {
+        /* Group mismatch */
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+    return mbedtls_ecp_copy(&key->Q, Q);
+}
+
 
 #define ECP_CURVE25519_KEY_SIZE 32
 #define ECP_CURVE448_KEY_SIZE   56
@@ -3267,16 +3283,17 @@ int mbedtls_ecp_read_key(mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key,
                 );
         }
     }
-
 #endif
 #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
     if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
         MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&key->d, buf, buflen));
+    }
+#endif
 
+    if (ret == 0) {
         MBEDTLS_MPI_CHK(mbedtls_ecp_check_privkey(&key->grp, &key->d));
     }
 
-#endif
 cleanup:
 
     if (ret != 0) {
@@ -3289,10 +3306,11 @@ cleanup:
 /*
  * Write a private key.
  */
+#if !defined MBEDTLS_DEPRECATED_REMOVED
 int mbedtls_ecp_write_key(mbedtls_ecp_keypair *key,
                           unsigned char *buf, size_t buflen)
 {
-    int ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
     if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
@@ -3319,8 +3337,53 @@ cleanup:
 
     return ret;
 }
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+
+int mbedtls_ecp_write_key_ext(const mbedtls_ecp_keypair *key,
+                              size_t *olen, unsigned char *buf, size_t buflen)
+{
+    size_t len = (key->grp.nbits + 7) / 8;
+    if (len > buflen) {
+        /* For robustness, ensure *olen <= buflen even on error. */
+        *olen = 0;
+        return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+    }
+    *olen = len;
+
+    /* Private key not set */
+    if (key->d.n == 0) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+#if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
+        return mbedtls_mpi_write_binary_le(&key->d, buf, len);
+    }
+#endif
+
+#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
+    if (mbedtls_ecp_get_type(&key->grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
+        return mbedtls_mpi_write_binary(&key->d, buf, len);
+    }
+#endif
+
+    /* Private key set but no recognized curve type? This shouldn't happen. */
+    return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+}
+
+/*
+ * Write a public key.
+ */
+int mbedtls_ecp_write_public_key(const mbedtls_ecp_keypair *key,
+                                 int format, size_t *olen,
+                                 unsigned char *buf, size_t buflen)
+{
+    return mbedtls_ecp_point_write_binary(&key->grp, &key->Q,
+                                          format, olen, buf, buflen);
+}
 
 
+#if defined(MBEDTLS_ECP_C)
 /*
  * Check a public-private key pair
  */
@@ -3362,6 +3425,21 @@ cleanup:
     return ret;
 }
 
+int mbedtls_ecp_keypair_calc_public(mbedtls_ecp_keypair *key,
+                                    int (*f_rng)(void *, unsigned char *, size_t),
+                                    void *p_rng)
+{
+    return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G,
+                           f_rng, p_rng);
+}
+#endif /* MBEDTLS_ECP_C */
+
+mbedtls_ecp_group_id mbedtls_ecp_keypair_get_group_id(
+    const mbedtls_ecp_keypair *key)
+{
+    return key->grp.id;
+}
+
 /*
  * Export generic key-pair parameters.
  */
@@ -3370,15 +3448,15 @@ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if ((ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) {
+    if (grp != NULL && (ret = mbedtls_ecp_group_copy(grp, &key->grp)) != 0) {
         return ret;
     }
 
-    if ((ret = mbedtls_mpi_copy(d, &key->d)) != 0) {
+    if (d != NULL && (ret = mbedtls_mpi_copy(d, &key->d)) != 0) {
         return ret;
     }
 
-    if ((ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) {
+    if (Q != NULL && (ret = mbedtls_ecp_copy(Q, &key->Q)) != 0) {
         return ret;
     }
 
@@ -3387,6 +3465,7 @@ int mbedtls_ecp_export(const mbedtls_ecp_keypair *key, mbedtls_ecp_group *grp,
 
 #if defined(MBEDTLS_SELF_TEST)
 
+#if defined(MBEDTLS_ECP_C)
 /*
  * PRNG for test - !!!INSECURE NEVER USE IN PRODUCTION!!!
  *
@@ -3494,12 +3573,14 @@ cleanup:
     }
     return ret;
 }
+#endif /* MBEDTLS_ECP_C */
 
 /*
  * Checkup routine
  */
 int mbedtls_ecp_self_test(int verbose)
 {
+#if defined(MBEDTLS_ECP_C)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group grp;
     mbedtls_ecp_point R, P;
@@ -3613,10 +3694,14 @@ cleanup:
     }
 
     return ret;
+#else /* MBEDTLS_ECP_C */
+    (void) verbose;
+    return 0;
+#endif /* MBEDTLS_ECP_C */
 }
 
 #endif /* MBEDTLS_SELF_TEST */
 
 #endif /* !MBEDTLS_ECP_ALT */
 
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_ECP_LIGHT */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_curves.c b/lib/libmbedtls/mbedtls/library/ecp_curves.c
index f9b452bb82be6d6e164162b2c8cf530ae1759887..b6287ac06b9a09194e2316d7ee4073c21fee6f14 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_curves.c
+++ b/lib/libmbedtls/mbedtls/library/ecp_curves.c
@@ -2,24 +2,14 @@
  *  Elliptic curves over GF(p): curve-specific data and functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
-#if defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_ECP_WITH_MPI_UINT)
+
+#if defined(MBEDTLS_ECP_LIGHT)
 
 #include "mbedtls/ecp.h"
 #include "mbedtls/platform_util.h"
@@ -33,21 +23,15 @@
 
 #if !defined(MBEDTLS_ECP_ALT)
 
-/* Parameter validation macros based on platform_util.h */
-#define ECP_VALIDATE_RET(cond)    \
-    MBEDTLS_INTERNAL_VALIDATE_RET(cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA)
-#define ECP_VALIDATE(cond)        \
-    MBEDTLS_INTERNAL_VALIDATE(cond)
-
-#define ECP_MPI_INIT(s, n, p) { s, (n), (mbedtls_mpi_uint *) (p) }
+#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }
 
 #define ECP_MPI_INIT_ARRAY(x)   \
-    ECP_MPI_INIT(1, sizeof(x) / sizeof(mbedtls_mpi_uint), x)
+    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))
 
 #define ECP_POINT_INIT_XY_Z0(x, y) { \
-        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 0, NULL) }
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) }
 #define ECP_POINT_INIT_XY_Z1(x, y) { \
-        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(1, 1, mpi_one) }
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) }
 
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
@@ -62,7 +46,7 @@
     defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
 /* For these curves, we build the group parameters dynamically. */
 #define ECP_LOAD_GROUP
-static mbedtls_mpi_uint mpi_one[] = { 1 };
+static const mbedtls_mpi_uint mpi_one[] = { 1 };
 #endif
 
 /*
@@ -4502,9 +4486,7 @@ static const mbedtls_ecp_point brainpoolP512r1_T[32] = {
 #endif
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
 
-
-#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
-    defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+#if defined(ECP_LOAD_GROUP)
 /*
  * Domain parameters for SM2 (GM/T 0003 Part 5)
  */
@@ -4554,12 +4536,10 @@ static const mbedtls_mpi_uint sm2_n[] = {
 static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len)
 {
     X->s = 1;
-    X->n = len / sizeof(mbedtls_mpi_uint);
+    X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint));
     X->p = (mbedtls_mpi_uint *) p;
 }
-#endif
 
-#if defined(ECP_LOAD_GROUP)
 /*
  * Set an MPI to static value 1
  */
@@ -4567,7 +4547,7 @@ static inline void ecp_mpi_set1(mbedtls_mpi *X)
 {
     X->s = 1;
     X->n = 1;
-    X->p = mpi_one;
+    X->p = (mbedtls_mpi_uint *) mpi_one; /* X->p will not be modified so the cast is safe */
 }
 
 /*
@@ -4612,26 +4592,18 @@ static int ecp_group_load(mbedtls_ecp_group *grp,
 /* Forward declarations */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
 static int ecp_mod_p192(mbedtls_mpi *);
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
 static int ecp_mod_p224(mbedtls_mpi *);
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
 static int ecp_mod_p256(mbedtls_mpi *);
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 static int ecp_mod_p384(mbedtls_mpi *);
 #endif
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
 static int ecp_mod_p521(mbedtls_mpi *);
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n);
 #endif
 
 #define NIST_MODP(P)      grp->modp = ecp_mod_ ## P;
@@ -4681,21 +4653,9 @@ static int ecp_mod_p256k1(mbedtls_mpi *);
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
 /* Constants used by ecp_use_curve25519() */
 static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;
-
-/* P = 2^255 - 19 */
-static const mbedtls_mpi_uint curve25519_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F)
-};
-
-/* N = 2^252 + 27742317777372353535851937790883648493 */
-static const mbedtls_mpi_uint curve25519_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14),
-    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00),
-    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10)
+static const unsigned char curve25519_part_of_n[] = {
+    0x14, 0xDE, 0xF9, 0xDE, 0xA2, 0xF7, 0x9C, 0xD6,
+    0x58, 0x12, 0x63, 0x1A, 0x5C, 0xF5, 0xD3, 0xED,
 };
 
 /*
@@ -4708,11 +4668,16 @@ static int ecp_use_curve25519(mbedtls_ecp_group *grp)
     /* Actually ( A + 2 ) / 4 */
     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24));
 
-    ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p));
-
+    /* P = 2^255 - 19 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 255));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 19));
     grp->pbits = mbedtls_mpi_bitlen(&grp->P);
 
-    ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n));
+    /* N = 2^252 + 27742317777372353535851937790883648493 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&grp->N,
+                                            curve25519_part_of_n, sizeof(curve25519_part_of_n)));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 252, 1));
 
     /* Y intentionally not set, since we use x/z coordinates.
      * This is used as a marker to identify Montgomery curves! */
@@ -4735,29 +4700,11 @@ cleanup:
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
 /* Constants used by ecp_use_curve448() */
 static const mbedtls_mpi_sint curve448_a24 = 0x98AA;
-
-/* P = 2^448 - 2^224 - 1 */
-static const mbedtls_mpi_uint curve448_p[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
-};
-
-/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
-static const mbedtls_mpi_uint curve448_n[] = {
-    MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23),
-    MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21),
-    MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
-    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F),
-    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
+static const unsigned char curve448_part_of_n[] = {
+    0x83, 0x35, 0xDC, 0x16, 0x3B, 0xB1, 0x24,
+    0xB6, 0x51, 0x29, 0xC9, 0x6F, 0xDE, 0x93,
+    0x3D, 0x8D, 0x72, 0x3A, 0x70, 0xAA, 0xDC,
+    0x87, 0x3D, 0x6D, 0x54, 0xA7, 0xBB, 0x0D,
 };
 
 /*
@@ -4765,12 +4712,20 @@ static const mbedtls_mpi_uint curve448_n[] = {
  */
 static int ecp_use_curve448(mbedtls_ecp_group *grp)
 {
+    mbedtls_mpi Ns;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
+    mbedtls_mpi_init(&Ns);
+
     /* Actually ( A + 2 ) / 4 */
     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24));
 
-    ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p));
+    /* P = 2^448 - 2^224 - 1 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_l(&grp->P, 224));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&grp->P, &grp->P, 1));
     grp->pbits = mbedtls_mpi_bitlen(&grp->P);
 
     /* Y intentionally not set, since we use x/z coordinates.
@@ -4779,12 +4734,17 @@ static int ecp_use_curve448(mbedtls_ecp_group *grp)
     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));
     mbedtls_mpi_free(&grp->G.Y);
 
-    ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n));
+    /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&grp->N, 446, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&Ns,
+                                            curve448_part_of_n, sizeof(curve448_part_of_n)));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&grp->N, &grp->N, &Ns));
 
     /* Actually, the required msb for private keys */
     grp->nbits = 447;
 
 cleanup:
+    mbedtls_mpi_free(&Ns);
     if (ret != 0) {
         mbedtls_ecp_group_free(grp);
     }
@@ -4798,7 +4758,6 @@ cleanup:
  */
 int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)
 {
-    ECP_VALIDATE_RET(grp != NULL);
     mbedtls_ecp_group_free(grp);
 
     mbedtls_ecp_group_init(grp);
@@ -4939,12 +4898,10 @@ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)
 }
 
 #define WIDTH       8 / sizeof(mbedtls_mpi_uint)
-#define A(i)        Np + (i) * WIDTH
-#define ADD(i)      add64(p, A(i), &c)
+#define A(i)      N->p + (i) * WIDTH
+#define ADD(i)    add64(p, A(i), &c)
 #define NEXT        p += WIDTH; carry64(p, &c)
 #define LAST        p += WIDTH; *p = c; while (++p < end) *p = 0
-#define RESET       last_carry[0] = c; c = 0; p = Np
-#define ADD_LAST    add64(p, last_carry, &c)
 
 /*
  * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
@@ -4952,42 +4909,21 @@ static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)
 static int ecp_mod_p192(mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t expected_width = 2 * ((192 + biL - 1) / biL);
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
-    ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width);
-
-cleanup:
-    return ret;
-}
-
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn)
-{
-    mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 };
+    mbedtls_mpi_uint c = 0;
     mbedtls_mpi_uint *p, *end;
 
-    if (Nn != 2*((192 + biL - 1)/biL)) {
-        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    }
-
-    p = Np;
-    end = p + Nn;
-
-    ADD(3); ADD(5);         NEXT;   // A0 += A3 + A5
-    ADD(3); ADD(4); ADD(5); NEXT;   // A1 += A3 + A4 + A5
-    ADD(4); ADD(5);                 // A2 += A4 + A5
+    /* Make sure we have enough blocks so that A(5) is legal */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, 6 * WIDTH));
 
-    RESET;
-
-    /* Use the reduction for the carry as well:
-     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192
-     */
-    ADD_LAST; NEXT;                 // A0 += last_carry
-    ADD_LAST; NEXT;                 // A1 += last_carry
+    p = N->p;
+    end = p + N->n;
 
-    LAST;                           // A2 += carry
+    ADD(3); ADD(5);             NEXT;     // A0 += A3 + A5
+    ADD(3); ADD(4); ADD(5);   NEXT;       // A1 += A3 + A4 + A5
+    ADD(4); ADD(5);             LAST;     // A2 += A4 + A5
 
-    return 0;
+cleanup:
+    return ret;
 }
 
 #undef WIDTH
@@ -4995,260 +4931,11 @@ int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn)
 #undef ADD
 #undef NEXT
 #undef LAST
-#undef RESET
-#undef ADD_LAST
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
     defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-
-/*
- * The reader is advised to first understand ecp_mod_p192() since the same
- * general structure is used here, but with additional complications:
- * (1) chunks of 32 bits, and (2) subtractions.
- */
-
-/*
- * For these primes, we need to handle data in chunks of 32 bits.
- * This makes it more complicated if we use 64 bits limbs in MPI,
- * which prevents us from using a uniform access method as for p192.
- *
- * So, we define a mini abstraction layer to access 32 bit chunks,
- * load them in 'cur' for work, and store them back from 'cur' when done.
- *
- * While at it, also define the size of N in terms of 32-bit chunks.
- */
-#define LOAD32      cur = A(i);
-
-#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
-
-#define MAX32       X_limbs
-#define A(j)        X[j]
-#define STORE32     X[i] = (mbedtls_mpi_uint) cur;
-#define STORE0      X[i] = 0;
-
-#else /* 64 bit */
-
-#define MAX32   X_limbs * 2
-#define A(j)                                                \
-    (j) % 2 ?                                               \
-    (uint32_t) (X[(j) / 2] >> 32) :                         \
-    (uint32_t) (X[(j) / 2])
-#define STORE32                                             \
-    if (i % 2) {                                            \
-        X[i/2] &= 0x00000000FFFFFFFF;                       \
-        X[i/2] |= (uint64_t) (cur) << 32;                   \
-    } else {                                                \
-        X[i/2] &= 0xFFFFFFFF00000000;                       \
-        X[i/2] |= (uint32_t) cur;                           \
-    }
-
-#define STORE0                                              \
-    if (i % 2) {                                            \
-        X[i/2] &= 0x00000000FFFFFFFF;                       \
-    } else {                                                \
-        X[i/2] &= 0xFFFFFFFF00000000;                       \
-    }
-
-#endif
-
-static inline int8_t extract_carry(int64_t cur)
-{
-    return (int8_t) (cur >> 32);
-}
-
-#define ADD(j)    cur += A(j)
-#define SUB(j)    cur -= A(j)
-
-#define ADD_CARRY(cc) cur += (cc)
-#define SUB_CARRY(cc) cur -= (cc)
-
-#define ADD_LAST ADD_CARRY(last_c)
-#define SUB_LAST SUB_CARRY(last_c)
-
-/*
- * Helpers for the main 'loop'
- */
-#define INIT(b)                                         \
-    int8_t c = 0, last_c;                               \
-    int64_t cur;                                        \
-    size_t i = 0;                                       \
-    LOAD32;
-
-#define NEXT                                            \
-    c = extract_carry(cur);                             \
-    STORE32; i++; LOAD32;                               \
-    ADD_CARRY(c);
-
-#define RESET                                           \
-    c = extract_carry(cur);                             \
-    last_c = c;                                         \
-    STORE32; i = 0; LOAD32;                             \
-    c = 0;                                              \
-
-#define LAST                                            \
-    c = extract_carry(cur);                             \
-    STORE32; i++;                                       \
-    if (c != 0)                                         \
-    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \
-    while (i < MAX32) { STORE0; i++; }
-
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-
-/*
- * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
- */
-static int ecp_mod_p224(mbedtls_mpi *N)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t expected_width =  2 * 224 / biL;
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
-    ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width);
-cleanup:
-    return ret;
-}
-
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs)
-{
-    if (X_limbs != 2 * 224 / biL) {
-        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    }
-
-    INIT(224);
-
-    SUB(7);  SUB(11);           NEXT;   // A0 += -A7  - A11
-    SUB(8);  SUB(12);           NEXT;   // A1 += -A8  - A12
-    SUB(9);  SUB(13);           NEXT;   // A2 += -A9  - A13
-    SUB(10); ADD(7);  ADD(11);  NEXT;   // A3 += -A10 + A7 + A11
-    SUB(11); ADD(8);  ADD(12);  NEXT;   // A4 += -A11 + A8 + A12
-    SUB(12); ADD(9);  ADD(13);  NEXT;   // A5 += -A12 + A9 + A13
-    SUB(13); ADD(10);                   // A6 += -A13 + A10
-
-    RESET;
-
-    /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */
-    SUB_LAST; NEXT;                     // A0 -= last_c
-    ;         NEXT;                     // A1
-    ;         NEXT;                     // A2
-    ADD_LAST; NEXT;                     // A3 += last_c
-    ;         NEXT;                     // A4
-    ;         NEXT;                     // A5
-                                        // A6
-
-    /* The carry reduction cannot generate a carry
-     * (see commit 73e8553 for details)*/
-
-    LAST;
-
-    return 0;
-}
-
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-
-/*
- * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
- */
-static int ecp_mod_p256(mbedtls_mpi *N)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t expected_width = 2 * 256 / biL;
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
-    ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width);
-cleanup:
-    return ret;
-}
-
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs)
-{
-    if (X_limbs != 2 * 256 / biL) {
-        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    }
-
-    INIT(256);
-
-    ADD(8);  ADD(9);
-    SUB(11); SUB(12); SUB(13); SUB(14);                   NEXT; // A0
-
-    ADD(9);  ADD(10);
-    SUB(12); SUB(13); SUB(14); SUB(15);                   NEXT; // A1
-
-    ADD(10); ADD(11);
-    SUB(13); SUB(14); SUB(15);                            NEXT; // A2
-
-    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);
-    SUB(15); SUB(8);  SUB(9);                             NEXT; // A3
-
-    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);
-    SUB(9);  SUB(10);                                     NEXT; // A4
-
-    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);
-    SUB(10); SUB(11);                                     NEXT; // A5
-
-    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);
-    SUB(8);  SUB(9);                                      NEXT; // A6
-
-    ADD(15); ADD(15); ADD(15); ADD(8);
-    SUB(10); SUB(11); SUB(12); SUB(13);                         // A7
-
-    RESET;
-
-    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
-     * to modulo reduce the final carry. */
-    ADD_LAST; NEXT;                                             // A0
-    ;         NEXT;                                             // A1
-    ;         NEXT;                                             // A2
-    SUB_LAST; NEXT;                                             // A3
-    ;         NEXT;                                             // A4
-    ;         NEXT;                                             // A5
-    SUB_LAST; NEXT;                                             // A6
-    ADD_LAST;                                                   // A7
-
-    RESET;
-
-    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
-     * to modulo reduce the carry generated by the previous reduction. */
-    ADD_LAST; NEXT;                                             // A0
-    ;         NEXT;                                             // A1
-    ;         NEXT;                                             // A2
-    SUB_LAST; NEXT;                                             // A3
-    ;         NEXT;                                             // A4
-    ;         NEXT;                                             // A5
-    SUB_LAST; NEXT;                                             // A6
-    ADD_LAST;                                                   // A7
-
-    LAST;
-
-    return 0;
-}
-
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-
-#undef LOAD32
-#undef MAX32
-#undef A
-#undef STORE32
-#undef STORE0
-#undef ADD
-#undef SUB
-#undef ADD_CARRY
-#undef SUB_CARRY
-#undef ADD_LAST
-#undef SUB_LAST
-#undef INIT
-#undef NEXT
-#undef RESET
-#undef LAST
-
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
-          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /*
  * The reader is advised to first understand ecp_mod_p192() since the same
  * general structure is used here, but with additional complications:
@@ -5338,8 +5025,7 @@ static inline void sub32(uint32_t *dst, uint32_t src, signed char *carry)
  * If the result is negative, we get it in the form
  * c * 2^bits + N, with c negative and N positive shorter than 'bits'
  */
-MBEDTLS_STATIC_TESTABLE
-void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits)
+static void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits)
 {
     size_t i;
 
@@ -5369,6 +5055,64 @@ void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits)
     N->p[bits / 8 / sizeof(mbedtls_mpi_uint)] += msw;
 }
 
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224(mbedtls_mpi *N)
+{
+    INIT(224);
+
+    SUB(7); SUB(11);               NEXT;      // A0 += -A7 - A11
+    SUB(8); SUB(12);               NEXT;      // A1 += -A8 - A12
+    SUB(9); SUB(13);               NEXT;      // A2 += -A9 - A13
+    SUB(10); ADD(7); ADD(11);    NEXT;        // A3 += -A10 + A7 + A11
+    SUB(11); ADD(8); ADD(12);    NEXT;        // A4 += -A11 + A8 + A12
+    SUB(12); ADD(9); ADD(13);    NEXT;        // A5 += -A12 + A9 + A13
+    SUB(13); ADD(10);               LAST;     // A6 += -A13 + A10
+
+cleanup:
+    return ret;
+}
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256(mbedtls_mpi *N)
+{
+    INIT(256);
+
+    ADD(8); ADD(9);
+    SUB(11); SUB(12); SUB(13); SUB(14);             NEXT;         // A0
+
+    ADD(9); ADD(10);
+    SUB(12); SUB(13); SUB(14); SUB(15);             NEXT;         // A1
+
+    ADD(10); ADD(11);
+    SUB(13); SUB(14); SUB(15);                        NEXT;       // A2
+
+    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);
+    SUB(15); SUB(8); SUB(9);                        NEXT;         // A3
+
+    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);
+    SUB(9); SUB(10);                                   NEXT;      // A4
+
+    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);
+    SUB(10); SUB(11);                                   NEXT;     // A5
+
+    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);
+    SUB(8); SUB(9);                                   NEXT;       // A6
+
+    ADD(15); ADD(15); ADD(15); ADD(8);
+    SUB(10); SUB(11); SUB(12); SUB(13);             LAST;         // A7
+
+cleanup:
+    return ret;
+}
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
 /*
  * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
@@ -5426,10 +5170,16 @@ cleanup:
 #undef NEXT
 #undef LAST
 
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
           MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+/*
+ * Here we have an actual Mersenne prime, so things are more straightforward.
+ * However, chunks are aligned on a 'weird' boundary (521 bits).
+ */
+
 /* Size of p521 in terms of mbedtls_mpi_uint */
 #define P521_WIDTH      (521 / 8 / sizeof(mbedtls_mpi_uint) + 1)
 
@@ -5437,81 +5187,48 @@ cleanup:
 #define P521_MASK       0x01FF
 
 /*
- * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
+ * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5)
+ * Write N as A1 + 2^521 A0, return A0 + A1
  */
 static int ecp_mod_p521(mbedtls_mpi *N)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t expected_width = 2 * P521_WIDTH;
-    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
-    ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width);
-cleanup:
-    return ret;
-}
+    size_t i;
+    mbedtls_mpi M;
+    mbedtls_mpi_uint Mp[P521_WIDTH + 1];
+    /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits:
+     * we need to hold bits 513 to 1056, which is 34 limbs, that is
+     * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */
 
-MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs)
-{
-    mbedtls_mpi_uint carry = 0;
+    if (N->n < P521_WIDTH) {
+        return 0;
+    }
 
-    if (X_limbs != 2 * P521_WIDTH || X[2 * P521_WIDTH - 1] != 0) {
-        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    /* M = A1 */
+    M.s = 1;
+    M.n = N->n - (P521_WIDTH - 1);
+    if (M.n > P521_WIDTH + 1) {
+        M.n = P521_WIDTH + 1;
     }
+    M.p = Mp;
+    memcpy(Mp, N->p + P521_WIDTH - 1, M.n * sizeof(mbedtls_mpi_uint));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&M, 521 % (8 * sizeof(mbedtls_mpi_uint))));
 
-    /* Step 1: Reduction to P521_WIDTH limbs */
-    /* Helper references for bottom part of X */
-    mbedtls_mpi_uint *X0 = X;
-    size_t X0_limbs = P521_WIDTH;
-    /* Helper references for top part of X */
-    mbedtls_mpi_uint *X1 = X + X0_limbs;
-    size_t X1_limbs = X_limbs - X0_limbs;
-    /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1.
-     * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that
-     * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.)
-     * The high order limb of the result will be held in carry and the rest
-     * in X0 (that is the result will be represented as
-     * 2^P521_WIDTH carry + X0).
-     *
-     * Also, note that the resulting carry is either 0 or 1:
-     * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512
-     * therefore
-     * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9)
-     * which in turn is less than 2 * 2^(512 + biL).
-     */
-    mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9);
-    carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift);
-    /* Set X to X0 (by clearing the top part). */
-    memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint));
-
-    /* Step 2: Reduction modulo P521
-     *
-     * At this point X is reduced to P521_WIDTH limbs. What remains is to add
-     * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */
-
-    /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521.
-     * Also, recall that carry is either 0 or 1. */
-    mbedtls_mpi_uint addend = carry << (biL - 9);
-    /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */
-    addend += (X[P521_WIDTH - 1] >> 9);
-    X[P521_WIDTH - 1] &= P521_MASK;
-
-    /* Reuse the top part of X (already zeroed) as a helper array for
-     * carrying out the addition. */
-    mbedtls_mpi_uint *addend_arr = X + P521_WIDTH;
-    addend_arr[0] = addend;
-    (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH);
-    /* Both addends were less than P521 therefore X < 2 * P521. (This also means
-     * that the result fit in P521_WIDTH limbs and there won't be any carry.) */
-
-    /* Clear the reused part of X. */
-    addend_arr[0] = 0;
+    /* N = A0 */
+    N->p[P521_WIDTH - 1] &= P521_MASK;
+    for (i = P521_WIDTH; i < N->n; i++) {
+        N->p[i] = 0;
+    }
 
-    return 0;
+    /* N = A0 + A1 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_abs(N, N, &M));
+
+cleanup:
+    return ret;
 }
 
 #undef P521_WIDTH
 #undef P521_MASK
-
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
@@ -5559,8 +5276,9 @@ static int ecp_mod_p255(mbedtls_mpi *N)
 
 /* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */
 #define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y))
-#define P224_WIDTH_MIN   (28 / sizeof(mbedtls_mpi_uint))
-#define P224_WIDTH_MAX   DIV_ROUND_UP(28, sizeof(mbedtls_mpi_uint))
+#define P224_SIZE        (224 / 8)
+#define P224_WIDTH_MIN   (P224_SIZE / sizeof(mbedtls_mpi_uint))
+#define P224_WIDTH_MAX   DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint))
 #define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224)
 
 /*
@@ -5640,7 +5358,7 @@ cleanup:
  */
 #define P_KOBLITZ_MAX   (256 / 8 / sizeof(mbedtls_mpi_uint))      // Max limbs in P
 #define P_KOBLITZ_R     (8 / sizeof(mbedtls_mpi_uint))            // Limbs in R
-static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs,
+static inline int ecp_mod_koblitz(mbedtls_mpi *N, const mbedtls_mpi_uint *Rp, size_t p_limbs,
                                   size_t adjust, size_t shift, mbedtls_mpi_uint mask)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -5654,7 +5372,7 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p
 
     /* Init R */
     R.s = 1;
-    R.p = Rp;
+    R.p = (mbedtls_mpi_uint *) Rp; /* R.p will not be modified so the cast is safe */
     R.n = P_KOBLITZ_R;
 
     /* Common setup for M */
@@ -5662,9 +5380,9 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p
     M.p = Mp;
 
     /* M = A1 */
-    M.n = N->n - (p_limbs - adjust);
+    M.n = (unsigned short) (N->n - (p_limbs - adjust));
     if (M.n > p_limbs + adjust) {
-        M.n = p_limbs + adjust;
+        M.n = (unsigned short) (p_limbs + adjust);
     }
     memset(Mp, 0, sizeof(Mp));
     memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
@@ -5688,9 +5406,9 @@ static inline int ecp_mod_koblitz(mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p
     /* Second pass */
 
     /* M = A1 */
-    M.n = N->n - (p_limbs - adjust);
+    M.n = (unsigned short) (N->n - (p_limbs - adjust));
     if (M.n > p_limbs + adjust) {
-        M.n = p_limbs + adjust;
+        M.n = (unsigned short) (p_limbs + adjust);
     }
     memset(Mp, 0, sizeof(Mp));
     memcpy(Mp, N->p + p_limbs - adjust, M.n * sizeof(mbedtls_mpi_uint));
@@ -5721,11 +5439,11 @@ cleanup:
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
 /*
  * Fast quasi-reduction modulo p192k1 = 2^192 - R,
- * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9
  */
 static int ecp_mod_p192k1(mbedtls_mpi *N)
 {
-    static mbedtls_mpi_uint Rp[] = {
+    static const mbedtls_mpi_uint Rp[] = {
         MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00,
                                   0x00)
     };
@@ -5742,7 +5460,7 @@ static int ecp_mod_p192k1(mbedtls_mpi *N)
  */
 static int ecp_mod_p224k1(mbedtls_mpi *N)
 {
-    static mbedtls_mpi_uint Rp[] = {
+    static const mbedtls_mpi_uint Rp[] = {
         MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00,
                                   0x00)
     };
@@ -5764,7 +5482,7 @@ static int ecp_mod_p224k1(mbedtls_mpi *N)
  */
 static int ecp_mod_p256k1(mbedtls_mpi *N)
 {
-    static mbedtls_mpi_uint Rp[] = {
+    static const mbedtls_mpi_uint Rp[] = {
         MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00,
                                   0x00)
     };
@@ -5774,187 +5492,16 @@ static int ecp_mod_p256k1(mbedtls_mpi *N)
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 
 #if defined(MBEDTLS_TEST_HOOKS)
+
 MBEDTLS_STATIC_TESTABLE
-int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
-                              const mbedtls_ecp_group_id id,
-                              const mbedtls_ecp_curve_type ctype)
+mbedtls_ecp_variant mbedtls_ecp_get_variant(void)
 {
-    mbedtls_mpi_uint *p = NULL;
-    size_t p_limbs;
-
-    if (!(ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE || \
-          ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_SCALAR)) {
-        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    }
-
-    switch (id) {
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP192R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp192r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp192r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP224R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp224r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp224r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP256R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp256r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp256r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP384R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp384r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp384r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP521R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp521r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp521r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-        case MBEDTLS_ECP_DP_BP256R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) brainpoolP256r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) brainpoolP256r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-        case MBEDTLS_ECP_DP_BP384R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) brainpoolP384r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) brainpoolP384r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-        case MBEDTLS_ECP_DP_BP512R1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) brainpoolP512r1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) brainpoolP512r1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-        case MBEDTLS_ECP_DP_CURVE25519:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) curve25519_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));
-            } else {
-                p = (mbedtls_mpi_uint *) curve25519_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP192K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp192k1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp192k1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP224K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp224k1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp224k1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-        case MBEDTLS_ECP_DP_SECP256K1:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) secp256k1_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));
-            } else {
-                p = (mbedtls_mpi_uint *) secp256k1_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n));
-            }
-            break;
-#endif
-
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-        case MBEDTLS_ECP_DP_CURVE448:
-            if (ctype == (mbedtls_ecp_curve_type) MBEDTLS_ECP_MOD_COORDINATE) {
-                p = (mbedtls_mpi_uint *) curve448_p;
-                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));
-            } else {
-                p = (mbedtls_mpi_uint *) curve448_n;
-                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n));
-            }
-            break;
-#endif
-
-        default:
-        case MBEDTLS_ECP_DP_NONE:
-            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-    }
-
-    if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs,
-                                      MBEDTLS_MPI_MOD_REP_MONTGOMERY)) {
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    }
-    return 0;
+    return MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT;
 }
+
 #endif /* MBEDTLS_TEST_HOOKS */
+
 #endif /* !MBEDTLS_ECP_ALT */
-#endif /* MBEDTLS_ECP_C */
+
+#endif /* MBEDTLS_ECP_LIGHT */
+#endif /* MBEDTLS_ECP_WITH_MPI_UINT */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_curves_new.c b/lib/libmbedtls/mbedtls/library/ecp_curves_new.c
new file mode 100644
index 0000000000000000000000000000000000000000..035b23a1b41cc0a4d6ed68d2287743507829936d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ecp_curves_new.c
@@ -0,0 +1,6036 @@
+/*
+ *  Elliptic curves over GF(p): curve-specific data and functions
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_ECP_WITH_MPI_UINT)
+
+#if defined(MBEDTLS_ECP_LIGHT)
+
+#include "mbedtls/ecp.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+
+#include "mbedtls/platform.h"
+
+#include "constant_time_internal.h"
+
+#include "bn_mul.h"
+#include "bignum_core.h"
+#include "ecp_invasive.h"
+
+#include <string.h>
+
+#if !defined(MBEDTLS_ECP_ALT)
+
+#define ECP_MPI_INIT(_p, _n) { .p = (mbedtls_mpi_uint *) (_p), .s = 1, .n = (_n) }
+
+#define ECP_MPI_INIT_ARRAY(x)   \
+    ECP_MPI_INIT(x, sizeof(x) / sizeof(mbedtls_mpi_uint))
+
+#define ECP_POINT_INIT_XY_Z0(x, y) { \
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(NULL, 0) }
+#define ECP_POINT_INIT_XY_Z1(x, y) { \
+        ECP_MPI_INIT_ARRAY(x), ECP_MPI_INIT_ARRAY(y), ECP_MPI_INIT(mpi_one, 1) }
+
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)   ||   \
+    defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)   ||   \
+    defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)   ||   \
+    defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+/* For these curves, we build the group parameters dynamically. */
+#define ECP_LOAD_GROUP
+static mbedtls_mpi_uint mpi_one[] = { 1 };
+#endif
+
+/*
+ * Note: the constants are in little-endian order
+ * to be directly usable in MPIs
+ */
+
+/*
+ * Domain parameters for secp192r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+static const mbedtls_mpi_uint secp192r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp192r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64),
+};
+static const mbedtls_mpi_uint secp192r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),
+};
+static const mbedtls_mpi_uint secp192r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),
+};
+static const mbedtls_mpi_uint secp192r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp192r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18),
+};
+static const mbedtls_mpi_uint secp192r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07),
+};
+static const mbedtls_mpi_uint secp192r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x9E, 0xE3, 0x60, 0x59, 0xD1, 0xC4, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBD, 0x22, 0xD7, 0x2D, 0x07, 0xBD, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x2A, 0xCF, 0x33, 0xF0, 0xBE, 0xD1, 0xED),
+};
+static const mbedtls_mpi_uint secp192r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x71, 0x4B, 0xA8, 0xED, 0x7E, 0xC9, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x2A, 0xF6, 0xDF, 0x0E, 0xE8, 0x4C, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x35, 0xF7, 0x8A, 0xC3, 0xEC, 0xDE, 0x1E),
+};
+static const mbedtls_mpi_uint secp192r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0xC2, 0x1D, 0x32, 0x8F, 0x10, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x2D, 0x17, 0xF3, 0xE4, 0xFE, 0xD8, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x45, 0x10, 0x70, 0x2C, 0x3E, 0x52, 0x3E),
+};
+static const mbedtls_mpi_uint secp192r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF1, 0x04, 0x5D, 0xEE, 0xD4, 0x56, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xB7, 0x38, 0x27, 0x61, 0xAA, 0x81, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0xD7, 0x0E, 0x29, 0x0E, 0x11, 0x14),
+};
+static const mbedtls_mpi_uint secp192r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x35, 0x52, 0xC6, 0x31, 0xB7, 0x27, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xD4, 0x15, 0x98, 0x0F, 0xE7, 0xF3, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x31, 0x70, 0x35, 0x09, 0xA0, 0x2B, 0xC2),
+};
+static const mbedtls_mpi_uint secp192r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x75, 0xA7, 0x4C, 0x88, 0xCF, 0x5B, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x17, 0x48, 0x8D, 0xF2, 0xF0, 0x86, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCF, 0xFE, 0x6B, 0xB0, 0xA5, 0x06, 0xAB),
+};
+static const mbedtls_mpi_uint secp192r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x6A, 0xDC, 0x9A, 0x6D, 0x7B, 0x47, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xFC, 0x51, 0x12, 0x62, 0x66, 0x0B, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x40, 0x93, 0xA0, 0xB5, 0x5A, 0x58, 0xD7),
+};
+static const mbedtls_mpi_uint secp192r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCB, 0xAF, 0xDC, 0x0B, 0xA1, 0x26, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x36, 0x9D, 0xA3, 0xD7, 0x3B, 0xAD, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x3B, 0x05, 0x9A, 0xA8, 0xAA, 0x69, 0xB2),
+};
+static const mbedtls_mpi_uint secp192r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD9, 0xD1, 0x4D, 0x4A, 0x6E, 0x96, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x66, 0x32, 0x39, 0xC6, 0x57, 0x7D, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xA0, 0x36, 0xC2, 0x45, 0xF9, 0x00, 0x62),
+};
+static const mbedtls_mpi_uint secp192r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xEF, 0x59, 0x46, 0xDC, 0x60, 0xD9, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xB0, 0xE9, 0x41, 0xA4, 0x87, 0x76, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xD4, 0x0E, 0xB2, 0xFA, 0x16, 0x56, 0xDC),
+};
+static const mbedtls_mpi_uint secp192r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x62, 0xD2, 0xB1, 0x34, 0xB2, 0xF1, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xED, 0x55, 0xC5, 0x47, 0xB5, 0x07, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF6, 0x2F, 0x94, 0xC3, 0xDD, 0x54, 0x2F),
+};
+static const mbedtls_mpi_uint secp192r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xA6, 0xD4, 0x8C, 0xA9, 0xCE, 0x4D, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x4B, 0x46, 0xCC, 0xB2, 0x55, 0xC8, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x31, 0xED, 0x89, 0x65, 0x59, 0x55),
+};
+static const mbedtls_mpi_uint secp192r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x0A, 0xD1, 0x1A, 0xC5, 0xF6, 0xEA, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xFC, 0x0C, 0x1A, 0xFB, 0xA0, 0xC8, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xFD, 0x53, 0x6F, 0x6D, 0xBF, 0xBA, 0xAF),
+};
+static const mbedtls_mpi_uint secp192r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xB0, 0x7D, 0x83, 0x96, 0xE3, 0xCB, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x6E, 0x55, 0x2C, 0x20, 0x53, 0x2F, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x66, 0x00, 0x17, 0x08, 0xFE, 0xAC, 0x31),
+};
+static const mbedtls_mpi_uint secp192r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x12, 0x97, 0x3A, 0xC7, 0x57, 0x45, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x25, 0x99, 0x00, 0xF6, 0x97, 0xB4, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x74, 0xE6, 0xE6, 0xA3, 0xDF, 0x9C, 0xCC),
+};
+static const mbedtls_mpi_uint secp192r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xF4, 0x76, 0xD5, 0x5F, 0x2A, 0xFD, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x80, 0x7E, 0x3E, 0xE5, 0xE8, 0xD6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xAD, 0x1E, 0x70, 0x79, 0x3E, 0x3D, 0x83),
+};
+static const mbedtls_mpi_uint secp192r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x15, 0xBB, 0xB3, 0x42, 0x6A, 0xA1, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x58, 0xCB, 0x43, 0x25, 0x00, 0x14, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x4E, 0x93, 0x11, 0xE0, 0x32, 0x54, 0x98),
+};
+static const mbedtls_mpi_uint secp192r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x52, 0xA2, 0xB4, 0x57, 0x32, 0xB9, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x43, 0xA1, 0xB1, 0xFB, 0x01, 0xE1, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xFB, 0x5A, 0x11, 0xB8, 0xC2, 0x03, 0xE5),
+};
+static const mbedtls_mpi_uint secp192r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x2B, 0x71, 0x26, 0x4E, 0x7C, 0xC5, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF5, 0xD3, 0xA8, 0xE4, 0x95, 0x48, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAE, 0xD9, 0x5D, 0x9F, 0x6A, 0x22, 0xAD),
+};
+static const mbedtls_mpi_uint secp192r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xCC, 0xA3, 0x4D, 0xA0, 0x1C, 0x34, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x3C, 0x62, 0xF8, 0x5E, 0xA6, 0x58, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x6E, 0x66, 0x8A, 0x3D, 0x17, 0xFF, 0x0F),
+};
+static const mbedtls_mpi_uint secp192r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xCD, 0xA8, 0xDD, 0xD1, 0x20, 0x5C, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xFE, 0x17, 0xE2, 0xCF, 0xEA, 0x63, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x51, 0xC9, 0x16, 0xDE, 0xB4, 0xB2, 0xDD),
+};
+static const mbedtls_mpi_uint secp192r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBE, 0x12, 0xD7, 0xA3, 0x0A, 0x50, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x87, 0xC5, 0x8A, 0x76, 0x57, 0x07, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x1F, 0xC6, 0x1B, 0x66, 0xC4, 0x3D, 0x8A),
+};
+static const mbedtls_mpi_uint secp192r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xA4, 0x85, 0x13, 0x8F, 0xA7, 0x35, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x0D, 0xFD, 0xFF, 0x1B, 0xD1, 0xD6, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x7A, 0xD0, 0xC3, 0xB4, 0xEF, 0x39, 0x66),
+};
+static const mbedtls_mpi_uint secp192r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xFE, 0xA5, 0x9C, 0x34, 0x30, 0x49, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xC5, 0x39, 0x26, 0x06, 0xE3, 0x01, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x2B, 0x66, 0xFC, 0x95, 0x5F, 0x35, 0xF7),
+};
+static const mbedtls_mpi_uint secp192r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xCF, 0x54, 0x63, 0x99, 0x57, 0x05, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x6F, 0x00, 0x5F, 0x65, 0x08, 0x47, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x2A, 0x90, 0x6D, 0x67, 0xC6, 0xBC, 0x45),
+};
+static const mbedtls_mpi_uint secp192r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x4D, 0x88, 0x0A, 0x35, 0x9E, 0x33, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x17, 0x0C, 0xF8, 0xE1, 0x7A, 0x49, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x44, 0x06, 0x8F, 0x0B, 0x70, 0x2F, 0x71),
+};
+static const mbedtls_mpi_uint secp192r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4B, 0xCB, 0xF9, 0x8E, 0x6A, 0xDA, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x43, 0xA1, 0x3F, 0xCE, 0x17, 0xD2, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x0D, 0xD2, 0x6C, 0x82, 0x37, 0xE5, 0xFC),
+};
+static const mbedtls_mpi_uint secp192r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x3C, 0xF4, 0x92, 0xB4, 0x8A, 0x95, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x96, 0xF1, 0x0A, 0x34, 0x2F, 0x74, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0xAA, 0xBA, 0x86, 0x77, 0x4F, 0xA2),
+};
+static const mbedtls_mpi_uint secp192r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x7F, 0xEF, 0x60, 0x50, 0x80, 0xD7, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xAC, 0xC9, 0xFE, 0xEC, 0x0A, 0x1A, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x2F, 0xBE, 0x91, 0xD7, 0xB7, 0x38, 0x48),
+};
+static const mbedtls_mpi_uint secp192r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xAE, 0x85, 0x98, 0xFE, 0x05, 0x7F, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBE, 0xFD, 0x11, 0x31, 0x3D, 0x14, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x75, 0xE8, 0x30, 0x01, 0xCB, 0x9B, 0x1C),
+};
+static const mbedtls_ecp_point secp192r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp192r1_T_0_X, secp192r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_1_X, secp192r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_2_X, secp192r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_3_X, secp192r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_4_X, secp192r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_5_X, secp192r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_6_X, secp192r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_7_X, secp192r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_8_X, secp192r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_9_X, secp192r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_10_X, secp192r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_11_X, secp192r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_12_X, secp192r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_13_X, secp192r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_14_X, secp192r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp192r1_T_15_X, secp192r1_T_15_Y),
+};
+#else
+#define secp192r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+/*
+ * Domain parameters for secp224r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+static const mbedtls_mpi_uint secp224r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x85, 0x0A, 0x05, 0xB4),
+};
+static const mbedtls_mpi_uint secp224r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xBD, 0x0C, 0x0E, 0xB7),
+};
+static const mbedtls_mpi_uint secp224r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x88, 0x63, 0x37, 0xBD),
+};
+static const mbedtls_mpi_uint secp224r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp224r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x0C, 0x0E, 0xB7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x63, 0x37, 0xBD, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF9, 0xB8, 0xD0, 0x3D, 0xD2, 0xD3, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xFD, 0x99, 0x26, 0x19, 0xFE, 0x13, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x0E, 0x4C, 0x48, 0x7C, 0xA2, 0x17, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA3, 0x13, 0x57, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x16, 0x5C, 0x8F, 0xAA, 0xED, 0x0F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xC5, 0x43, 0x34, 0x93, 0x05, 0x2A, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE3, 0x6C, 0xCA, 0xC6, 0x14, 0xC2, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x43, 0x6C, 0xD7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x5A, 0x98, 0x1E, 0xC8, 0xA5, 0x42, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x49, 0x56, 0x78, 0xF8, 0xEF, 0xED, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xBB, 0x64, 0xB6, 0x4C, 0x54, 0x5F, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x0C, 0x33, 0xCC, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x79, 0xCB, 0x2E, 0x08, 0xFF, 0xD8, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x1F, 0xD4, 0xD7, 0x57, 0xE9, 0x39, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xD6, 0x3B, 0x0A, 0x1C, 0x87, 0xB7, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x30, 0xD8, 0x05, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x79, 0x74, 0x9A, 0xE6, 0xBB, 0xC2, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x5B, 0xA6, 0x67, 0xC1, 0x91, 0xE7, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xDF, 0x38, 0x82, 0x19, 0x2C, 0x4C, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x2E, 0x39, 0xC5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x36, 0x78, 0x4E, 0xAE, 0x5B, 0x02, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF6, 0x8B, 0xF8, 0xF4, 0x92, 0x6B, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x4D, 0x71, 0x35, 0xE7, 0x0C, 0x2C, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xA5, 0x1F, 0xAE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x1C, 0x4B, 0xDF, 0x5B, 0xF2, 0x51, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0xB1, 0x5A, 0xC6, 0x0F, 0x0E, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x24, 0x09, 0x62, 0xAF, 0xFC, 0xDB, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xE1, 0x80, 0x55, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x82, 0xFE, 0xAD, 0xC3, 0xE5, 0xCF, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xA2, 0x62, 0x17, 0x76, 0xF0, 0x5A, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB8, 0xE5, 0xAC, 0xB7, 0x66, 0x38, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xFD, 0x86, 0x05, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0x0C, 0x3C, 0xD1, 0x66, 0xB0, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x59, 0xB4, 0x8D, 0x90, 0x10, 0xB7, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x47, 0x9B, 0xE6, 0x55, 0x8A, 0xE4, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x49, 0xDB, 0x78, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x97, 0xED, 0xDE, 0xFF, 0xB3, 0xDF, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xB9, 0x83, 0xB7, 0xEB, 0xBE, 0x40, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xD3, 0xD3, 0xCD, 0x0E, 0x82, 0x79, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x83, 0x1B, 0xF0, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x22, 0xBB, 0x54, 0xD3, 0x31, 0x56, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0xE5, 0xE0, 0x89, 0x96, 0x8E, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xEF, 0x0A, 0xED, 0xD0, 0x11, 0x4A, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x00, 0x57, 0x27, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCA, 0x3D, 0xF7, 0x64, 0x9B, 0x6E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xE3, 0x70, 0x6B, 0x41, 0xD7, 0xED, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x44, 0x44, 0x80, 0xCE, 0x13, 0x37, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x73, 0x80, 0x79, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x4D, 0x70, 0x7D, 0x31, 0x0F, 0x1C, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x35, 0x88, 0x47, 0xC4, 0x24, 0x78, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF0, 0xCD, 0x91, 0x81, 0xB3, 0xDE, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xCE, 0xC6, 0xF7, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x9C, 0x2D, 0xE8, 0xD2, 0x00, 0x8F, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x5E, 0x7C, 0x0E, 0x0C, 0x6E, 0x58, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x81, 0x21, 0xCE, 0x43, 0xF4, 0x24, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xBC, 0xF0, 0xF4, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x10, 0xC2, 0x74, 0x4A, 0x8F, 0x8A, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x67, 0xF4, 0x2B, 0x38, 0x2B, 0x35, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0C, 0xA9, 0xFA, 0x77, 0x5C, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x19, 0x2B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x3E, 0x96, 0x22, 0x53, 0xE1, 0xE9, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x13, 0xBC, 0xA1, 0x16, 0xEC, 0x01, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x00, 0xC9, 0x7A, 0xC3, 0x73, 0xA5, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xF4, 0x5E, 0xC1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x95, 0xD6, 0xD9, 0x32, 0x30, 0x2B, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x42, 0x09, 0x05, 0x61, 0x2A, 0x7E, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x84, 0xA2, 0x05, 0x88, 0x64, 0x65, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2D, 0x90, 0xB3, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE7, 0x2E, 0x85, 0x55, 0x80, 0x7C, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC1, 0xAC, 0x78, 0xB4, 0xAF, 0xFB, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xC3, 0x28, 0x8E, 0x79, 0x18, 0x1F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x46, 0xCF, 0x49, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x5F, 0xA8, 0x6C, 0x46, 0x83, 0x43, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xA9, 0x93, 0x11, 0xB6, 0x07, 0x57, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x2A, 0x9D, 0x03, 0x89, 0x7E, 0xD7, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x8C, 0x62, 0xCF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x2C, 0x13, 0x59, 0xCC, 0xFA, 0x84, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB9, 0x48, 0xBC, 0x57, 0xC7, 0xB3, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x0A, 0x38, 0x24, 0x2E, 0x3A, 0x28, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x0A, 0x43, 0xB8, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x25, 0xAB, 0xC1, 0xEE, 0x70, 0x3C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xDB, 0x45, 0x1D, 0x4A, 0x80, 0x75, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1F, 0x4D, 0x2D, 0x9A, 0x05, 0xF4, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x10, 0xF0, 0x5A, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x95, 0xE1, 0xDC, 0x15, 0x86, 0xC3, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xDC, 0x27, 0xD1, 0x56, 0xA1, 0x14, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x0B, 0xD6, 0x77, 0x4E, 0x44, 0xA2, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x42, 0x71, 0x1F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x86, 0xB2, 0xB0, 0xC8, 0x2F, 0x7B, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xEF, 0xCB, 0xDB, 0xBC, 0x9E, 0x3B, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x03, 0x86, 0xDD, 0x5B, 0xF5, 0x8D, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x95, 0x79, 0xD6, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x32, 0x14, 0xDA, 0x9B, 0x4F, 0x07, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x3E, 0xFB, 0x06, 0xEE, 0xA7, 0x40, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x1F, 0xDF, 0x71, 0x61, 0xFD, 0x8B, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x8B, 0xAB, 0x8B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x34, 0xB3, 0xB4, 0xBC, 0x9F, 0xB0, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x58, 0x48, 0xA8, 0x77, 0xBB, 0x13, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC6, 0xF7, 0x34, 0xCC, 0x89, 0x21, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x33, 0xDD, 0x1F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x81, 0xEF, 0xA4, 0xF2, 0x10, 0x0B, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF7, 0x6E, 0x72, 0x4A, 0xDF, 0xDD, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x23, 0x0A, 0x53, 0x03, 0x16, 0x62, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x76, 0xFD, 0x3C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x14, 0xA1, 0xFA, 0xA0, 0x18, 0xBE, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x2A, 0xE1, 0xD7, 0xB0, 0x6C, 0xA0, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xC0, 0xB0, 0xC6, 0x63, 0x24, 0xCD, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x38, 0x2C, 0xB1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCD, 0x7D, 0x20, 0x0C, 0xFE, 0xAC, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x9F, 0xA2, 0xB6, 0x45, 0xF7, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x99, 0xF3, 0xD2, 0x20, 0x02, 0xEB, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x5B, 0x7B, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xDD, 0x77, 0x91, 0x60, 0xEA, 0xFD, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xD3, 0xB5, 0xD6, 0x90, 0x17, 0x0E, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xF4, 0x28, 0xC1, 0xF2, 0x53, 0xF6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x58, 0xDC, 0x61, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x20, 0x01, 0xFB, 0xF1, 0xBD, 0x5F, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x7F, 0x06, 0xDA, 0x11, 0xCB, 0xBA, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x41, 0x00, 0xA4, 0x1B, 0x30, 0x33, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xFF, 0x27, 0xCA, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp224r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp224r1_T_0_X, secp224r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_1_X, secp224r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_2_X, secp224r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_3_X, secp224r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_4_X, secp224r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_5_X, secp224r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_6_X, secp224r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_7_X, secp224r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_8_X, secp224r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_9_X, secp224r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_10_X, secp224r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_11_X, secp224r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_12_X, secp224r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_13_X, secp224r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_14_X, secp224r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp224r1_T_15_X, secp224r1_T_15_Y),
+};
+#else
+#define secp224r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+/*
+ * Domain parameters for secp256r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+static const mbedtls_mpi_uint secp256r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp256r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A),
+};
+static const mbedtls_mpi_uint secp256r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),
+};
+static const mbedtls_mpi_uint secp256r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),
+};
+static const mbedtls_mpi_uint secp256r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp256r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B),
+};
+static const mbedtls_mpi_uint secp256r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F),
+};
+static const mbedtls_mpi_uint secp256r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xC8, 0xBA, 0x04, 0xB7, 0x4B, 0xD2, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC6, 0x23, 0x3A, 0xA0, 0x09, 0x3A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x9D, 0x4C, 0xF9, 0x58, 0x23, 0xCC, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xED, 0x7B, 0x29, 0x87, 0x0F, 0xFA, 0x3C),
+};
+static const mbedtls_mpi_uint secp256r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x69, 0xF2, 0x40, 0x0B, 0xA3, 0x98, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xA8, 0x48, 0x02, 0x0D, 0x1C, 0x12, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xAF, 0x09, 0x83, 0x80, 0xAA, 0x58, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x12, 0xBE, 0x70, 0x94, 0x76, 0xE3, 0xE4),
+};
+static const mbedtls_mpi_uint secp256r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x7D, 0xEF, 0x86, 0xFF, 0xE3, 0x37, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x86, 0x8B, 0x08, 0x27, 0x7C, 0xD7, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x54, 0x4C, 0x25, 0x4F, 0x9A, 0xFE, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xFD, 0xF0, 0x6D, 0x37, 0x03, 0x69, 0xD6),
+};
+static const mbedtls_mpi_uint secp256r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xD5, 0xDA, 0xAD, 0x92, 0x49, 0xF0, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x73, 0x43, 0x9E, 0xAF, 0xA7, 0xD1, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x41, 0x07, 0xDF, 0x78, 0x95, 0x3E, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x3D, 0xD1, 0xE6, 0x3C, 0xA5, 0xE2, 0x20),
+};
+static const mbedtls_mpi_uint secp256r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x6A, 0x5D, 0x52, 0x35, 0xD7, 0xBF, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xA2, 0xBE, 0x96, 0xF4, 0xF8, 0x02, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x20, 0x49, 0x54, 0xEA, 0xB3, 0x82, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0xDB, 0xEA, 0x02, 0xD1, 0x75, 0x1C, 0x62),
+};
+static const mbedtls_mpi_uint secp256r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x85, 0xF4, 0x9E, 0x4C, 0xDC, 0x39, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x6D, 0xC4, 0x57, 0xD8, 0x03, 0x5D, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x7F, 0x2D, 0x52, 0x6F, 0xC9, 0xDA, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x64, 0xFA, 0xB4, 0xFE, 0xA4, 0xC4, 0xD7),
+};
+static const mbedtls_mpi_uint secp256r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x37, 0xB9, 0xC0, 0xAA, 0x59, 0xC6, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x58, 0xD9, 0xED, 0x58, 0x99, 0x65, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x7D, 0x26, 0x8C, 0x4A, 0xF9, 0x05, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x73, 0x9A, 0xC9, 0xE7, 0x46, 0xDC, 0x00),
+};
+static const mbedtls_mpi_uint secp256r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xD0, 0x55, 0xDF, 0x00, 0x0A, 0xF5, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xBF, 0x56, 0x81, 0x2D, 0x20, 0xEB, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC1, 0x28, 0x52, 0xAB, 0xE3, 0xD1, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x34, 0x79, 0x45, 0x57, 0xA5, 0x12, 0x03),
+};
+static const mbedtls_mpi_uint secp256r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xCF, 0xB8, 0x7E, 0xF7, 0x92, 0x96, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x01, 0x8C, 0x0D, 0x23, 0xF2, 0xE3, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x2E, 0xE3, 0x84, 0x52, 0x7A, 0x34, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xA1, 0xB0, 0x15, 0x90, 0xE2, 0x53, 0x3C),
+};
+static const mbedtls_mpi_uint secp256r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x98, 0xE7, 0xFA, 0xA5, 0x7D, 0x8B, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x35, 0xD2, 0x00, 0xD1, 0x1B, 0x9F, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x69, 0x08, 0x9A, 0x72, 0xF0, 0xA9, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xFE, 0x0E, 0x14, 0xDA, 0x7C, 0x0E, 0xD3),
+};
+static const mbedtls_mpi_uint secp256r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xF6, 0xE8, 0xF8, 0x87, 0xF7, 0xFC, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xBE, 0x7F, 0x3F, 0x7A, 0x2B, 0xD7, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x32, 0xF2, 0x2D, 0x94, 0x6D, 0x42, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x9A, 0xE3, 0x5F, 0x42, 0xBB, 0x84, 0xED),
+};
+static const mbedtls_mpi_uint secp256r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x95, 0x29, 0x73, 0xA1, 0x67, 0x3E, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x30, 0x54, 0x35, 0x8E, 0x0A, 0xDD, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xD7, 0xA1, 0x97, 0x61, 0x3B, 0xF8, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x33, 0x3C, 0x58, 0x55, 0x34, 0x23, 0xA3),
+};
+static const mbedtls_mpi_uint secp256r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x5D, 0x16, 0x5F, 0x7B, 0xBC, 0xBB, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xEE, 0x4E, 0x8A, 0xC1, 0x51, 0xCC, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0D, 0x4D, 0x1B, 0x53, 0x23, 0x1D, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x2A, 0x38, 0x66, 0x52, 0x84, 0xE1, 0x95),
+};
+static const mbedtls_mpi_uint secp256r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x9B, 0x83, 0x0A, 0x81, 0x4F, 0xAD, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xFF, 0x42, 0x41, 0x6E, 0xA9, 0xA2, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA1, 0x4F, 0x1F, 0x89, 0x82, 0xAA, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xB8, 0x0F, 0x6B, 0x8F, 0x8C, 0xD6, 0x68),
+};
+static const mbedtls_mpi_uint secp256r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0xB3, 0xBB, 0x51, 0x69, 0xA2, 0x11, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x4F, 0x0F, 0x8D, 0xBD, 0x26, 0x0F, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xCB, 0xEC, 0x6B, 0x34, 0xC3, 0x3D, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x5D, 0x1E, 0x10, 0xD5, 0x44, 0xE2, 0x54),
+};
+static const mbedtls_mpi_uint secp256r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x9E, 0xB1, 0xF1, 0x6E, 0x4C, 0xAD, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE3, 0xC2, 0x58, 0xC0, 0xFB, 0x34, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x9C, 0xDF, 0x35, 0x07, 0x41, 0xBD, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x10, 0xEC, 0x0E, 0xEC, 0xBB, 0xD6),
+};
+static const mbedtls_mpi_uint secp256r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xCF, 0xEF, 0x3F, 0x83, 0x1A, 0x88, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x29, 0xB5, 0xB9, 0xE0, 0xC9, 0xA3, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x46, 0x1E, 0x77, 0xCD, 0x7E, 0xB3, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x21, 0xD0, 0xD4, 0xA3, 0x16, 0x08, 0xEE),
+};
+static const mbedtls_mpi_uint secp256r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xCA, 0xA8, 0xB3, 0xBF, 0x29, 0x99, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF2, 0x05, 0xC1, 0xCF, 0x5D, 0x91, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x01, 0x49, 0xDB, 0x82, 0xDF, 0x5F, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x06, 0x90, 0xAD, 0xE3, 0x38, 0xA4, 0xC4),
+};
+static const mbedtls_mpi_uint secp256r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xD2, 0x3A, 0xE8, 0x03, 0xC5, 0x6D, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x35, 0xD0, 0xAE, 0x1D, 0x7A, 0x9F, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x1E, 0xD2, 0xCB, 0xAC, 0x88, 0x27, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x9C, 0xE0, 0x31, 0xDD, 0x99, 0x86),
+};
+static const mbedtls_mpi_uint secp256r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xF9, 0x9B, 0x32, 0x96, 0x41, 0x58, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x5A, 0x2A, 0xB8, 0x96, 0x0E, 0xB2, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x78, 0x2C, 0xC7, 0x08, 0x99, 0x19, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x59, 0x28, 0xE9, 0x84, 0x54, 0xE6, 0x16),
+};
+static const mbedtls_mpi_uint secp256r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x38, 0x30, 0xDB, 0x70, 0x2C, 0x0A, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x5C, 0x9D, 0xE9, 0xD5, 0x46, 0x0B, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x0B, 0x60, 0x4B, 0x37, 0x7D, 0xB9, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x24, 0xF3, 0x3D, 0x79, 0x7F, 0x6C, 0x18),
+};
+static const mbedtls_mpi_uint secp256r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7F, 0xE5, 0x1C, 0x4F, 0x60, 0x24, 0xF7, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xD8, 0xE2, 0x91, 0x7F, 0x89, 0x49, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xA7, 0x2E, 0x8D, 0x6A, 0xB3, 0x39, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x89, 0xB5, 0x9A, 0xB8, 0x8D, 0x42, 0x9C),
+};
+static const mbedtls_mpi_uint secp256r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x45, 0xE6, 0x4B, 0x3F, 0x4F, 0x1E, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x65, 0x5E, 0x59, 0x22, 0xCC, 0x72, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x93, 0x1A, 0x27, 0x1E, 0x34, 0xC5, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xF2, 0xA5, 0x58, 0x5C, 0x15, 0x2E, 0xC6),
+};
+static const mbedtls_mpi_uint secp256r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x7F, 0xBA, 0x58, 0x5A, 0x84, 0x6F, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA6, 0x36, 0x7E, 0xDC, 0xF7, 0xE1, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x4D, 0xAA, 0xEE, 0x57, 0x76, 0x3A, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x7E, 0x26, 0x18, 0x22, 0x23, 0x9F, 0xFF),
+};
+static const mbedtls_mpi_uint secp256r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x4C, 0x64, 0xC7, 0x55, 0x02, 0x3F, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x02, 0x90, 0xBB, 0xC3, 0xEC, 0x30, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x6F, 0x64, 0xF4, 0x16, 0x69, 0x48, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x44, 0x9C, 0x95, 0x0C, 0x7D, 0x67, 0x5E),
+};
+static const mbedtls_mpi_uint secp256r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x91, 0x8B, 0xD8, 0xD0, 0xD7, 0xE7, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xF9, 0x48, 0x62, 0x6F, 0xA8, 0x93, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x3A, 0x99, 0x02, 0xD5, 0x0B, 0x3D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xD3, 0x00, 0x31, 0xE6, 0x0C, 0x9F, 0x44),
+};
+static const mbedtls_mpi_uint secp256r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xB2, 0xAA, 0xFD, 0x88, 0x15, 0xDF, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0x35, 0x27, 0x31, 0x44, 0xCD, 0xC0, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xF8, 0x91, 0xA5, 0x71, 0x94, 0x84, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xCB, 0xD0, 0x93, 0xE9, 0x88, 0xDA, 0xE4),
+};
+static const mbedtls_mpi_uint secp256r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC6, 0x39, 0x16, 0x5D, 0xA3, 0x1E, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x07, 0x37, 0x26, 0x36, 0x2A, 0xFE, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xBC, 0xF3, 0xD0, 0xDE, 0x50, 0xFC, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x2E, 0x06, 0x10, 0x15, 0x4D, 0xFA, 0xF7),
+};
+static const mbedtls_mpi_uint secp256r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x65, 0x69, 0x5B, 0x66, 0xA2, 0x75, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x16, 0x00, 0x5A, 0xB0, 0x30, 0x25, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xFB, 0x86, 0x42, 0x80, 0xC1, 0xC4, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x1D, 0x83, 0x8E, 0x94, 0x01, 0x5F, 0x82),
+};
+static const mbedtls_mpi_uint secp256r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x37, 0x70, 0xEF, 0x1F, 0xA1, 0xF0, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x5B, 0xCE, 0xC4, 0x9B, 0x6F, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x11, 0x11, 0x24, 0x4F, 0x4C, 0x79, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x3A, 0x72, 0xBC, 0xFE, 0x72, 0x58, 0x43),
+};
+static const mbedtls_ecp_point secp256r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp256r1_T_0_X, secp256r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_1_X, secp256r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_2_X, secp256r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_3_X, secp256r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_4_X, secp256r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_5_X, secp256r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_6_X, secp256r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_7_X, secp256r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_8_X, secp256r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_9_X, secp256r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_10_X, secp256r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_11_X, secp256r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_12_X, secp256r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_13_X, secp256r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_14_X, secp256r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp256r1_T_15_X, secp256r1_T_15_Y),
+};
+#else
+#define secp256r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+/*
+ * Domain parameters for secp384r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+static const mbedtls_mpi_uint secp384r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp384r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3),
+};
+static const mbedtls_mpi_uint secp384r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),
+};
+static const mbedtls_mpi_uint secp384r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp384r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36),
+};
+static const mbedtls_mpi_uint secp384r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x92, 0x00, 0x2C, 0x78, 0xDB, 0x1F, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xF3, 0xEB, 0xB7, 0x06, 0xF7, 0xB6, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBC, 0x2C, 0xCF, 0xD8, 0xED, 0x53, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x75, 0x7B, 0xA3, 0xAB, 0xC3, 0x2C, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x9D, 0x78, 0x41, 0xF6, 0x76, 0x84, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x56, 0xE8, 0x52, 0xB3, 0xCB, 0xA8, 0xBD),
+};
+static const mbedtls_mpi_uint secp384r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xF2, 0xAE, 0xA4, 0xB6, 0x89, 0x1B, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0xCE, 0x1C, 0x7C, 0xF6, 0x50, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xEB, 0x90, 0xE6, 0x4D, 0xC7, 0xD4, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x49, 0x2D, 0x8A, 0x01, 0x99, 0x60, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x80, 0x9B, 0x9B, 0x6A, 0xB0, 0x07, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xA2, 0xEE, 0x59, 0xBE, 0x95, 0xBC, 0x23),
+};
+static const mbedtls_mpi_uint secp384r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x9D, 0x56, 0xAE, 0x59, 0xFB, 0x1F, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xAC, 0x91, 0x80, 0x87, 0xA8, 0x6E, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x08, 0xA7, 0x08, 0x94, 0x32, 0xFC, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x29, 0x9E, 0x84, 0xF4, 0xE5, 0x6E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x21, 0xB9, 0x50, 0x24, 0xF8, 0x9C, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x04, 0x01, 0xC2, 0xFB, 0x77, 0x3E, 0xDE),
+};
+static const mbedtls_mpi_uint secp384r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x38, 0xEE, 0xE3, 0xC7, 0x9D, 0xEC, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x88, 0xCF, 0x43, 0xFA, 0x92, 0x5E, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xCA, 0x43, 0xF8, 0x3B, 0x49, 0x7E, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xE7, 0xEB, 0x17, 0x45, 0x86, 0xC2, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x69, 0x57, 0x32, 0xE0, 0x9C, 0xD1, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x10, 0xB8, 0x4D, 0xB8, 0xF4, 0x0D, 0xE3),
+};
+static const mbedtls_mpi_uint secp384r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0xDC, 0x9A, 0xB2, 0x79, 0x39, 0x27, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x71, 0xE4, 0x3B, 0x4D, 0x60, 0x0C, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xBD, 0x19, 0x40, 0xFA, 0x19, 0x2A, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xF8, 0x1E, 0x43, 0xA1, 0x50, 0x8D, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x18, 0x7C, 0x41, 0xFA, 0x7C, 0x1B, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x24, 0xC4, 0xE9, 0xB7, 0xD3, 0xAD),
+};
+static const mbedtls_mpi_uint secp384r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x01, 0x3D, 0x63, 0x54, 0x45, 0x6F, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xB2, 0x19, 0xA3, 0x86, 0x1D, 0x42, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x02, 0x87, 0x18, 0x92, 0x52, 0x1A, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x18, 0xB1, 0x5D, 0x18, 0x1B, 0x37, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x74, 0x61, 0xBA, 0x18, 0xAF, 0x40, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7D, 0x3C, 0x52, 0x0F, 0x07, 0xB0, 0x6F),
+};
+static const mbedtls_mpi_uint secp384r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x39, 0x13, 0xAA, 0x60, 0x15, 0x99, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x00, 0xCB, 0xC6, 0xB1, 0xDB, 0x97, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xFA, 0x60, 0xB8, 0x24, 0xE4, 0x7D, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x75, 0xB3, 0x70, 0xB2, 0x83, 0xB1, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xE3, 0x6C, 0xCD, 0x33, 0x62, 0x7A, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x30, 0xDC, 0x0F, 0x9F, 0xBB, 0xB8, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD5, 0x0A, 0x60, 0x81, 0xB9, 0xC5, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xAA, 0x2F, 0xD6, 0xF2, 0x73, 0xDF, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x7B, 0x74, 0xC9, 0xB3, 0x5B, 0x95, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x04, 0xEB, 0x15, 0xC8, 0x5F, 0x00, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x50, 0x20, 0x28, 0xD1, 0x01, 0xAF, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x4F, 0x31, 0x81, 0x2F, 0x94, 0x48),
+};
+static const mbedtls_mpi_uint secp384r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2F, 0xD8, 0xB6, 0x63, 0x7C, 0xE9, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x8C, 0xB9, 0x14, 0xD9, 0x37, 0x63, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x02, 0xB8, 0x46, 0xAD, 0xCE, 0x7B, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x47, 0x2D, 0x66, 0xA7, 0xE9, 0x33, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF9, 0x93, 0x94, 0xA8, 0x48, 0xB3, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x4A, 0xAC, 0x51, 0x08, 0x72, 0x2F, 0x1A),
+};
+static const mbedtls_mpi_uint secp384r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xAD, 0xA0, 0xF9, 0x81, 0xE1, 0x78, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9A, 0x63, 0xD8, 0xBA, 0x79, 0x1A, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x31, 0x7B, 0x7A, 0x5A, 0x5D, 0x7D, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x96, 0x12, 0x4B, 0x19, 0x09, 0xE0, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8A, 0x57, 0xEE, 0x4E, 0x6E, 0x7E, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x9D, 0x69, 0xDC, 0xB3, 0xDA, 0xD8, 0x08),
+};
+static const mbedtls_mpi_uint secp384r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x49, 0x03, 0x03, 0x33, 0x6F, 0x28, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xDB, 0xA7, 0x05, 0x8C, 0xF3, 0x4D, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x92, 0xB1, 0xA8, 0xEC, 0x0D, 0x64, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0xFC, 0xFD, 0xD0, 0x4B, 0x88, 0x1B, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x9C, 0x51, 0x69, 0xCE, 0x71, 0x73, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5A, 0x14, 0x23, 0x1A, 0x46, 0x63, 0x5F),
+};
+static const mbedtls_mpi_uint secp384r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x4C, 0x70, 0x44, 0x18, 0xCD, 0xEF, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x49, 0xDD, 0x64, 0x7E, 0x7E, 0x4D, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x32, 0x7C, 0x09, 0xD0, 0x3F, 0xD6, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE0, 0x4F, 0x65, 0x0C, 0x7A, 0x54, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFA, 0xFB, 0x4A, 0xB4, 0x79, 0x5A, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x1B, 0x2B, 0xDA, 0xBC, 0x9A, 0x74),
+};
+static const mbedtls_mpi_uint secp384r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xAC, 0x56, 0xF7, 0x5F, 0x51, 0x68, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xE0, 0x1D, 0xBC, 0x13, 0x4E, 0xAC, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF5, 0xC5, 0xE6, 0xD2, 0x88, 0xBA, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x0E, 0x28, 0x23, 0x58, 0x67, 0xFA, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x80, 0x4B, 0xD8, 0xC4, 0xDF, 0x15, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x0E, 0x58, 0xE6, 0x2C, 0x59, 0xC2, 0x03),
+};
+static const mbedtls_mpi_uint secp384r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x26, 0x27, 0x99, 0x16, 0x2B, 0x22, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xF3, 0x8F, 0xC3, 0x2A, 0x9B, 0xFC, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2E, 0x83, 0x3D, 0xFE, 0x9E, 0x3C, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0xCD, 0x2D, 0xC1, 0x49, 0x38, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x42, 0x8B, 0x33, 0x89, 0x1F, 0xEA, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x1D, 0x13, 0xD7, 0x50, 0xBB, 0x3E, 0xEB),
+};
+static const mbedtls_mpi_uint secp384r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x9A, 0x52, 0xD2, 0x54, 0x7C, 0x97, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x33, 0x6E, 0xED, 0xD9, 0x87, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x35, 0x7E, 0x16, 0x40, 0x15, 0x83, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x2B, 0xA4, 0xAB, 0x03, 0x91, 0xEA, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x47, 0x39, 0xEF, 0x05, 0x59, 0xD0, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x24, 0x0D, 0x76, 0x11, 0x53, 0x08, 0xAF),
+};
+static const mbedtls_mpi_uint secp384r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x2F, 0xDD, 0xBD, 0x50, 0x48, 0xB1, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x1C, 0x84, 0x55, 0x78, 0x14, 0xEB, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x5E, 0x3E, 0xA6, 0xAF, 0xF6, 0xC7, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x11, 0xE2, 0x65, 0xCA, 0x41, 0x95, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x83, 0xD8, 0xE6, 0x4D, 0x22, 0x06, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x7F, 0x25, 0x2A, 0xAA, 0x28, 0x46, 0x97),
+};
+static const mbedtls_mpi_uint secp384r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xDB, 0x15, 0x56, 0x84, 0xCB, 0xC0, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xDB, 0x0E, 0x08, 0xC9, 0xF5, 0xD4, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x62, 0xD0, 0x1A, 0x7C, 0x13, 0xD5, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xAD, 0x53, 0xE0, 0x32, 0x21, 0xA0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x38, 0x81, 0x21, 0x23, 0x0E, 0xD2, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x51, 0x05, 0xD0, 0x1E, 0x82, 0xA9, 0x71),
+};
+static const mbedtls_mpi_uint secp384r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xC3, 0x27, 0xBF, 0xC6, 0xAA, 0xB7, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x65, 0x45, 0xDF, 0xB9, 0x46, 0x17, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x38, 0x3F, 0xB2, 0xB1, 0x5D, 0xCA, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x29, 0x6C, 0x63, 0xE9, 0xD7, 0x48, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xF1, 0xD7, 0x99, 0x8C, 0xC2, 0x05, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE6, 0x5E, 0x82, 0x6D, 0xE5, 0x7E, 0xD5),
+};
+static const mbedtls_mpi_uint secp384r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x61, 0xFA, 0x7D, 0x01, 0xDB, 0xB6, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xC6, 0x58, 0x39, 0xF4, 0xC6, 0x82, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0x7A, 0x80, 0x08, 0xCD, 0xAA, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x8C, 0xC6, 0x3F, 0x3C, 0xA5, 0x68, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xF5, 0xD5, 0x17, 0xAE, 0x36, 0xD8, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xAD, 0x92, 0xC5, 0x57, 0x6C, 0xDA, 0x91),
+};
+static const mbedtls_mpi_uint secp384r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x67, 0x17, 0xC0, 0x40, 0x78, 0x8C, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x9F, 0xF4, 0xAA, 0xDA, 0x5C, 0x7E, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xDB, 0x42, 0x3E, 0x72, 0x64, 0xA0, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xF9, 0x41, 0x17, 0x43, 0xE3, 0xE8, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xDD, 0xCC, 0x43, 0x7E, 0x16, 0x05, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x4B, 0xCF, 0x48, 0x8F, 0x41, 0x90, 0xE5),
+};
+static const mbedtls_mpi_uint secp384r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x0C, 0x6B, 0x9D, 0x22, 0x04, 0xBC, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x63, 0x79, 0x2F, 0x6A, 0x0E, 0x8A, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x67, 0x3F, 0x02, 0xB8, 0x91, 0x7F, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x14, 0x64, 0xA0, 0x33, 0xF4, 0x6B, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x44, 0x71, 0x87, 0xB8, 0x88, 0x3F, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x2B, 0x85, 0x05, 0xC5, 0x44, 0x53, 0x15),
+};
+static const mbedtls_mpi_uint secp384r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x2B, 0xFE, 0xD1, 0x1C, 0x73, 0xE3, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x33, 0xA1, 0xD3, 0x69, 0x1C, 0x9D, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x5A, 0xBA, 0xB6, 0xAE, 0x1B, 0x94, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x74, 0x90, 0x5C, 0x57, 0xB0, 0x3A, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x2F, 0x93, 0x20, 0x24, 0x54, 0x1D, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x78, 0x9D, 0x71, 0x67, 0x5D, 0x49, 0x98),
+};
+static const mbedtls_mpi_uint secp384r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xC8, 0x0E, 0x11, 0x8D, 0xE0, 0x8F, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x7F, 0x79, 0x6C, 0x5F, 0xB7, 0xBC, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xE1, 0x83, 0x3C, 0x12, 0xBB, 0xEE, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC2, 0xC4, 0x1B, 0x41, 0x71, 0xB9, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0xEE, 0xBB, 0x1D, 0x89, 0x50, 0x88, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x1C, 0x55, 0x74, 0xEB, 0xDE, 0x92, 0x3F),
+};
+static const mbedtls_mpi_uint secp384r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x38, 0x92, 0x06, 0x19, 0xD0, 0xB3, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x99, 0x26, 0xA3, 0x5F, 0xE2, 0xC1, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xFC, 0xFD, 0xC3, 0xB6, 0x26, 0x24, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xAD, 0xE7, 0x49, 0xB7, 0x64, 0x4B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x4E, 0x95, 0xAD, 0x07, 0xFE, 0xB6, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x15, 0xE7, 0x2D, 0x19, 0xA9, 0x08, 0x10),
+};
+static const mbedtls_mpi_uint secp384r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xBD, 0xAC, 0x0A, 0x3F, 0x6B, 0xFF, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xE4, 0x74, 0x14, 0xD9, 0x70, 0x1D, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xB0, 0x71, 0xBB, 0xD8, 0x18, 0x96, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0xB8, 0x19, 0x90, 0x80, 0xB5, 0xEE, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x21, 0x20, 0xA6, 0x17, 0x48, 0x03, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0xBB, 0x6D, 0x94, 0x20, 0x34, 0xF1),
+};
+static const mbedtls_mpi_uint secp384r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x82, 0x67, 0x4B, 0x8E, 0x4E, 0xBE, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xDA, 0x77, 0xF8, 0x23, 0x55, 0x2B, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x02, 0xDE, 0x25, 0x35, 0x2D, 0x74, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0C, 0xB8, 0x0B, 0x39, 0xBA, 0xAD, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x0E, 0x28, 0x4D, 0xE1, 0x3D, 0xE4, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xEC, 0x0A, 0xD4, 0xB8, 0xC4, 0x8D, 0xB0),
+};
+static const mbedtls_mpi_uint secp384r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x68, 0xCE, 0xC2, 0x55, 0x4D, 0x0C, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x20, 0x93, 0x32, 0x90, 0xD6, 0xAE, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x78, 0xAB, 0x43, 0x9E, 0xEB, 0x73, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x97, 0xC3, 0x83, 0xA6, 0x3C, 0xF1, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x25, 0x25, 0x66, 0x08, 0x26, 0xFA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xFB, 0x44, 0x5D, 0x82, 0xEC, 0x3B, 0xAC),
+};
+static const mbedtls_mpi_uint secp384r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x90, 0xEA, 0xB5, 0x04, 0x99, 0xD0, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0xF2, 0x22, 0xA0, 0xEB, 0xFD, 0x45, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA4, 0x81, 0x32, 0xFC, 0xFA, 0xEE, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xBB, 0xA4, 0x6A, 0x77, 0x41, 0x5C, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x1E, 0xAA, 0x4F, 0xF0, 0x10, 0xB3, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x74, 0x13, 0x14, 0x9E, 0x90, 0xD7, 0xE6),
+};
+static const mbedtls_mpi_uint secp384r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xBD, 0x70, 0x4F, 0xA8, 0xD1, 0x06, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4E, 0x2E, 0x68, 0xFC, 0x35, 0xFA, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x53, 0x75, 0xED, 0xF2, 0x5F, 0xC2, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x87, 0x6B, 0x9F, 0x05, 0xE2, 0x22, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x1A, 0xA8, 0xB7, 0x03, 0x9E, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD0, 0x69, 0x88, 0xA8, 0x39, 0x9E, 0x3A),
+};
+static const mbedtls_mpi_uint secp384r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xEF, 0x68, 0xFE, 0xEC, 0x24, 0x08, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x4B, 0x92, 0x0D, 0xB7, 0x34, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xF4, 0xDD, 0x1A, 0xA0, 0x4A, 0xE4, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x63, 0x4F, 0x4F, 0xCE, 0xBB, 0xD6, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xEE, 0x8D, 0xDF, 0x3F, 0x73, 0xB7, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x06, 0xB6, 0x80, 0x4D, 0x81, 0xD9, 0x53),
+};
+static const mbedtls_mpi_uint secp384r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF5, 0x13, 0xDF, 0x13, 0x19, 0x97, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xF9, 0xB3, 0x33, 0x66, 0x82, 0x21, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xFC, 0x39, 0x16, 0x23, 0x43, 0x76, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x48, 0x25, 0xA1, 0x64, 0x95, 0x1C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xAC, 0x15, 0x57, 0xD9, 0xDE, 0xA0, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x5F, 0xB8, 0x3D, 0x48, 0x91, 0x24, 0xCC),
+};
+static const mbedtls_mpi_uint secp384r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xF2, 0xC8, 0x54, 0xD1, 0x32, 0xBD, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x3B, 0xF0, 0xAA, 0x9D, 0xD8, 0xF4, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xC3, 0xBB, 0x6C, 0x66, 0xAC, 0x25, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x25, 0x10, 0xB2, 0xE1, 0x41, 0xDE, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xE8, 0x30, 0xB8, 0x37, 0xBC, 0x2A, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x57, 0x01, 0x4A, 0x1E, 0x78, 0x9F, 0x85),
+};
+static const mbedtls_mpi_uint secp384r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x19, 0xCD, 0x12, 0x0B, 0x51, 0x4F, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x4B, 0x3D, 0x24, 0xA4, 0x16, 0x59, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xEB, 0xD3, 0x59, 0x2E, 0x75, 0x7C, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB9, 0xB4, 0xA5, 0xD9, 0x2E, 0x29, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x16, 0x05, 0x75, 0x02, 0xB3, 0x06, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x7C, 0x9F, 0x79, 0x91, 0xF1, 0x4F, 0x23),
+};
+static const mbedtls_mpi_uint secp384r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x98, 0x7C, 0x84, 0xE1, 0xFF, 0x30, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE2, 0xC2, 0x5F, 0x55, 0x40, 0xBD, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x65, 0x87, 0x3F, 0xC4, 0xC2, 0x24, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x30, 0x0A, 0x60, 0x15, 0xD1, 0x24, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x99, 0xD9, 0xB6, 0xAE, 0xB1, 0xAF, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x80, 0xEE, 0xA2, 0x0F, 0x74, 0xB9, 0xF3),
+};
+static const mbedtls_mpi_uint secp384r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xE6, 0x0F, 0x37, 0xC1, 0x10, 0x99, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xAD, 0x9D, 0x5D, 0x80, 0x01, 0xA6, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x0F, 0x10, 0x2A, 0x9D, 0x20, 0x38, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x60, 0xCB, 0xCE, 0x5A, 0xA0, 0xA7, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xCF, 0x14, 0xDF, 0xBF, 0xE5, 0x74, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x12, 0x1A, 0xDD, 0x59, 0x02, 0x5D, 0xC6),
+};
+static const mbedtls_mpi_uint secp384r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0xF8, 0xF5, 0xB6, 0x13, 0x4D, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x45, 0xB1, 0x93, 0xB3, 0xA2, 0x79, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xF6, 0xCF, 0xF7, 0xE6, 0x29, 0x9C, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x50, 0x65, 0x80, 0xBC, 0x59, 0x0A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xF0, 0x24, 0x35, 0xA2, 0x46, 0xF0, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x26, 0xC0, 0x9D, 0x61, 0x56, 0x62, 0x67),
+};
+static const mbedtls_mpi_uint secp384r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xBB, 0xC2, 0x24, 0x43, 0x2E, 0x37, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xF7, 0xCE, 0x35, 0xFC, 0x77, 0xF3, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x34, 0x96, 0xD5, 0x4A, 0x76, 0x9D, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x3B, 0x0F, 0xEA, 0xA8, 0x12, 0x0B, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x3F, 0x5D, 0x2D, 0x1C, 0xD4, 0x9E, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x2E, 0xDD, 0xC7, 0x6E, 0xAB, 0xAF, 0xDC),
+};
+static const mbedtls_mpi_uint secp384r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xB2, 0x7B, 0x0C, 0x9A, 0x83, 0x8E, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x51, 0x90, 0x92, 0x79, 0x32, 0x19, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x89, 0xF9, 0xD0, 0xCF, 0x2C, 0xA5, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x50, 0x21, 0xDE, 0x50, 0x41, 0x9D, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x7D, 0x2B, 0x9E, 0x9D, 0x95, 0xA8, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA5, 0x20, 0x87, 0x88, 0x97, 0x5F, 0xAA),
+};
+static const mbedtls_mpi_uint secp384r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x59, 0xB4, 0x66, 0x7E, 0xE8, 0x5A, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x5C, 0x7E, 0xB2, 0xAD, 0xD9, 0xC9, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x97, 0x49, 0xA3, 0x13, 0x83, 0x07, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x26, 0xC7, 0x13, 0x35, 0x0D, 0xB0, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x60, 0xAB, 0xFA, 0x4B, 0x93, 0x18, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2D, 0x1C, 0x31, 0x4C, 0xE4, 0x61, 0xAE),
+};
+static const mbedtls_mpi_uint secp384r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x4D, 0x1E, 0x51, 0x59, 0x6E, 0x91, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x54, 0x4D, 0x51, 0xED, 0x36, 0xCC, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xA8, 0x56, 0xC7, 0x78, 0x27, 0x33, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB7, 0x95, 0xC9, 0x8B, 0xC8, 0x6A, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xE9, 0x13, 0x96, 0xB3, 0xE1, 0xF9, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x46, 0xB0, 0x5E, 0xC3, 0x94, 0x03, 0x05),
+};
+static const mbedtls_mpi_uint secp384r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x5B, 0x29, 0x30, 0x41, 0x1A, 0x9E, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xCA, 0x83, 0x31, 0x5B, 0xA7, 0xCB, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x41, 0x50, 0x44, 0x4D, 0x64, 0x31, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x84, 0xC2, 0x5D, 0x97, 0xA5, 0x3C, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x0F, 0xA5, 0xFD, 0x8E, 0x5A, 0x47, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x58, 0x02, 0x2D, 0x40, 0xB1, 0x0B, 0xBA),
+};
+static const mbedtls_mpi_uint secp384r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x33, 0x8C, 0x67, 0xCE, 0x23, 0x43, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x53, 0x47, 0x72, 0x44, 0x1F, 0x5B, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xC1, 0xD9, 0xA4, 0x50, 0x88, 0x63, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xF2, 0x75, 0x69, 0x73, 0x00, 0xC4, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x90, 0x1D, 0xDF, 0x1A, 0x00, 0xD8, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xB1, 0x89, 0x48, 0xA8, 0x70, 0x62, 0xEF),
+};
+static const mbedtls_mpi_uint secp384r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x8A, 0x55, 0x50, 0x7B, 0xEF, 0x8A, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1B, 0x23, 0x48, 0x23, 0x63, 0x91, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x04, 0x54, 0x3C, 0x24, 0x9B, 0xC7, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x38, 0xC3, 0x84, 0xFB, 0xFF, 0x9F, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x2A, 0xE0, 0x6D, 0x68, 0x8A, 0x5C, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x93, 0x53, 0x85, 0xA1, 0x0D, 0xAF, 0x63),
+};
+static const mbedtls_mpi_uint secp384r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x88, 0x95, 0x4C, 0x0B, 0xD0, 0x06, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xAF, 0x8D, 0x49, 0xA2, 0xC8, 0xB4, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x76, 0x53, 0x09, 0x88, 0x43, 0x87, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA4, 0x77, 0x3F, 0x5E, 0x21, 0xB4, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x9E, 0x86, 0x64, 0xCC, 0x91, 0xC1, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x17, 0x56, 0xCB, 0xC3, 0x7D, 0x5B, 0xB1),
+};
+static const mbedtls_mpi_uint secp384r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x74, 0x9F, 0xB5, 0x91, 0x21, 0xB1, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xED, 0xE1, 0x11, 0xEF, 0x45, 0xAF, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x31, 0xBE, 0xB2, 0xBC, 0x72, 0x65, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x4B, 0x8C, 0x77, 0xCE, 0x1E, 0x42, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC9, 0xAA, 0xB9, 0xD9, 0x86, 0x99, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x23, 0x80, 0xC6, 0x4E, 0x35, 0x0B, 0x6D),
+};
+static const mbedtls_mpi_uint secp384r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xD8, 0xA2, 0x0A, 0x39, 0x32, 0x1D, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0xC8, 0x86, 0xF1, 0x12, 0x9A, 0x4A, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xF1, 0x7C, 0xAA, 0x70, 0x8E, 0xBC, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x01, 0x47, 0x8F, 0xDD, 0x8B, 0xA5, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x08, 0x21, 0xF4, 0xAB, 0xC7, 0xF5, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x76, 0xA5, 0x95, 0xC4, 0x0F, 0x88, 0x1D),
+};
+static const mbedtls_mpi_uint secp384r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x42, 0x2A, 0x52, 0xCD, 0x75, 0x51, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x36, 0xE5, 0x04, 0x2B, 0x44, 0xC6, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xEE, 0x16, 0x13, 0x07, 0x83, 0xB5, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x59, 0xC6, 0xA2, 0x19, 0x05, 0xD3, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8B, 0xA8, 0x16, 0x09, 0xB7, 0xEA, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xEE, 0x14, 0xAF, 0xB5, 0xFD, 0xD0, 0xEF),
+};
+static const mbedtls_mpi_uint secp384r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x7C, 0xCA, 0x71, 0x3E, 0x6E, 0x66, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x31, 0x0E, 0x3F, 0xE5, 0x91, 0xC4, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x3D, 0xC2, 0x3E, 0x95, 0x37, 0x58, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x1F, 0x02, 0x03, 0xF3, 0xEF, 0xEE, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x5B, 0x1A, 0xFC, 0x38, 0xCD, 0xE8, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x57, 0x42, 0x85, 0xC6, 0x21, 0x68, 0x71),
+};
+static const mbedtls_mpi_uint secp384r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA2, 0x4A, 0x66, 0xB1, 0x0A, 0xE6, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x0C, 0x94, 0x9D, 0x5E, 0x99, 0xB2, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x03, 0x40, 0xCA, 0xB2, 0xB3, 0x30, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0x48, 0x27, 0x34, 0x1E, 0xE2, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x72, 0x5B, 0xAC, 0xC1, 0x6D, 0xE3, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAB, 0x46, 0xCB, 0xEA, 0x5E, 0x4B, 0x0B),
+};
+static const mbedtls_mpi_uint secp384r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x08, 0xAD, 0x4E, 0x51, 0x9F, 0x2A, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5C, 0x7D, 0x4C, 0xD6, 0xCF, 0xDD, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x76, 0x26, 0xE0, 0x8B, 0x10, 0xD9, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA7, 0x23, 0x4E, 0x5F, 0xD2, 0x42, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xE5, 0xA4, 0xEC, 0x77, 0x21, 0x34, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x14, 0x65, 0xEA, 0x4A, 0x85, 0xC3, 0x2F),
+};
+static const mbedtls_mpi_uint secp384r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xD8, 0x40, 0x27, 0x73, 0x15, 0x7E, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xBB, 0x53, 0x7E, 0x0F, 0x40, 0xC8, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x37, 0x19, 0x73, 0xEF, 0x5A, 0x5E, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x73, 0x2B, 0x49, 0x7E, 0xAC, 0x97, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xB2, 0xC3, 0x1E, 0x0E, 0xE7, 0xD2, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x08, 0xD6, 0xDD, 0xAC, 0x21, 0xD6, 0x3E),
+};
+static const mbedtls_mpi_uint secp384r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x26, 0xBE, 0x6D, 0x6D, 0xF2, 0x38, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6C, 0x31, 0xA7, 0x49, 0x50, 0x3A, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x99, 0xC6, 0xF5, 0xD2, 0xC2, 0x30, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE4, 0xF6, 0x8B, 0x8B, 0x97, 0xE9, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x21, 0xB7, 0x0D, 0xFC, 0x15, 0x54, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x83, 0x1C, 0xA4, 0xCD, 0x6B, 0x9D, 0xF2),
+};
+static const mbedtls_mpi_uint secp384r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE8, 0x4C, 0x48, 0xE4, 0xAA, 0x69, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x7A, 0x27, 0xFC, 0x37, 0x96, 0x1A, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xE7, 0x30, 0xA5, 0xCF, 0x13, 0x46, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xD8, 0xAF, 0x74, 0x23, 0x4D, 0x56, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3D, 0x44, 0x14, 0x1B, 0x97, 0x83, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x47, 0xD7, 0x5F, 0xFD, 0x98, 0x38, 0xF7),
+};
+static const mbedtls_mpi_uint secp384r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x73, 0x64, 0x36, 0xFD, 0x7B, 0xC1, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x5D, 0x32, 0xD2, 0x47, 0x94, 0x89, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xE9, 0x30, 0xAC, 0x06, 0xC8, 0x65, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x6C, 0xB9, 0x1B, 0xF7, 0x61, 0x49, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xFF, 0x32, 0x43, 0x80, 0xDA, 0xA6, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF8, 0x04, 0x01, 0x95, 0x35, 0xCE, 0x21),
+};
+static const mbedtls_mpi_uint secp384r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x06, 0x46, 0x0D, 0x51, 0xE2, 0xD8, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x57, 0x1D, 0x6F, 0x79, 0xA0, 0xCD, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xFB, 0x36, 0xCA, 0xAD, 0xF5, 0x9E, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x7A, 0x1D, 0x9E, 0x1D, 0x95, 0x48, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x26, 0xA5, 0xB7, 0x15, 0x2C, 0xC2, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x42, 0x72, 0xAA, 0x11, 0xDC, 0xC9, 0xB6),
+};
+static const mbedtls_mpi_uint secp384r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x6C, 0x64, 0xA7, 0x62, 0x3C, 0xAB, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x6A, 0x44, 0xD8, 0x60, 0xC0, 0xA8, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x76, 0x58, 0x12, 0x57, 0x3C, 0x89, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x4F, 0x83, 0xCE, 0xCB, 0xB8, 0xD0, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0x04, 0xB0, 0xAD, 0xEB, 0xFA, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA4, 0xC3, 0x41, 0x44, 0x4E, 0x65, 0x3E),
+};
+static const mbedtls_mpi_uint secp384r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x16, 0xA9, 0x1C, 0xE7, 0x65, 0x20, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x53, 0x32, 0xF8, 0xC0, 0xA6, 0xBD, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xF0, 0xE6, 0x57, 0x31, 0xCC, 0x26, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xE3, 0x54, 0x1C, 0x34, 0xD3, 0x17, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xAE, 0xED, 0xFB, 0xCD, 0xE7, 0x1E, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x16, 0x1C, 0x34, 0x40, 0x00, 0x1F, 0xB6),
+};
+static const mbedtls_mpi_uint secp384r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x32, 0x00, 0xC2, 0xD4, 0x3B, 0x1A, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xE0, 0x99, 0x8F, 0x0C, 0x4A, 0x16, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x73, 0x18, 0x1B, 0xD4, 0x94, 0x29, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA4, 0x2D, 0xB1, 0x9D, 0x74, 0x32, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0xF4, 0xB1, 0x0C, 0x37, 0x62, 0x8B, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xFF, 0xDA, 0xE2, 0x35, 0xA3, 0xB6, 0x42),
+};
+static const mbedtls_mpi_uint secp384r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x49, 0x99, 0x65, 0xC5, 0xED, 0x16, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x42, 0x9A, 0xF3, 0xA7, 0x4E, 0x6F, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x0A, 0x7E, 0xC0, 0xD7, 0x4E, 0x07, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x7A, 0x31, 0x69, 0xA6, 0xB9, 0x15, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xE0, 0x72, 0xA4, 0x3F, 0xB9, 0xF8, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x75, 0x32, 0x85, 0xA2, 0xDE, 0x37, 0x12),
+};
+static const mbedtls_mpi_uint secp384r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC0, 0x0D, 0xCF, 0x25, 0x41, 0xA4, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xFC, 0xB2, 0x48, 0xC3, 0x85, 0x83, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBE, 0x0B, 0x58, 0x2D, 0x7A, 0x9A, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xF3, 0x81, 0x18, 0x1B, 0x74, 0x4F, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x43, 0xA3, 0x0A, 0x16, 0x8B, 0xA3, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x18, 0x81, 0x7B, 0x8D, 0xA2, 0x35, 0x77),
+};
+static const mbedtls_mpi_uint secp384r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xC4, 0x3F, 0x2C, 0xE7, 0x5F, 0x99, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2B, 0xB7, 0xB6, 0xAD, 0x5A, 0x56, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x00, 0xA4, 0x48, 0xC8, 0xE8, 0xBA, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xA1, 0xB5, 0x13, 0x5A, 0xCD, 0x99, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x95, 0xAD, 0xFC, 0xE2, 0x7E, 0xE7, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x6B, 0xD1, 0x34, 0x99, 0x53, 0x63, 0x0B),
+};
+static const mbedtls_mpi_uint secp384r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x8A, 0x77, 0x5D, 0x2B, 0xAB, 0x01, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x85, 0xD0, 0xD5, 0x49, 0x83, 0x4D, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xC6, 0x91, 0x30, 0x3B, 0x00, 0xAF, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xAE, 0x61, 0x07, 0xE1, 0xB6, 0xE2, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x43, 0x41, 0xFE, 0x9B, 0xB6, 0xF0, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x97, 0xAE, 0xAD, 0x89, 0x88, 0x9E, 0x41),
+};
+static const mbedtls_ecp_point secp384r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(secp384r1_T_0_X, secp384r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_1_X, secp384r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_2_X, secp384r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_3_X, secp384r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_4_X, secp384r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_5_X, secp384r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_6_X, secp384r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_7_X, secp384r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_8_X, secp384r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_9_X, secp384r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_10_X, secp384r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_11_X, secp384r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_12_X, secp384r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_13_X, secp384r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_14_X, secp384r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_15_X, secp384r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_16_X, secp384r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_17_X, secp384r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_18_X, secp384r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_19_X, secp384r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_20_X, secp384r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_21_X, secp384r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_22_X, secp384r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_23_X, secp384r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_24_X, secp384r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_25_X, secp384r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_26_X, secp384r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_27_X, secp384r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_28_X, secp384r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_29_X, secp384r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_30_X, secp384r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(secp384r1_T_31_X, secp384r1_T_31_Y),
+};
+#else
+#define secp384r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+/*
+ * Domain parameters for secp521r1
+ */
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+static const mbedtls_mpi_uint secp521r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),
+};
+static const mbedtls_mpi_uint secp521r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_2(0x51, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xC6, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_2(0x18, 0x01),
+};
+static const mbedtls_mpi_uint secp521r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_2(0xFF, 0x01),
+};
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp521r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xB1, 0x2D, 0xEB, 0x27, 0x2F, 0xE8, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x4B, 0x44, 0x25, 0xDB, 0x5C, 0x5F, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x85, 0x28, 0x78, 0x2E, 0x75, 0x34, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x57, 0x0F, 0x73, 0x78, 0x7A, 0xE3, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD8, 0xEC, 0xDC, 0xDA, 0x04, 0xAD, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x8A, 0x09, 0xF3, 0x58, 0x79, 0xD8, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x03, 0xCB, 0x50, 0x1A, 0x7F, 0x56, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA6, 0x78, 0x38, 0x85, 0x67, 0x0B, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xD5, 0xD2, 0x22, 0xC4, 0x00, 0x3B, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x93, 0x0E, 0x7B, 0x85, 0x51, 0xC3, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA6, 0x5F, 0x54, 0x49, 0x02, 0x81, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xE9, 0x6B, 0x3A, 0x92, 0xE7, 0x72, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x5F, 0x28, 0x9E, 0x91, 0x27, 0x88, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x28, 0x31, 0xB3, 0x84, 0xCA, 0x12, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xF9, 0xAC, 0x22, 0x10, 0x0A, 0x64, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xC6, 0x33, 0x1F, 0x69, 0x19, 0x18, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x48, 0xB8, 0xC7, 0x37, 0x5A, 0x00, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xCC, 0x32, 0xE0, 0xEE, 0x03, 0xC2, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x29, 0xC2, 0xE4, 0x6E, 0x24, 0x20, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x6B, 0x7F, 0x7B, 0xF9, 0xB0, 0xB8, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x7B, 0x3C, 0xE1, 0x19, 0xA1, 0x23, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE3, 0xC2, 0x53, 0xC0, 0x07, 0x13, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFE, 0x36, 0x35, 0x9F, 0x5E, 0x59, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x55, 0x89, 0x84, 0xBC, 0xEF, 0xA2, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x1A, 0x08, 0x67, 0xB4, 0xE7, 0x22, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x26, 0xDF, 0x81, 0x3C, 0x5F, 0x1C, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x4D, 0xD0, 0x0A, 0x48, 0x06, 0xF4, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x18, 0x39, 0xF7, 0xD1, 0x20, 0x77, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x8F, 0x44, 0x13, 0xCB, 0x78, 0x11, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE2, 0x49, 0xEA, 0x43, 0x79, 0x08, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xD1, 0xD8, 0x73, 0x2C, 0x71, 0x2F, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE5, 0xE7, 0xF4, 0x46, 0xAB, 0x20, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x0B, 0xB9, 0x71, 0x1A, 0x27, 0xB7, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xA2, 0x2C, 0xD1, 0xDA, 0xBC, 0xC1, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xA3, 0x10, 0x1F, 0x90, 0xF2, 0xA5, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xFB, 0x20, 0xF4, 0xC0, 0x70, 0xC0, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xA7, 0x99, 0xF0, 0xA5, 0xD3, 0x09, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xE8, 0x14, 0x39, 0xBE, 0xCB, 0x60, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD6, 0x14, 0xA9, 0xC9, 0x20, 0xC3, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x5B, 0xFD, 0x2D, 0x96, 0xBC, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x04, 0x45, 0xBE, 0xCE, 0x75, 0x95, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xDA, 0x58, 0x49, 0x35, 0x09, 0x8D, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xF0, 0xC0, 0x36, 0xF2, 0xA6, 0x2D, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFC, 0x3D, 0xA8, 0xFB, 0x3C, 0xD2, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x4D, 0x71, 0x09, 0x18, 0x42, 0xF0, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xC1, 0xCE, 0x9E, 0x6A, 0x49, 0x60, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xB1, 0x00, 0xF7, 0xA1, 0x7A, 0x31, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xC3, 0x86, 0xCD, 0x20, 0x4A, 0x17, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xAB, 0x8B, 0x47, 0x8D, 0xAA, 0xA6, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x97, 0xF0, 0xBC, 0x2D, 0xDC, 0x9D, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x86, 0xB0, 0x74, 0xB2, 0xF4, 0xF6, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBD, 0xAC, 0xE3, 0x8F, 0x43, 0x5C, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xC3, 0xE2, 0x6E, 0x25, 0x49, 0xCD, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5E, 0x08, 0xB3, 0xB9, 0xAC, 0x5F, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xB7, 0xD1, 0xF4, 0xDC, 0x19, 0xE9, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xE4, 0xFA, 0xE1, 0x36, 0x3E, 0xED, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x67, 0x92, 0x84, 0x6E, 0x48, 0x03, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x95, 0xEF, 0x8F, 0xB2, 0x82, 0x6B, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFA, 0xB9, 0x55, 0x23, 0xFE, 0x09, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x79, 0x85, 0x4B, 0x0E, 0xD4, 0x35, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x27, 0x45, 0x81, 0xE0, 0x88, 0x52, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x63, 0xA2, 0x4B, 0xBC, 0x5D, 0xB1, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x8C, 0x83, 0xD9, 0x3E, 0xD3, 0x42, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x03, 0x3A, 0x31, 0xBA, 0xE9, 0x3A, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x10, 0xCD, 0x2D, 0x00, 0xFE, 0x32, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x6E, 0x1F, 0xDA, 0xF8, 0x6F, 0x4D, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x79, 0x7D, 0x09, 0xE5, 0xD3, 0x03, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC3, 0xBE, 0xDF, 0x07, 0x65, 0x49, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x57, 0x33, 0xEF, 0xAE, 0x4F, 0x04, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xE9, 0x9B, 0xFE, 0xBF, 0xE6, 0x85, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xBA, 0xAA, 0x06, 0xC4, 0xC6, 0xB8, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x83, 0x01, 0xA9, 0xF6, 0x51, 0xE7, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xA6, 0x15, 0x8E, 0xAB, 0x1F, 0x10, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x08, 0x27, 0x1A, 0xA1, 0x21, 0xAD, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x09, 0x90, 0x6E, 0x50, 0x90, 0x9A, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x9A, 0xFE, 0xD7, 0xA1, 0xF5, 0xA2, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x7D, 0xE3, 0xDC, 0x21, 0xFB, 0xA4, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBF, 0x07, 0xFF, 0x45, 0xDF, 0x51, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x5C, 0x34, 0x02, 0x62, 0x9B, 0x08, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xCE, 0x9A, 0x6A, 0xEC, 0x75, 0xF6, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x59, 0xF4, 0x78, 0x3C, 0x60, 0xB1, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x37, 0x84, 0x6A, 0xDC, 0xF2, 0x9A, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9A, 0x9A, 0x15, 0x36, 0xE0, 0x2B, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x38, 0x9C, 0x50, 0x3D, 0x1E, 0x37, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x79, 0xF0, 0x92, 0xF2, 0x8B, 0x18, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE0, 0x82, 0x1E, 0x80, 0x82, 0x4B, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xBB, 0x59, 0x6B, 0x8A, 0x77, 0x41, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xF9, 0xD4, 0xB8, 0x4A, 0x82, 0xCF, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x8C, 0xC8, 0x9B, 0x72, 0x9E, 0xF7, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xCE, 0xE9, 0x77, 0x0A, 0x19, 0x59, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xA1, 0x41, 0x6A, 0x72, 0x4B, 0xB4, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x35, 0x43, 0xE2, 0x8C, 0xBE, 0x0D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xEB, 0xAD, 0xF3, 0xA9, 0xA6, 0x68, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2F, 0xE2, 0x48, 0x0C, 0xDB, 0x1F, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x1E, 0x60, 0x9B, 0x2A, 0xD2, 0xC1, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x64, 0xB5, 0xD2, 0xF6, 0xF6, 0x6E, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x3D, 0x30, 0x78, 0x10, 0x18, 0x41, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x1D, 0x1C, 0xE0, 0x6D, 0x83, 0xD1, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x03, 0x0B, 0xF5, 0x2F, 0x6C, 0x04, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x3E, 0xD5, 0xFC, 0x31, 0x5B, 0x3A, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x82, 0x2F, 0xFB, 0xFE, 0xF8, 0x76, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x26, 0xDA, 0x9C, 0x36, 0xF5, 0x93, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xE7, 0x6E, 0xD2, 0x7D, 0x81, 0x09, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x03, 0xF9, 0x58, 0x48, 0x24, 0xA2, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x79, 0x0C, 0x8E, 0x6B, 0x95, 0xF3, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x10, 0x5C, 0x87, 0x03, 0x39, 0xCF, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xF0, 0xF7, 0xC1, 0x07, 0xA4, 0xF4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE8, 0x02, 0x89, 0x65, 0xC4, 0x72, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x88, 0xEA, 0x96, 0x67, 0x0B, 0x5D, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x75, 0x60, 0xA8, 0xBD, 0x74, 0xDF, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xE5, 0x71, 0x50, 0x67, 0xD0, 0xD2, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFC, 0xE5, 0xC7, 0x77, 0xB0, 0x7F, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x86, 0x69, 0xCD, 0x0D, 0x9A, 0xBD, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x17, 0xBC, 0xBB, 0x59, 0x85, 0x7D, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xA8, 0x76, 0xAC, 0x80, 0xA9, 0x72, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x78, 0xC1, 0xE2, 0x4D, 0xAF, 0xF9, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x97, 0x8E, 0x74, 0xC4, 0x4B, 0xB2, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD8, 0xF6, 0xF3, 0xAF, 0x2F, 0x52, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x57, 0xF4, 0xCE, 0xEE, 0x43, 0xED, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x46, 0x38, 0xDE, 0x20, 0xFD, 0x59, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x18, 0xE8, 0x58, 0xB9, 0x76, 0x2C, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x54, 0xE4, 0xFE, 0xC7, 0xBC, 0x31, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF8, 0x89, 0xEE, 0x70, 0xB5, 0xB0, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x22, 0x26, 0x9A, 0x53, 0xB9, 0x38, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xA7, 0x19, 0x8C, 0x74, 0x7E, 0x88, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xDA, 0x0A, 0xE8, 0xDA, 0xA5, 0xBE, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x5C, 0xF7, 0xB1, 0x0C, 0x72, 0xFB, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0xE2, 0x23, 0xE7, 0x46, 0xB7, 0xE0, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x36, 0xBC, 0xBD, 0x48, 0x11, 0x8E, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xBB, 0xA1, 0xF7, 0x0B, 0x9E, 0xBF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x28, 0xE1, 0xA2, 0x8F, 0xFC, 0xFC, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xFE, 0x19, 0x0A, 0xE5, 0xE7, 0x69, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xCD, 0x12, 0xF5, 0xBE, 0xD3, 0x04, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA8, 0x0D, 0x81, 0x59, 0xC4, 0x79, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xF3, 0x4B, 0x92, 0x65, 0xC3, 0x31, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xB5, 0x4F, 0x4D, 0x91, 0xD4, 0xE2, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x09, 0x41, 0x79, 0x1D, 0x4D, 0x0D, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x31, 0x18, 0xBA, 0xA0, 0xF2, 0x6E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x5B, 0x4D, 0x4F, 0xAF, 0xC9, 0x8C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x9C, 0x06, 0x68, 0xDE, 0xD8, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x04, 0xE1, 0xB5, 0x9D, 0x00, 0xBC, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x95, 0x92, 0x8D, 0x72, 0xD3, 0x37, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x4B, 0x27, 0xA2, 0xE8, 0xA4, 0x26, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x45, 0x9C, 0xA9, 0xCB, 0x9F, 0xBA, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x7E, 0x1B, 0x64, 0xF4, 0xE8, 0xA5, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x20, 0xA9, 0xCA, 0xF3, 0x89, 0xE5, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xED, 0xFC, 0xAB, 0xD9, 0x0A, 0xB9, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x6F, 0x46, 0x7C, 0xCD, 0x78, 0xFF, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAB, 0x71, 0x5A, 0x94, 0xAB, 0x20, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x2E, 0xEE, 0x87, 0x57, 0x1F, 0xAD, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x4C, 0x3D, 0xFB, 0x7E, 0xA1, 0x8B, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xCF, 0x07, 0x86, 0xBA, 0x53, 0x37, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x26, 0xB2, 0xB9, 0xE2, 0x91, 0xE3, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xC9, 0x54, 0x84, 0x08, 0x3D, 0x0B, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xA8, 0x77, 0x2F, 0x64, 0x45, 0x99, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x96, 0x16, 0x1F, 0xDB, 0x96, 0x28, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x2B, 0x8D, 0xFF, 0xA2, 0x4F, 0x55, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xE6, 0x48, 0xBD, 0x99, 0x3D, 0x12, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x84, 0x59, 0xDA, 0xB9, 0xB6, 0x66, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x78, 0x41, 0x92, 0xDF, 0xF4, 0x3F, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x86, 0x6F, 0x4F, 0xBF, 0x67, 0xDF, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x2B, 0x1E, 0x5F, 0x00, 0xEA, 0xF6, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xB9, 0x6A, 0x89, 0xD8, 0xC0, 0xD7, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x9A, 0x32, 0x23, 0xA0, 0x02, 0x91, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x7F, 0x6A, 0x15, 0x64, 0x6A, 0x8B, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x57, 0x82, 0x58, 0xA9, 0x56, 0xB5, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x50, 0x92, 0x60, 0xCC, 0x81, 0x24, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x3D, 0xAD, 0xDA, 0xD9, 0x51, 0x3E, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xFE, 0x8F, 0xB0, 0x0B, 0xDE, 0x2E, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xD2, 0xBE, 0xEF, 0xAC, 0x76, 0x71, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xE8, 0x72, 0x0B, 0xAC, 0xFE, 0xCA, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0xC7, 0xFC, 0xE3, 0x3C, 0x7C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x04, 0xA7, 0xB9, 0x9B, 0x93, 0xC0, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x48, 0x4B, 0x8E, 0x32, 0xC5, 0xF0, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x42, 0x07, 0xC1, 0xF2, 0xF1, 0x72, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x37, 0x54, 0x9C, 0x88, 0xD2, 0x62, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x19, 0x8A, 0x89, 0x58, 0xA2, 0x0F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xCC, 0x4C, 0x97, 0x30, 0x66, 0x34, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x6A, 0x1E, 0x1F, 0xDB, 0xC9, 0x5E, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x4D, 0x49, 0xFF, 0x9B, 0x9C, 0xAC, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xE4, 0x4B, 0xF2, 0xD4, 0x1A, 0xD2, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xDA, 0xE8, 0x61, 0x9F, 0xC8, 0x49, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xCB, 0xF2, 0x2D, 0x85, 0xF6, 0x8D, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xC5, 0xCD, 0x2C, 0x79, 0xC6, 0x0E, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x1D, 0x55, 0x0F, 0xF8, 0x22, 0x9F, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x56, 0xBA, 0xE7, 0x57, 0x32, 0xEC, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x9A, 0xC6, 0x4C, 0x09, 0xC4, 0x52, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x1E, 0x6F, 0xF4, 0x7D, 0x27, 0xDD, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x11, 0x16, 0xEC, 0x79, 0x83, 0xAD, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x4E, 0x92, 0x1F, 0x19, 0x7D, 0x65, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xFF, 0x78, 0x15, 0x45, 0x63, 0x32, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x91, 0xD0, 0x78, 0x58, 0xDA, 0x50, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xDE, 0x40, 0xF6, 0x41, 0xB4, 0x3B, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x8D, 0xE0, 0xE1, 0xA9, 0xF0, 0x35, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xD4, 0xBA, 0x7B, 0xCC, 0x1B, 0x3A, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x5A, 0x2E, 0x74, 0x47, 0x14, 0xC3, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xF0, 0x8B, 0x06, 0x15, 0x8E, 0x0E, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xD2, 0xEB, 0x97, 0x50, 0x7D, 0x31, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x93, 0x4C, 0xDB, 0x97, 0x79, 0x44, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xA2, 0xA0, 0x0B, 0xC8, 0x3A, 0x8A, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x50, 0x92, 0x9E, 0x24, 0x1F, 0xCB, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x16, 0xC9, 0xC5, 0x3D, 0x5A, 0xAF, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xE3, 0x97, 0xE4, 0xA8, 0x50, 0xF6, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x57, 0x97, 0x42, 0x78, 0x92, 0x49, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEB, 0x62, 0x24, 0xFB, 0x8F, 0x32, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x0C, 0x36, 0x6E, 0x8F, 0xE8, 0xE8, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xD3, 0x7C, 0xC7, 0x8D, 0x3F, 0x5C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x64, 0x6A, 0x73, 0x10, 0x79, 0xB8, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xF9, 0xEF, 0xA5, 0x20, 0x4A, 0x5C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xF3, 0xF4, 0x49, 0x5B, 0x73, 0xAA, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xF2, 0xEA, 0x0F, 0x00, 0xAD, 0x53, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xB8, 0x66, 0xED, 0xC4, 0x2B, 0x4C, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x2F, 0xC1, 0x9A, 0x37, 0xD2, 0x7F, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xA7, 0x81, 0x38, 0x64, 0xC9, 0x37, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x3B, 0x6C, 0x9F, 0x5B, 0xD9, 0x8B, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x14, 0xD9, 0x08, 0xD8, 0xD2, 0x7E, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x71, 0xE6, 0x3D, 0xD1, 0xB0, 0xE7, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x81, 0x23, 0xEC, 0x2D, 0x42, 0x45, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x5B, 0x44, 0x6B, 0x89, 0x03, 0x67, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x27, 0xAE, 0x80, 0x5A, 0x33, 0xBE, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB6, 0x64, 0x1A, 0xDF, 0xD3, 0x85, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x8C, 0x22, 0xBA, 0xD0, 0xBD, 0xCC, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x3C, 0x01, 0x3A, 0xFF, 0x9D, 0xC7, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC7, 0x64, 0xB4, 0x59, 0x4E, 0x9F, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x34, 0x0A, 0x41, 0x94, 0xA8, 0xF2, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD4, 0xE4, 0xF0, 0x97, 0x45, 0x6D, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x1F, 0x4D, 0x6D, 0xFE, 0xA0, 0xC4, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x28, 0x5C, 0x40, 0xBB, 0x65, 0xD4, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xA8, 0x87, 0x35, 0x20, 0x3A, 0x89, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFD, 0x4F, 0xAB, 0x2D, 0xD1, 0xD0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE8, 0x00, 0xFC, 0x69, 0x52, 0xF8, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x9A, 0x99, 0xE1, 0xDC, 0x9C, 0x3F, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x08, 0x98, 0xD9, 0xCA, 0x73, 0xD5, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x2C, 0xE0, 0xA7, 0x3E, 0x91, 0xD7, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x04, 0xB0, 0x54, 0x09, 0xF4, 0x72, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xEE, 0x28, 0xCC, 0xE8, 0x50, 0x78, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x91, 0x03, 0x76, 0xDB, 0x68, 0x24, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xE0, 0x56, 0xB2, 0x5D, 0x12, 0xD3, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x42, 0x59, 0x8B, 0xDF, 0x67, 0xB5, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xCC, 0xE5, 0x31, 0x53, 0x7A, 0x46, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8D, 0x59, 0xB5, 0x1B, 0x0F, 0xF4, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x2F, 0xD1, 0x2C, 0xE0, 0xD8, 0x04, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0xD7, 0xBA, 0xB0, 0xA3, 0x7E, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x08, 0x51, 0x56, 0xA6, 0x76, 0x67, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x17, 0x63, 0xFE, 0x56, 0xD0, 0xD9, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xF6, 0xC3, 0x14, 0x47, 0xC5, 0xA7, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x4C, 0x80, 0xF6, 0xA2, 0x57, 0xA7, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xB3, 0x7B, 0xF8, 0x2F, 0xE1, 0x3E, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0xF4, 0xF9, 0x6B, 0x7B, 0x90, 0xDF, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x82, 0xEF, 0x62, 0xA1, 0x4C, 0x53, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x99, 0x76, 0x01, 0xBA, 0x8D, 0x0F, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xF4, 0x58, 0x73, 0x56, 0xFE, 0xDD, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xCE, 0xF9, 0xE8, 0xA1, 0x34, 0xC3, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x5F, 0xDC, 0x6A, 0x3D, 0xD8, 0x7F, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xF4, 0x51, 0xB8, 0xB8, 0xC1, 0xD7, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x7D, 0x58, 0xD1, 0xD4, 0x1B, 0x4D, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x95, 0xDF, 0x00, 0xD8, 0x21, 0xDE, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x47, 0x3C, 0xC3, 0xB2, 0x01, 0x53, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x17, 0x43, 0x23, 0xBD, 0xCA, 0x71, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xBA, 0x0F, 0x4F, 0xDC, 0x41, 0x54, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x39, 0x26, 0x70, 0x53, 0x32, 0x18, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x46, 0x07, 0x97, 0x3A, 0x57, 0xE0, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x92, 0x4F, 0xCE, 0xDF, 0x25, 0x80, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x6F, 0x9A, 0x03, 0x05, 0x4B, 0xD1, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x01, 0x72, 0x30, 0x90, 0x17, 0x51, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xFB, 0x41, 0x65, 0x5C, 0xB4, 0x2D, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xCD, 0xCD, 0xAA, 0x41, 0xCC, 0xBB, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xCE, 0x08, 0x0A, 0x63, 0xE9, 0xA2, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xA8, 0x21, 0x7F, 0x7A, 0x5B, 0x9B, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x6B, 0x89, 0x44, 0x0A, 0x7F, 0x85, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0xDE, 0x7C, 0x19, 0x5C, 0x65, 0x26, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0xAC, 0x62, 0x29, 0x4A, 0xF1, 0xD0, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x00, 0x40, 0x87, 0xEB, 0xA9, 0x58, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x51, 0x0B, 0xFF, 0x56, 0x35, 0x51, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xAC, 0x08, 0x94, 0x71, 0xDA, 0xEC, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x4D, 0xC5, 0x7B, 0x31, 0x8B, 0x8D, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x05, 0xF1, 0x3E, 0x9E, 0x8F, 0x17, 0x8F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x9C, 0x4B, 0x62, 0x94, 0xAD, 0x49, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xC9, 0xC6, 0x8F, 0xFD, 0x33, 0x44, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x96, 0x17, 0x7F, 0x42, 0xBE, 0xF7, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x29, 0x39, 0x13, 0x08, 0x8D, 0x91, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x79, 0xF9, 0x2F, 0xA9, 0x0A, 0xCF, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x87, 0x7A, 0xA3, 0x19, 0xAB, 0x55, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x0B, 0x01, 0xC5, 0x56, 0x19, 0x9D, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xDE, 0x82, 0x3B, 0xEA, 0xD3, 0x0B, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x6B, 0xC7, 0xF3, 0x0F, 0x82, 0x87, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x2E, 0x23, 0xF2, 0x39, 0x9D, 0x49, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0xDE, 0xAF, 0x7A, 0xEE, 0xB0, 0xDA, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x4E, 0x2A, 0x50, 0xFD, 0x8E, 0xC0, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x0F, 0x7C, 0x76, 0x63, 0xD8, 0x89, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x2D, 0xB9, 0x4E, 0xF4, 0xEE, 0x85, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x95, 0x5C, 0x96, 0x5D, 0xAA, 0x59, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xDB, 0xD2, 0x68, 0x8E, 0x5A, 0x94, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x02, 0xBF, 0x77, 0x9F, 0xB9, 0x4C, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xDC, 0xC0, 0xCF, 0x81, 0x1E, 0xC4, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xCC, 0x37, 0x86, 0xDC, 0xE2, 0x64, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x30, 0xB1, 0x59, 0x20, 0x9D, 0x98, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x0C, 0x9D, 0xF8, 0x20, 0xDC, 0x90, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xA0, 0xF4, 0xE7, 0x3E, 0x9C, 0x9E, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x25, 0xA2, 0xB0, 0x54, 0xCD, 0x2E, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD9, 0x42, 0xB0, 0x80, 0xB0, 0xA3, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xFE, 0x9D, 0x8D, 0x40, 0xFF, 0x27, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x9D, 0xA6, 0x88, 0x3A, 0x8B, 0x6F, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x39, 0xEE, 0x1F, 0x3F, 0xB1, 0x4F, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xD7, 0x9E, 0xFF, 0xD2, 0x35, 0x67, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x4F, 0x15, 0x5D, 0xE3, 0xE8, 0x53, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xF7, 0x24, 0x98, 0xA2, 0xCB, 0x11, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x2E, 0x25, 0xE1, 0x94, 0xC5, 0xA3, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x82, 0x6E, 0xBA, 0xE7, 0x43, 0x25, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x65, 0xB4, 0x49, 0x73, 0x18, 0x35, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0x5B, 0xBC, 0x62, 0x86, 0x4C, 0xC1, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xF2, 0x95, 0xA2, 0xBB, 0xA2, 0x35, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x59, 0x62, 0xB0, 0x4B, 0x1E, 0xB4, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x55, 0xCE, 0xB0, 0x69, 0xBA, 0x63, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x69, 0x86, 0xDB, 0x34, 0x7D, 0x68, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x06, 0xCA, 0x55, 0x44, 0x36, 0x2B, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xD4, 0xC4, 0x3D, 0xCD, 0x9E, 0x69, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x44, 0xE4, 0xBF, 0x31, 0xE6, 0x40, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x4F, 0xFA, 0x75, 0xE3, 0xFB, 0x97, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xC0, 0xBD, 0x1C, 0x48, 0xB0, 0x26, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x7B, 0x32, 0xFA, 0xF2, 0x6D, 0x84, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x21, 0x03, 0x1D, 0x0D, 0x22, 0x55, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xF9, 0x42, 0x03, 0x9C, 0xC2, 0xCB, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xA1, 0x96, 0xD9, 0x9D, 0x11, 0x6F, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x40, 0x57, 0xEB, 0x40, 0x2D, 0xC0, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x96, 0xBB, 0x4F, 0x2F, 0x23, 0xA8, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x29, 0x85, 0x21, 0xA5, 0x50, 0x62, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x7D, 0x92, 0xCF, 0x87, 0x0C, 0x22, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x0E, 0xA5, 0x32, 0x5B, 0xDF, 0x9C, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x96, 0x37, 0x2C, 0x88, 0x35, 0x30, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xB4, 0x69, 0xFF, 0xEB, 0xC6, 0x94, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x55, 0x60, 0xAD, 0xAA, 0x58, 0x14, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xFF, 0xF2, 0xB2, 0xD5, 0xA7, 0xD9, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xAE, 0x54, 0xD2, 0x60, 0x31, 0xF3, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x92, 0x83, 0xE3, 0xF1, 0x42, 0x83, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD2, 0xC8, 0xB7, 0x76, 0x45, 0x7F, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x11, 0xA4, 0xFB, 0x7A, 0x01, 0xBC, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x27, 0x73, 0x8D, 0x02, 0x91, 0x27, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x62, 0xF6, 0xDD, 0x6B, 0xFA, 0x5B, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xCA, 0xA2, 0x44, 0x2C, 0xF0, 0x28, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xF1, 0x7A, 0xA2, 0x42, 0x4C, 0x50, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x83, 0x3E, 0x50, 0xAB, 0x9C, 0xF7, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xED, 0x78, 0xCB, 0x76, 0x69, 0xDA, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x01, 0x1E, 0x43, 0x27, 0x47, 0x6E, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x4F, 0x54, 0xB9, 0x3E, 0xBD, 0xD5, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x40, 0x69, 0x7F, 0x74, 0x9D, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x06, 0x6F, 0x67, 0x68, 0x2B, 0x4D, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x65, 0x41, 0xFC, 0x7C, 0x1E, 0xE8, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x79, 0x37, 0xAF, 0xFD, 0xD2, 0xDA, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xA8, 0x69, 0x56, 0x62, 0xA4, 0xE4, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x71, 0x73, 0x21, 0x8A, 0x17, 0x81, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x55, 0x8F, 0x7B, 0xB8, 0xAF, 0xF7, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xD1, 0xBD, 0xBE, 0x8C, 0xBC, 0x60, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA6, 0x57, 0x8C, 0xAE, 0x5C, 0x19, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x43, 0xE4, 0xD9, 0xD8, 0x7B, 0xE7, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xB9, 0xE4, 0x85, 0x7C, 0x2E, 0xFC, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2E, 0x01, 0x2A, 0x6D, 0x56, 0xBE, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x0C, 0x25, 0x9B, 0xAE, 0x86, 0x37, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x22, 0xB3, 0xCB, 0x99, 0x66, 0xB7, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xF7, 0x90, 0xF0, 0x1B, 0x09, 0x27, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x16, 0x08, 0xEF, 0x39, 0x64, 0x49, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA0, 0xE3, 0x97, 0xA9, 0x07, 0x54, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xFF, 0xE2, 0x00, 0x07, 0x21, 0x88, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xFD, 0x59, 0x53, 0x05, 0x6C, 0x42, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xF7, 0x39, 0x5C, 0x82, 0x36, 0xE8, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x83, 0xA8, 0xE2, 0xA8, 0x43, 0x07, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xAF, 0x2B, 0x79, 0xED, 0xD8, 0x39, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x20, 0x91, 0x7A, 0xC4, 0x07, 0xEF, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x10, 0x2F, 0xAA, 0x0C, 0x94, 0x0E, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x81, 0x87, 0x41, 0x23, 0xEB, 0x55, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x53, 0xCC, 0x79, 0xB6, 0xEB, 0x6C, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x77, 0x73, 0x9D, 0xFC, 0x64, 0x6F, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x40, 0xE3, 0x6D, 0x1C, 0x16, 0x71, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xF4, 0x1B, 0xFF, 0x1C, 0x2F, 0xA5, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x0E, 0x0B, 0x11, 0xF4, 0x8D, 0x93, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xC5, 0x64, 0x6F, 0x24, 0x19, 0xF2, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xB3, 0xAF, 0xA5, 0x0E, 0x4F, 0x5E, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x77, 0xCA, 0xF2, 0x6D, 0xC5, 0xF6, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x18, 0x8E, 0x33, 0x68, 0x6C, 0xE8, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x8B, 0x80, 0x90, 0x19, 0x7F, 0x90, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x80, 0x6B, 0x68, 0xE2, 0x7D, 0xD4, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xC1, 0x67, 0xB3, 0x72, 0xCB, 0xBF, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xD5, 0xD3, 0x1D, 0x14, 0x58, 0x0A, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x7A, 0x65, 0x98, 0xB3, 0x07, 0x4B, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x87, 0x0F, 0x5F, 0xCF, 0xA2, 0x01, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xC9, 0xC8, 0x6E, 0x35, 0x87, 0xA5, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x3E, 0x91, 0xA0, 0xAB, 0x24, 0x1E, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xBC, 0x02, 0x35, 0x70, 0xC1, 0x5F, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x59, 0xA0, 0x50, 0x04, 0x80, 0x52, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x56, 0x6E, 0x42, 0x8F, 0x8C, 0x91, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xA2, 0xCB, 0xA5, 0xDE, 0x14, 0x24, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xCB, 0x74, 0x28, 0xE6, 0xA7, 0xE7, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x73, 0xA8, 0x8F, 0x9E, 0x0E, 0x63, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x1B, 0x77, 0xC7, 0xC1, 0x38, 0xF9, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x3C, 0xCF, 0xA8, 0x7A, 0xD7, 0xF3, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x5F, 0x9A, 0xC9, 0xAD, 0xE9, 0x1A, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0x2B, 0x5E, 0xD5, 0x81, 0x95, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x88, 0x75, 0x29, 0x1F, 0xC7, 0xC7, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA9, 0x5A, 0x4D, 0x63, 0x95, 0xF9, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xCD, 0x04, 0x8F, 0xCD, 0x91, 0xDE, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xD4, 0xFD, 0x25, 0x11, 0x99, 0x6E, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x83, 0x01, 0x3D, 0xFB, 0x56, 0xA5, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x3A, 0xDC, 0x74, 0xC2, 0xD7, 0xCF, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0xBD, 0xF1, 0xDD, 0xA3, 0x07, 0x03, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xBE, 0xE9, 0x2E, 0x58, 0x84, 0x66, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x20, 0x78, 0x37, 0x79, 0x0B, 0xA6, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xF2, 0xAC, 0x65, 0xC8, 0xC9, 0x2F, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x93, 0xE5, 0x0D, 0x0C, 0xC6, 0xB8, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xAD, 0x5C, 0x19, 0x12, 0x61, 0x0E, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x4F, 0x0B, 0x1F, 0x49, 0x7E, 0xCD, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2E, 0x30, 0x61, 0xDB, 0x08, 0x68, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x78, 0xAF, 0xB3, 0x08, 0xC1, 0x69, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x5F, 0x5D, 0xC1, 0x57, 0x6F, 0xD8, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xD3, 0x6A, 0xF7, 0xFD, 0x86, 0xE5, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x63, 0xBD, 0x70, 0x7B, 0x47, 0xE8, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x62, 0xC8, 0x7E, 0x9D, 0x11, 0x2B, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x84, 0xFD, 0xD5, 0x9A, 0x56, 0x7F, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBB, 0xA4, 0x6F, 0x12, 0x6E, 0x4D, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x08, 0xA1, 0x82, 0x9C, 0x62, 0x74, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x22, 0x05, 0x1D, 0x15, 0x35, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x88, 0xCF, 0x5C, 0x05, 0x78, 0xFB, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x6B, 0x2F, 0x79, 0x09, 0x73, 0x67, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA0, 0x80, 0xD8, 0xE8, 0xEC, 0xFB, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xE7, 0x0B, 0xB7, 0x81, 0x48, 0x7B, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x53, 0xA9, 0xED, 0x61, 0x92, 0xD7, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x49, 0xD9, 0x5D, 0x9B, 0x4E, 0x89, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x12, 0xEB, 0x9A, 0xC9, 0xCB, 0xC1, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xDC, 0x95, 0x16, 0xFE, 0x29, 0x70, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x33, 0xB1, 0xD6, 0x78, 0xB9, 0xE2, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xCE, 0x88, 0xC3, 0xFD, 0x7A, 0x6B, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x1E, 0x50, 0x1E, 0xAF, 0xB1, 0x25, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xE7, 0xD7, 0xD5, 0xBD, 0x7A, 0x12, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xAA, 0xA2, 0x80, 0x5D, 0x8F, 0xCD, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x39, 0x79, 0x64, 0xA1, 0x67, 0x3C, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xC7, 0x49, 0xFF, 0x7F, 0xAC, 0xAB, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x54, 0x3E, 0x83, 0xF0, 0x3D, 0xBC, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x92, 0x4A, 0x38, 0x42, 0x8A, 0xAB, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x0B, 0x4F, 0xEE, 0x9E, 0x92, 0xA5, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0xDD, 0x19, 0x96, 0xF2, 0xF0, 0x6B, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xFC, 0xDD, 0xB2, 0x8A, 0xE5, 0x4C, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x06, 0x49, 0xAC, 0x99, 0x7E, 0xF8, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xC8, 0x01, 0x51, 0xEA, 0xF6, 0x52, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x89, 0x66, 0x2B, 0x1F, 0x9B, 0x2A, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x0F, 0x95, 0x07, 0x2B, 0x6C, 0x6E, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0xC3, 0xB4, 0xBB, 0x91, 0x1F, 0xA3, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x6E, 0x54, 0x28, 0x7B, 0x9C, 0x79, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x45, 0xFF, 0xA6, 0xDA, 0xA2, 0x83, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xDE, 0x8F, 0x17, 0x37, 0x82, 0xCB, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x94, 0x3F, 0x26, 0xC9, 0x1D, 0xD9, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x97, 0x28, 0x20, 0xCD, 0xC1, 0xF3, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC9, 0xB5, 0x60, 0x9B, 0x1E, 0xDC, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xB9, 0x5B, 0x7D, 0xA0, 0xB2, 0x8C, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xD1, 0x42, 0xE6, 0x39, 0x33, 0x6D, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xC0, 0xFC, 0xD2, 0x14, 0x5D, 0x3E, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x4A, 0x3E, 0x40, 0x16, 0x93, 0x15, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x24, 0xC1, 0x27, 0x27, 0xE5, 0x4B, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x50, 0xD8, 0xBC, 0xC1, 0x46, 0x22, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x0E, 0x60, 0xA1, 0xB3, 0x50, 0xD4, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xB1, 0x26, 0xB6, 0x6D, 0x47, 0x5A, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0xAC, 0x11, 0x35, 0x3E, 0xB9, 0xF4, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x97, 0xFA, 0xBB, 0x6B, 0x39, 0x13, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x34, 0x12, 0x75, 0x8E, 0x9B, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x9E, 0xCD, 0x29, 0xB6, 0xEF, 0x8D, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xAC, 0xE9, 0x25, 0x27, 0xBB, 0x78, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x7A, 0xA8, 0xD3, 0xE3, 0x66, 0xE5, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x4C, 0xC4, 0x2C, 0x76, 0x81, 0x50, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x71, 0x08, 0xB8, 0x52, 0x7C, 0xAF, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x59, 0x24, 0xDD, 0xFB, 0x2F, 0xD0, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCD, 0x56, 0xE9, 0xAC, 0x91, 0xE6, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x64, 0x20, 0xC6, 0x9F, 0xE4, 0xEF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x2C, 0x8F, 0x8C, 0x97, 0xF6, 0x22, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xF4, 0x88, 0xAA, 0xA8, 0xD7, 0xA5, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x6C, 0xAE, 0x83, 0xB1, 0x55, 0x55, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x67, 0x84, 0x47, 0x7C, 0x83, 0x5C, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x10, 0x4D, 0xDD, 0x30, 0x60, 0xB0, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xA7, 0x36, 0x76, 0x24, 0x32, 0x9F, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x42, 0x81, 0xFB, 0xA4, 0x2E, 0x13, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x94, 0x91, 0xFF, 0x99, 0xA0, 0x09, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x83, 0xA1, 0x76, 0xAF, 0x37, 0x5C, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA8, 0x04, 0x86, 0xC4, 0xA9, 0x79, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x8C, 0xC2, 0x34, 0xFB, 0x83, 0x28, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x03, 0x7D, 0x5E, 0x9E, 0x0E, 0xB0, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x02, 0x46, 0x7F, 0xB9, 0xAC, 0xBB, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xED, 0x48, 0xC2, 0x96, 0x4D, 0x56, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xC5, 0xD1, 0xE6, 0x1C, 0x7E, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x2E, 0x18, 0x71, 0x2D, 0x7B, 0xD7, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x46, 0x9D, 0xDE, 0xAA, 0x78, 0x8E, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD7, 0x69, 0x2E, 0xE1, 0xD9, 0x48, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp521r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFF, 0x9E, 0x09, 0x22, 0x22, 0xE6, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x14, 0x28, 0x13, 0x1B, 0x62, 0x12, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x7F, 0x67, 0x03, 0xB0, 0xC0, 0xF3, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xC3, 0x0F, 0xFB, 0x25, 0x48, 0x3E, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x6E, 0x53, 0x98, 0x36, 0xB3, 0xD3, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x81, 0x54, 0x22, 0xA4, 0xCC, 0xC1, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xBA, 0xFC, 0xA9, 0xDF, 0x68, 0x86, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x92, 0x0E, 0xC3, 0xF2, 0x58, 0xE8, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp521r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(secp521r1_T_0_X, secp521r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_1_X, secp521r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_2_X, secp521r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_3_X, secp521r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_4_X, secp521r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_5_X, secp521r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_6_X, secp521r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_7_X, secp521r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_8_X, secp521r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_9_X, secp521r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_10_X, secp521r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_11_X, secp521r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_12_X, secp521r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_13_X, secp521r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_14_X, secp521r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_15_X, secp521r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_16_X, secp521r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_17_X, secp521r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_18_X, secp521r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_19_X, secp521r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_20_X, secp521r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_21_X, secp521r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_22_X, secp521r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_23_X, secp521r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_24_X, secp521r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_25_X, secp521r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_26_X, secp521r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_27_X, secp521r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_28_X, secp521r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_29_X, secp521r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_30_X, secp521r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(secp521r1_T_31_X, secp521r1_T_31_Y),
+};
+#else
+#define secp521r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+static const mbedtls_mpi_uint secp192k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp192k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp192k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x03, 0x00),
+};
+static const mbedtls_mpi_uint secp192k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),
+};
+static const mbedtls_mpi_uint secp192k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),
+};
+static const mbedtls_mpi_uint secp192k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp192k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB),
+};
+static const mbedtls_mpi_uint secp192k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B),
+};
+static const mbedtls_mpi_uint secp192k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x77, 0x3D, 0x0D, 0x85, 0x48, 0xA8, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x07, 0xDF, 0x1D, 0xB3, 0xB3, 0x01, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x86, 0xF6, 0xAF, 0x19, 0x2A, 0x88, 0x2E),
+};
+static const mbedtls_mpi_uint secp192k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x90, 0xB6, 0x2F, 0x48, 0x36, 0x4C, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x11, 0x14, 0xA6, 0xCB, 0xBA, 0x15, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB0, 0xF2, 0xD4, 0xC9, 0xDA, 0xBA, 0xD7),
+};
+static const mbedtls_mpi_uint secp192k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0xC1, 0x9C, 0xE6, 0xBB, 0xFB, 0xCF, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x19, 0xAC, 0x5A, 0xC9, 0x8A, 0x1C, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xF6, 0x76, 0x86, 0x89, 0x27, 0x8D, 0x28),
+};
+static const mbedtls_mpi_uint secp192k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xE0, 0x6F, 0x34, 0xBA, 0x5E, 0xD3, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xDC, 0xA6, 0x87, 0xC9, 0x9D, 0xC0, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x11, 0x7E, 0xD6, 0xF7, 0x33, 0xFC, 0xE4),
+};
+static const mbedtls_mpi_uint secp192k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x37, 0x3E, 0xC0, 0x7F, 0x62, 0xE7, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3B, 0x69, 0x9D, 0x44, 0xBC, 0x82, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x84, 0xB3, 0x5F, 0x2B, 0xA5, 0x9E, 0x2C),
+};
+static const mbedtls_mpi_uint secp192k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x95, 0xEB, 0x4C, 0x04, 0xB4, 0xF4, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xAD, 0x4B, 0xD5, 0x9A, 0xEB, 0xC4, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xB1, 0xC5, 0x59, 0xE3, 0xD5, 0x16, 0x2A),
+};
+static const mbedtls_mpi_uint secp192k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x2A, 0xCC, 0xAC, 0xD0, 0xEE, 0x50, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x83, 0xE0, 0x5B, 0x14, 0x44, 0x52, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x15, 0x2D, 0x78, 0xF6, 0x51, 0x32, 0xCF),
+};
+static const mbedtls_mpi_uint secp192k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x36, 0x9B, 0xDD, 0xF8, 0xDD, 0xEF, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xB1, 0x6A, 0x2B, 0xAF, 0xEB, 0x2B, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x87, 0x7A, 0x66, 0x5D, 0x5B, 0xDF, 0x8F),
+};
+static const mbedtls_mpi_uint secp192k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x45, 0xE5, 0x81, 0x9B, 0xEB, 0x37, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x29, 0xE2, 0x20, 0x64, 0x23, 0x6B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x1D, 0x41, 0xE1, 0x9B, 0x61, 0x7B, 0xD9),
+};
+static const mbedtls_mpi_uint secp192k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x57, 0xA3, 0x0A, 0x13, 0xE4, 0x59, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x6E, 0x4A, 0x48, 0x84, 0x90, 0xAC, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB8, 0xF5, 0xF3, 0xDE, 0xA0, 0xA1, 0x1D),
+};
+static const mbedtls_mpi_uint secp192k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x32, 0x81, 0xA9, 0x91, 0x5A, 0x4E, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xA8, 0x90, 0xBE, 0x0F, 0xEC, 0xC0, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x30, 0xD7, 0x08, 0xAE, 0xC4, 0x3A, 0xA5),
+};
+static const mbedtls_mpi_uint secp192k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x55, 0xE3, 0x76, 0xB3, 0x64, 0x74, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x75, 0xD4, 0xDB, 0x98, 0xD7, 0x39, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xEB, 0x8A, 0xAB, 0x16, 0xD9, 0xD4, 0x0B),
+};
+static const mbedtls_mpi_uint secp192k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xBE, 0xF9, 0xC7, 0xC7, 0xBA, 0xF3, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x85, 0x59, 0xF3, 0x60, 0x41, 0x02, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x1C, 0x4A, 0xA4, 0xC7, 0xED, 0x66, 0xBC),
+};
+static const mbedtls_mpi_uint secp192k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x2E, 0x46, 0x52, 0x18, 0x87, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x35, 0x5A, 0x75, 0xAC, 0x4D, 0x75, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0x2F, 0xAC, 0xFC, 0xBC, 0xE6, 0x93, 0x5E),
+};
+static const mbedtls_mpi_uint secp192k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x4D, 0xC9, 0x18, 0xE9, 0x00, 0xEB, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x69, 0x72, 0x07, 0x5A, 0x59, 0xA8, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x65, 0x83, 0x20, 0x10, 0xF9, 0x69, 0x82),
+};
+static const mbedtls_mpi_uint secp192k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x56, 0x7F, 0x9F, 0xBF, 0x46, 0x0C, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xCF, 0xF0, 0xDC, 0xDF, 0x2D, 0xE6, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xF0, 0x72, 0x3A, 0x7A, 0x03, 0xE5, 0x22),
+};
+static const mbedtls_mpi_uint secp192k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xAA, 0x57, 0x13, 0x37, 0xA7, 0x2C, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xAC, 0xA2, 0x23, 0xF9, 0x84, 0x60, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xEB, 0x51, 0x70, 0x64, 0x78, 0xCA, 0x05),
+};
+static const mbedtls_mpi_uint secp192k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xCC, 0x30, 0x62, 0x93, 0x46, 0x13, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x26, 0xCC, 0x6C, 0x3D, 0x5C, 0xDA, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xAA, 0xB8, 0x03, 0xA4, 0x1A, 0x00, 0x96),
+};
+static const mbedtls_mpi_uint secp192k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x9D, 0xE6, 0xCC, 0x4E, 0x2E, 0xC2, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xC3, 0x8A, 0xAE, 0x6F, 0x40, 0x05, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x8F, 0x4A, 0x4D, 0x35, 0xD3, 0x50, 0x9D),
+};
+static const mbedtls_mpi_uint secp192k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xFD, 0x98, 0xAB, 0xC7, 0x03, 0xB4, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x40, 0xD2, 0x9F, 0xCA, 0xD0, 0x53, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x84, 0x00, 0x6F, 0xC8, 0xAD, 0xED, 0x8D),
+};
+static const mbedtls_mpi_uint secp192k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xD3, 0x57, 0xD7, 0xC3, 0x07, 0xBD, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xBA, 0x47, 0x1D, 0x3D, 0xEF, 0x98, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC0, 0x6C, 0x7F, 0x12, 0xEE, 0x9F, 0x67),
+};
+static const mbedtls_mpi_uint secp192k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x02, 0xDA, 0x79, 0xAA, 0xC9, 0x27, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x79, 0xC7, 0x71, 0x84, 0xCB, 0xE5, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x37, 0x06, 0xBA, 0xB5, 0xD5, 0x18, 0x4C),
+};
+static const mbedtls_mpi_uint secp192k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x65, 0x72, 0x6C, 0xF2, 0x63, 0x27, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0xBC, 0x71, 0xDF, 0x75, 0xF8, 0x98, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x70, 0x9B, 0xDC, 0xE7, 0x18, 0x71, 0xFF),
+};
+static const mbedtls_mpi_uint secp192k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x5B, 0x9F, 0x00, 0x5A, 0xB6, 0x80, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xE0, 0xBB, 0xFC, 0x5E, 0x78, 0x9C, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x03, 0x68, 0x83, 0x3D, 0x2E, 0x4C, 0xDD),
+};
+static const mbedtls_mpi_uint secp192k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x49, 0x23, 0xA8, 0xCB, 0x3B, 0x1A, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x3D, 0xA7, 0x46, 0xCF, 0x75, 0xB6, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0xFD, 0x30, 0x01, 0xB6, 0xEF, 0xF9, 0xE8),
+};
+static const mbedtls_mpi_uint secp192k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xFA, 0xDA, 0xB8, 0x29, 0x42, 0xC9, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xD7, 0xA0, 0xE6, 0x6B, 0x86, 0x61, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0xE9, 0xD3, 0x37, 0xD8, 0xE7, 0x35, 0xA9),
+};
+static const mbedtls_mpi_uint secp192k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC8, 0x8E, 0xB1, 0xCB, 0xB1, 0xB5, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xD7, 0x46, 0x7D, 0xAF, 0xE2, 0xDC, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x46, 0xE7, 0xD8, 0x76, 0x31, 0x90, 0x76),
+};
+static const mbedtls_mpi_uint secp192k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD3, 0xF4, 0x74, 0xE1, 0x67, 0xD8, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x70, 0x3C, 0xC8, 0xAF, 0x5F, 0xF4, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x4E, 0xED, 0x5C, 0x43, 0xB3, 0x16, 0x35),
+};
+static const mbedtls_mpi_uint secp192k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAE, 0xD1, 0xDD, 0x31, 0x14, 0xD3, 0xF0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x14, 0x06, 0x13, 0x12, 0x1C, 0x81, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xF9, 0x0C, 0x91, 0xF7, 0x67, 0x59, 0x63),
+};
+static const mbedtls_mpi_uint secp192k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x91, 0xE2, 0xF4, 0x9D, 0xEB, 0x88, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x82, 0x30, 0x9C, 0xAE, 0x18, 0x4D, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x79, 0xCF, 0x17, 0xA5, 0x1E, 0xE8, 0xC8),
+};
+static const mbedtls_ecp_point secp192k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp192k1_T_0_X, secp192k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_1_X, secp192k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_2_X, secp192k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_3_X, secp192k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_4_X, secp192k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_5_X, secp192k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_6_X, secp192k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_7_X, secp192k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_8_X, secp192k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_9_X, secp192k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_10_X, secp192k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_11_X, secp192k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_12_X, secp192k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_13_X, secp192k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_14_X, secp192k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp192k1_T_15_X, secp192k1_T_15_Y),
+};
+#else
+#define secp192k1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+static const mbedtls_mpi_uint secp224k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp224k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x05, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_4(0x33, 0x5B, 0x45, 0xA1),
+};
+static const mbedtls_mpi_uint secp224k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_4(0xED, 0x9F, 0x08, 0x7E),
+};
+static const mbedtls_mpi_uint secp224k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp224k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x5B, 0x45, 0xA1, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x9F, 0x08, 0x7E, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x6C, 0x22, 0x22, 0x40, 0x89, 0xAE, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x92, 0xE1, 0x87, 0x56, 0x35, 0xAF, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xAF, 0x08, 0x35, 0x27, 0xEA, 0x04, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x53, 0xFD, 0xCF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0xD0, 0x9F, 0x8D, 0xF3, 0x63, 0x54, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xDB, 0x0F, 0x61, 0x54, 0x26, 0xD1, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x21, 0xF7, 0x1B, 0xB5, 0x1D, 0xF6, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x05, 0xDA, 0x8F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x26, 0x73, 0xBC, 0xE4, 0x29, 0x62, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x95, 0x17, 0x8B, 0xC3, 0x9B, 0xAC, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0xDB, 0x77, 0xDF, 0xDD, 0x13, 0x04, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0xFC, 0x22, 0x93, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0xF1, 0x5A, 0x37, 0xEF, 0x79, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x01, 0x37, 0xAC, 0x9A, 0x5B, 0x51, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x75, 0x13, 0xA9, 0x4A, 0xAD, 0xFE, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x82, 0x6F, 0x66, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x5E, 0xF0, 0x40, 0xC3, 0xA6, 0xE2, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x9A, 0x6F, 0xCF, 0x11, 0x26, 0x66, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0x73, 0xA8, 0xCF, 0x2B, 0x12, 0x36, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xB3, 0x0A, 0x58, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x79, 0x00, 0x55, 0x04, 0x34, 0x90, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x54, 0x1C, 0xC2, 0x45, 0x0C, 0x1B, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x19, 0xAB, 0xA8, 0xFC, 0x73, 0xDC, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xFB, 0x93, 0xCE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x75, 0xD0, 0x66, 0x95, 0x86, 0xCA, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xEA, 0x29, 0x16, 0x6A, 0x38, 0xDF, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xA2, 0x36, 0x2F, 0xDC, 0xBB, 0x5E, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x89, 0x59, 0x49, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xA3, 0x99, 0x9D, 0xB8, 0x77, 0x9D, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x93, 0x43, 0x47, 0xC6, 0x5C, 0xF9, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x00, 0x79, 0x42, 0x64, 0xB8, 0x25, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x54, 0xB4, 0x33, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x0C, 0x42, 0x90, 0x83, 0x0B, 0x31, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x2E, 0xAE, 0xC8, 0xC7, 0x5F, 0xD2, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xBC, 0xAD, 0x41, 0xE7, 0x32, 0x3A, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x97, 0x52, 0x83, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x13, 0x7A, 0xBD, 0xAE, 0x94, 0x60, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x9B, 0x95, 0xB4, 0x6E, 0x68, 0xB2, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x49, 0xBE, 0x51, 0xFE, 0x66, 0x15, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x37, 0xE4, 0xFE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x9B, 0xEE, 0x64, 0xC9, 0x1B, 0xBD, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x5F, 0x34, 0xA9, 0x0B, 0xB7, 0x25, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0x13, 0xB1, 0x38, 0xFB, 0x9D, 0x78, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xE7, 0x1B, 0xFA, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xB3, 0xB7, 0x44, 0x92, 0x6B, 0x00, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x82, 0x44, 0x3E, 0x18, 0x1A, 0x58, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0xF8, 0xC0, 0xE4, 0xEE, 0xC1, 0xBF, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x32, 0x27, 0xB2, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x9A, 0x42, 0x62, 0x8B, 0x26, 0x54, 0x21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x85, 0x74, 0xA0, 0x79, 0xA8, 0xEE, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x36, 0x60, 0xB3, 0x28, 0x4D, 0x55, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x27, 0x82, 0x29, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xFC, 0x73, 0x77, 0xAF, 0x5C, 0xAC, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xED, 0xE5, 0xF6, 0x1D, 0xA8, 0x67, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xDE, 0x33, 0x1C, 0xF1, 0x80, 0x73, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xE2, 0xDE, 0x3C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x3E, 0x6B, 0xFE, 0xF0, 0x04, 0x28, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xB2, 0x14, 0x9D, 0x18, 0x11, 0x7D, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xC4, 0xD6, 0x2E, 0x6E, 0x57, 0x4D, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x55, 0x1B, 0xDE, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xF7, 0x17, 0xBC, 0x45, 0xAB, 0x16, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xB0, 0xEF, 0x61, 0xE3, 0x20, 0x7C, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x85, 0x41, 0x4D, 0xF1, 0x7E, 0x4D, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC2, 0x9B, 0x5E, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x2E, 0x49, 0x3D, 0x3E, 0x4B, 0xD3, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x2B, 0x9D, 0xD5, 0x27, 0xFA, 0xCA, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0xB3, 0x6A, 0xE0, 0x79, 0x14, 0x28, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x1E, 0xDC, 0xF5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x44, 0x56, 0xCD, 0xFC, 0x9F, 0x09, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x8C, 0x59, 0xA4, 0x64, 0x2A, 0x3A, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xA0, 0xB5, 0x86, 0x4E, 0x69, 0xDA, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x8B, 0x11, 0x38, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x17, 0x16, 0x12, 0x17, 0xDC, 0x00, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0x76, 0x24, 0x6C, 0x97, 0x2C, 0xB5, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x71, 0xE3, 0xB0, 0xBB, 0x4E, 0x50, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0x48, 0x26, 0xD5, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x5F, 0x28, 0xF6, 0x01, 0x5A, 0x60, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x95, 0xFE, 0xD0, 0xAD, 0x15, 0xD4, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x5B, 0x7A, 0xFD, 0x80, 0xF7, 0x9F, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xBC, 0x1B, 0xDF, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xE6, 0xDF, 0x14, 0x29, 0xF4, 0xD4, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x12, 0xDD, 0xEC, 0x5B, 0x8A, 0x59, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x92, 0x3E, 0x35, 0x08, 0xE9, 0xCF, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0x35, 0x29, 0x97, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xDB, 0xD6, 0x6A, 0xC5, 0x43, 0xA4, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x33, 0x50, 0x61, 0x70, 0xA1, 0xE9, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x15, 0x6E, 0x5F, 0x01, 0x0C, 0x8C, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xA1, 0x9A, 0x9D, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xC6, 0xF7, 0xE2, 0x4A, 0xCD, 0x9B, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x4D, 0x5A, 0xB8, 0xE2, 0x6D, 0xA6, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x3F, 0xB6, 0x17, 0xE3, 0x2C, 0x6F, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xA4, 0x59, 0x51, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x4F, 0x7C, 0x49, 0xCD, 0x6E, 0xEB, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xC9, 0x1F, 0xB7, 0x4D, 0x98, 0xC7, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4C, 0xFD, 0x98, 0x20, 0x95, 0xBB, 0x20, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xF2, 0x73, 0x92, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xEF, 0xFB, 0x30, 0xFA, 0x12, 0x1A, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x4C, 0x24, 0xB4, 0x5B, 0xC9, 0x4C, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xDD, 0x5E, 0x84, 0x95, 0x4D, 0x26, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xFA, 0xF9, 0x3A, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0xA3, 0x2E, 0x7A, 0xDC, 0xA7, 0x53, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x9F, 0x81, 0x84, 0xB2, 0x0D, 0xFE, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x89, 0x1B, 0x77, 0x0C, 0x89, 0x71, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xFF, 0x7F, 0xB2, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xE9, 0x2C, 0x79, 0xA6, 0x3C, 0xAD, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xE0, 0x23, 0x02, 0x86, 0x0F, 0x77, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x93, 0x6D, 0xE9, 0xF9, 0x3C, 0xBE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0xE7, 0x24, 0x92, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x3C, 0x5B, 0x4B, 0x1B, 0x25, 0x37, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xE8, 0x38, 0x1B, 0xA1, 0x5A, 0x2E, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x19, 0xFD, 0xF4, 0x78, 0x01, 0x6B, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0x69, 0x37, 0x4F, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xE2, 0xBF, 0xD3, 0xEC, 0x95, 0x9C, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x7B, 0xFC, 0xD5, 0xD3, 0x25, 0x5E, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x55, 0x09, 0xA2, 0x58, 0x6A, 0xC9, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xCC, 0x3B, 0xD9, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp224k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x08, 0x65, 0x5E, 0xCB, 0xAB, 0x48, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x79, 0x8B, 0xC0, 0x11, 0xC0, 0x69, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xE8, 0x8C, 0x4C, 0xC5, 0x28, 0xE4, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x1F, 0x34, 0x5C, 0x00, 0x00, 0x00, 0x00),
+};
+static const mbedtls_ecp_point secp224k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp224k1_T_0_X, secp224k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_1_X, secp224k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_2_X, secp224k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_3_X, secp224k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_4_X, secp224k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_5_X, secp224k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_6_X, secp224k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_7_X, secp224k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_8_X, secp224k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_9_X, secp224k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_10_X, secp224k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_11_X, secp224k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_12_X, secp224k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_13_X, secp224k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_14_X, secp224k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp224k1_T_15_X, secp224k1_T_15_Y),
+};
+#else
+#define secp224k1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+static const mbedtls_mpi_uint secp256k1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+static const mbedtls_mpi_uint secp256k1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x00, 0x00),
+};
+static const mbedtls_mpi_uint secp256k1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_2(0x07, 0x00),
+};
+static const mbedtls_mpi_uint secp256k1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),
+};
+static const mbedtls_mpi_uint secp256k1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),
+};
+static const mbedtls_mpi_uint secp256k1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint secp256k1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79),
+};
+static const mbedtls_mpi_uint secp256k1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48),
+};
+static const mbedtls_mpi_uint secp256k1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xEE, 0xD7, 0x1E, 0x67, 0x86, 0x32, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0xB1, 0xA9, 0xD5, 0xCC, 0x27, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x0E, 0x11, 0x01, 0x71, 0xFE, 0x92, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x28, 0x63, 0x6D, 0x72, 0x09, 0xA6, 0xC0),
+};
+static const mbedtls_mpi_uint secp256k1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0x69, 0xDC, 0x3E, 0x2C, 0x75, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xB7, 0x3F, 0x30, 0x26, 0x3C, 0xDF, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xBE, 0xB9, 0x5D, 0x0E, 0xE8, 0x5E, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0xC3, 0x05, 0xD6, 0xB7, 0xD5, 0x24, 0xFC),
+};
+static const mbedtls_mpi_uint secp256k1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0xCF, 0x7B, 0xDC, 0xCD, 0xC3, 0x39, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0xDA, 0xB9, 0xE5, 0x64, 0xA7, 0x47, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0x46, 0xA8, 0x61, 0xF6, 0x23, 0xEB, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xC1, 0xFF, 0xE4, 0x55, 0xD5, 0xC2, 0xBF),
+};
+static const mbedtls_mpi_uint secp256k1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xBE, 0xB9, 0x59, 0x24, 0x13, 0x4A, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x45, 0x12, 0xDE, 0xBA, 0x4F, 0xEF, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x08, 0xBF, 0xC1, 0x66, 0xAA, 0x0A, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xFE, 0x30, 0x55, 0x31, 0x86, 0xA7, 0xB4),
+};
+static const mbedtls_mpi_uint secp256k1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBF, 0x18, 0x81, 0x67, 0x27, 0x42, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x05, 0x83, 0xA4, 0xDD, 0x57, 0xD3, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x63, 0xAB, 0xE4, 0x90, 0x70, 0xD0, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x5D, 0xFD, 0xA0, 0xEF, 0xCF, 0x1C, 0x54),
+};
+static const mbedtls_mpi_uint secp256k1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x80, 0xE4, 0xF6, 0x09, 0xBC, 0x57, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x9F, 0x6E, 0x88, 0x54, 0x6E, 0x51, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x5F, 0x85, 0xFB, 0x84, 0x3E, 0x4A, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x19, 0xF5, 0x55, 0xC9, 0x07, 0xD8, 0xCE),
+};
+static const mbedtls_mpi_uint secp256k1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xB4, 0xC3, 0xD9, 0x5C, 0xA0, 0xD4, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x30, 0xAF, 0x59, 0x9B, 0xF8, 0x04, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xA6, 0xFD, 0x66, 0x7B, 0xC3, 0x39, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE0, 0xBF, 0xF0, 0xC2, 0xE9, 0x71, 0xA4, 0x9E),
+};
+static const mbedtls_mpi_uint secp256k1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x2D, 0xB9, 0x88, 0x28, 0xF1, 0xBE, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xF3, 0x1A, 0x0E, 0xB9, 0x01, 0x66, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0xA4, 0xF4, 0x05, 0xD0, 0xAA, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x39, 0x1E, 0x47, 0xE5, 0x68, 0xC8, 0xC0),
+};
+static const mbedtls_mpi_uint secp256k1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xB9, 0xFC, 0xE0, 0x33, 0x8A, 0x7D, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x93, 0xA5, 0x53, 0x55, 0x16, 0xB4, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x5F, 0xEA, 0x9B, 0x29, 0x52, 0x71, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xF0, 0x24, 0xB8, 0x7D, 0xB7, 0xA0, 0x9B),
+};
+static const mbedtls_mpi_uint secp256k1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x00, 0x27, 0xB2, 0xDF, 0x73, 0xA2, 0xE0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x2E, 0x4D, 0x7C, 0xDE, 0x7A, 0x23, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x65, 0x60, 0xC7, 0x97, 0x1E, 0xA4, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x13, 0x5B, 0x77, 0x59, 0xCB, 0x36, 0xE1),
+};
+static const mbedtls_mpi_uint secp256k1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xBC, 0x9F, 0x9E, 0x2D, 0x53, 0x2A, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x5F, 0x64, 0x9F, 0x1A, 0x19, 0xE6, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x7B, 0x39, 0xD2, 0xDB, 0x85, 0x84, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xC7, 0x0D, 0x58, 0x6E, 0x3F, 0x52, 0x15),
+};
+static const mbedtls_mpi_uint secp256k1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x68, 0x19, 0x0B, 0x68, 0xC9, 0x1E, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x4E, 0x21, 0x49, 0x3D, 0x55, 0xCC, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xF9, 0x25, 0x45, 0x54, 0x45, 0xB1, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xF7, 0xCD, 0x80, 0xA4, 0x04, 0x05),
+};
+static const mbedtls_mpi_uint secp256k1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x1E, 0x88, 0xC4, 0xAA, 0x18, 0x7E, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xAC, 0xD9, 0xB2, 0xA1, 0xC0, 0x71, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xA2, 0xF1, 0x15, 0xA6, 0x5F, 0x6C, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x5B, 0x05, 0xBC, 0xB7, 0xC6, 0x4E, 0x72),
+};
+static const mbedtls_mpi_uint secp256k1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x80, 0xF8, 0x5C, 0x20, 0x2A, 0xE1, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x48, 0x2E, 0x68, 0x82, 0x7F, 0xEB, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x3B, 0x25, 0xDB, 0x32, 0x4D, 0x88, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0x6E, 0xA6, 0xB6, 0x6D, 0x62, 0x78, 0x22),
+};
+static const mbedtls_mpi_uint secp256k1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4D, 0x3E, 0x86, 0x58, 0xC3, 0xEB, 0xBA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x89, 0x33, 0x18, 0x21, 0x1D, 0x9B, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x9D, 0xFF, 0xC3, 0x79, 0xC1, 0x88, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0xD4, 0x48, 0x53, 0xE8, 0xAD, 0x21, 0x16),
+};
+static const mbedtls_mpi_uint secp256k1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x7B, 0xDE, 0xCB, 0xD8, 0x39, 0x17, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xF3, 0x03, 0xF2, 0x5C, 0xBC, 0xC8, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0xAE, 0x4C, 0xB0, 0x16, 0xA4, 0x93, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8B, 0x6B, 0xDC, 0xD7, 0x9A, 0x3E, 0x7E),
+};
+static const mbedtls_mpi_uint secp256k1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x2D, 0x7A, 0xD2, 0x59, 0x05, 0xA2, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x56, 0x09, 0x32, 0xF1, 0xE8, 0xE3, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0xCA, 0xE5, 0x2E, 0xF0, 0xFB, 0x18, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x85, 0xA9, 0x23, 0x15, 0x31, 0x1F, 0x0E),
+};
+static const mbedtls_mpi_uint secp256k1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xE5, 0xB1, 0x86, 0xB9, 0x6E, 0x8D, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x77, 0xFC, 0xC9, 0xA3, 0x3F, 0x89, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x6A, 0xDC, 0x25, 0xB0, 0xC7, 0x41, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x11, 0x6B, 0xA6, 0x11, 0x62, 0xD4, 0x2D),
+};
+static const mbedtls_mpi_uint secp256k1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7D, 0x34, 0xB3, 0x20, 0x7F, 0x37, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xD4, 0x45, 0xE8, 0xC2, 0xE9, 0xC5, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x32, 0x3B, 0x25, 0x7E, 0x79, 0xAF, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xE4, 0x54, 0x71, 0xBE, 0x35, 0x4E, 0xD0),
+};
+static const mbedtls_mpi_uint secp256k1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x94, 0xDD, 0x8F, 0xB5, 0xC2, 0xDD, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x49, 0xE9, 0x1C, 0x2F, 0x08, 0x49, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xB6, 0x03, 0x88, 0x6F, 0xB8, 0x15, 0x67),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xD3, 0x1C, 0xF3, 0xA5, 0xEB, 0x79, 0x01),
+};
+static const mbedtls_mpi_uint secp256k1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF9, 0x43, 0x88, 0x89, 0x0D, 0x06, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x2D, 0xF5, 0x98, 0x32, 0xF6, 0xB1, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x73, 0x8F, 0x2B, 0x50, 0x27, 0x0A, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE3, 0xBD, 0x16, 0x05, 0xC8, 0x93, 0x12),
+};
+static const mbedtls_mpi_uint secp256k1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0x6A, 0xF7, 0xE3, 0x3D, 0xDE, 0x5F, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA3, 0x9C, 0x22, 0x3C, 0x33, 0x36, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x24, 0x4C, 0x69, 0x45, 0x78, 0x14, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xF8, 0xD4, 0xBF, 0xB8, 0xC0, 0xA1, 0x25),
+};
+static const mbedtls_mpi_uint secp256k1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x88, 0xE1, 0x91, 0x03, 0xEB, 0xB3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x11, 0xA1, 0xEF, 0x14, 0x0D, 0xC4, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0xD4, 0x0D, 0x1D, 0x96, 0x33, 0x5C, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x45, 0x2A, 0x1A, 0xE6, 0x57, 0x04, 0x9B),
+};
+static const mbedtls_mpi_uint secp256k1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xB5, 0xA7, 0x80, 0xE9, 0x93, 0x97, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0xB9, 0x7C, 0xA0, 0xC9, 0x57, 0x26, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0xEF, 0x56, 0xDA, 0x66, 0xF6, 0x1B, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x89, 0x6B, 0x91, 0xE0, 0xA9, 0x65, 0x2B),
+};
+static const mbedtls_mpi_uint secp256k1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x98, 0x96, 0x9B, 0x06, 0x7D, 0x5E, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xFA, 0xC1, 0x5F, 0x19, 0x37, 0x94, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xBE, 0x6B, 0x1A, 0x05, 0xE4, 0xBF, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xCD, 0x5D, 0x35, 0xB4, 0x51, 0xF7, 0x64),
+};
+static const mbedtls_mpi_uint secp256k1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xEF, 0x96, 0xDB, 0xF2, 0x61, 0x63, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x04, 0x88, 0xC9, 0x9F, 0x1B, 0x94, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x30, 0x79, 0x7E, 0x24, 0xE7, 0x5F, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xB8, 0x90, 0xB7, 0x94, 0x25, 0xBB, 0x0F),
+};
+static const mbedtls_mpi_uint secp256k1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x79, 0xEA, 0xAD, 0xC0, 0x6D, 0x18, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xA4, 0x58, 0x2A, 0x8D, 0x95, 0xB3, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC4, 0xC2, 0x12, 0x0D, 0x79, 0xE2, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6F, 0xBE, 0x97, 0x4D, 0xA4, 0x20, 0x07),
+};
+static const mbedtls_mpi_uint secp256k1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x31, 0x71, 0xC6, 0xA6, 0x91, 0xEB, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x9B, 0xA8, 0x4A, 0xE7, 0x77, 0xE1, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0x06, 0xD3, 0x3D, 0x94, 0x30, 0xEF, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xDF, 0xCA, 0xFA, 0xF5, 0x28, 0xF8, 0xC9),
+};
+static const mbedtls_mpi_uint secp256k1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0xE1, 0x32, 0xFD, 0x3E, 0x81, 0xF8, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0xF2, 0x4B, 0x1D, 0x19, 0xC9, 0x0F, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB1, 0x8A, 0x22, 0x8B, 0x05, 0x6B, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0x21, 0xEF, 0x30, 0xEC, 0x09, 0x2A, 0x89),
+};
+static const mbedtls_mpi_uint secp256k1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x84, 0x4A, 0x46, 0x07, 0x6C, 0x3C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x18, 0x3A, 0xF4, 0xCC, 0xF5, 0xB2, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0x8F, 0xCD, 0x0A, 0x9C, 0xF4, 0xBD, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x89, 0x7F, 0x8A, 0xB1, 0x52, 0x3A, 0xAB),
+};
+static const mbedtls_ecp_point secp256k1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(secp256k1_T_0_X, secp256k1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_1_X, secp256k1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_2_X, secp256k1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_3_X, secp256k1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_4_X, secp256k1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_5_X, secp256k1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_6_X, secp256k1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_7_X, secp256k1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_8_X, secp256k1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_9_X, secp256k1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_10_X, secp256k1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_11_X, secp256k1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_12_X, secp256k1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_13_X, secp256k1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_14_X, secp256k1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(secp256k1_T_15_X, secp256k1_T_15_Y),
+};
+#else
+#define secp256k1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP256r1 (RFC 5639 3.4)
+ */
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP256r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP256r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xA2, 0xED, 0x52, 0xC9, 0x8C, 0xE3, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0xC9, 0xC4, 0x87, 0x3F, 0x93, 0x7A, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x12, 0x53, 0x61, 0x3E, 0x76, 0x08, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0x8C, 0x74, 0xF4, 0x08, 0xC3, 0x76, 0x80),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0xDD, 0x09, 0xA6, 0xED, 0xEE, 0xC4, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xD9, 0xBE, 0x4B, 0xA5, 0xB7, 0x2B, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x20, 0x12, 0xCA, 0x0A, 0x38, 0x24, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x72, 0x71, 0x90, 0x7A, 0x2E, 0xB7, 0x23),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x66, 0xA1, 0x93, 0x10, 0x2A, 0x51, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0x10, 0x11, 0x12, 0xBC, 0xB0, 0xB6, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x58, 0xD7, 0x0A, 0x84, 0x05, 0xA3, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x8E, 0x95, 0x61, 0xD3, 0x0B, 0xDF, 0x36),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x92, 0x12, 0x0F, 0x5E, 0x87, 0x70, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0xE9, 0x9B, 0xEB, 0x3A, 0xFB, 0xCF, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0x92, 0xB9, 0xF7, 0x45, 0xD3, 0x06, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x28, 0x65, 0xE1, 0xC5, 0x6C, 0x57, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x0E, 0x77, 0x01, 0x81, 0x9E, 0x38, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0xF0, 0xD5, 0xA5, 0x91, 0x2B, 0xDF, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xEE, 0xB6, 0x25, 0xD6, 0x98, 0xDE, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0xA1, 0x55, 0x63, 0x39, 0xEB, 0xB5, 0x47),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD6, 0xB8, 0xE3, 0x13, 0xED, 0x7F, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xE8, 0xAE, 0x36, 0xB8, 0xCD, 0x19, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x82, 0x83, 0x7A, 0x7B, 0x46, 0x56, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x60, 0x46, 0x15, 0x5A, 0xAC, 0x99, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x61, 0x50, 0xC6, 0xFF, 0x10, 0x7D, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x51, 0xDF, 0xA9, 0x7D, 0x78, 0x26, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0x15, 0x9A, 0xF7, 0x01, 0xC1, 0xBB, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x0F, 0xE6, 0x2A, 0xBD, 0x4A, 0x9E, 0x87),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF8, 0xD1, 0x77, 0xD2, 0x49, 0xB3, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x86, 0xFB, 0x9E, 0x1F, 0x5A, 0x60, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xC4, 0x8D, 0xCD, 0x86, 0x61, 0x2F, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xF6, 0xB9, 0xAC, 0x37, 0x9D, 0xE9, 0x28),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x77, 0xAA, 0x97, 0x9C, 0x0B, 0x04, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0xA6, 0x60, 0x81, 0xCE, 0x25, 0x13, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x00, 0xF3, 0xBB, 0x82, 0x99, 0x95, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x5A, 0xCE, 0x90, 0x71, 0x38, 0x2F, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x1A, 0xC0, 0x84, 0x27, 0xD6, 0x9D, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x37, 0x52, 0x16, 0x13, 0x0E, 0xCE, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBF, 0x5A, 0xDB, 0xDB, 0x6E, 0x1E, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0xB7, 0x5E, 0xF9, 0x86, 0xDD, 0x8A, 0x5C),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xAB, 0x5C, 0x8D, 0x1D, 0xF2, 0x2D, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0xC5, 0xF8, 0xF7, 0x1D, 0x96, 0x0B, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x4C, 0xA7, 0x45, 0x20, 0x6A, 0x1E, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x5D, 0xEF, 0xDE, 0xEE, 0x39, 0x44, 0x19),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x2F, 0x6D, 0x52, 0xC9, 0x58, 0x60, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xC9, 0x62, 0xCB, 0x38, 0x3C, 0x55, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xA5, 0x09, 0x10, 0x88, 0xDB, 0xE3, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xE0, 0x3C, 0xCE, 0x06, 0x0B, 0x4B, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x1D, 0xB4, 0x10, 0x76, 0x8F, 0xBA, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x70, 0x5A, 0x07, 0xF5, 0x1A, 0x74, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xE9, 0x94, 0xA8, 0xC0, 0xD5, 0x4A, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x6D, 0xD4, 0xE8, 0x9B, 0xE9, 0x6D, 0x0E),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x00, 0x32, 0x41, 0x57, 0x84, 0x89, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC7, 0x14, 0xEC, 0xE9, 0x27, 0xFF, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x67, 0x9E, 0xFB, 0xB6, 0xB8, 0x96, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0x4A, 0xE3, 0x97, 0x4B, 0x58, 0xDE, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0x1E, 0x5C, 0xF5, 0x7F, 0xD5, 0xD4, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x08, 0x7A, 0xF1, 0xBD, 0x89, 0xC7, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0xF9, 0x11, 0x1B, 0xF5, 0x3C, 0x6D, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x50, 0xE5, 0x69, 0x1D, 0x59, 0xFC, 0x0C),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x2F, 0xF8, 0x3F, 0xEC, 0x55, 0x99, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0xA7, 0x29, 0x90, 0x43, 0x81, 0x31, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x18, 0x44, 0x50, 0x5D, 0x76, 0xCB, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xC5, 0x5B, 0x9A, 0x03, 0xE6, 0x17, 0x39),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x89, 0xFC, 0x55, 0x94, 0x91, 0x6A, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x46, 0x35, 0xF2, 0x3A, 0x42, 0x08, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0xD2, 0x76, 0x49, 0x42, 0x87, 0xD3, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xEA, 0xA0, 0x52, 0xF1, 0x6A, 0x30, 0x57),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0xB2, 0x57, 0xA3, 0x8A, 0x4D, 0x1B, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0xA3, 0x99, 0x94, 0xB5, 0x3D, 0x64, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC3, 0xD7, 0x53, 0xF6, 0x49, 0x1C, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x23, 0x41, 0x4D, 0xFB, 0x7A, 0x5C, 0x53),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xB8, 0x15, 0x65, 0x5C, 0x85, 0x94, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x37, 0xC7, 0xF8, 0x7E, 0xAE, 0x6C, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xD8, 0x11, 0x54, 0x98, 0x44, 0xE3, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x4D, 0xA6, 0x4B, 0x28, 0xF2, 0x57, 0x9E),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xD0, 0xEB, 0x1E, 0xAA, 0x30, 0xD3, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x9B, 0x4D, 0xA7, 0x73, 0x6E, 0xB6, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x47, 0xF6, 0xED, 0x37, 0xEF, 0x71, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xB5, 0x49, 0x61, 0x5E, 0x45, 0xF6, 0x4A),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x0E, 0xB3, 0x84, 0x3A, 0x63, 0x72, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x53, 0x5C, 0xA7, 0xC6, 0x2E, 0xAB, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x0F, 0x8F, 0x87, 0x50, 0x28, 0xB4, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x98, 0x4A, 0x98, 0x31, 0x86, 0xCA, 0x51),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC9, 0xE2, 0xFD, 0x5D, 0x1F, 0xE8, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x90, 0x91, 0xC4, 0x84, 0xF0, 0xBA, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x5A, 0xB3, 0x4E, 0xFB, 0xE0, 0x57, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x0B, 0x90, 0xA6, 0xFD, 0x9D, 0x8E, 0x02),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x41, 0x8F, 0x31, 0xFA, 0x5A, 0xF6, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xE9, 0xE3, 0xF6, 0xE0, 0x4A, 0xE7, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0x4E, 0xCD, 0xA2, 0x22, 0x14, 0xD4, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xED, 0x21, 0xB7, 0x0F, 0x53, 0x10, 0x17),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x06, 0x24, 0x2C, 0x4E, 0xD1, 0x1E, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x3F, 0xC1, 0x9F, 0xAB, 0xF0, 0x37, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x03, 0x5E, 0x12, 0xCE, 0x83, 0x1B, 0x2A, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x65, 0xCF, 0xE8, 0x5C, 0xA5, 0xA2, 0x70),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x86, 0x76, 0x3A, 0x94, 0xF6, 0x1D, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xDA, 0xC9, 0xA6, 0x29, 0x93, 0x15, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x61, 0x6A, 0x7D, 0xC7, 0xA9, 0xF3, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x03, 0x71, 0xA2, 0x15, 0xCE, 0x50, 0x72),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xD0, 0xA8, 0x1E, 0x91, 0xC4, 0x4F, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x4B, 0x7E, 0xD7, 0x71, 0x58, 0x7E, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x45, 0xAF, 0x2A, 0x18, 0x93, 0x95, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x8F, 0xC7, 0xFA, 0x4C, 0x7A, 0x86, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0xAF, 0x68, 0x3A, 0x23, 0xC1, 0x2E, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x50, 0x11, 0x67, 0x39, 0xB9, 0xAF, 0x48),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x86, 0xAA, 0x1E, 0x88, 0x21, 0x29, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x28, 0xA4, 0x9D, 0x89, 0xA9, 0x9A, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xBA, 0x04, 0x67, 0xB7, 0x01, 0x40, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xE9, 0x09, 0xA3, 0xCA, 0xA6, 0x37, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x97, 0xA8, 0xB6, 0x3C, 0xEE, 0x90, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xED, 0xC4, 0xF7, 0xC3, 0x95, 0xEC, 0x85),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x84, 0xBD, 0xEB, 0xD5, 0x64, 0xBB, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x9B, 0xE2, 0x28, 0x50, 0xC2, 0x72, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0xF2, 0x74, 0xD1, 0x26, 0xBF, 0x32, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xCB, 0xAF, 0x72, 0xDB, 0x6D, 0x30, 0x98),
+};
+static const mbedtls_mpi_uint brainpoolP256r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x50, 0x85, 0xF4, 0x2B, 0x48, 0xC1, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x28, 0xBB, 0x11, 0xBA, 0x5B, 0x22, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xA1, 0xE5, 0x5C, 0xC9, 0x1D, 0x44, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xE8, 0xE6, 0x6F, 0xBB, 0xC1, 0x81, 0x7F),
+};
+static const mbedtls_ecp_point brainpoolP256r1_T[16] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP256r1_T_0_X, brainpoolP256r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_1_X, brainpoolP256r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_2_X, brainpoolP256r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_3_X, brainpoolP256r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_4_X, brainpoolP256r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_5_X, brainpoolP256r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_6_X, brainpoolP256r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_7_X, brainpoolP256r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_8_X, brainpoolP256r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_9_X, brainpoolP256r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_10_X, brainpoolP256r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_11_X, brainpoolP256r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_12_X, brainpoolP256r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_13_X, brainpoolP256r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_14_X, brainpoolP256r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP256r1_T_15_X, brainpoolP256r1_T_15_Y),
+};
+#else
+#define brainpoolP256r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP384r1 (RFC 5639 3.6)
+ */
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP384r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP384r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xD8, 0x8A, 0x54, 0x41, 0xD6, 0x6B, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x3B, 0xF1, 0x22, 0xFD, 0x2D, 0x4B, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x55, 0xE3, 0x33, 0xF0, 0x73, 0x52, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x3F, 0x30, 0x26, 0xCA, 0x7F, 0x52, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD3, 0x6E, 0x17, 0x9B, 0xD5, 0x2A, 0x4A, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xDA, 0x6B, 0xE5, 0x03, 0x07, 0x1D, 0x2E),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x7A, 0xAF, 0x98, 0xE3, 0xA4, 0xF6, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x7D, 0xFE, 0x51, 0x40, 0x3B, 0x47, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x88, 0xEC, 0xC4, 0xE2, 0x8F, 0xCB, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xE2, 0x88, 0x2D, 0x4E, 0x50, 0xEB, 0x9A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x54, 0x94, 0x5E, 0xF4, 0x7F, 0x3A, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x07, 0x1C, 0xE1, 0xBD, 0x0F, 0xF8, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x92, 0x28, 0x2E, 0x32, 0x04, 0xB1, 0x4D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x82, 0x44, 0x43, 0x76, 0x0D, 0x55, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xE3, 0xFF, 0x89, 0x46, 0xDE, 0x4E, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0x22, 0xBB, 0x67, 0x1A, 0x81, 0xEE, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x54, 0xE2, 0x7A, 0xAE, 0xDA, 0x2C, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x9A, 0x90, 0xAA, 0x6E, 0x8B, 0xCC, 0x5F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x40, 0xAC, 0xED, 0x7D, 0x37, 0x87, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0xF8, 0xB1, 0x80, 0x4C, 0x8C, 0x04, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x98, 0x2C, 0xAD, 0x30, 0x69, 0x35, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x2E, 0x00, 0x2F, 0x44, 0x8C, 0xF0, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x58, 0x07, 0xD7, 0xCD, 0x60, 0xA1, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0xFB, 0x7B, 0x03, 0x05, 0x5E, 0x79, 0x73),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x17, 0xCE, 0x38, 0x4B, 0x5E, 0x5B, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x0E, 0x0A, 0x61, 0x9D, 0x7C, 0x62, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xF0, 0x98, 0x71, 0x7F, 0x17, 0x26, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0xD3, 0xFA, 0x3C, 0xF0, 0x70, 0x07, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x47, 0x5C, 0x09, 0x43, 0xB7, 0x65, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xA7, 0x3E, 0xFA, 0xF3, 0xEC, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x78, 0x22, 0x2B, 0x58, 0x71, 0xFA, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x30, 0xCE, 0x6A, 0xB3, 0xB0, 0x4F, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0x95, 0x20, 0xA9, 0x23, 0xC2, 0x65, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0xCF, 0x03, 0x5B, 0x8A, 0x80, 0x44, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xF8, 0x91, 0xF7, 0xD5, 0xED, 0xEA, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x5B, 0x16, 0x10, 0x25, 0xAC, 0x2A, 0x17),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEC, 0xDC, 0xC4, 0x7B, 0x8C, 0x6B, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xBB, 0x1C, 0xD3, 0x5A, 0xEE, 0xD9, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x5D, 0x30, 0x5E, 0xF7, 0xB2, 0x41, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xCE, 0x0F, 0x1A, 0xC6, 0x41, 0x64, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x18, 0xE1, 0xE3, 0x82, 0x15, 0x66, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0xE2, 0x24, 0x04, 0x72, 0x39, 0xA0, 0x7C),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x51, 0xA2, 0x58, 0x88, 0x62, 0xE1, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xD2, 0x65, 0x14, 0xE9, 0x4C, 0x82, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE1, 0xAC, 0x87, 0xAE, 0x31, 0x1A, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0x4F, 0x96, 0x1E, 0x85, 0x7A, 0xC3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x86, 0xBB, 0xF0, 0xC0, 0x9D, 0x08, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x53, 0x03, 0x09, 0x80, 0x91, 0xEF, 0x68),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0xD7, 0xAF, 0x6F, 0x69, 0x7B, 0x88, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x13, 0xE4, 0x30, 0xA2, 0x47, 0xB5, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD2, 0xC0, 0xDD, 0x8A, 0x1C, 0x3C, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x8C, 0xB3, 0x4C, 0xBA, 0x8B, 0x6D, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xC7, 0xA1, 0xA8, 0x6E, 0x3C, 0x4F, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x4A, 0x97, 0xC8, 0x03, 0x6F, 0x01, 0x82),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x18, 0x12, 0xA9, 0x39, 0xD5, 0x22, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0xA7, 0xC0, 0xBD, 0x9D, 0x8D, 0x78, 0x38),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xB3, 0xD0, 0x7F, 0xDF, 0xD0, 0x30, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x73, 0x96, 0xEC, 0xA8, 0x1D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xD1, 0x65, 0x66, 0xDC, 0xD9, 0xCF, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xED, 0x7B, 0x37, 0xAD, 0xE2, 0xBE, 0x2D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x79, 0x42, 0x6A, 0x07, 0x66, 0xB1, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x53, 0x62, 0x65, 0x92, 0x09, 0x4C, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xAF, 0xC3, 0x03, 0xF6, 0xF4, 0x2D, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xCA, 0x41, 0xD9, 0xA2, 0x69, 0x9B, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0xB2, 0xA6, 0x8D, 0xE1, 0xAA, 0x61, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xBA, 0x4D, 0x12, 0xB6, 0xBE, 0xF3, 0x7E),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x92, 0x22, 0x07, 0xCE, 0xC9, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xA1, 0x7C, 0x91, 0xDB, 0x32, 0xF7, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x49, 0x4B, 0x6D, 0xFB, 0xD9, 0x70, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xFB, 0x4E, 0x4C, 0x5E, 0x66, 0x81, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xB3, 0xE1, 0x00, 0xB7, 0xD9, 0xCC, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x36, 0x8B, 0xC4, 0x39, 0x20, 0xFD, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x1F, 0x60, 0x03, 0xBB, 0xD7, 0x60, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x3C, 0x62, 0xDD, 0x71, 0x95, 0xE9, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x5B, 0x7A, 0x5F, 0x68, 0x81, 0xC5, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xAF, 0xB5, 0xB9, 0x98, 0x42, 0x28, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x29, 0x8E, 0x11, 0x49, 0xB4, 0xD7, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x3E, 0xD2, 0x30, 0xA1, 0xBA, 0xCA, 0x03),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x37, 0x64, 0x44, 0x2F, 0x03, 0xE5, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x42, 0xBC, 0xFF, 0xA2, 0x1A, 0x5F, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0x04, 0xAB, 0x04, 0xE0, 0x24, 0xAD, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x45, 0x17, 0x67, 0x1F, 0x3E, 0x53, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x0F, 0xB3, 0x1B, 0x57, 0x54, 0xC2, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xD3, 0xF8, 0xC4, 0x1B, 0x9B, 0xFA, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x90, 0xFD, 0xFB, 0xCA, 0x49, 0x38, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xCF, 0xC6, 0xDD, 0xF0, 0xFF, 0x8C, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x69, 0x9D, 0xBD, 0x5F, 0x33, 0xE9, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x19, 0x82, 0x3D, 0xAC, 0x1C, 0x40, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0xC7, 0x02, 0x46, 0x14, 0x77, 0x00, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x05, 0xF2, 0x77, 0x3A, 0x66, 0x5C, 0x39),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xE6, 0x17, 0xDE, 0xB2, 0xA1, 0xE5, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x71, 0xEC, 0x9D, 0xD8, 0xF5, 0xD4, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xC6, 0x42, 0x5E, 0xE7, 0x18, 0xBA, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x21, 0x68, 0x5A, 0x26, 0xFB, 0xD7, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x00, 0x5C, 0xBA, 0x8A, 0x34, 0xEC, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0x9C, 0x3C, 0xAF, 0x53, 0xE8, 0x65, 0x35),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xEF, 0x28, 0xDC, 0x67, 0x05, 0xC8, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x78, 0xC3, 0x85, 0x49, 0xA0, 0xBC, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x3E, 0x2D, 0xA0, 0xCF, 0xD4, 0x7A, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x93, 0xFE, 0x60, 0xB3, 0x6E, 0x99, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x62, 0xAD, 0x04, 0xE7, 0x49, 0xAF, 0x5E, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x7A, 0xED, 0xA6, 0x9E, 0x18, 0x09, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x05, 0x94, 0x44, 0xDC, 0xB8, 0x85, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xB7, 0x37, 0xC2, 0x50, 0x75, 0x15, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0xC6, 0x0F, 0xB2, 0xA9, 0x91, 0x3E, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x81, 0xAD, 0x25, 0xA1, 0x26, 0x73, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xF1, 0xD1, 0x61, 0x7C, 0x76, 0x8F, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0xDB, 0x4A, 0xFF, 0x14, 0xA7, 0x48, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x73, 0xC6, 0xC2, 0xCC, 0xF1, 0x57, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0xED, 0x73, 0x27, 0x70, 0x82, 0xB6, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xBA, 0xAC, 0x3A, 0xCF, 0xF4, 0xEA, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xD6, 0xB1, 0x8F, 0x0E, 0x08, 0x2C, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xE3, 0x8F, 0x2F, 0x0E, 0xA1, 0xF3, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0xF5, 0x7C, 0x9B, 0x29, 0x0A, 0xF6, 0x28),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0xEE, 0x17, 0x47, 0x34, 0x15, 0xA3, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBE, 0x88, 0x48, 0xE7, 0xA2, 0xBB, 0xDE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xAD, 0xDC, 0x65, 0x61, 0x37, 0x0F, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x67, 0xAD, 0xA2, 0x3A, 0x1C, 0x91, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x07, 0x0C, 0x3A, 0x41, 0x6E, 0x13, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBD, 0x7E, 0xED, 0xAA, 0x14, 0xDD, 0x61),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC3, 0xDC, 0x20, 0x01, 0x72, 0x11, 0x48, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xC4, 0x7B, 0xF8, 0x62, 0x3D, 0xF0, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xC2, 0x3D, 0x2E, 0x52, 0xA3, 0x4A, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xE2, 0x53, 0x46, 0x5E, 0x21, 0xF8, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xC7, 0x8F, 0xA9, 0x26, 0x42, 0x32, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xA6, 0xA0, 0x8D, 0x4B, 0x9A, 0x19, 0x03),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xAB, 0x6D, 0x1E, 0xFB, 0xEE, 0x60, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x56, 0x3C, 0xC5, 0x5D, 0x10, 0x79, 0x1C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0xBC, 0x41, 0x9F, 0x71, 0xEF, 0x02, 0xF9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x36, 0xC4, 0xD0, 0x88, 0x9B, 0x32, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xD4, 0x5D, 0x17, 0x39, 0xE6, 0x22, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7B, 0x26, 0x01, 0xCE, 0xBE, 0x4A, 0x9C, 0x27),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x6D, 0x11, 0xCA, 0x6C, 0x5A, 0x93, 0x0C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x96, 0x26, 0xAF, 0x2F, 0xE4, 0x30, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xC1, 0x4C, 0xC6, 0x30, 0x1F, 0x5C, 0x04),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x59, 0xB3, 0xE8, 0xFC, 0x35, 0xEB, 0x63, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x1D, 0xCA, 0xFC, 0x50, 0x36, 0x4B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0E, 0x23, 0x5B, 0xAF, 0xEB, 0x2D, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0x88, 0xB6, 0xD7, 0x74, 0x4A, 0x23, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x66, 0xE2, 0xBB, 0x29, 0xA6, 0x4F, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0x6F, 0x7E, 0x68, 0x6E, 0xA0, 0x14, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x73, 0xD4, 0xE8, 0xAB, 0x5B, 0xF6, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xE0, 0x3C, 0x24, 0x00, 0x95, 0xE9, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x0D, 0x4F, 0x81, 0xD0, 0xF2, 0x3F, 0x00),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0x1D, 0xCD, 0x78, 0x39, 0xC4, 0x6B, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x45, 0xC7, 0xB8, 0x2F, 0xAA, 0x5D, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0x8C, 0x6E, 0xA3, 0x24, 0xB2, 0xDB, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x2D, 0xD9, 0xF1, 0xC7, 0x9B, 0x8A, 0xAF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xE1, 0x2C, 0xB9, 0x40, 0x37, 0x91, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x2C, 0xB5, 0x23, 0x03, 0x2B, 0xAF, 0x2F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0x9D, 0x5A, 0x20, 0x10, 0xA9, 0x84, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x30, 0x89, 0x20, 0x13, 0xE9, 0xB2, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x6E, 0x52, 0xEB, 0x03, 0x18, 0x1F, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x9E, 0x1C, 0x35, 0x87, 0x92, 0x69, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0xC9, 0x88, 0xAF, 0xC6, 0x6C, 0x83, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0xD5, 0x7A, 0x54, 0x34, 0x99, 0xB6, 0x6F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0xAD, 0x45, 0x9B, 0x4B, 0x41, 0x4D, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0x5D, 0xAB, 0x7F, 0x35, 0x34, 0xE9, 0x29),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0xBE, 0x78, 0x34, 0x44, 0xF3, 0x4A, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xDE, 0xE3, 0xC4, 0xEE, 0x0B, 0xF9, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x86, 0x16, 0x48, 0x32, 0xB8, 0x74, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0xEE, 0x7C, 0xBA, 0xBD, 0x81, 0xE3, 0x55),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x6A, 0xFA, 0x84, 0xDA, 0xB8, 0xD5, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x9F, 0x8A, 0xD5, 0x1B, 0x2E, 0x1A, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x0C, 0x61, 0xE2, 0xFF, 0x5B, 0xE6, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x62, 0xC1, 0x87, 0x53, 0x1B, 0x92, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x90, 0x00, 0xD1, 0x6A, 0x0C, 0x0E, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x2E, 0xB5, 0x3B, 0x44, 0xB5, 0xA0, 0x78),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x5D, 0x02, 0x58, 0xB5, 0xBE, 0x45, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xEF, 0x8E, 0x90, 0x4D, 0x2A, 0x32, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0x99, 0x75, 0x5C, 0x0A, 0x33, 0x8F, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x6C, 0x95, 0xD4, 0x1F, 0xF3, 0xEB, 0xDA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0xE4, 0x4C, 0x91, 0x20, 0xF3, 0x25, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x95, 0xEB, 0x29, 0x6F, 0x20, 0x34, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x15, 0xE5, 0x13, 0x7E, 0x64, 0x8B, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xBC, 0x0D, 0x18, 0x7E, 0x37, 0x9E, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x82, 0x20, 0xF7, 0x2D, 0x7A, 0x77, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x29, 0xA2, 0xDB, 0x7A, 0xE6, 0x6F, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xC6, 0x50, 0x5C, 0xBC, 0xE6, 0x4F, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x9F, 0xD5, 0xE8, 0xC5, 0x3D, 0xB7, 0x30),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x03, 0x55, 0x10, 0xDB, 0xA6, 0x8B, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x17, 0xAE, 0x78, 0xC9, 0x1D, 0x43, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x35, 0x49, 0xD4, 0x47, 0x84, 0x8D, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x95, 0x2F, 0xEA, 0xBC, 0xB4, 0x18, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x48, 0xAE, 0x89, 0xF5, 0x65, 0x3D, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xF2, 0x2B, 0x20, 0xD1, 0x75, 0x50, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0xE6, 0x5C, 0x2C, 0xE0, 0x7D, 0xDF, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x07, 0x3E, 0xCE, 0x9F, 0x18, 0xB6, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0xF8, 0xF0, 0xD5, 0xFA, 0x42, 0x1D, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x6C, 0x1D, 0x03, 0xC9, 0x0E, 0x2B, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x18, 0x52, 0xA5, 0xB4, 0x63, 0xE1, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x0A, 0xD9, 0xC4, 0xFD, 0x16, 0x60, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x7D, 0xDE, 0xDF, 0x4B, 0x4A, 0xB0, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x4E, 0x8C, 0x94, 0xC1, 0xE2, 0x85, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4F, 0xF0, 0xEA, 0xB5, 0x9B, 0x70, 0xEF, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x56, 0xC2, 0x39, 0x5D, 0xF3, 0x2C, 0xD9, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0x1C, 0x2E, 0xCC, 0x2F, 0x54, 0x87, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB0, 0x72, 0xC7, 0xB5, 0x50, 0xA3, 0x84, 0x77),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xD1, 0xAF, 0xA9, 0xB4, 0x8B, 0x5D, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xF6, 0x52, 0x8A, 0xC3, 0x56, 0xA5, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x52, 0xFF, 0xEA, 0x05, 0x42, 0x77, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x08, 0x90, 0x72, 0x86, 0xC4, 0xC3, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x15, 0xF8, 0xF1, 0x16, 0x67, 0xC6, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x87, 0xAC, 0x8F, 0x71, 0xEC, 0x83, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0xE1, 0xE6, 0x2D, 0x0E, 0x11, 0xA1, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0xE2, 0xA8, 0x32, 0xE6, 0xE3, 0x83, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x56, 0xE5, 0xCD, 0xB7, 0x2B, 0x67, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xED, 0xC9, 0x65, 0x6D, 0x87, 0xE1, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xFD, 0x9A, 0x53, 0x0E, 0xFA, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0x4C, 0x4A, 0xE2, 0x23, 0x84, 0xFA, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xFE, 0x49, 0x81, 0xD1, 0x3E, 0xF4, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x72, 0xE0, 0xEF, 0x0D, 0xB8, 0x3E, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x00, 0x0F, 0x5F, 0xCE, 0x60, 0x72, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xCC, 0xD8, 0x03, 0x07, 0x6E, 0x5A, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x3A, 0x35, 0x50, 0x4E, 0x1F, 0xCA, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0xEA, 0x88, 0x55, 0xBD, 0x6E, 0x05, 0x7F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x6D, 0xF1, 0x97, 0xA6, 0x69, 0x39, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0x41, 0x99, 0xFF, 0x3B, 0xA1, 0x26, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x2F, 0x95, 0x80, 0x12, 0x4A, 0x1B, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xBF, 0x51, 0xAA, 0xAE, 0x2D, 0xDA, 0xCF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1C, 0xB3, 0x52, 0x36, 0x49, 0xD4, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xC1, 0x1F, 0x3A, 0xD3, 0x3E, 0x5C, 0x1A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x51, 0xF7, 0x2B, 0xC8, 0xA9, 0xA7, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0x4E, 0x7F, 0x98, 0x41, 0x66, 0xB0, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x1D, 0xC0, 0x42, 0xCD, 0xF8, 0xC3, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x41, 0x91, 0x7D, 0xCC, 0x8B, 0xCC, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xAE, 0x76, 0xED, 0x56, 0x18, 0xC5, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x6A, 0x06, 0xA3, 0x7F, 0x65, 0x10, 0x1F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xEC, 0x3C, 0x05, 0x05, 0xCA, 0xF6, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x48, 0xCD, 0x02, 0x51, 0x12, 0x16, 0x3C, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0xEB, 0xB3, 0x43, 0x7B, 0xDD, 0xB2, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x59, 0x90, 0x41, 0xDB, 0xE4, 0xF5, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x0E, 0x18, 0x2A, 0x5A, 0x83, 0x7C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x37, 0xA1, 0x0D, 0xF1, 0x2F, 0x63, 0x79),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC0, 0xFA, 0x6F, 0x1F, 0x67, 0xCF, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x34, 0x45, 0xBB, 0xF4, 0xF9, 0x9B, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0x69, 0xFE, 0x67, 0x1D, 0x64, 0x8F, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x39, 0xBF, 0xD8, 0xB3, 0xC7, 0xAD, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x93, 0xFF, 0xF3, 0x28, 0xFA, 0x39, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF9, 0xC3, 0x85, 0x26, 0x7A, 0x88, 0x89),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xD5, 0x79, 0xD8, 0x11, 0xDE, 0xEB, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x46, 0xA4, 0x6A, 0xDA, 0x74, 0x34, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0xBD, 0xD3, 0xF5, 0x14, 0xEE, 0xFE, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x4C, 0xA3, 0x71, 0x43, 0x65, 0xF8, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x6C, 0x35, 0xFA, 0x90, 0x25, 0xD8, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x34, 0x84, 0x96, 0xA1, 0x43, 0x03, 0x4D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x3B, 0x3B, 0x2F, 0xCA, 0x59, 0xF2, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCD, 0x48, 0x24, 0x74, 0xD8, 0x72, 0x90, 0xA3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x42, 0x74, 0x8C, 0x6F, 0x52, 0x19, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x40, 0x9E, 0x41, 0x63, 0x68, 0x78, 0x4C, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x94, 0xB6, 0x6B, 0x38, 0x52, 0xA8, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x30, 0x25, 0x93, 0xA1, 0x6F, 0x6E, 0x68),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x2F, 0x4B, 0x64, 0x79, 0x50, 0xFF, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0x36, 0xED, 0x57, 0x39, 0x3B, 0xE7, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x85, 0xEA, 0x35, 0xD6, 0xC0, 0xA0, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x89, 0x3A, 0xCC, 0x22, 0x1C, 0x46, 0x02),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x7A, 0xB0, 0xA1, 0x1B, 0x69, 0x62, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xB8, 0x8A, 0x6C, 0x18, 0x85, 0x0D, 0x88),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB6, 0x50, 0xE9, 0x4E, 0x7F, 0xE8, 0x07),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5B, 0x5C, 0xD1, 0x4B, 0x11, 0x9A, 0xD8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x25, 0x56, 0x74, 0x51, 0x9C, 0xEC, 0x9C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x7F, 0xB6, 0x8A, 0xCB, 0x3A, 0x10, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x60, 0x33, 0x07, 0x01, 0xE9, 0x49, 0x59, 0xE6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xA5, 0x2E, 0xF2, 0xBA, 0x32, 0x63, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x06, 0x0B, 0xA5, 0x44, 0x27, 0x7F, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x74, 0xAC, 0x0F, 0xCC, 0x4F, 0x13, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0xB1, 0xBF, 0x97, 0x49, 0xA5, 0x1C, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x64, 0x68, 0x7B, 0x0F, 0xCC, 0x77, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x39, 0xF9, 0x4E, 0x84, 0x9C, 0xF6, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xCF, 0x6D, 0xE2, 0xA1, 0x2D, 0xF9, 0x2B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0xC4, 0x90, 0x57, 0x31, 0x01, 0x05, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x1E, 0xBB, 0xBF, 0x98, 0xA4, 0x7C, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xE3, 0xA0, 0xB2, 0xCD, 0x39, 0x9A, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x34, 0x60, 0x7A, 0x89, 0x98, 0xB5, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0x20, 0x3D, 0x3A, 0x04, 0x8F, 0x5A, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x26, 0xB6, 0x49, 0x09, 0x9C, 0x0F, 0x59),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x66, 0xD2, 0x38, 0x2A, 0x62, 0x81, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0xC8, 0x20, 0x5E, 0x28, 0xA3, 0x81, 0xA7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x31, 0xA4, 0xF1, 0xEA, 0x7D, 0x87, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8F, 0x2C, 0x99, 0x09, 0x6F, 0x63, 0xEB, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x73, 0x76, 0xDA, 0x1A, 0x06, 0xBE, 0xDE, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x09, 0x2E, 0x75, 0x39, 0x30, 0x2D, 0x42),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x9B, 0xC1, 0x5A, 0x17, 0xC3, 0x8C, 0x31),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x58, 0x8D, 0x94, 0x4D, 0x3D, 0xAB, 0x60, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xFD, 0x1E, 0x0F, 0x43, 0xAE, 0x9D, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF2, 0xF3, 0x20, 0x1B, 0xAA, 0xB7, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0x5B, 0xA4, 0xF4, 0x90, 0x3B, 0xE3, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x78, 0x72, 0xBD, 0x65, 0x09, 0x0B, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x37, 0x2A, 0x6C, 0x16, 0x4F, 0x64, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0xCE, 0xA3, 0x90, 0xB4, 0x9A, 0xBC, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x55, 0x63, 0x1D, 0x3A, 0x6E, 0x18),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xB4, 0xAA, 0x99, 0x22, 0x45, 0x89, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0x7C, 0x8C, 0xA6, 0x3D, 0xA7, 0x3E, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x06, 0x42, 0xDC, 0xA6, 0xE3, 0xC6, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x8C, 0x3D, 0x5D, 0x47, 0x31, 0x7C, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x85, 0xEE, 0x46, 0x7E, 0x13, 0x04, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x3C, 0x8B, 0x43, 0x2E, 0x74, 0xF5, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x88, 0x8E, 0x07, 0x29, 0x08, 0x03, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0x9B, 0x89, 0xEB, 0x08, 0xE8, 0x43, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x07, 0x67, 0xFD, 0xD9, 0x73, 0x6F, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0xEB, 0x21, 0x8D, 0x98, 0x43, 0x74, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x88, 0xCC, 0x14, 0xD8, 0x08, 0xBB, 0xA6, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x98, 0xF2, 0x6A, 0x18, 0xC3, 0xDD, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x38, 0x91, 0xA0, 0x03, 0xF2, 0x04, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0xAF, 0xE8, 0xFD, 0xFB, 0x13, 0x70, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x93, 0x87, 0x98, 0x4A, 0xE0, 0x00, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x2E, 0x69, 0x9C, 0xA2, 0x2D, 0x03, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFE, 0xF3, 0xB9, 0xC1, 0x85, 0x2A, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xFD, 0x86, 0xB1, 0xCD, 0xBF, 0x41, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xD8, 0x9A, 0x21, 0xF3, 0xFE, 0xCB, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x78, 0x04, 0x60, 0xB7, 0xA9, 0xA2, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1E, 0x66, 0x2A, 0x54, 0x51, 0xBD, 0x8B),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x16, 0x36, 0xEF, 0x61, 0x2D, 0xEE, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x5F, 0x88, 0xA0, 0x13, 0x12, 0xF7, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA9, 0xC6, 0xAD, 0x4A, 0x4A, 0x07, 0x01, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB8, 0x74, 0xB1, 0x4F, 0xEB, 0xBD, 0xD5, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xF9, 0x71, 0xA2, 0x06, 0x4F, 0xD7, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x8B, 0x4D, 0x48, 0xE0, 0x98, 0xFB, 0x6A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xBA, 0x10, 0xA3, 0x0D, 0x52, 0xAC, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xD0, 0xE0, 0x36, 0xE6, 0x07, 0x3A, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x80, 0xF0, 0xAA, 0x49, 0x22, 0x4B, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xC7, 0xAB, 0x1C, 0x89, 0xCD, 0x24, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x82, 0x2A, 0xFC, 0xB3, 0x6D, 0x45, 0x96, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xE4, 0xDB, 0x52, 0x3F, 0xC4, 0xB4, 0x19),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5B, 0xCC, 0xC8, 0x7F, 0xBB, 0x6B, 0x87, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x21, 0x3C, 0x69, 0x7D, 0x38, 0x57, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x4C, 0x18, 0x3C, 0x53, 0xA5, 0x48, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xC3, 0x64, 0x45, 0xDB, 0xC4, 0x6D, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xCC, 0xD1, 0xBB, 0x17, 0xB8, 0x34, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x69, 0x71, 0xFA, 0xA0, 0x28, 0x4A, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xE8, 0x9E, 0x39, 0xEA, 0x8D, 0x38, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x9C, 0xBB, 0xCD, 0x80, 0x1A, 0xEE, 0xB7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xA0, 0x45, 0xBF, 0xD9, 0x22, 0x11, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x7C, 0x5C, 0xD9, 0xC0, 0x9F, 0x69, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x8A, 0xA6, 0x79, 0x4E, 0x35, 0xB9, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCC, 0x8B, 0x9A, 0x3E, 0xA1, 0xB8, 0x28, 0x10),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x2F, 0xEF, 0xBB, 0xA9, 0x72, 0x7F, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x34, 0xB7, 0x12, 0xB9, 0xE7, 0xC3, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x1D, 0xD9, 0x42, 0x77, 0x0C, 0x71, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x01, 0x59, 0xA7, 0x56, 0x03, 0x91, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x91, 0x99, 0x33, 0x30, 0x3E, 0xEF, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xC9, 0x5A, 0x9A, 0x54, 0x66, 0xF1, 0x70),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0x2C, 0xB7, 0x6E, 0x71, 0x7D, 0x35, 0x30),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x0D, 0xEF, 0xD1, 0x2D, 0x99, 0x63, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x31, 0xAF, 0x2D, 0xC9, 0xC6, 0xC2, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0xC0, 0xDF, 0x80, 0x54, 0xC4, 0xAC, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x6B, 0xA0, 0x84, 0x96, 0xF7, 0x31, 0xC8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0xE2, 0x7C, 0x7A, 0x41, 0x45, 0x75, 0x6A),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xEE, 0x58, 0x31, 0xE8, 0x68, 0xD6, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x2E, 0x48, 0xB7, 0x09, 0x9F, 0xD4, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xA9, 0x5C, 0xE7, 0x64, 0x43, 0x5D, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9E, 0x58, 0x9F, 0x50, 0xAB, 0x68, 0xFF, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0x88, 0x2D, 0xBA, 0x12, 0xBF, 0x8D, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xDF, 0x6F, 0xB3, 0x75, 0xA4, 0x55, 0x73),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x17, 0x92, 0x39, 0xB7, 0x13, 0x37, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x43, 0x71, 0xA7, 0xCA, 0x17, 0x1B, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE7, 0xB9, 0xB0, 0x78, 0xEF, 0xA0, 0xDA, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x84, 0xF2, 0x0F, 0x85, 0xA2, 0xB6, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x72, 0x65, 0x2E, 0x6E, 0x45, 0xB9, 0x4C, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x6A, 0x8C, 0x2B, 0x77, 0x96, 0x36, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x7A, 0x13, 0x4A, 0x97, 0x63, 0x02, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x1E, 0x06, 0x03, 0x8F, 0xB9, 0xEE, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0xEE, 0x8B, 0x89, 0xA9, 0x70, 0xDB, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x7B, 0x81, 0xC9, 0x70, 0x8D, 0x62, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0xDA, 0x46, 0xF8, 0xF9, 0x3A, 0xBE, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0x9C, 0x7A, 0x97, 0x62, 0xEB, 0xFA, 0x0F),
+};
+static const mbedtls_mpi_uint brainpoolP384r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x03, 0x3D, 0x3C, 0x46, 0x27, 0x9E, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x08, 0x1C, 0xD5, 0x25, 0xAF, 0xE9, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x69, 0xDC, 0x59, 0xF4, 0x8A, 0x7C, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x9A, 0x7A, 0x99, 0x21, 0x0C, 0x4E, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xCE, 0x85, 0x5F, 0xAC, 0xAA, 0x82, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x83, 0x57, 0x69, 0x90, 0x76, 0xF3, 0x53, 0x3F),
+};
+static const mbedtls_ecp_point brainpoolP384r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP384r1_T_0_X, brainpoolP384r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_1_X, brainpoolP384r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_2_X, brainpoolP384r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_3_X, brainpoolP384r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_4_X, brainpoolP384r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_5_X, brainpoolP384r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_6_X, brainpoolP384r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_7_X, brainpoolP384r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_8_X, brainpoolP384r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_9_X, brainpoolP384r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_10_X, brainpoolP384r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_11_X, brainpoolP384r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_12_X, brainpoolP384r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_13_X, brainpoolP384r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_14_X, brainpoolP384r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_15_X, brainpoolP384r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_16_X, brainpoolP384r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_17_X, brainpoolP384r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_18_X, brainpoolP384r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_19_X, brainpoolP384r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_20_X, brainpoolP384r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_21_X, brainpoolP384r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_22_X, brainpoolP384r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_23_X, brainpoolP384r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_24_X, brainpoolP384r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_25_X, brainpoolP384r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_26_X, brainpoolP384r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_27_X, brainpoolP384r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_28_X, brainpoolP384r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_29_X, brainpoolP384r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_30_X, brainpoolP384r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP384r1_T_31_X, brainpoolP384r1_T_31_Y),
+};
+#else
+#define brainpoolP384r1_T NULL
+#endif
+
+#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
+
+/*
+ * Domain parameters for brainpoolP512r1 (RFC 5639 3.7)
+ */
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+static const mbedtls_mpi_uint brainpoolP512r1_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_a[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_b[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_gx[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_gy[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA),
+};
+
+#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1
+static const mbedtls_mpi_uint brainpoolP512r1_T_0_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_0_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_1_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xE9, 0x6B, 0x8C, 0x6F, 0x9D, 0x88, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x4F, 0x86, 0x96, 0xA7, 0x56, 0xD1, 0x37),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xAB, 0xFA, 0xEE, 0xA7, 0xF5, 0x0E, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x40, 0xEF, 0x9E, 0x6D, 0xD6, 0x32, 0x33),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xED, 0x56, 0x14, 0x57, 0x1A, 0x8D, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xED, 0x4D, 0x3A, 0xFA, 0x71, 0x75, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xC5, 0x76, 0x1C, 0x14, 0xBE, 0xB5, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x5A, 0xCB, 0xE7, 0x36, 0x1D, 0x52, 0x1C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_1_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8D, 0x7A, 0xEB, 0xA3, 0x8B, 0xD5, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0xA3, 0x41, 0xF8, 0xAC, 0x9E, 0xAB, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x12, 0xE3, 0x65, 0x0D, 0x1C, 0xFE, 0x09, 0x2B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0xCA, 0x13, 0x3F, 0xC5, 0xF9, 0x7E, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0x5D, 0x63, 0x28, 0xA6, 0x89, 0xD3, 0x91),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x95, 0x3F, 0x7A, 0x82, 0xD4, 0x77, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xBB, 0x92, 0x32, 0x00, 0xF4, 0x66, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x58, 0x31, 0xD1, 0x17, 0x9F, 0x2A, 0x22),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_2_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x36, 0xA9, 0xCD, 0x80, 0xA5, 0x2D, 0x78),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x91, 0x44, 0xAB, 0xCE, 0x71, 0xFF, 0x0C, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0x24, 0x58, 0x35, 0x5A, 0x21, 0x32, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1B, 0xA6, 0x28, 0xF8, 0x7A, 0x97, 0xAE, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xE7, 0x08, 0xFA, 0x47, 0xC9, 0x55, 0x09),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xAC, 0x2E, 0x84, 0xA4, 0xF5, 0x52, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x58, 0x05, 0x9D, 0xA7, 0xC8, 0x71, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x92, 0xB4, 0x92, 0xC1, 0x92, 0xEC, 0x6B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_2_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4A, 0x48, 0x2D, 0x79, 0x5E, 0x58, 0xE5, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x85, 0x26, 0xEC, 0xE9, 0x6E, 0xD4, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x68, 0x26, 0x87, 0x38, 0xA2, 0xD2, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0x17, 0x60, 0xCE, 0x75, 0xF8, 0xA5, 0x6F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0x51, 0xDB, 0xA9, 0xAE, 0x87, 0xF1, 0x15),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x49, 0x92, 0x3B, 0x19, 0x96, 0xF5, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0xD5, 0x52, 0x52, 0x8C, 0xCE, 0xFD, 0xFA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x18, 0x0A, 0xE6, 0xF6, 0xAE, 0x08, 0x41),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_3_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x2B, 0xD8, 0x54, 0xCE, 0xB0, 0x57, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xB0, 0xF8, 0x9E, 0x03, 0x03, 0x3C, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x0E, 0x29, 0x29, 0x00, 0xF3, 0x70, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0x33, 0x99, 0x0E, 0x00, 0x5D, 0xFE, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0x2D, 0xF2, 0x59, 0x32, 0xCF, 0x03, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0xC9, 0x72, 0xAE, 0x0C, 0xEF, 0xD1, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x5A, 0x27, 0xBF, 0x2F, 0x45, 0xF9, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD4, 0xBE, 0xE5, 0x2C, 0xFF, 0x5B, 0x1E, 0x88),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_3_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0xAC, 0xBB, 0xD8, 0x83, 0xC2, 0x46, 0xF6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xDC, 0xCE, 0x15, 0xB4, 0xEF, 0xCF, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xDB, 0x5E, 0x94, 0x31, 0x0B, 0xB2, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0xB9, 0xE3, 0xE3, 0x11, 0x71, 0x41, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xE3, 0x01, 0xB7, 0x7D, 0xBC, 0x65, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x07, 0x65, 0x87, 0xA7, 0xE8, 0x48, 0xE3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x48, 0x8F, 0xD4, 0x30, 0x8E, 0xB4, 0x6C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0xE0, 0x73, 0xBE, 0x1E, 0xBF, 0x56, 0x36),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_4_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFE, 0x0E, 0x5E, 0x87, 0xC5, 0xAB, 0x0E, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0xF9, 0x5F, 0x80, 0x24, 0x4C, 0x2A, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDE, 0x15, 0x21, 0x54, 0x92, 0x84, 0x8D, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA8, 0x8A, 0x47, 0x74, 0xDC, 0x42, 0xB1, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0xF7, 0x30, 0xFD, 0xC1, 0x9B, 0x0C, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x6C, 0xCC, 0xDF, 0xC5, 0xE3, 0xA9, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x67, 0x59, 0x10, 0x5C, 0x51, 0x54, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x37, 0xFB, 0x6E, 0xB0, 0x78, 0x63, 0x8E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_4_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0xEF, 0xC4, 0x39, 0x20, 0xF1, 0x46, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0x62, 0xAE, 0xFF, 0x10, 0xE4, 0xE2, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x5C, 0xF5, 0x2E, 0x22, 0x89, 0xE5, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0x0C, 0x29, 0xA8, 0x62, 0xAE, 0xDB, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x9E, 0x0F, 0xCA, 0x87, 0x2A, 0x6F, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCE, 0xDC, 0x9B, 0x9F, 0x65, 0xD4, 0xAD, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0xC3, 0x08, 0x0F, 0xCF, 0x67, 0xE9, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x5C, 0xD7, 0xFF, 0x41, 0x9C, 0xCB, 0x26),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_5_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x25, 0x05, 0x12, 0xAD, 0x73, 0x63, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x99, 0x07, 0x86, 0x57, 0xE7, 0x94, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x4B, 0xA5, 0xBF, 0x18, 0xA9, 0xEF, 0x6A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0x4C, 0xC4, 0x09, 0xF2, 0x2F, 0x0C, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x3A, 0x04, 0xEA, 0x89, 0x6C, 0x91, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x6C, 0x3A, 0xE7, 0xA3, 0xEC, 0x24, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xA1, 0x26, 0x21, 0x04, 0xE3, 0xB9, 0x40),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0x71, 0x4B, 0x7B, 0xC2, 0x89, 0xCD, 0xA2),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_5_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB7, 0xB9, 0xA8, 0x9D, 0xFD, 0x00, 0x3A, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x41, 0x6C, 0xBB, 0x5A, 0xCA, 0x1F, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0xD7, 0xE2, 0x6C, 0x6B, 0xA7, 0x48, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x19, 0xAD, 0xA7, 0xC1, 0x7E, 0x4F, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0xF7, 0x19, 0x3C, 0x06, 0x74, 0x2C, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x23, 0x4F, 0x0C, 0x09, 0xB0, 0x80, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4E, 0x74, 0x34, 0x08, 0x44, 0x7E, 0xA3, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xCC, 0x8D, 0x12, 0x6E, 0xE1, 0x3D, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_6_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x18, 0xB1, 0x71, 0x02, 0x93, 0xC2, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x89, 0x40, 0xE2, 0x1F, 0xE7, 0x5E, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x8E, 0xAE, 0x89, 0x01, 0xD4, 0x0C, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAE, 0xDA, 0x58, 0x70, 0x24, 0xF2, 0xE4, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0xC7, 0x1D, 0xD6, 0x4A, 0x6F, 0x66, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x1D, 0x7E, 0x4A, 0x2C, 0xCA, 0xEC, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA1, 0x06, 0x7F, 0xA8, 0x99, 0xE4, 0xD3, 0x4E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x1D, 0x5A, 0xDF, 0x5E, 0x58, 0x36, 0x49),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_6_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0xB9, 0x32, 0x69, 0x1F, 0x72, 0x2A, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0x73, 0xE2, 0x03, 0x39, 0x35, 0xAA, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x5E, 0x5D, 0x48, 0xEF, 0xAE, 0x30, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x7F, 0x60, 0x19, 0xAF, 0xEC, 0x9D, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCA, 0xD9, 0x19, 0xE4, 0x1B, 0x56, 0x15, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xD7, 0x33, 0x59, 0x1F, 0x43, 0x59, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xCE, 0xEE, 0xCA, 0xA4, 0x7F, 0x63, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBD, 0x40, 0xC0, 0xF6, 0x19, 0x89, 0x43, 0x20),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_7_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x92, 0xEA, 0x07, 0x65, 0x79, 0x86, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0xB7, 0x13, 0x75, 0xD3, 0xC5, 0x0A, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x9E, 0xFA, 0xE1, 0x1F, 0x0C, 0xF9, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x8C, 0xED, 0x5C, 0x21, 0xE9, 0x09, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0x4D, 0xD8, 0x18, 0xC4, 0xF6, 0x36, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xC9, 0xAC, 0x5C, 0xFA, 0x69, 0xA4, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0x8C, 0x94, 0x1C, 0x7B, 0x71, 0x36, 0x58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xBD, 0x46, 0xCE, 0xB7, 0x1D, 0x9C, 0x5E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_7_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xD6, 0x96, 0x4B, 0xA6, 0x47, 0xEB, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xF1, 0x5F, 0x15, 0xDE, 0x99, 0x6F, 0x66),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xBD, 0xE5, 0x04, 0xB8, 0xE6, 0xC0, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x49, 0xD3, 0xF0, 0x04, 0x00, 0xE4, 0x05, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xF3, 0x06, 0xA3, 0x1A, 0xFF, 0xEA, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x32, 0xAA, 0x99, 0x33, 0x09, 0xB6, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xEF, 0xFC, 0x61, 0x10, 0x42, 0x31, 0x94),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0xF1, 0xF4, 0x33, 0xCF, 0x28, 0x90, 0x9C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_8_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xDE, 0xF9, 0x88, 0x87, 0x7B, 0xEB, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0xB8, 0xDA, 0xFA, 0xDA, 0x3D, 0xA6, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF0, 0x62, 0x82, 0x53, 0x32, 0x55, 0x03),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xA5, 0x32, 0x4A, 0x19, 0x11, 0x9C, 0x10),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xB3, 0x27, 0xE9, 0x75, 0x90, 0x05, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x1C, 0x90, 0x48, 0x77, 0x01, 0x85, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD6, 0x9B, 0x84, 0xA8, 0xD7, 0xC5, 0x28),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x7A, 0xCB, 0xB3, 0x11, 0x46, 0xD7, 0x99),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_8_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0x23, 0xBF, 0x75, 0x75, 0xA1, 0x95, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4B, 0x66, 0x5D, 0x34, 0x13, 0xA9, 0x03, 0xBE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x80, 0x9D, 0x5F, 0xD2, 0x44, 0xE1, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x5D, 0xBD, 0xA8, 0xBF, 0xB4, 0x25, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x99, 0x1F, 0x53, 0xF1, 0x57, 0xDB, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x7C, 0xE5, 0xC5, 0x51, 0x0B, 0x4C, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6B, 0xB0, 0x1A, 0x9C, 0x16, 0xB0, 0x32, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xE3, 0xCF, 0xDD, 0x48, 0xB4, 0x7B, 0x33),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_9_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0xDD, 0x9E, 0x3C, 0x98, 0x0E, 0x77, 0x65),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0xAB, 0x01, 0xD3, 0x87, 0x74, 0x25, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xA3, 0xE3, 0x76, 0x43, 0x87, 0x12, 0xBD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x54, 0xB1, 0x3B, 0x60, 0x66, 0xEB, 0x98, 0x54),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x78, 0xC8, 0xD7, 0x4E, 0x75, 0xCA, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xDF, 0x71, 0x19, 0xE7, 0x07, 0x36, 0xB5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0xC9, 0xA8, 0x5F, 0x91, 0xBF, 0x47, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x96, 0x58, 0x96, 0x18, 0xB6, 0xFA, 0x01),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_9_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x2D, 0xA9, 0x9B, 0x86, 0xDB, 0x0C, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x0B, 0x2D, 0x56, 0x4A, 0xD3, 0x93, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x15, 0xE2, 0x65, 0x12, 0x86, 0x0E, 0xB2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x41, 0x4D, 0xC1, 0xCB, 0xE4, 0xC3, 0xD7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x53, 0x10, 0xCA, 0xA3, 0xAC, 0x83, 0x26),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x01, 0x22, 0x96, 0x10, 0xAD, 0x69, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x42, 0x46, 0x4E, 0xD8, 0xEA, 0xD6, 0x9D, 0xF3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x2F, 0x7F, 0x62, 0x62, 0x80, 0xD0, 0x14),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_10_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xDA, 0x00, 0x63, 0x09, 0xBD, 0x6A, 0x83),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0F, 0xD4, 0x6E, 0x48, 0x05, 0xB7, 0xF7, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0x4D, 0xD7, 0x00, 0x4A, 0x15, 0x27, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x15, 0xAA, 0x37, 0x27, 0x34, 0x18, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x20, 0x2C, 0x84, 0x1B, 0x88, 0xBA, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x09, 0xD6, 0x04, 0xA2, 0x60, 0x84, 0x72),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0x04, 0x94, 0x08, 0xD4, 0xED, 0x47, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xF3, 0xE4, 0x3E, 0xB9, 0x5B, 0x35, 0x42),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_10_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5F, 0xD8, 0xB6, 0x80, 0xD6, 0xF1, 0x30, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x14, 0xA6, 0x85, 0xEE, 0xA7, 0xD8, 0x61),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x49, 0x2A, 0x1E, 0x7C, 0xE9, 0x2D, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3A, 0x87, 0x56, 0x91, 0x03, 0x77, 0x4D, 0x55),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0x52, 0xD4, 0xAA, 0xF7, 0xFA, 0xB0, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x5D, 0x11, 0x39, 0xB1, 0xE7, 0x76, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x13, 0xBC, 0x37, 0x5D, 0x74, 0xCD, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x48, 0x14, 0x23, 0x30, 0xF8, 0x46, 0x37),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_11_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x27, 0xB0, 0xD9, 0xB2, 0x74, 0xB4, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEA, 0xA6, 0xB9, 0x6F, 0x9F, 0x64, 0x36, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2E, 0x2B, 0x78, 0x40, 0x05, 0x2B, 0x7B, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x68, 0x3A, 0xB6, 0x4A, 0xE2, 0xDB, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1E, 0x33, 0xD7, 0x34, 0x8B, 0x25, 0x45, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xCE, 0xA8, 0xC9, 0x01, 0xFB, 0x0E, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF9, 0x51, 0x4C, 0x12, 0x9F, 0x60, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0x85, 0xBD, 0x30, 0x37, 0x84, 0x39, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_11_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x26, 0x33, 0xAF, 0x2E, 0xB8, 0x2E, 0xCC, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0xB1, 0x73, 0x59, 0x4E, 0x0C, 0x09, 0x4A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0x24, 0x89, 0x81, 0x12, 0xFF, 0xBB, 0x6E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x71, 0x37, 0x1A, 0x66, 0xEE, 0xED, 0xB6, 0x9B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0xBD, 0x04, 0x20, 0x5D, 0xFB, 0xBF, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0xF8, 0x34, 0xA3, 0xFF, 0x45, 0xDE, 0x92),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x18, 0x73, 0xF1, 0x32, 0x25, 0x58, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0xC1, 0x14, 0xE3, 0x9E, 0x40, 0x0F, 0x12),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_12_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x07, 0x9D, 0x9C, 0x00, 0xF7, 0x56, 0x19),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0xBA, 0x87, 0xF9, 0x15, 0x0C, 0x66, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0x1F, 0xC1, 0x28, 0xB0, 0x47, 0x0D, 0xF5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0xCA, 0x27, 0xEE, 0x4B, 0x23, 0x2B, 0x89),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7E, 0xB5, 0x68, 0xC8, 0x17, 0x5D, 0xC3, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0x02, 0x08, 0xEE, 0x20, 0x9D, 0xEA, 0x64),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x14, 0x50, 0xD4, 0x7D, 0x5F, 0xCF, 0xA0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0xFA, 0xF8, 0xA7, 0xC6, 0xDC, 0x14, 0x8C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_12_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x76, 0xBD, 0x0A, 0x1A, 0x18, 0x98, 0xDC, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x63, 0x63, 0x02, 0xB7, 0xD5, 0x5B, 0x5A, 0xC6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0xB1, 0xD7, 0x4B, 0x15, 0x39, 0x61, 0x5D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0x32, 0xE1, 0x9E, 0x70, 0x1B, 0xCE, 0x51),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x64, 0xD8, 0x18, 0x83, 0x52, 0x9B, 0x6D, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x55, 0x56, 0x19, 0x34, 0xA4, 0xEA, 0xFC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0xA9, 0x55, 0x80, 0xE3, 0x15, 0x36, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0x06, 0xC8, 0x1D, 0x17, 0x0D, 0xAD, 0x16),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_13_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xD6, 0xF0, 0xCC, 0xF3, 0x63, 0x53, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x5A, 0xDC, 0x46, 0xBD, 0x0D, 0xAD, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0x2F, 0x11, 0x60, 0x15, 0x51, 0x4A, 0xEA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xE3, 0x93, 0x38, 0xD5, 0x83, 0xAA, 0x0D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x90, 0xA6, 0xCC, 0xB1, 0xFD, 0xBB, 0x1A, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3B, 0x54, 0xC8, 0x54, 0x6F, 0x79, 0x1A, 0x59),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4A, 0xDA, 0x28, 0x92, 0x97, 0x9D, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD6, 0x4B, 0xDB, 0xC7, 0x52, 0xC5, 0x66, 0x34),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_13_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7E, 0x92, 0x53, 0x30, 0x93, 0xFD, 0xFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0x6A, 0xB1, 0x91, 0x0A, 0xB4, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6D, 0x9D, 0x40, 0x3F, 0xE3, 0xF1, 0x01, 0x46),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x0E, 0xD8, 0xED, 0x11, 0x8E, 0x4C, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x86, 0x4A, 0x1B, 0x88, 0xDF, 0x8D, 0x29, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x23, 0x21, 0x11, 0xAB, 0x77, 0x81, 0x62),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0B, 0xAF, 0x11, 0xFA, 0xBA, 0x40, 0x63, 0xE7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x6F, 0x8D, 0x80, 0xDF, 0x67, 0xF5, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_14_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0x8B, 0xB7, 0x08, 0xF4, 0xD7, 0x2D, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x2B, 0x30, 0x02, 0x45, 0x71, 0x08, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x97, 0x3A, 0xCA, 0x50, 0xF6, 0xC2, 0x19, 0x8C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xB9, 0x9B, 0x3E, 0x73, 0x95, 0x1D, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x60, 0x59, 0x48, 0xCB, 0xD8, 0xD6, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0xB9, 0x6C, 0x89, 0xAB, 0x99, 0xA8, 0xF8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0xA1, 0x8B, 0x4E, 0x06, 0x19, 0xEC, 0x99),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x95, 0x04, 0xCF, 0xD5, 0x94, 0xB3, 0x02),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_14_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x29, 0x35, 0x93, 0x7C, 0xB3, 0xB8, 0x9E, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC4, 0x45, 0x5C, 0x7E, 0xBF, 0x75, 0x81, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xE8, 0x24, 0xDF, 0xEC, 0x2F, 0x7D, 0xB9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF2, 0x8B, 0xD5, 0x6A, 0x9B, 0xA0, 0xE0, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0xE3, 0x27, 0x82, 0xDE, 0xDD, 0xCA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x57, 0x56, 0x46, 0x05, 0x06, 0x01, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x74, 0x35, 0xA7, 0x47, 0xE2, 0x6B, 0x2C, 0x4F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x9D, 0x4C, 0xEC, 0x1F, 0x11, 0x75, 0x2B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_15_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0xAA, 0x41, 0xC1, 0xE9, 0x0E, 0xE9, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xCF, 0x9C, 0x4B, 0xE8, 0xED, 0x0A, 0x49),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0x73, 0xCA, 0x0C, 0x46, 0x0A, 0x9C, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE1, 0x9E, 0xBC, 0xFE, 0x44, 0x63, 0x6D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x31, 0x43, 0x71, 0xEE, 0xF8, 0xC1, 0x8C, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6A, 0x4B, 0xF0, 0x69, 0x25, 0xBD, 0x71, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFD, 0x9A, 0xFE, 0x82, 0xE7, 0xC1, 0xC1, 0xEE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFC, 0x5A, 0x6E, 0x5E, 0x97, 0x6A, 0x35, 0x8D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_15_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA2, 0x18, 0x6C, 0x7E, 0xB8, 0x9E, 0x57, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x35, 0xB9, 0xC1, 0xD0, 0xFE, 0x78, 0xFB, 0x32),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x08, 0xAE, 0x46, 0x34, 0xEA, 0x7A, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x1C, 0x56, 0xA9, 0x18, 0x37, 0xD4, 0x9E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x28, 0x63, 0xE9, 0x0A, 0xB6, 0x38, 0x3C, 0xC1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3E, 0x4F, 0xA4, 0x6E, 0x85, 0x31, 0x23, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0D, 0xAD, 0xC4, 0xC3, 0xB1, 0x4B, 0x1C, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x56, 0x4A, 0x38, 0xB3, 0x6B, 0x6F, 0x2C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_16_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x67, 0xC7, 0x19, 0xDE, 0x21, 0xED, 0x89, 0xD0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2F, 0xBE, 0xA6, 0xAE, 0xEB, 0x9D, 0xA7, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x0E, 0x13, 0x1E, 0x86, 0x57, 0xC3, 0x3B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x4B, 0x30, 0x46, 0x52, 0xC1, 0xEC, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6E, 0xD5, 0x44, 0x31, 0x96, 0x3B, 0x26, 0x27),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x68, 0xA8, 0x67, 0x78, 0x39, 0xE8, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0x78, 0xB7, 0xDD, 0xF2, 0x58, 0xB6, 0x3D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x81, 0x3C, 0xB3, 0x26, 0xC4, 0x2C, 0x8C, 0xA5),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_16_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB9, 0x24, 0xE5, 0x73, 0xEE, 0x9A, 0x02, 0xA9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0x6A, 0x65, 0x60, 0xF3, 0x62, 0xE3, 0xE9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFB, 0x07, 0x84, 0xE6, 0x3B, 0x46, 0x65, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0x8F, 0x0C, 0xB0, 0xE1, 0x04, 0x82, 0x9D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEB, 0x13, 0xBF, 0x3D, 0xA0, 0x48, 0xA2, 0x74),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0x26, 0x76, 0x74, 0xAB, 0x0B, 0x29, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x30, 0x6E, 0x5F, 0x03, 0x34, 0x7C, 0x38, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x72, 0xF9, 0x3B, 0x3C, 0xA4, 0xBC, 0x7C),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_17_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5C, 0xCE, 0x18, 0x80, 0xB8, 0x24, 0x45, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x09, 0x03, 0xB8, 0x06, 0x64, 0xF7, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF1, 0x26, 0xB1, 0x10, 0x6D, 0x71, 0x12, 0x2E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x12, 0xC6, 0x6E, 0x1E, 0x6A, 0xC3, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE5, 0xD3, 0x0A, 0xDE, 0xD8, 0x6B, 0x04, 0x5C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x87, 0x5B, 0xAE, 0xDB, 0x3C, 0xC0, 0xC5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8E, 0xF5, 0xF9, 0xC1, 0x9A, 0x89, 0xBB, 0x7E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0x69, 0x72, 0x8B, 0xAE, 0x32, 0x13, 0x11),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_17_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x16, 0x07, 0x50, 0xFA, 0x4C, 0xCF, 0xE8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x50, 0x21, 0xE9, 0xDE, 0xEC, 0x7E, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x2F, 0xE8, 0x83, 0x30, 0x0B, 0x65, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x0B, 0x99, 0xAC, 0xC9, 0xBA, 0x6C, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x59, 0x5A, 0x0D, 0x7B, 0x9E, 0x08, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x34, 0x91, 0xB2, 0xDC, 0x90, 0xCE, 0x67, 0xED),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x93, 0x60, 0x0C, 0xD7, 0x1F, 0x2F, 0x17),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x19, 0x7F, 0x9D, 0x40, 0xF8, 0x78, 0x7A, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_18_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x13, 0x22, 0x95, 0xE8, 0xEF, 0x31, 0x57, 0x35),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x88, 0x53, 0xFE, 0xAF, 0x7C, 0x47, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xCE, 0xCC, 0x79, 0xE8, 0x9F, 0x8C, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDB, 0x16, 0xDD, 0x77, 0x6E, 0x8A, 0x73, 0x97),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x07, 0x97, 0x21, 0x3B, 0xF8, 0x5F, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC6, 0xB5, 0xD2, 0x81, 0x84, 0xF0, 0xE7, 0x9F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCB, 0x8F, 0x75, 0x09, 0x6A, 0x0E, 0x53, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x4F, 0x70, 0x97, 0xC7, 0xAC, 0x7D, 0x3F),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_18_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF9, 0x3C, 0x6A, 0xB4, 0x10, 0xA9, 0xC8, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xC5, 0xD6, 0x69, 0x16, 0xB8, 0xAC, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x44, 0xDC, 0xEB, 0x48, 0x54, 0x5D, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6F, 0x48, 0x9B, 0xD7, 0x72, 0x69, 0xA4, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x0D, 0x36, 0x9A, 0x66, 0x0B, 0xEC, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0xC6, 0xD4, 0xB6, 0x60, 0xE5, 0xC3, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBA, 0x29, 0x42, 0xE0, 0x9D, 0xFD, 0x7C, 0x3E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x10, 0xBA, 0x55, 0xBC, 0x3B, 0x38, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_19_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x25, 0x66, 0xFA, 0x05, 0x73, 0x03, 0x1B, 0x69),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x11, 0xA4, 0x66, 0x12, 0x96, 0x7B, 0x02, 0x4C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x44, 0xB5, 0xDE, 0x6D, 0x98, 0xD1, 0xD5, 0xA8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE2, 0xF5, 0x44, 0xB8, 0x8E, 0xF6, 0x8C, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x15, 0x2B, 0x72, 0xBC, 0x49, 0xE5, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x6C, 0x44, 0xD7, 0xDF, 0x8F, 0xEB, 0x8D, 0x80),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x64, 0x88, 0xAA, 0xB7, 0xE4, 0x70, 0x1D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9C, 0x14, 0xBB, 0xE9, 0x9B, 0xB9, 0x65, 0x5D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_19_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x66, 0x8E, 0x88, 0xF5, 0xF1, 0xC1, 0x89, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x16, 0x30, 0x53, 0xE6, 0xFB, 0x2D, 0x82, 0xB4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0xE4, 0xFF, 0xBA, 0x31, 0x79, 0xAB, 0xC2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x45, 0x09, 0xF7, 0xB7, 0x09, 0x78, 0x4C, 0x90),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xAE, 0xC2, 0x44, 0xDC, 0x17, 0x78, 0x47),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xD4, 0x17, 0x43, 0x19, 0x74, 0x9E, 0x23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x64, 0x3B, 0x73, 0xA2, 0x99, 0x27, 0x76),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x74, 0x36, 0x5F, 0xD3, 0x14, 0xB1, 0x31),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_20_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAC, 0x07, 0xAB, 0xFD, 0x9B, 0x03, 0xC5, 0xD5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0xBE, 0xB0, 0x1D, 0xF2, 0x0C, 0x73, 0x73),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xE7, 0x7B, 0x87, 0xD3, 0x34, 0xFD, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9A, 0x25, 0x3D, 0xC7, 0x36, 0x83, 0x53, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x7C, 0xCF, 0x63, 0x55, 0x12, 0x11, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC0, 0x34, 0x4D, 0x27, 0x92, 0xAC, 0x18, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x42, 0x61, 0x9D, 0x2E, 0xFF, 0x13, 0x16),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF4, 0xDE, 0x92, 0x65, 0x57, 0x0D, 0xBC, 0x0A),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_20_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEF, 0x7B, 0x6E, 0xC6, 0x2A, 0x21, 0x74, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0xA7, 0x53, 0x4D, 0x29, 0x36, 0xEF, 0xE5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE1, 0xD6, 0x41, 0xC7, 0x99, 0xAD, 0x50, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x99, 0xAC, 0x41, 0x9F, 0xFB, 0x4C, 0x86, 0xF1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xBB, 0xE6, 0x25, 0x28, 0xAA, 0xEB, 0x1E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x92, 0x04, 0xA2, 0xC3, 0xAA, 0x08, 0x8A, 0xCC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x2B, 0x5B, 0xE2, 0x8D, 0x76, 0xEA, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB3, 0x33, 0xD2, 0x21, 0x4D, 0x62, 0xE3, 0x8E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_21_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0x06, 0x8B, 0x2B, 0xC2, 0xC4, 0xB1, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFA, 0xF5, 0xA1, 0xC0, 0x03, 0x6A, 0x29, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF5, 0xA9, 0xEF, 0x55, 0xB6, 0x1A, 0x9F, 0x6B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9B, 0x54, 0x32, 0xBE, 0x06, 0x43, 0xB5, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF7, 0xD6, 0xD9, 0x20, 0x89, 0xBE, 0xD4, 0x1B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0x26, 0x95, 0x10, 0xCE, 0xB4, 0x88, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0xA6, 0x27, 0xAC, 0x32, 0xBA, 0xBD, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0xA6, 0xAE, 0x9C, 0x7B, 0xBE, 0xA1, 0x63),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_21_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8B, 0xCD, 0x4D, 0x3D, 0xDF, 0x96, 0xBB, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0xA7, 0x11, 0x06, 0xCC, 0x0E, 0x31, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x20, 0xE4, 0xF4, 0xAD, 0x7B, 0x5F, 0xF1, 0xEF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE4, 0x54, 0xBE, 0xF4, 0x8A, 0x03, 0x47, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0x53, 0x00, 0x7F, 0xB0, 0x8A, 0x68, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x16, 0xB1, 0x73, 0x6F, 0x5B, 0x0E, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x32, 0xE3, 0x43, 0x64, 0x75, 0xFB, 0xFB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x18, 0x55, 0x8A, 0x4E, 0x6E, 0x35, 0x54),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_22_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x80, 0x97, 0x15, 0x1E, 0xCB, 0xF2, 0x9C, 0xA5),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0xD1, 0xBB, 0xF3, 0x70, 0xAD, 0x13, 0xAD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0x96, 0xA4, 0xC5, 0x5E, 0xDA, 0xD5, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x81, 0xE9, 0x65, 0x66, 0x76, 0x47, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x35, 0x87, 0x06, 0x73, 0xCF, 0x34, 0xD2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x81, 0x15, 0x42, 0xA2, 0x79, 0x5B, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x08, 0xA2, 0x7D, 0x09, 0x14, 0x64, 0xC6, 0xAE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0x6D, 0xC4, 0xED, 0xF1, 0xD6, 0xE9, 0x24),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_22_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB4, 0xD5, 0xBB, 0x25, 0xA3, 0xDD, 0xA3, 0x88),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xF2, 0x68, 0x67, 0x39, 0x8F, 0x73, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x76, 0x28, 0x89, 0xAD, 0x32, 0xE0, 0xDF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0x90, 0xCC, 0x57, 0x58, 0xAA, 0xC9, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD7, 0x43, 0xD2, 0xCE, 0x5E, 0xA0, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x33, 0xB0, 0xB8, 0xA4, 0x9E, 0x96, 0x26, 0x86),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x94, 0x61, 0x1D, 0xF3, 0x65, 0x5E, 0x60, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC7, 0x1E, 0x65, 0xED, 0xCF, 0x07, 0x60, 0x20),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_23_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x30, 0x17, 0x8A, 0x91, 0x88, 0x0A, 0xA4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x05, 0x7D, 0x18, 0xA4, 0xAC, 0x59, 0xFC, 0x5F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x31, 0x8B, 0x25, 0x65, 0x39, 0x9A, 0xDC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x15, 0x16, 0x4B, 0x68, 0xBA, 0x59, 0x13, 0x2F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8D, 0xFD, 0xD3, 0xC5, 0x56, 0xC9, 0x8C, 0x5E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBC, 0xC6, 0x9F, 0xF4, 0xE6, 0xF7, 0xB4, 0x01),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2D, 0x7C, 0x03, 0x00, 0x26, 0x9F, 0xD8, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x1D, 0x6E, 0x00, 0xB9, 0x00, 0x6E, 0x93),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_23_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x63, 0xDA, 0x03, 0x2B, 0xD5, 0x0B, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x46, 0xFC, 0xE2, 0xC8, 0x47, 0xF0, 0xAE, 0xF2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x51, 0x4C, 0xF7, 0x50, 0x0C, 0x48, 0x06, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDF, 0x2B, 0x32, 0x98, 0x0E, 0x7E, 0x61, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x02, 0x27, 0xFE, 0x75, 0x86, 0xDF, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2B, 0x30, 0xB1, 0x22, 0x32, 0x1B, 0xFE, 0x24),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC2, 0x27, 0xF7, 0x78, 0x6F, 0xD7, 0xFD, 0xE4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA0, 0x78, 0xCC, 0xEA, 0xC0, 0x50, 0x24, 0x44),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_24_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x2B, 0x4F, 0x7F, 0x58, 0xE6, 0xC2, 0x70),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x43, 0xD5, 0xA7, 0x35, 0x3C, 0x80, 0xB8),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1A, 0x6D, 0x4B, 0x12, 0x00, 0x7B, 0xE6, 0xA6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x15, 0xBD, 0xD0, 0x9B, 0xCA, 0xAA, 0x81),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xCF, 0xCE, 0x9C, 0xE3, 0x8B, 0x60, 0x7A, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0xDA, 0x4B, 0x03, 0xA7, 0x8D, 0x43, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0xAF, 0x00, 0x2B, 0x32, 0xF0, 0x22, 0x68),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDC, 0xD9, 0x99, 0x99, 0xBE, 0x43, 0x99, 0x3E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_24_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1F, 0x71, 0x41, 0xF4, 0xB5, 0xFD, 0xDD, 0x36),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9D, 0xE2, 0x20, 0x4C, 0xD1, 0x2E, 0x1F, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x96, 0x43, 0x48, 0x76, 0x8A, 0x49, 0xAC, 0x87),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0C, 0x1A, 0x55, 0xA8, 0xA3, 0xD4, 0x57, 0x75),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0xA6, 0x84, 0x39, 0xC9, 0x13, 0xBB, 0x60),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD9, 0xFA, 0xA9, 0x70, 0xDE, 0x83, 0xDD, 0xC9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEC, 0xC9, 0xD9, 0x3E, 0x44, 0x91, 0x68, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB6, 0x9F, 0x85, 0x6D, 0xF7, 0x54, 0x36, 0x82),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_25_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x68, 0x6B, 0xA6, 0xA3, 0xE5, 0xD4, 0x46, 0xDB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x3E, 0xDC, 0x84, 0x7C, 0x7B, 0x24, 0x34),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x14, 0xED, 0x7F, 0x86, 0x07, 0x6C, 0x57, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x95, 0x06, 0xFE, 0x52, 0x12, 0x79, 0x69, 0x56),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x84, 0xD1, 0x44, 0x5F, 0x21, 0x3A, 0xC3, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5E, 0xD9, 0x4A, 0xC0, 0x75, 0xAB, 0x17, 0xAC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xFF, 0x81, 0x94, 0xB6, 0x80, 0x6B, 0x6F, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xBE, 0x8E, 0xA5, 0xAA, 0xBC, 0x1E, 0x3E),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_25_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x89, 0xC7, 0x85, 0xA6, 0x59, 0x9B, 0xB1, 0x52),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xCE, 0x40, 0xD1, 0xFB, 0xDF, 0x94, 0xF7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x18, 0xB8, 0x5E, 0xBF, 0x45, 0xA8, 0x2D, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x98, 0x9C, 0x06, 0x1B, 0xA9, 0x57, 0xB9, 0x79),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x53, 0xE9, 0xCE, 0xA2, 0xD3, 0x74, 0xA1, 0x3C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAA, 0x5F, 0x34, 0x78, 0xDB, 0xAE, 0x3A, 0x14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7D, 0x32, 0x84, 0x3E, 0x68, 0x6A, 0x43, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0xBC, 0x39, 0x36, 0xA4, 0xC5, 0xBB, 0x11),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_26_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8C, 0x07, 0xA2, 0xB5, 0xC9, 0x0F, 0x4D, 0x0F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0x1D, 0x67, 0xE6, 0xF1, 0x46, 0xEB, 0x71),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD7, 0x41, 0x23, 0x95, 0xE7, 0xE0, 0x10, 0xDD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x69, 0xFE, 0x68, 0x8C, 0xC6, 0x5F, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE3, 0xB9, 0x2B, 0x3D, 0xD2, 0x4F, 0xD8, 0x1A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA3, 0x09, 0xF5, 0x5F, 0xCF, 0xF6, 0x91, 0x57),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x65, 0x15, 0x42, 0x6B, 0x6D, 0xB5, 0xF3, 0xB6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBF, 0x56, 0x9D, 0xC5, 0xFF, 0xCA, 0x13, 0x9B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_26_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x4D, 0x38, 0xE6, 0x23, 0x63, 0x48, 0x3C, 0xCA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD2, 0x68, 0x3C, 0xD1, 0x3B, 0xE9, 0x3B, 0x82),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB5, 0x08, 0x54, 0x49, 0xD1, 0x46, 0x45, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x70, 0x52, 0x6E, 0x79, 0xC4, 0x5E, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0xDF, 0xE8, 0x5A, 0x32, 0x81, 0xDA, 0xD3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3C, 0x2D, 0x94, 0x5B, 0xB5, 0x35, 0x9F, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2A, 0x12, 0x8D, 0xC3, 0x36, 0x36, 0xB2, 0x2A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x39, 0x2F, 0x22, 0x38, 0x5B, 0x18, 0x4C, 0x35),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_27_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0xC1, 0x22, 0x0E, 0xF0, 0x73, 0x11, 0x05),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB2, 0xAE, 0xA4, 0x56, 0x18, 0x61, 0x66, 0x12),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x79, 0xFB, 0x72, 0x08, 0x84, 0x38, 0x51, 0xB0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDA, 0x86, 0xA8, 0xB9, 0x31, 0x99, 0x29, 0xC3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x8A, 0xFB, 0xC3, 0x42, 0xB3, 0xC7, 0x6F, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD8, 0xF8, 0xE1, 0x09, 0xBE, 0x75, 0xB0, 0x22),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5A, 0x7D, 0xFF, 0xF4, 0x99, 0xFC, 0x13, 0xAB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE6, 0x1B, 0x84, 0x81, 0x42, 0x22, 0xC6, 0x3D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_27_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x21, 0xE0, 0x37, 0xA4, 0xA0, 0x2F, 0x38, 0x7F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x3D, 0xB7, 0x40, 0x2F, 0x39, 0x3C, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7A, 0x3B, 0x8A, 0x51, 0xAE, 0x40, 0x49, 0x7A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x36, 0x20, 0x9F, 0xDD, 0xA9, 0xD0, 0x77, 0xC7),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x78, 0x1D, 0x64, 0xDA, 0xA0, 0x53, 0xC7, 0x7D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x37, 0x7B, 0x66, 0x55, 0x94, 0xD1, 0x51, 0x44),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0E, 0xA9, 0xB5, 0x5B, 0x38, 0x35, 0x40, 0xC0),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC8, 0xC9, 0x0F, 0xF0, 0x73, 0x79, 0x43, 0x61),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_28_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x47, 0x45, 0x69, 0x80, 0x72, 0x72, 0x42),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x11, 0x99, 0x59, 0xDB, 0x48, 0x80, 0x39),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x75, 0x6E, 0x3D, 0xFC, 0x37, 0x15, 0xF4, 0xBF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x17, 0xBB, 0x5B, 0xA6, 0x35, 0x8D, 0x28, 0x20),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0x1A, 0x3B, 0x2C, 0x8F, 0xD3, 0xAA, 0x2D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x55, 0x1C, 0x1A, 0xF8, 0x02, 0xD9, 0x7B, 0x41),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAF, 0x69, 0xAC, 0xF8, 0x54, 0x31, 0x14, 0xA1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x8A, 0xE6, 0xDE, 0x58, 0xB9, 0xC4, 0x7A),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_28_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x57, 0x83, 0x52, 0xFE, 0xF9, 0x7B, 0xE9, 0x1F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0xA2, 0x55, 0x46, 0x15, 0x49, 0xC1, 0x3A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xBC, 0x5C, 0x91, 0xBD, 0xB9, 0x9C, 0xF4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBB, 0xFD, 0xB1, 0x4E, 0x5F, 0x74, 0xEE, 0x53),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xB1, 0x8B, 0xD8, 0x8B, 0x17, 0x73, 0x1B, 0x96),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x22, 0x92, 0xD7, 0x67, 0x06, 0xAD, 0x25, 0xCD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x01, 0x0F, 0x80, 0x24, 0xE2, 0x27, 0x5F, 0x8B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x61, 0x1C, 0xCE, 0xD0, 0x67, 0xCA, 0xD4, 0x0B),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_29_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x87, 0xF1, 0xDD, 0x33, 0x66, 0xF9, 0x05, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1D, 0xE5, 0x6B, 0x79, 0xBD, 0x48, 0x42, 0xAA),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x14, 0x52, 0xE3, 0x53, 0xB4, 0x50, 0xD4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x32, 0x84, 0x6C, 0xCF, 0xDA, 0xB2, 0x20, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0xD6, 0x1A, 0xE5, 0xE2, 0x29, 0x70, 0xCE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x61, 0xFE, 0xBB, 0x21, 0x82, 0xD1, 0xFE),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x2C, 0xF0, 0x9C, 0x8B, 0x1A, 0x42, 0x30, 0x06),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0xD6, 0x49, 0x81, 0x92, 0xF1, 0xD0, 0x90),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_29_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x91, 0x93, 0x6A, 0xA6, 0x22, 0xE9, 0xD6),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x09, 0xDC, 0xC3, 0x69, 0x11, 0x95, 0x7D, 0xEC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x1C, 0xA3, 0x9D, 0x87, 0x5E, 0x64, 0x41, 0xA2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xBE, 0x87, 0x5A, 0x15, 0xBD, 0x6E, 0x3C, 0x8D),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD0, 0x8D, 0x50, 0xCC, 0xCF, 0xB7, 0x8F, 0x0B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x38, 0x65, 0xCD, 0x31, 0x30, 0xF1, 0x68, 0x13),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x10, 0x5C, 0x66, 0x67, 0x92, 0x30, 0x57, 0x95),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x23, 0x9B, 0x01, 0x3D, 0x20, 0x8B, 0xD1, 0x0D),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_30_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAB, 0xC0, 0xE6, 0x4F, 0xDE, 0x62, 0xAB, 0xB3),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA4, 0x48, 0xB3, 0x1C, 0x0F, 0x16, 0x93, 0x45),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x77, 0x63, 0xBD, 0x1F, 0x16, 0x50, 0x56, 0x98),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x5D, 0x06, 0xBC, 0xE9, 0x27, 0x1C, 0x9A, 0x7B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF8, 0xFE, 0x21, 0xC5, 0x39, 0x55, 0xE1, 0xFD),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF6, 0xA8, 0xD0, 0x96, 0x0E, 0xB5, 0xB2, 0x84),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3D, 0xE7, 0x4B, 0xF3, 0x11, 0x0C, 0xC9, 0x5B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x43, 0x3A, 0xC4, 0x87, 0x71, 0xEE, 0xFA, 0x18),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_30_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA7, 0x77, 0xEE, 0x81, 0x5E, 0x96, 0xEA, 0x4B),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xEE, 0xDF, 0xA9, 0xF4, 0x4F, 0x7C, 0xB2, 0x43),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x9F, 0xD4, 0xDF, 0x35, 0x63, 0x47, 0x25, 0x8A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xA5, 0x3D, 0xFF, 0xA4, 0x02, 0xC3, 0x95, 0x11),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xD5, 0x10, 0x78, 0xD1, 0x2B, 0xB7, 0xBE, 0x0E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x0A, 0xE9, 0x57, 0xF9, 0xE0, 0xD8, 0xFC, 0xBC),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF3, 0xC4, 0x01, 0xD6, 0xB4, 0xE7, 0x78, 0xE2),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x02, 0x6C, 0xB9, 0x13, 0xA4, 0xE8, 0x6D, 0x6F),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_31_X[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE8, 0xB0, 0xC9, 0xCD, 0xBF, 0xA2, 0x1E, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xDD, 0x4F, 0x86, 0x22, 0x9B, 0xEA, 0xE8, 0xBB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x50, 0x46, 0xDF, 0x43, 0xB9, 0x82, 0x2D, 0x0A),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x07, 0x32, 0xF1, 0x4E, 0x95, 0x41, 0xAE, 0x8E),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x52, 0x93, 0x26, 0xFC, 0xD3, 0x90, 0xDC, 0xEB),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x04, 0x05, 0x45, 0xCA, 0xF9, 0x5A, 0x89, 0x93),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xC5, 0x82, 0x63, 0x4E, 0x55, 0x1D, 0x3A, 0x08),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x7C, 0x69, 0x52, 0x49, 0xE9, 0xED, 0x57, 0x34),
+};
+static const mbedtls_mpi_uint brainpoolP512r1_T_31_Y[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0x70, 0x64, 0xE9, 0xAC, 0x4C, 0x4A, 0xEA, 0x25),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xE9, 0xE9, 0x0B, 0x99, 0xE7, 0xF9, 0xA9, 0x2C),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x24, 0x0C, 0xC1, 0xF4, 0x8D, 0x07, 0xB6, 0xB1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xAD, 0x68, 0xFA, 0x35, 0xE4, 0x9E, 0xAE, 0xD9),
+    MBEDTLS_BYTES_TO_T_UINT_8(0xF0, 0x2D, 0x1A, 0x13, 0x8E, 0x02, 0xE2, 0x63),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x27, 0x38, 0x28, 0x86, 0x46, 0x7B, 0x3A, 0xE1),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x3F, 0x4C, 0x64, 0x59, 0x0A, 0xF9, 0x02, 0xC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x41, 0x4F, 0x23, 0xA2, 0xC3, 0xD5, 0xEF, 0x42),
+};
+static const mbedtls_ecp_point brainpoolP512r1_T[32] = {
+    ECP_POINT_INIT_XY_Z1(brainpoolP512r1_T_0_X, brainpoolP512r1_T_0_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_1_X, brainpoolP512r1_T_1_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_2_X, brainpoolP512r1_T_2_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_3_X, brainpoolP512r1_T_3_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_4_X, brainpoolP512r1_T_4_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_5_X, brainpoolP512r1_T_5_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_6_X, brainpoolP512r1_T_6_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_7_X, brainpoolP512r1_T_7_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_8_X, brainpoolP512r1_T_8_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_9_X, brainpoolP512r1_T_9_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_10_X, brainpoolP512r1_T_10_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_11_X, brainpoolP512r1_T_11_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_12_X, brainpoolP512r1_T_12_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_13_X, brainpoolP512r1_T_13_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_14_X, brainpoolP512r1_T_14_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_15_X, brainpoolP512r1_T_15_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_16_X, brainpoolP512r1_T_16_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_17_X, brainpoolP512r1_T_17_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_18_X, brainpoolP512r1_T_18_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_19_X, brainpoolP512r1_T_19_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_20_X, brainpoolP512r1_T_20_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_21_X, brainpoolP512r1_T_21_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_22_X, brainpoolP512r1_T_22_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_23_X, brainpoolP512r1_T_23_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_24_X, brainpoolP512r1_T_24_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_25_X, brainpoolP512r1_T_25_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_26_X, brainpoolP512r1_T_26_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_27_X, brainpoolP512r1_T_27_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_28_X, brainpoolP512r1_T_28_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_29_X, brainpoolP512r1_T_29_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_30_X, brainpoolP512r1_T_30_Y),
+    ECP_POINT_INIT_XY_Z0(brainpoolP512r1_T_31_X, brainpoolP512r1_T_31_Y),
+};
+#else
+#define brainpoolP512r1_T NULL
+#endif
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+
+
+#if defined(ECP_LOAD_GROUP) || defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
+    defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+/*
+ * Create an MPI from embedded constants
+ * (assumes len is an exact multiple of sizeof(mbedtls_mpi_uint) and
+ * len < 1048576)
+ */
+static inline void ecp_mpi_load(mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len)
+{
+    X->s = 1;
+    X->n = (unsigned short) (len / sizeof(mbedtls_mpi_uint));
+    X->p = (mbedtls_mpi_uint *) p;
+}
+#endif
+
+#if defined(ECP_LOAD_GROUP)
+/*
+ * Set an MPI to static value 1
+ */
+static inline void ecp_mpi_set1(mbedtls_mpi *X)
+{
+    X->s = 1;
+    X->n = 1;
+    X->p = mpi_one;
+}
+
+/*
+ * Make group available from embedded constants
+ */
+static int ecp_group_load(mbedtls_ecp_group *grp,
+                          const mbedtls_mpi_uint *p,  size_t plen,
+                          const mbedtls_mpi_uint *a,  size_t alen,
+                          const mbedtls_mpi_uint *b,  size_t blen,
+                          const mbedtls_mpi_uint *gx, size_t gxlen,
+                          const mbedtls_mpi_uint *gy, size_t gylen,
+                          const mbedtls_mpi_uint *n,  size_t nlen,
+                          const mbedtls_ecp_point *T)
+{
+    ecp_mpi_load(&grp->P, p, plen);
+    if (a != NULL) {
+        ecp_mpi_load(&grp->A, a, alen);
+    }
+    ecp_mpi_load(&grp->B, b, blen);
+    ecp_mpi_load(&grp->N, n, nlen);
+
+    ecp_mpi_load(&grp->G.X, gx, gxlen);
+    ecp_mpi_load(&grp->G.Y, gy, gylen);
+    ecp_mpi_set1(&grp->G.Z);
+
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
+    grp->nbits = mbedtls_mpi_bitlen(&grp->N);
+
+    grp->h = 1;
+
+    grp->T = (mbedtls_ecp_point *) T;
+    /*
+     * Set T_size to 0 to prevent T free by mbedtls_ecp_group_free.
+     */
+    grp->T_size = 0;
+
+    return 0;
+}
+#endif /* ECP_LOAD_GROUP */
+
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+/* Forward declarations */
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+static int ecp_mod_p192(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+static int ecp_mod_p224(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+static int ecp_mod_p256(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+static int ecp_mod_p384(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+static int ecp_mod_p521(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *N_p, size_t N_n);
+#endif
+
+#define NIST_MODP(P)      grp->modp = ecp_mod_ ## P;
+#else
+#define NIST_MODP(P)
+#endif /* MBEDTLS_ECP_NIST_OPTIM */
+
+/* Additional forward declarations */
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+static int ecp_mod_p255(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+static int ecp_mod_p448(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *, size_t);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+static int ecp_mod_p192k1(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+static int ecp_mod_p224k1(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+static int ecp_mod_p256k1(mbedtls_mpi *);
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+#endif
+
+#if defined(ECP_LOAD_GROUP)
+#define LOAD_GROUP_A(G)   ecp_group_load(grp,            \
+                                         G ## _p,  sizeof(G ## _p),   \
+                                         G ## _a,  sizeof(G ## _a),   \
+                                         G ## _b,  sizeof(G ## _b),   \
+                                         G ## _gx, sizeof(G ## _gx),   \
+                                         G ## _gy, sizeof(G ## _gy),   \
+                                         G ## _n,  sizeof(G ## _n),   \
+                                         G ## _T                         \
+                                         )
+
+#define LOAD_GROUP(G)     ecp_group_load(grp,            \
+                                         G ## _p,  sizeof(G ## _p),   \
+                                         NULL,     0,                    \
+                                         G ## _b,  sizeof(G ## _b),   \
+                                         G ## _gx, sizeof(G ## _gx),   \
+                                         G ## _gy, sizeof(G ## _gy),   \
+                                         G ## _n,  sizeof(G ## _n),   \
+                                         G ## _T                         \
+                                         )
+#endif /* ECP_LOAD_GROUP */
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+/* Constants used by ecp_use_curve25519() */
+static const mbedtls_mpi_sint curve25519_a24 = 0x01DB42;
+
+/* P = 2^255 - 19 */
+static const mbedtls_mpi_uint curve25519_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0xED, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X7F)
+};
+
+/* N = 2^252 + 27742317777372353535851937790883648493 */
+static const mbedtls_mpi_uint curve25519_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XED, 0XD3, 0XF5, 0X5C, 0X1A, 0X63, 0X12, 0X58),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XD6, 0X9C, 0XF7, 0XA2, 0XDE, 0XF9, 0XDE, 0X14),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0x00, 0x00, 0x00, 0x00),
+    MBEDTLS_BYTES_TO_T_UINT_8(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10)
+};
+
+/*
+ * Specialized function for creating the Curve25519 group
+ */
+static int ecp_use_curve25519(mbedtls_ecp_group *grp)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* Actually ( A + 2 ) / 4 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve25519_a24));
+
+    ecp_mpi_load(&grp->P, curve25519_p, sizeof(curve25519_p));
+
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
+
+    ecp_mpi_load(&grp->N, curve25519_n, sizeof(curve25519_n));
+
+    /* Y intentionally not set, since we use x/z coordinates.
+     * This is used as a marker to identify Montgomery curves! */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 9));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));
+    mbedtls_mpi_free(&grp->G.Y);
+
+    /* Actually, the required msb for private keys */
+    grp->nbits = 254;
+
+cleanup:
+    if (ret != 0) {
+        mbedtls_ecp_group_free(grp);
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+/* Constants used by ecp_use_curve448() */
+static const mbedtls_mpi_sint curve448_a24 = 0x98AA;
+
+/* P = 2^448 - 2^224 - 1 */
+static const mbedtls_mpi_uint curve448_p[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFE, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
+};
+
+/* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */
+static const mbedtls_mpi_uint curve448_n[] = {
+    MBEDTLS_BYTES_TO_T_UINT_8(0XF3, 0X44, 0X58, 0XAB, 0X92, 0XC2, 0X78, 0X23),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X55, 0X8F, 0XC5, 0X8D, 0X72, 0XC2, 0X6C, 0X21),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X90, 0X36, 0XD6, 0XAE, 0X49, 0XDB, 0X4E, 0XC4),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XE9, 0X23, 0XCA, 0X7C, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF),
+    MBEDTLS_BYTES_TO_T_UINT_8(0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X3F),
+    MBEDTLS_BYTES_TO_T_UINT_8(0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00)
+};
+
+/*
+ * Specialized function for creating the Curve448 group
+ */
+static int ecp_use_curve448(mbedtls_ecp_group *grp)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* Actually ( A + 2 ) / 4 */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->A, curve448_a24));
+
+    ecp_mpi_load(&grp->P, curve448_p, sizeof(curve448_p));
+    grp->pbits = mbedtls_mpi_bitlen(&grp->P);
+
+    /* Y intentionally not set, since we use x/z coordinates.
+     * This is used as a marker to identify Montgomery curves! */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.X, 5));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&grp->G.Z, 1));
+    mbedtls_mpi_free(&grp->G.Y);
+
+    ecp_mpi_load(&grp->N, curve448_n, sizeof(curve448_n));
+
+    /* Actually, the required msb for private keys */
+    grp->nbits = 447;
+
+cleanup:
+    if (ret != 0) {
+        mbedtls_ecp_group_free(grp);
+    }
+
+    return ret;
+}
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+
+/*
+ * Set a group using well-known domain parameters
+ */
+int mbedtls_ecp_group_load(mbedtls_ecp_group *grp, mbedtls_ecp_group_id id)
+{
+    mbedtls_ecp_group_free(grp);
+
+    mbedtls_ecp_group_init(grp);
+
+    grp->id = id;
+
+    switch (id) {
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192R1:
+            NIST_MODP(p192);
+            return LOAD_GROUP(secp192r1);
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224R1:
+            NIST_MODP(p224);
+            return LOAD_GROUP(secp224r1);
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256R1:
+            NIST_MODP(p256);
+            return LOAD_GROUP(secp256r1);
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP384R1:
+            NIST_MODP(p384);
+            return LOAD_GROUP(secp384r1);
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP521R1:
+            NIST_MODP(p521);
+            return LOAD_GROUP(secp521r1);
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192K1:
+            grp->modp = ecp_mod_p192k1;
+            return LOAD_GROUP_A(secp192k1);
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224K1:
+            grp->modp = ecp_mod_p224k1;
+            return LOAD_GROUP_A(secp224k1);
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256K1:
+            grp->modp = ecp_mod_p256k1;
+            return LOAD_GROUP_A(secp256k1);
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP256R1:
+            return LOAD_GROUP_A(brainpoolP256r1);
+#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP384R1:
+            return LOAD_GROUP_A(brainpoolP384r1);
+#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP512R1:
+            return LOAD_GROUP_A(brainpoolP512r1);
+#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE25519:
+            grp->modp = ecp_mod_p255;
+            return ecp_use_curve25519(grp);
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE448:
+            grp->modp = ecp_mod_p448;
+            return ecp_use_curve448(grp);
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+
+        default:
+            grp->id = MBEDTLS_ECP_DP_NONE;
+            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+    }
+}
+
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+/*
+ * Fast reduction modulo the primes used by the NIST curves.
+ *
+ * These functions are critical for speed, but not needed for correct
+ * operations. So, we make the choice to heavily rely on the internals of our
+ * bignum library, which creates a tight coupling between these functions and
+ * our MPI implementation.  However, the coupling between the ECP module and
+ * MPI remains loose, since these functions can be deactivated at will.
+ */
+
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+/*
+ * Compared to the way things are presented in FIPS 186-3 D.2,
+ * we proceed in columns, from right (least significant chunk) to left,
+ * adding chunks to N in place, and keeping a carry for the next chunk.
+ * This avoids moving things around in memory, and uselessly adding zeros,
+ * compared to the more straightforward, line-oriented approach.
+ *
+ * For this prime we need to handle data in chunks of 64 bits.
+ * Since this is always a multiple of our basic mbedtls_mpi_uint, we can
+ * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it.
+ */
+
+/* Add 64-bit chunks (dst += src) and update carry */
+static inline void add64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry)
+{
+    unsigned char i;
+    mbedtls_mpi_uint c = 0;
+    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++, src++) {
+        *dst += c;      c  = (*dst < c);
+        *dst += *src;   c += (*dst < *src);
+    }
+    *carry += c;
+}
+
+/* Add carry to a 64-bit chunk and update carry */
+static inline void carry64(mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry)
+{
+    unsigned char i;
+    for (i = 0; i < 8 / sizeof(mbedtls_mpi_uint); i++, dst++) {
+        *dst += *carry;
+        *carry  = (*dst < *carry);
+    }
+}
+
+#define WIDTH       8 / sizeof(mbedtls_mpi_uint)
+#define A(i)        Np + (i) * WIDTH
+#define ADD(i)      add64(p, A(i), &c)
+#define NEXT        p += WIDTH; carry64(p, &c)
+#define LAST        p += WIDTH; do *p = 0; while (++p < end)
+#define RESET       last_carry[0] = c; c = 0; p = Np
+#define ADD_LAST    add64(p, last_carry, &c)
+
+/*
+ * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1)
+ */
+static int ecp_mod_p192(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(192) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p192_raw(N->p, expected_width);
+
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn)
+{
+    mbedtls_mpi_uint c = 0, last_carry[WIDTH] = { 0 };
+    mbedtls_mpi_uint *p, *end;
+
+    if (Nn != BITS_TO_LIMBS(192) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    p = Np;
+    end = p + Nn;
+
+    ADD(3); ADD(5);         NEXT;   // A0 += A3 + A5
+    ADD(3); ADD(4); ADD(5); NEXT;   // A1 += A3 + A4 + A5
+    ADD(4); ADD(5);                 // A2 += A4 + A5
+
+    RESET;
+
+    /* Use the reduction for the carry as well:
+     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192
+     * It can generate a carry. */
+    ADD_LAST; NEXT;                 // A0 += last_carry
+    ADD_LAST; NEXT;                 // A1 += last_carry
+                                    // A2 += carry
+
+    RESET;
+
+    /* Use the reduction for the carry as well:
+     * 2^192 * last_carry = 2^64 * last_carry + last_carry mod P192
+     */
+    ADD_LAST; NEXT;                 // A0 += last_carry
+    ADD_LAST; NEXT;                 // A1 += last_carry
+                                    // A2 += carry
+
+    LAST;
+
+    return 0;
+}
+
+#undef WIDTH
+#undef A
+#undef ADD
+#undef NEXT
+#undef LAST
+#undef RESET
+#undef ADD_LAST
+#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+
+/*
+ * The reader is advised to first understand ecp_mod_p192() since the same
+ * general structure is used here, but with additional complications:
+ * (1) chunks of 32 bits, and (2) subtractions.
+ */
+
+/*
+ * For these primes, we need to handle data in chunks of 32 bits.
+ * This makes it more complicated if we use 64 bits limbs in MPI,
+ * which prevents us from using a uniform access method as for p192.
+ *
+ * So, we define a mini abstraction layer to access 32 bit chunks,
+ * load them in 'cur' for work, and store them back from 'cur' when done.
+ *
+ * While at it, also define the size of N in terms of 32-bit chunks.
+ */
+#define LOAD32      cur = A(i);
+
+#if defined(MBEDTLS_HAVE_INT32)  /* 32 bit */
+
+#define MAX32       X_limbs
+#define A(j)        X[j]
+#define STORE32     X[i] = (mbedtls_mpi_uint) cur;
+#define STORE0      X[i] = 0;
+
+#else /* 64 bit */
+
+#define MAX32   X_limbs * 2
+#define A(j)                                                \
+    (j) % 2 ?                                               \
+    (uint32_t) (X[(j) / 2] >> 32) :                         \
+    (uint32_t) (X[(j) / 2])
+#define STORE32                                             \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+        X[i/2] |= (uint64_t) (cur) << 32;                   \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+        X[i/2] |= (uint32_t) cur;                           \
+    }
+
+#define STORE0                                              \
+    if (i % 2) {                                            \
+        X[i/2] &= 0x00000000FFFFFFFF;                       \
+    } else {                                                \
+        X[i/2] &= 0xFFFFFFFF00000000;                       \
+    }
+
+#endif
+
+static inline int8_t extract_carry(int64_t cur)
+{
+    return (int8_t) (cur >> 32);
+}
+
+#define ADD(j)    cur += A(j)
+#define SUB(j)    cur -= A(j)
+
+#define ADD_CARRY(cc) cur += (cc)
+#define SUB_CARRY(cc) cur -= (cc)
+
+#define ADD_LAST ADD_CARRY(last_c)
+#define SUB_LAST SUB_CARRY(last_c)
+
+/*
+ * Helpers for the main 'loop'
+ */
+#define INIT(b)                                         \
+    int8_t c = 0, last_c;                               \
+    int64_t cur;                                        \
+    size_t i = 0;                                       \
+    LOAD32;
+
+#define NEXT                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++; LOAD32;                               \
+    ADD_CARRY(c);
+
+#define RESET                                           \
+    c = extract_carry(cur);                             \
+    last_c = c;                                         \
+    STORE32; i = 0; LOAD32;                             \
+    c = 0;                                              \
+
+#define LAST                                            \
+    c = extract_carry(cur);                             \
+    STORE32; i++;                                       \
+    if (c != 0)                                         \
+    return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;              \
+    while (i < MAX32) { STORE0; i++; }
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2)
+ */
+static int ecp_mod_p224(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(224) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p224_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != BITS_TO_LIMBS(224) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(224);
+
+    SUB(7);  SUB(11);           NEXT;   // A0 += -A7  - A11
+    SUB(8);  SUB(12);           NEXT;   // A1 += -A8  - A12
+    SUB(9);  SUB(13);           NEXT;   // A2 += -A9  - A13
+    SUB(10); ADD(7);  ADD(11);  NEXT;   // A3 += -A10 + A7 + A11
+    SUB(11); ADD(8);  ADD(12);  NEXT;   // A4 += -A11 + A8 + A12
+    SUB(12); ADD(9);  ADD(13);  NEXT;   // A5 += -A12 + A9 + A13
+    SUB(13); ADD(10);                   // A6 += -A13 + A10
+
+    RESET;
+
+    /* Use 2^224 = P + 2^96 - 1 to modulo reduce the final carry */
+    SUB_LAST; NEXT;                     // A0 -= last_c
+    ;         NEXT;                     // A1
+    ;         NEXT;                     // A2
+    ADD_LAST; NEXT;                     // A3 += last_c
+    ;         NEXT;                     // A4
+    ;         NEXT;                     // A5
+                                        // A6
+
+    /* The carry reduction cannot generate a carry
+     * (see commit 73e8553 for details)*/
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3)
+ */
+static int ecp_mod_p256(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(256) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p256_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != BITS_TO_LIMBS(256) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(256);
+
+    ADD(8);  ADD(9);
+    SUB(11); SUB(12); SUB(13); SUB(14);                   NEXT; // A0
+
+    ADD(9);  ADD(10);
+    SUB(12); SUB(13); SUB(14); SUB(15);                   NEXT; // A1
+
+    ADD(10); ADD(11);
+    SUB(13); SUB(14); SUB(15);                            NEXT; // A2
+
+    ADD(11); ADD(11); ADD(12); ADD(12); ADD(13);
+    SUB(15); SUB(8);  SUB(9);                             NEXT; // A3
+
+    ADD(12); ADD(12); ADD(13); ADD(13); ADD(14);
+    SUB(9);  SUB(10);                                     NEXT; // A4
+
+    ADD(13); ADD(13); ADD(14); ADD(14); ADD(15);
+    SUB(10); SUB(11);                                     NEXT; // A5
+
+    ADD(14); ADD(14); ADD(15); ADD(15); ADD(14); ADD(13);
+    SUB(8);  SUB(9);                                      NEXT; // A6
+
+    ADD(15); ADD(15); ADD(15); ADD(8);
+    SUB(10); SUB(11); SUB(12); SUB(13);                         // A7
+
+    RESET;
+
+    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
+     * to modulo reduce the final carry. */
+    ADD_LAST; NEXT;                                             // A0
+    ;         NEXT;                                             // A1
+    ;         NEXT;                                             // A2
+    SUB_LAST; NEXT;                                             // A3
+    ;         NEXT;                                             // A4
+    ;         NEXT;                                             // A5
+    SUB_LAST; NEXT;                                             // A6
+    ADD_LAST;                                                   // A7
+
+    RESET;
+
+    /* Use 2^224 * (2^32 - 1) + 2^192 + 2^96 - 1
+     * to modulo reduce the carry generated by the previous reduction. */
+    ADD_LAST; NEXT;                                             // A0
+    ;         NEXT;                                             // A1
+    ;         NEXT;                                             // A2
+    SUB_LAST; NEXT;                                             // A3
+    ;         NEXT;                                             // A4
+    ;         NEXT;                                             // A5
+    SUB_LAST; NEXT;                                             // A6
+    ADD_LAST;                                                   // A7
+
+    LAST;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+/*
+ * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ */
+static int ecp_mod_p384(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(384) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p384_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    if (X_limbs != BITS_TO_LIMBS(384) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    INIT(384);
+
+    ADD(12); ADD(21); ADD(20);
+    SUB(23);                                                NEXT; // A0
+
+    ADD(13); ADD(22); ADD(23);
+    SUB(12); SUB(20);                                       NEXT; // A1
+
+    ADD(14); ADD(23);
+    SUB(13); SUB(21);                                       NEXT; // A2
+
+    ADD(15); ADD(12); ADD(20); ADD(21);
+    SUB(14); SUB(22); SUB(23);                              NEXT; // A3
+
+    ADD(21); ADD(21); ADD(16); ADD(13); ADD(12); ADD(20); ADD(22);
+    SUB(15); SUB(23); SUB(23);                              NEXT; // A4
+
+    ADD(22); ADD(22); ADD(17); ADD(14); ADD(13); ADD(21); ADD(23);
+    SUB(16);                                                NEXT; // A5
+
+    ADD(23); ADD(23); ADD(18); ADD(15); ADD(14); ADD(22);
+    SUB(17);                                                NEXT; // A6
+
+    ADD(19); ADD(16); ADD(15); ADD(23);
+    SUB(18);                                                NEXT; // A7
+
+    ADD(20); ADD(17); ADD(16);
+    SUB(19);                                                NEXT; // A8
+
+    ADD(21); ADD(18); ADD(17);
+    SUB(20);                                                NEXT; // A9
+
+    ADD(22); ADD(19); ADD(18);
+    SUB(21);                                                NEXT; // A10
+
+    ADD(23); ADD(20); ADD(19);
+    SUB(22);                                                      // A11
+
+    RESET;
+
+    /* Use 2^384 = P + 2^128 + 2^96 - 2^32 + 1 to modulo reduce the final carry */
+    ADD_LAST; NEXT;                                               // A0
+    SUB_LAST; NEXT;                                               // A1
+    ;         NEXT;                                               // A2
+    ADD_LAST; NEXT;                                               // A3
+    ADD_LAST; NEXT;                                               // A4
+    ;         NEXT;                                               // A5
+    ;         NEXT;                                               // A6
+    ;         NEXT;                                               // A7
+    ;         NEXT;                                               // A8
+    ;         NEXT;                                               // A9
+    ;         NEXT;                                               // A10
+                                                                  // A11
+
+    RESET;
+
+    ADD_LAST; NEXT;                                               // A0
+    SUB_LAST; NEXT;                                               // A1
+    ;         NEXT;                                               // A2
+    ADD_LAST; NEXT;                                               // A3
+    ADD_LAST; NEXT;                                               // A4
+    ;         NEXT;                                               // A5
+    ;         NEXT;                                               // A6
+    ;         NEXT;                                               // A7
+    ;         NEXT;                                               // A8
+    ;         NEXT;                                               // A9
+    ;         NEXT;                                               // A10
+                                                                  // A11
+
+    LAST;
+
+    return 0;
+}
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#undef LOAD32
+#undef MAX32
+#undef A
+#undef STORE32
+#undef STORE0
+#undef ADD
+#undef SUB
+#undef ADD_CARRY
+#undef SUB_CARRY
+#undef ADD_LAST
+#undef SUB_LAST
+#undef INIT
+#undef NEXT
+#undef RESET
+#undef LAST
+
+#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP256R1_ENABLED ||
+          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+/* Size of p521 in terms of mbedtls_mpi_uint */
+#define P521_WIDTH      (521 / 8 / sizeof(mbedtls_mpi_uint) + 1)
+
+/* Bits to keep in the most significant mbedtls_mpi_uint */
+#define P521_MASK       0x01FF
+
+/*
+ * Fast quasi-reduction modulo p521 = 2^521 - 1 (FIPS 186-3 D.2.5)
+ */
+static int ecp_mod_p521(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(521) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p521_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    mbedtls_mpi_uint carry = 0;
+
+    if (X_limbs != BITS_TO_LIMBS(521) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    /* Step 1: Reduction to P521_WIDTH limbs */
+    /* Helper references for bottom part of X */
+    mbedtls_mpi_uint *X0 = X;
+    size_t X0_limbs = P521_WIDTH;
+    /* Helper references for top part of X */
+    mbedtls_mpi_uint *X1 = X + X0_limbs;
+    size_t X1_limbs = X_limbs - X0_limbs;
+    /* Split X as X0 + 2^P521_WIDTH X1 and compute X0 + 2^(biL - 9) X1.
+     * (We are using that 2^P521_WIDTH = 2^(512 + biL) and that
+     * 2^(512 + biL) X1 = 2^(biL - 9) X1 mod P521.)
+     * The high order limb of the result will be held in carry and the rest
+     * in X0 (that is the result will be represented as
+     * 2^P521_WIDTH carry + X0).
+     *
+     * Also, note that the resulting carry is either 0 or 1:
+     * X0 < 2^P521_WIDTH = 2^(512 + biL) and X1 < 2^(P521_WIDTH-biL) = 2^512
+     * therefore
+     * X0 + 2^(biL - 9) X1 < 2^(512 + biL) + 2^(512 + biL - 9)
+     * which in turn is less than 2 * 2^(512 + biL).
+     */
+    mbedtls_mpi_uint shift = ((mbedtls_mpi_uint) 1u) << (biL - 9);
+    carry = mbedtls_mpi_core_mla(X0, X0_limbs, X1, X1_limbs, shift);
+    /* Set X to X0 (by clearing the top part). */
+    memset(X1, 0, X1_limbs * sizeof(mbedtls_mpi_uint));
+
+    /* Step 2: Reduction modulo P521
+     *
+     * At this point X is reduced to P521_WIDTH limbs. What remains is to add
+     * the carry (that is 2^P521_WIDTH carry) and to reduce mod P521. */
+
+    /* 2^P521_WIDTH carry = 2^(512 + biL) carry = 2^(biL - 9) carry mod P521.
+     * Also, recall that carry is either 0 or 1. */
+    mbedtls_mpi_uint addend = carry << (biL - 9);
+    /* Keep the top 9 bits and reduce the rest, using 2^521 = 1 mod P521. */
+    addend += (X[P521_WIDTH - 1] >> 9);
+    X[P521_WIDTH - 1] &= P521_MASK;
+
+    /* Reuse the top part of X (already zeroed) as a helper array for
+     * carrying out the addition. */
+    mbedtls_mpi_uint *addend_arr = X + P521_WIDTH;
+    addend_arr[0] = addend;
+    (void) mbedtls_mpi_core_add(X, X, addend_arr, P521_WIDTH);
+    /* Both addends were less than P521 therefore X < 2 * P521. (This also means
+     * that the result fit in P521_WIDTH limbs and there won't be any carry.) */
+
+    /* Clear the reused part of X. */
+    addend_arr[0] = 0;
+
+    return 0;
+}
+
+#undef P521_WIDTH
+#undef P521_MASK
+
+#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+
+#endif /* MBEDTLS_ECP_NIST_OPTIM */
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+
+/* Size of p255 in terms of mbedtls_mpi_uint */
+#define P255_WIDTH      (255 / 8 / sizeof(mbedtls_mpi_uint) + 1)
+
+/*
+ * Fast quasi-reduction modulo p255 = 2^255 - 19
+ * Write N as A0 + 2^256 A1, return A0 + 38 * A1
+ */
+static int ecp_mod_p255(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(255) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p255_raw(N->p, expected_width);
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_Limbs)
+{
+
+    if (X_Limbs != BITS_TO_LIMBS(255) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    mbedtls_mpi_uint *carry = mbedtls_calloc(P255_WIDTH, ciL);
+    if (carry == NULL) {
+        return MBEDTLS_ERR_ECP_ALLOC_FAILED;
+    }
+
+    /* Step 1: Reduction to P255_WIDTH limbs */
+    if (X_Limbs > P255_WIDTH) {
+        /* Helper references for top part of X */
+        mbedtls_mpi_uint * const A1 = X + P255_WIDTH;
+        const size_t A1_limbs = X_Limbs - P255_WIDTH;
+
+        /* X = A0 + 38 * A1, capture carry out */
+        *carry = mbedtls_mpi_core_mla(X, P255_WIDTH, A1, A1_limbs, 38);
+        /* Clear top part */
+        memset(A1, 0, sizeof(mbedtls_mpi_uint) * A1_limbs);
+    }
+
+    /* Step 2: Reduce to <2p
+     * Split as A0 + 2^255*c, with c a scalar, and compute A0 + 19*c */
+    *carry <<= 1;
+    *carry += (X[P255_WIDTH - 1] >> (biL - 1));
+    *carry *= 19;
+
+    /* Clear top bit */
+    X[P255_WIDTH - 1] <<= 1; X[P255_WIDTH - 1] >>= 1;
+    /* Since the top bit for X has been cleared 0 + 0 + Carry
+     * will not overflow.
+     *
+     * Furthermore for 2p = 2^256-38. When a carry propagation on the highest
+     * limb occurs, X > 2^255 and all the remaining bits on the limb are zero.
+     *   - If X < 2^255 ==> X < 2p
+     *   - If X > 2^255 ==> X < 2^256 - 2^255 < 2p  */
+    (void) mbedtls_mpi_core_add(X, X, carry, P255_WIDTH);
+
+    mbedtls_free(carry);
+    return 0;
+}
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+
+/* Size of p448 in terms of mbedtls_mpi_uint */
+#define P448_WIDTH      (448 / 8 / sizeof(mbedtls_mpi_uint))
+
+/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */
+#define DIV_ROUND_UP(X, Y) (((X) + (Y) -1) / (Y))
+#define P224_SIZE        (224 / 8)
+#define P224_WIDTH_MIN   (P224_SIZE / sizeof(mbedtls_mpi_uint))
+#define P224_WIDTH_MAX   DIV_ROUND_UP(P224_SIZE, sizeof(mbedtls_mpi_uint))
+#define P224_UNUSED_BITS ((P224_WIDTH_MAX * sizeof(mbedtls_mpi_uint) * 8) - 224)
+
+static int ecp_mod_p448(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(448) * 2;
+
+    /* This is required as some tests and use cases do not pass in a Bignum of
+     * the correct size, and expect the growth to be done automatically, which
+     * will no longer happen. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+
+    ret = mbedtls_ecp_mod_p448_raw(N->p, N->n);
+
+cleanup:
+    return ret;
+}
+
+/*
+ * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1
+ * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 +
+ * (B0 + B1) * 2^224.  This is different to the reference implementation of
+ * Curve448, which uses its own special 56-bit limbs rather than a generic
+ * bignum library.  We could squeeze some extra speed out on 32-bit machines by
+ * splitting N up into 32-bit limbs and doing the arithmetic using the limbs
+ * directly as we do for the NIST primes above, but for 64-bit targets it should
+ * use half the number of operations if we do the reduction with 224-bit limbs,
+ * since mpi_core_add will then use 64-bit adds.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    size_t round;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (X_limbs != BITS_TO_LIMBS(448) * 2) {
+        return 0;
+    }
+
+    size_t M_limbs = X_limbs - (P448_WIDTH);
+
+    if (M_limbs > P448_WIDTH) {
+        /* Shouldn't be called with X larger than 2^896! */
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    /* Both M and Q require an extra limb to catch carries. */
+    M_limbs++;
+
+    const size_t Q_limbs = M_limbs;
+    mbedtls_mpi_uint *M = NULL;
+    mbedtls_mpi_uint *Q = NULL;
+
+    M = mbedtls_calloc(M_limbs, ciL);
+
+    if (M == NULL) {
+        return MBEDTLS_ERR_ECP_ALLOC_FAILED;
+    }
+
+    Q = mbedtls_calloc(Q_limbs, ciL);
+
+    if (Q == NULL) {
+        ret =  MBEDTLS_ERR_ECP_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    /* M = A1 */
+    memset(M, 0, (M_limbs * ciL));
+    /* Do not copy into the overflow limb, as this would read past the end of
+     * X. */
+    memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL));
+
+    /* X = A0 */
+    memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL));
+
+    /* X = X + M = A0 + A1 */
+    /* Carry here fits in oversize X. Oversize M means it will get
+     * added in, not returned as carry. */
+    (void) mbedtls_mpi_core_add(X, X, M, M_limbs);
+
+    /* Q = B1 = M >> 224 */
+    memcpy(Q, (char *) M + P224_SIZE, P224_SIZE);
+    memset((char *) Q + P224_SIZE, 0, P224_SIZE);
+
+    /* X = X + Q = (A0 + A1) + B1
+     * Oversize Q catches potential carry here when X is already max 448 bits.
+     */
+    (void) mbedtls_mpi_core_add(X, X, Q, Q_limbs);
+
+    /* M = B0 */
+#ifdef MBEDTLS_HAVE_INT64
+    M[P224_WIDTH_MIN] &= ((mbedtls_mpi_uint)-1) >> (P224_UNUSED_BITS);
+ #endif
+    memset(M + P224_WIDTH_MAX, 0, ((M_limbs - P224_WIDTH_MAX) * ciL));
+
+    /* M = M + Q = B0 + B1 */
+    (void) mbedtls_mpi_core_add(M, M, Q, Q_limbs);
+
+    /* M = (B0 + B1) * 2^224 */
+    /* Shifted carry bit from the addition fits in oversize M. */
+    memmove((char *) M + P224_SIZE, M, P224_SIZE + ciL);
+    memset(M, 0, P224_SIZE);
+
+    /* X = X + M = (A0 + A1 + B1) + (B0 + B1) * 2^224 */
+    (void) mbedtls_mpi_core_add(X, X, M, M_limbs);
+
+    /* In the second and third rounds A1 and B0 have at most 1 non-zero limb and
+     * B1=0.
+     * Using this we need to calculate:
+     * A0 + A1 + B1 + (B0 + B1) * 2^224 = A0 + A1 + B0 * 2^224. */
+    for (round = 0; round < 2; ++round) {
+
+        /* M = A1 */
+        memset(M, 0, (M_limbs * ciL));
+        memcpy(M, X + P448_WIDTH, ((M_limbs - 1) * ciL));
+
+        /* X = A0 */
+        memset(X + P448_WIDTH, 0, ((M_limbs - 1) * ciL));
+
+        /* M = A1 + B0 * 2^224
+         * We know that only one limb of A1 will be non-zero and that it will be
+         * limb 0. We also know that B0 is the bottom 224 bits of A1 (which is
+         * then shifted up 224 bits), so, given M is currently A1 this turns
+         * into:
+         * M = M + (M << 224)
+         * As the single non-zero limb in B0 will be A1 limb 0 shifted up by 224
+         * bits, we can just move that into the right place, shifted up
+         * accordingly.*/
+        M[P224_WIDTH_MIN] = M[0] << (224 & (biL - 1));
+
+        /* X = A0 + (A1 + B0 * 2^224) */
+        (void) mbedtls_mpi_core_add(X, X, M, M_limbs);
+    }
+
+    ret = 0;
+
+cleanup:
+    mbedtls_free(M);
+    mbedtls_free(Q);
+
+    return ret;
+}
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||   \
+    defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo P = 2^s - R,
+ * with R about 33 bits, used by the Koblitz curves.
+ *
+ * Write X as A0 + 2^224 A1, return A0 + R * A1.
+ */
+#define P_KOBLITZ_R     (8 / sizeof(mbedtls_mpi_uint))            // Limbs in R
+
+static inline int ecp_mod_koblitz(mbedtls_mpi_uint *X,
+                                  size_t X_limbs,
+                                  mbedtls_mpi_uint *R,
+                                  size_t bits)
+{
+    int ret = 0;
+
+    /* Determine if A1 is aligned to limb bitsize. If not then the used limbs
+     * of P, A0 and A1 must be set accordingly and there is a middle limb
+     * which is shared by A0 and A1 and need to handle accordingly.
+     */
+    size_t shift   = bits % biL;
+    size_t adjust  = (shift + biL - 1) / biL;
+    size_t P_limbs = bits / biL + adjust;
+
+    mbedtls_mpi_uint *A1 = mbedtls_calloc(P_limbs, ciL);
+    if (A1 == NULL) {
+        return MBEDTLS_ERR_ECP_ALLOC_FAILED;
+    }
+
+    /* Create a buffer to store the value of `R * A1` */
+    size_t R_limbs = P_KOBLITZ_R;
+    size_t M_limbs = P_limbs + R_limbs;
+    mbedtls_mpi_uint *M = mbedtls_calloc(M_limbs, ciL);
+    if (M == NULL) {
+        ret = MBEDTLS_ERR_ECP_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    mbedtls_mpi_uint mask = 0;
+    if (adjust != 0) {
+        mask  = ((mbedtls_mpi_uint) 1 << shift) - 1;
+    }
+
+    /* Two passes are needed to reduce the value of `A0 + R * A1` and then
+     * we need an additional one to reduce the possible overflow during
+     * the addition.
+     */
+    for (size_t pass = 0; pass < 3; pass++) {
+        /* Copy A1 */
+        memcpy(A1, X + P_limbs - adjust, P_limbs * ciL);
+
+        /* Shift A1 to be aligned */
+        if (shift != 0) {
+            mbedtls_mpi_core_shift_r(A1, P_limbs, shift);
+        }
+
+        /* Zeroize the A1 part of the shared limb */
+        if (mask != 0) {
+            X[P_limbs - 1] &= mask;
+        }
+
+        /* X = A0
+         * Zeroize the A1 part of X to keep only the A0 part.
+         */
+        for (size_t i = P_limbs; i < X_limbs; i++) {
+            X[i] = 0;
+        }
+
+        /* X = A0 + R * A1 */
+        mbedtls_mpi_core_mul(M, A1, P_limbs, R, R_limbs);
+        (void) mbedtls_mpi_core_add(X, X, M, P_limbs + R_limbs);
+
+        /* Carry can not be generated since R is a 33-bit value and stored in
+         * 64 bits. The result value of the multiplication is at most
+         * P length + 33 bits in length and the result value of the addition
+         * is at most P length + 34 bits in length. So the result of the
+         * addition always fits in P length + 64 bits.
+         */
+    }
+
+cleanup:
+    mbedtls_free(M);
+    mbedtls_free(A1);
+
+    return ret;
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) ||
+          MBEDTLS_ECP_DP_SECP224K1_ENABLED) ||
+          MBEDTLS_ECP_DP_SECP256K1_ENABLED) */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p192k1 = 2^192 - R,
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9
+ */
+static int ecp_mod_p192k1(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(192) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p192k1_raw(N->p, expected_width);
+
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    static mbedtls_mpi_uint Rp[] = {
+        MBEDTLS_BYTES_TO_T_UINT_8(0xC9, 0x11, 0x00, 0x00,
+                                  0x01, 0x00, 0x00, 0x00)
+    };
+
+    if (X_limbs != BITS_TO_LIMBS(192) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    return ecp_mod_koblitz(X, X_limbs, Rp, 192);
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p224k1 = 2^224 - R,
+ * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
+ */
+static int ecp_mod_p224k1(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(224) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p224k1_raw(N->p, expected_width);
+
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    static mbedtls_mpi_uint Rp[] = {
+        MBEDTLS_BYTES_TO_T_UINT_8(0x93, 0x1A, 0x00, 0x00,
+                                  0x01, 0x00, 0x00, 0x00)
+    };
+
+    if (X_limbs !=  BITS_TO_LIMBS(224) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    return ecp_mod_koblitz(X, X_limbs, Rp, 224);
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+
+/*
+ * Fast quasi-reduction modulo p256k1 = 2^256 - R,
+ * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
+ */
+static int ecp_mod_p256k1(mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t expected_width = BITS_TO_LIMBS(256) * 2;
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(N, expected_width));
+    ret = mbedtls_ecp_mod_p256k1_raw(N->p, expected_width);
+
+cleanup:
+    return ret;
+}
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs)
+{
+    static mbedtls_mpi_uint Rp[] = {
+        MBEDTLS_BYTES_TO_T_UINT_8(0xD1, 0x03, 0x00, 0x00,
+                                  0x01, 0x00, 0x00, 0x00)
+    };
+
+    if (X_limbs != BITS_TO_LIMBS(256) * 2) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    return ecp_mod_koblitz(X, X_limbs, Rp, 256);
+}
+
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
+                              const mbedtls_ecp_group_id id,
+                              const mbedtls_ecp_modulus_type ctype)
+{
+    mbedtls_mpi_modp_fn modp = NULL;
+    mbedtls_mpi_uint *p = NULL;
+    size_t p_limbs;
+
+    if (!(ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE || \
+          ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_SCALAR)) {
+        return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    switch (id) {
+#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p192_raw;
+#endif
+                p = (mbedtls_mpi_uint *) secp192r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p224_raw;
+#endif
+                p = (mbedtls_mpi_uint *) secp224r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p256_raw;
+#endif
+                p = (mbedtls_mpi_uint *) secp256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP384R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p384_raw;
+#endif
+                p = (mbedtls_mpi_uint *) secp384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP521R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+#if defined(MBEDTLS_ECP_NIST_OPTIM)
+                modp = &mbedtls_ecp_mod_p521_raw;
+#endif
+                p = (mbedtls_mpi_uint *) secp521r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp521r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp521r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP256R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP256r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP256r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP384R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP384r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP384r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+        case MBEDTLS_ECP_DP_BP512R1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) brainpoolP512r1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(brainpoolP512r1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE25519:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p255_raw;
+                p = (mbedtls_mpi_uint *) curve25519_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve25519_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve25519_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP192K1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p192k1_raw;
+                p = (mbedtls_mpi_uint *) secp192k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp192k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp192k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP224K1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p224k1_raw;
+                p = (mbedtls_mpi_uint *) secp224k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp224k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp224k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+        case MBEDTLS_ECP_DP_SECP256K1:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p256k1_raw;
+                p = (mbedtls_mpi_uint *) secp256k1_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_p));
+            } else {
+                p = (mbedtls_mpi_uint *) secp256k1_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(secp256k1_n));
+            }
+            break;
+#endif
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+        case MBEDTLS_ECP_DP_CURVE448:
+            if (ctype == (mbedtls_ecp_modulus_type) MBEDTLS_ECP_MOD_COORDINATE) {
+                modp = &mbedtls_ecp_mod_p448_raw;
+                p = (mbedtls_mpi_uint *) curve448_p;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_p));
+            } else {
+                p = (mbedtls_mpi_uint *) curve448_n;
+                p_limbs = CHARS_TO_LIMBS(sizeof(curve448_n));
+            }
+            break;
+#endif
+
+        default:
+        case MBEDTLS_ECP_DP_NONE:
+            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+    }
+
+    if (modp != NULL) {
+        if (mbedtls_mpi_mod_optred_modulus_setup(N, p, p_limbs, modp)) {
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        }
+    } else {
+        if (mbedtls_mpi_mod_modulus_setup(N, p, p_limbs)) {
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        }
+    }
+    return 0;
+}
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#if defined(MBEDTLS_TEST_HOOKS)
+
+MBEDTLS_STATIC_TESTABLE
+mbedtls_ecp_variant mbedtls_ecp_get_variant(void)
+{
+    return MBEDTLS_ECP_VARIANT_WITH_MPI_UINT;
+}
+
+#endif /* MBEDTLS_TEST_HOOKS */
+
+#endif /* !MBEDTLS_ECP_ALT */
+#endif /* MBEDTLS_ECP_LIGHT */
+#endif /* MBEDTLS_ECP_WITH_MPI_UINT */
diff --git a/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h b/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h
index f663d6737c77294b8ba9433c77c0d8e39b29a813..668edc74c9763c9e71cba3d6f769ef1b8af66203 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h
+++ b/lib/libmbedtls/mbedtls/library/ecp_internal_alt.h
@@ -6,19 +6,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
diff --git a/lib/libmbedtls/mbedtls/library/ecp_invasive.h b/lib/libmbedtls/mbedtls/library/ecp_invasive.h
index cb16d23728d2b54f3e304f604dcd87cabf0eef95..ff9f9ecf1d1c83fede1a56f50f9adf10ad80db87 100644
--- a/lib/libmbedtls/mbedtls/library/ecp_invasive.h
+++ b/lib/libmbedtls/mbedtls/library/ecp_invasive.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ECP_INVASIVE_H
 #define MBEDTLS_ECP_INVASIVE_H
@@ -31,20 +19,29 @@
 #include "bignum_mod.h"
 #include "mbedtls/ecp.h"
 
-#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_C)
+/*
+ * Curve modulus types
+ */
+typedef enum {
+    MBEDTLS_ECP_MOD_NONE = 0,
+    MBEDTLS_ECP_MOD_COORDINATE,
+    MBEDTLS_ECP_MOD_SCALAR
+} mbedtls_ecp_modulus_type;
 
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-/* Preconditions:
- *   - bits is a multiple of 64 or is 224
- *   - c is -1 or -2
- *   - 0 <= N < 2^bits
- *   - N has room for bits plus one limb
+typedef enum {
+    MBEDTLS_ECP_VARIANT_NONE = 0,
+    MBEDTLS_ECP_VARIANT_WITH_MPI_STRUCT,
+    MBEDTLS_ECP_VARIANT_WITH_MPI_UINT
+} mbedtls_ecp_variant;
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_ECP_LIGHT)
+
+/** Queries the ecp variant.
  *
- * Behavior:
- * Set N to c * 2^bits + old_value_of_N.
+ * \return  The id of the ecp variant.
  */
-void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits);
-#endif
+MBEDTLS_STATIC_TESTABLE
+mbedtls_ecp_variant mbedtls_ecp_get_variant(void);
 
 #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
 /** Generate a private key on a Montgomery curve (Curve25519 or Curve448).
@@ -60,7 +57,7 @@ void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits);
  *                  This is the bit-size of the key minus 1:
  *                  254 for Curve25519 or 447 for Curve448.
  * \param d         The randomly generated key. This is a number of size
- *                  exactly \p n_bits + 1 bits, with the least significant bits
+ *                  exactly \p high_bit + 1 bits, with the least significant bits
  *                  masked as specified in [Curve25519] and in [RFC7748] §5.
  * \param f_rng     The RNG function.
  * \param p_rng     The RNG context to be passed to \p f_rng.
@@ -68,7 +65,7 @@ void mbedtls_ecp_fix_negative(mbedtls_mpi *N, signed char c, size_t bits);
  * \return          \c 0 on success.
  * \return          \c MBEDTLS_ERR_ECP_xxx or MBEDTLS_ERR_MPI_xxx on failure.
  */
-int mbedtls_ecp_gen_privkey_mx(size_t n_bits,
+int mbedtls_ecp_gen_privkey_mx(size_t high_bit,
                                mbedtls_mpi *d,
                                int (*f_rng)(void *, unsigned char *, size_t),
                                void *p_rng);
@@ -160,6 +157,147 @@ int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 
+#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+
+/** Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4)
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 768-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (384 bits).
+ * \param[in]       X_limbs The length of \p N in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p N_n does not have
+ *                  twice as many limbs as the modulus.
+ */
+MBEDTLS_STATIC_TESTABLE
+int  mbedtls_ecp_mod_p384_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+
+/** Fast quasi-reduction modulo p192k1 = 2^192 - R,
+ * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x01000011C9
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 384-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (192 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
+ *                  twice as many limbs as the modulus.
+ * \return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p192k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+
+/** Fast quasi-reduction modulo p224k1 = 2^224 - R,
+ * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 448-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (224 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
+ *                  twice as many limbs as the modulus.
+ * \return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p224k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+
+/** Fast quasi-reduction modulo p256k1 = 2^256 - R,
+ * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 512-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ *                          The bitlength of the reduced value is the same as
+ *                          that of the modulus (256 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
+ *                  twice as many limbs as the modulus.
+ * \return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p256k1_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
+
+/** Fast quasi-reduction modulo p255 = 2^255 - 19
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 510-bit MPI
+ *                          (double the bitlength of the modulus).
+ *                          Upon return holds the reduced value which is
+ *                          in range `0 <= X < 2 * N` (where N is the modulus).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
+ *                  twice as many limbs as the modulus.
+ * \return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation failed.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p255_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
+
+#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
+
+/** Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1
+ * Write X as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return A0 + A1 + B1 +
+ * (B0 + B1) * 2^224.
+ *
+ * \param[in,out]   X       The address of the MPI to be converted.
+ *                          Must have exact limb size that stores a 896-bit MPI
+ *                          (double the bitlength of the modulus). Upon return
+ *                          holds the reduced value which is in range `0 <= X <
+ *                          N` (where N is the modulus). The bitlength of the
+ *                          reduced value is the same as that of the modulus
+ *                          (448 bits).
+ * \param[in]       X_limbs The length of \p X in limbs.
+ *
+ * \return          \c 0 on Success.
+ * \return          #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if \p X does not have
+ *                  twice as many limbs as the modulus.
+ * \return          #MBEDTLS_ERR_ECP_ALLOC_FAILED if memory allocation
+ *                  failed.
+ */
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ecp_mod_p448_raw(mbedtls_mpi_uint *X, size_t X_limbs);
+
+#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
+
 /** Initialise a modulus with hard-coded const curve data.
  *
  * \note            The caller is responsible for the \p N modulus' memory.
@@ -169,7 +307,7 @@ int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);
  * \param[in,out] N The address of the modulus structure to populate.
  *                  Must be initialized.
  * \param[in] id    The mbedtls_ecp_group_id for which to initialise the modulus.
- * \param[in] ctype The mbedtls_ecp_curve_type identifier for a coordinate modulus (P)
+ * \param[in] ctype The mbedtls_ecp_modulus_type identifier for a coordinate modulus (P)
  *                  or a scalar modulus (N).
  *
  * \return          \c 0 if successful.
@@ -180,7 +318,7 @@ int mbedtls_ecp_mod_p521_raw(mbedtls_mpi_uint *X, size_t X_limbs);
 MBEDTLS_STATIC_TESTABLE
 int mbedtls_ecp_modulus_setup(mbedtls_mpi_mod_modulus *N,
                               const mbedtls_ecp_group_id id,
-                              const mbedtls_ecp_curve_type ctype);
+                              const mbedtls_ecp_modulus_type ctype);
 
 #endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_ECP_C */
 
diff --git a/lib/libmbedtls/mbedtls/library/entropy.c b/lib/libmbedtls/mbedtls/library/entropy.c
index e55410c76d6858cdcd862010ea229f6da9bbf014..7dcf067a526eaa75e2d1daccfd0fda303bc85c47 100644
--- a/lib/libmbedtls/mbedtls/library/entropy.c
+++ b/lib/libmbedtls/mbedtls/library/entropy.c
@@ -2,19 +2,7 @@
  *  Entropy accumulator implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -34,9 +22,6 @@
 
 #include "mbedtls/platform.h"
 
-#include "mbedtls/platform.h"
-
-
 #define ENTROPY_MAX_LOOP    256     /**< Maximum amount to loop before error */
 
 void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
@@ -49,11 +34,7 @@ void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
 #endif
 
     ctx->accumulator_started = 0;
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    mbedtls_sha512_init(&ctx->accumulator);
-#else
-    mbedtls_sha256_init(&ctx->accumulator);
-#endif
+    mbedtls_md_init(&ctx->accumulator);
 
     /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
      *           when adding more strong entropy sources here. */
@@ -80,6 +61,10 @@ void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
 
 void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     /* If the context was already free, don't call free() again.
      * This is important for mutexes which don't allow double-free. */
     if (ctx->accumulator_started == -1) {
@@ -89,11 +74,7 @@ void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
 #if defined(MBEDTLS_THREADING_C)
     mbedtls_mutex_free(&ctx->mutex);
 #endif
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    mbedtls_sha512_free(&ctx->accumulator);
-#else
-    mbedtls_sha256_free(&ctx->accumulator);
-#endif
+    mbedtls_md_free(&ctx->accumulator);
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
     ctx->initial_entropy_run = 0;
 #endif
@@ -150,15 +131,10 @@ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
     int ret = 0;
 
     if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-        if ((ret = mbedtls_sha512(data, len, tmp, 0)) != 0) {
+        if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
+                              data, len, tmp)) != 0) {
             goto cleanup;
         }
-#else
-        if ((ret = mbedtls_sha256(data, len, tmp, 0)) != 0) {
-            goto cleanup;
-        }
-#endif
         p = tmp;
         use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
     }
@@ -171,29 +147,22 @@ static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
      * it is sufficient to start the accumulator here only because all calls to
      * gather entropy eventually execute this code.
      */
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
-    if (ctx->accumulator_started == 0 &&
-        (ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0) {
-        goto cleanup;
-    } else {
-        ctx->accumulator_started = 1;
-    }
-    if ((ret = mbedtls_sha512_update(&ctx->accumulator, header, 2)) != 0) {
-        goto cleanup;
-    }
-    ret = mbedtls_sha512_update(&ctx->accumulator, p, use_len);
-#else
-    if (ctx->accumulator_started == 0 &&
-        (ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0) {
-        goto cleanup;
-    } else {
+    if (ctx->accumulator_started == 0) {
+        ret = mbedtls_md_setup(&ctx->accumulator,
+                               mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
+        if (ret != 0) {
+            goto cleanup;
+        }
+        ret = mbedtls_md_starts(&ctx->accumulator);
+        if (ret != 0) {
+            goto cleanup;
+        }
         ctx->accumulator_started = 1;
     }
-    if ((ret = mbedtls_sha256_update(&ctx->accumulator, header, 2)) != 0) {
+    if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {
         goto cleanup;
     }
-    ret = mbedtls_sha256_update(&ctx->accumulator, p, use_len);
-#endif
+    ret = mbedtls_md_update(&ctx->accumulator, p, use_len);
 
 cleanup:
     mbedtls_platform_zeroize(tmp, sizeof(tmp));
@@ -354,62 +323,41 @@ int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
 
     memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
 
-#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
     /*
      * Note that at this stage it is assumed that the accumulator was started
      * in a previous call to entropy_update(). If this is not guaranteed, the
      * code below will fail.
      */
-    if ((ret = mbedtls_sha512_finish(&ctx->accumulator, buf)) != 0) {
+    if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {
         goto exit;
     }
 
     /*
      * Reset accumulator and counters and recycle existing entropy
      */
-    mbedtls_sha512_free(&ctx->accumulator);
-    mbedtls_sha512_init(&ctx->accumulator);
-    if ((ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0) {
-        goto exit;
-    }
-    if ((ret = mbedtls_sha512_update(&ctx->accumulator, buf,
-                                     MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
-        goto exit;
-    }
-
-    /*
-     * Perform second SHA-512 on entropy
-     */
-    if ((ret = mbedtls_sha512(buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
-                              buf, 0)) != 0) {
-        goto exit;
-    }
-#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
-    if ((ret = mbedtls_sha256_finish(&ctx->accumulator, buf)) != 0) {
+    mbedtls_md_free(&ctx->accumulator);
+    mbedtls_md_init(&ctx->accumulator);
+    ret = mbedtls_md_setup(&ctx->accumulator,
+                           mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
+    if (ret != 0) {
         goto exit;
     }
-
-    /*
-     * Reset accumulator and counters and recycle existing entropy
-     */
-    mbedtls_sha256_free(&ctx->accumulator);
-    mbedtls_sha256_init(&ctx->accumulator);
-    if ((ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0) {
+    ret = mbedtls_md_starts(&ctx->accumulator);
+    if (ret != 0) {
         goto exit;
     }
-    if ((ret = mbedtls_sha256_update(&ctx->accumulator, buf,
-                                     MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
+    if ((ret = mbedtls_md_update(&ctx->accumulator, buf,
+                                 MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
         goto exit;
     }
 
     /*
-     * Perform second SHA-256 on entropy
+     * Perform second hashing on entropy
      */
-    if ((ret = mbedtls_sha256(buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
-                              buf, 0)) != 0) {
+    if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
+                          buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {
         goto exit;
     }
-#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
 
     for (i = 0; i < ctx->source_count; i++) {
         ctx->source[i].size = 0;
diff --git a/lib/libmbedtls/mbedtls/library/entropy_poll.c b/lib/libmbedtls/mbedtls/library/entropy_poll.c
index b5024c83fa7387d3d45e9fac3f882f3e392773d9..611768cd8556d588abc1cafd0088c0409a332fc9 100644
--- a/lib/libmbedtls/mbedtls/library/entropy_poll.c
+++ b/lib/libmbedtls/mbedtls/library/entropy_poll.c
@@ -2,25 +2,15 @@
  *  Platform-specific and custom entropy polling functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
-#if defined(__linux__) && !defined(_GNU_SOURCE)
+#if defined(__linux__) || defined(__midipix__)
 /* Ensure that syscall() is available even when compiling with -std=c99 */
+#if !defined(_GNU_SOURCE)
 #define _GNU_SOURCE
 #endif
+#endif
 
 #include "common.h"
 
@@ -41,39 +31,41 @@
 
 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
     !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
-    !defined(__HAIKU__) && !defined(__midipix__)
+    !defined(__HAIKU__) && !defined(__midipix__) && !defined(__MVS__)
 #error \
     "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in mbedtls_config.h"
 #endif
 
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
 
-#if !defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
-#endif
 #include <windows.h>
-#include <wincrypt.h>
+#include <bcrypt.h>
+#include <intsafe.h>
 
 int mbedtls_platform_entropy_poll(void *data, unsigned char *output, size_t len,
                                   size_t *olen)
 {
-    HCRYPTPROV provider;
     ((void) data);
     *olen = 0;
 
-    if (CryptAcquireContext(&provider, NULL, NULL,
-                            PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) == FALSE) {
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
-    }
+    /*
+     * BCryptGenRandom takes ULONG for size, which is smaller than size_t on
+     * 64-bit Windows platforms. Extract entropy in chunks of len (dependent
+     * on ULONG_MAX) size.
+     */
+    while (len != 0) {
+        unsigned long ulong_bytes =
+            (len > ULONG_MAX) ? ULONG_MAX : (unsigned long) len;
+
+        if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, output, ulong_bytes,
+                                            BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
+            return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+        }
 
-    if (CryptGenRandom(provider, (DWORD) len, output) == FALSE) {
-        CryptReleaseContext(provider, 0);
-        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+        *olen += ulong_bytes;
+        len -= ulong_bytes;
     }
 
-    CryptReleaseContext(provider, 0);
-    *olen = len;
-
     return 0;
 }
 #else /* _WIN32 && !EFIX64 && !EFI32 */
@@ -98,7 +90,7 @@ static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
     memset(buf, 0, buflen);
 #endif
 #endif
-    return syscall(SYS_getrandom, buf, buflen, flags);
+    return (int) syscall(SYS_getrandom, buf, buflen, flags);
 }
 #endif /* SYS_getrandom */
 #endif /* __linux__ || __midipix__ */
@@ -112,7 +104,7 @@ static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
 #define HAVE_GETRANDOM
 static int getrandom_wrapper(void *buf, size_t buflen, unsigned int flags)
 {
-    return getrandom(buf, buflen, flags);
+    return (int) getrandom(buf, buflen, flags);
 }
 #endif /* (__FreeBSD__ && __FreeBSD_version >= 1200000) ||
           (__DragonFly__ && __DragonFly_version >= 500700) */
@@ -166,7 +158,7 @@ int mbedtls_platform_entropy_poll(void *data,
 #if defined(HAVE_GETRANDOM)
     ret = getrandom_wrapper(output, len, 0);
     if (ret >= 0) {
-        *olen = ret;
+        *olen = (size_t) ret;
         return 0;
     } else if (errno != ENOSYS) {
         return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
diff --git a/lib/libmbedtls/mbedtls/library/entropy_poll.h b/lib/libmbedtls/mbedtls/library/entropy_poll.h
index 3cfd4a444421eaa96ee0219a03fa2572a6e81775..6b4aec03e18b269653814c31cffefec13870a76e 100644
--- a/lib/libmbedtls/mbedtls/library/entropy_poll.h
+++ b/lib/libmbedtls/mbedtls/library/entropy_poll.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_ENTROPY_POLL_H
 #define MBEDTLS_ENTROPY_POLL_H
@@ -50,7 +38,7 @@ int mbedtls_platform_entropy_poll(void *data,
 /**
  * \brief           Entropy poll callback for a hardware source
  *
- * \warning         This is not provided by mbed TLS!
+ * \warning         This is not provided by Mbed TLS!
  *                  See \c MBEDTLS_ENTROPY_HARDWARE_ALT in mbedtls_config.h.
  *
  * \note            This must accept NULL as its first argument.
diff --git a/lib/libmbedtls/mbedtls/library/error.c b/lib/libmbedtls/mbedtls/library/error.c
index 85e315434642359177ab1ba179fdf8cfb98e0062..6ad7162ab57436476d9937f318de0e9ee65c25a5 100644
--- a/lib/libmbedtls/mbedtls/library/error.c
+++ b/lib/libmbedtls/mbedtls/library/error.c
@@ -2,19 +2,7 @@
  *  Error message information
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -162,6 +150,10 @@
 #include "mbedtls/sha256.h"
 #endif
 
+#if defined(MBEDTLS_SHA3_C)
+#include "mbedtls/sha3.h"
+#endif
+
 #if defined(MBEDTLS_SHA512_C)
 #include "mbedtls/sha512.h"
 #endif
@@ -426,11 +418,15 @@ const char *mbedtls_high_level_strerr(int error_code)
         case -(MBEDTLS_ERR_SSL_BAD_CERTIFICATE):
             return( "SSL - Processing of the Certificate handshake message failed" );
         case -(MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET):
-            return( "SSL - * Received NewSessionTicket Post Handshake Message. This error code is experimental and may be changed or removed without notice" );
+            return( "SSL - A TLS 1.3 NewSessionTicket message has been received" );
         case -(MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA):
             return( "SSL - Not possible to read early data" );
+        case -(MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA):
+            return( "SSL - * Early data has been received as part of an on-going handshake. This error code can be returned only on server side if and only if early data has been enabled by means of the mbedtls_ssl_conf_early_data() API. This error code can then be returned by mbedtls_ssl_handshake(), mbedtls_ssl_handshake_step(), mbedtls_ssl_read() or mbedtls_ssl_write() if early data has been received as part of the handshake sequence they triggered. To read the early data, call mbedtls_ssl_read_early_data()" );
         case -(MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA):
             return( "SSL - Not possible to write early data" );
+        case -(MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND):
+            return( "SSL - Cache entry not found" );
         case -(MBEDTLS_ERR_SSL_ALLOC_FAILED):
             return( "SSL - Memory allocation failed" );
         case -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED):
@@ -766,6 +762,11 @@ const char *mbedtls_low_level_strerr(int error_code)
             return( "SHA256 - SHA-256 input data was malformed" );
 #endif /* MBEDTLS_SHA256_C */
 
+#if defined(MBEDTLS_SHA3_C)
+        case -(MBEDTLS_ERR_SHA3_BAD_INPUT_DATA):
+            return( "SHA3 - SHA-3 input data was malformed" );
+#endif /* MBEDTLS_SHA3_C */
+
 #if defined(MBEDTLS_SHA512_C)
         case -(MBEDTLS_ERR_SHA512_BAD_INPUT_DATA):
             return( "SHA512 - SHA-512 input data was malformed" );
diff --git a/lib/libmbedtls/mbedtls/library/gcm.c b/lib/libmbedtls/mbedtls/library/gcm.c
index 71fcc3540580462da378a0e715f1b462e7a3f855..5dfac2349c82cbf1d3789370d332a79b50d3a549 100644
--- a/lib/libmbedtls/mbedtls/library/gcm.c
+++ b/lib/libmbedtls/mbedtls/library/gcm.c
@@ -2,19 +2,7 @@
  *  NIST SP800-38D compliant GCM implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -35,6 +23,11 @@
 #include "mbedtls/platform.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
+
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+#include "block_cipher_internal.h"
+#endif
 
 #include <string.h>
 
@@ -48,6 +41,12 @@
 
 #if !defined(MBEDTLS_GCM_ALT)
 
+/* Used to select the acceleration mechanism */
+#define MBEDTLS_GCM_ACC_SMALLTABLE  0
+#define MBEDTLS_GCM_ACC_LARGETABLE  1
+#define MBEDTLS_GCM_ACC_AESNI       2
+#define MBEDTLS_GCM_ACC_AESCE       3
+
 /*
  * Initialize a context
  */
@@ -56,6 +55,39 @@ void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
     memset(ctx, 0, sizeof(mbedtls_gcm_context));
 }
 
+static inline void gcm_set_acceleration(mbedtls_gcm_context *ctx)
+{
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+    ctx->acceleration = MBEDTLS_GCM_ACC_LARGETABLE;
+#else
+    ctx->acceleration = MBEDTLS_GCM_ACC_SMALLTABLE;
+#endif
+
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+    /* With CLMUL support, we need only h, not the rest of the table */
+    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
+        ctx->acceleration = MBEDTLS_GCM_ACC_AESNI;
+    }
+#endif
+
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+    if (MBEDTLS_AESCE_HAS_SUPPORT()) {
+        ctx->acceleration = MBEDTLS_GCM_ACC_AESCE;
+    }
+#endif
+}
+
+static inline void gcm_gen_table_rightshift(uint64_t dst[2], const uint64_t src[2])
+{
+    uint8_t *u8Dst = (uint8_t *) dst;
+    uint8_t *u8Src = (uint8_t *) src;
+
+    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[1], 0) >> 1, &dst[1], 0);
+    u8Dst[8] |= (u8Src[7] & 0x01) << 7;
+    MBEDTLS_PUT_UINT64_BE(MBEDTLS_GET_UINT64_BE(&src[0], 0) >> 1, &dst[0], 0);
+    u8Dst[0] ^= (u8Src[15] & 0x01) ? 0xE1 : 0;
+}
+
 /*
  * Precompute small multiples of H, that is set
  *      HH[i] || HL[i] = H times i,
@@ -67,63 +99,61 @@ void mbedtls_gcm_init(mbedtls_gcm_context *ctx)
 static int gcm_gen_table(mbedtls_gcm_context *ctx)
 {
     int ret, i, j;
-    uint64_t hi, lo;
-    uint64_t vl, vh;
-    unsigned char h[16];
-    size_t olen = 0;
+    uint64_t u64h[2] = { 0 };
+    uint8_t *h = (uint8_t *) u64h;
 
-    memset(h, 0, 16);
-    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, h, h);
+#else
+    size_t olen = 0;
+    ret = mbedtls_cipher_update(&ctx->cipher_ctx, h, 16, h, &olen);
+#endif
+    if (ret != 0) {
         return ret;
     }
 
-    /* pack h as two 64-bits ints, big-endian */
-    hi = MBEDTLS_GET_UINT32_BE(h,  0);
-    lo = MBEDTLS_GET_UINT32_BE(h,  4);
-    vh = (uint64_t) hi << 32 | lo;
+    gcm_set_acceleration(ctx);
 
-    hi = MBEDTLS_GET_UINT32_BE(h,  8);
-    lo = MBEDTLS_GET_UINT32_BE(h,  12);
-    vl = (uint64_t) hi << 32 | lo;
-
-    /* 8 = 1000 corresponds to 1 in GF(2^128) */
-    ctx->HL[8] = vl;
-    ctx->HH[8] = vh;
+    /* MBEDTLS_GCM_HTABLE_SIZE/2 = 1000 corresponds to 1 in GF(2^128) */
+    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][0] = u64h[0];
+    ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2][1] = u64h[1];
 
+    switch (ctx->acceleration) {
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
-    /* With CLMUL support, we need only h, not the rest of the table */
-    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
-        return 0;
-    }
+        case MBEDTLS_GCM_ACC_AESNI:
+            return 0;
 #endif
 
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-    if (mbedtls_aesce_has_support()) {
-        return 0;
-    }
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+        case MBEDTLS_GCM_ACC_AESCE:
+            return 0;
 #endif
 
-    /* 0 corresponds to 0 in GF(2^128) */
-    ctx->HH[0] = 0;
-    ctx->HL[0] = 0;
+        default:
+            /* 0 corresponds to 0 in GF(2^128) */
+            ctx->H[0][0] = 0;
+            ctx->H[0][1] = 0;
 
-    for (i = 4; i > 0; i >>= 1) {
-        uint32_t T = (vl & 1) * 0xe1000000U;
-        vl  = (vh << 63) | (vl >> 1);
-        vh  = (vh >> 1) ^ ((uint64_t) T << 32);
+            for (i = MBEDTLS_GCM_HTABLE_SIZE/4; i > 0; i >>= 1) {
+                gcm_gen_table_rightshift(ctx->H[i], ctx->H[i*2]);
+            }
 
-        ctx->HL[i] = vl;
-        ctx->HH[i] = vh;
-    }
+#if !defined(MBEDTLS_GCM_LARGE_TABLE)
+            /* pack elements of H as 64-bits ints, big-endian */
+            for (i = MBEDTLS_GCM_HTABLE_SIZE/2; i > 0; i >>= 1) {
+                MBEDTLS_PUT_UINT64_BE(ctx->H[i][0], &ctx->H[i][0], 0);
+                MBEDTLS_PUT_UINT64_BE(ctx->H[i][1], &ctx->H[i][1], 0);
+            }
+#endif
 
-    for (i = 2; i <= 8; i *= 2) {
-        uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
-        vh = *HiH;
-        vl = *HiL;
-        for (j = 1; j < i; j++) {
-            HiH[j] = vh ^ ctx->HH[j];
-            HiL[j] = vl ^ ctx->HL[j];
-        }
+            for (i = 2; i < MBEDTLS_GCM_HTABLE_SIZE; i <<= 1) {
+                for (j = 1; j < i; j++) {
+                    mbedtls_xor_no_simd((unsigned char *) ctx->H[i+j],
+                                        (unsigned char *) ctx->H[i],
+                                        (unsigned char *) ctx->H[j],
+                                        16);
+                }
+            }
     }
 
     return 0;
@@ -135,19 +165,31 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
                        unsigned int keybits)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_cipher_info_t *cipher_info;
 
     if (keybits != 128 && keybits != 192 && keybits != 256) {
         return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
+
+    if ((ret = mbedtls_block_cipher_setup(&ctx->block_cipher_ctx, cipher)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_block_cipher_setkey(&ctx->block_cipher_ctx, key, keybits)) != 0) {
+        return ret;
+    }
+#else
+    const mbedtls_cipher_info_t *cipher_info;
+
     cipher_info = mbedtls_cipher_info_from_values(cipher, keybits,
                                                   MBEDTLS_MODE_ECB);
     if (cipher_info == NULL) {
         return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
-    if (cipher_info->block_size != 16) {
+    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
         return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
@@ -161,6 +203,7 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
                                      MBEDTLS_ENCRYPT)) != 0) {
         return ret;
     }
+#endif
 
     if ((ret = gcm_gen_table(ctx)) != 0) {
         return ret;
@@ -169,12 +212,86 @@ int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx,
     return 0;
 }
 
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+static const uint16_t last8[256] = {
+    0x0000, 0xc201, 0x8403, 0x4602, 0x0807, 0xca06, 0x8c04, 0x4e05,
+    0x100e, 0xd20f, 0x940d, 0x560c, 0x1809, 0xda08, 0x9c0a, 0x5e0b,
+    0x201c, 0xe21d, 0xa41f, 0x661e, 0x281b, 0xea1a, 0xac18, 0x6e19,
+    0x3012, 0xf213, 0xb411, 0x7610, 0x3815, 0xfa14, 0xbc16, 0x7e17,
+    0x4038, 0x8239, 0xc43b, 0x063a, 0x483f, 0x8a3e, 0xcc3c, 0x0e3d,
+    0x5036, 0x9237, 0xd435, 0x1634, 0x5831, 0x9a30, 0xdc32, 0x1e33,
+    0x6024, 0xa225, 0xe427, 0x2626, 0x6823, 0xaa22, 0xec20, 0x2e21,
+    0x702a, 0xb22b, 0xf429, 0x3628, 0x782d, 0xba2c, 0xfc2e, 0x3e2f,
+    0x8070, 0x4271, 0x0473, 0xc672, 0x8877, 0x4a76, 0x0c74, 0xce75,
+    0x907e, 0x527f, 0x147d, 0xd67c, 0x9879, 0x5a78, 0x1c7a, 0xde7b,
+    0xa06c, 0x626d, 0x246f, 0xe66e, 0xa86b, 0x6a6a, 0x2c68, 0xee69,
+    0xb062, 0x7263, 0x3461, 0xf660, 0xb865, 0x7a64, 0x3c66, 0xfe67,
+    0xc048, 0x0249, 0x444b, 0x864a, 0xc84f, 0x0a4e, 0x4c4c, 0x8e4d,
+    0xd046, 0x1247, 0x5445, 0x9644, 0xd841, 0x1a40, 0x5c42, 0x9e43,
+    0xe054, 0x2255, 0x6457, 0xa656, 0xe853, 0x2a52, 0x6c50, 0xae51,
+    0xf05a, 0x325b, 0x7459, 0xb658, 0xf85d, 0x3a5c, 0x7c5e, 0xbe5f,
+    0x00e1, 0xc2e0, 0x84e2, 0x46e3, 0x08e6, 0xcae7, 0x8ce5, 0x4ee4,
+    0x10ef, 0xd2ee, 0x94ec, 0x56ed, 0x18e8, 0xdae9, 0x9ceb, 0x5eea,
+    0x20fd, 0xe2fc, 0xa4fe, 0x66ff, 0x28fa, 0xeafb, 0xacf9, 0x6ef8,
+    0x30f3, 0xf2f2, 0xb4f0, 0x76f1, 0x38f4, 0xfaf5, 0xbcf7, 0x7ef6,
+    0x40d9, 0x82d8, 0xc4da, 0x06db, 0x48de, 0x8adf, 0xccdd, 0x0edc,
+    0x50d7, 0x92d6, 0xd4d4, 0x16d5, 0x58d0, 0x9ad1, 0xdcd3, 0x1ed2,
+    0x60c5, 0xa2c4, 0xe4c6, 0x26c7, 0x68c2, 0xaac3, 0xecc1, 0x2ec0,
+    0x70cb, 0xb2ca, 0xf4c8, 0x36c9, 0x78cc, 0xbacd, 0xfccf, 0x3ece,
+    0x8091, 0x4290, 0x0492, 0xc693, 0x8896, 0x4a97, 0x0c95, 0xce94,
+    0x909f, 0x529e, 0x149c, 0xd69d, 0x9898, 0x5a99, 0x1c9b, 0xde9a,
+    0xa08d, 0x628c, 0x248e, 0xe68f, 0xa88a, 0x6a8b, 0x2c89, 0xee88,
+    0xb083, 0x7282, 0x3480, 0xf681, 0xb884, 0x7a85, 0x3c87, 0xfe86,
+    0xc0a9, 0x02a8, 0x44aa, 0x86ab, 0xc8ae, 0x0aaf, 0x4cad, 0x8eac,
+    0xd0a7, 0x12a6, 0x54a4, 0x96a5, 0xd8a0, 0x1aa1, 0x5ca3, 0x9ea2,
+    0xe0b5, 0x22b4, 0x64b6, 0xa6b7, 0xe8b2, 0x2ab3, 0x6cb1, 0xaeb0,
+    0xf0bb, 0x32ba, 0x74b8, 0xb6b9, 0xf8bc, 0x3abd, 0x7cbf, 0xbebe
+};
+
+static void gcm_mult_largetable(uint8_t *output, const uint8_t *x, uint64_t H[256][2])
+{
+    int i;
+    uint64_t u64z[2];
+    uint16_t *u16z = (uint16_t *) u64z;
+    uint8_t *u8z = (uint8_t *) u64z;
+    uint8_t rem;
+
+    u64z[0] = 0;
+    u64z[1] = 0;
+
+    if (MBEDTLS_IS_BIG_ENDIAN) {
+        for (i = 15; i > 0; i--) {
+            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+            rem = u8z[15];
+
+            u64z[1] >>= 8;
+            u8z[8] = u8z[7];
+            u64z[0] >>= 8;
+
+            u16z[0] ^= MBEDTLS_GET_UINT16_LE(&last8[rem], 0);
+        }
+    } else {
+        for (i = 15; i > 0; i--) {
+            mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[x[i]], 16);
+            rem = u8z[15];
+
+            u64z[1] <<= 8;
+            u8z[8] = u8z[7];
+            u64z[0] <<= 8;
+
+            u16z[0] ^= last8[rem];
+        }
+    }
+
+    mbedtls_xor_no_simd(output, u8z, (uint8_t *) H[x[0]], 16);
+}
+#else
 /*
  * Shoup's method for multiplication use this table with
  *      last4[x] = x times P^128
  * where x and last4[x] are seen as elements of GF(2^128) as in [MGV]
  */
-static const uint64_t last4[16] =
+static const uint16_t last4[16] =
 {
     0x0000, 0x1c20, 0x3840, 0x2460,
     0x7080, 0x6ca0, 0x48c0, 0x54e0,
@@ -182,78 +299,79 @@ static const uint64_t last4[16] =
     0x9180, 0x8da0, 0xa9c0, 0xb5e0
 };
 
-/*
- * Sets output to x times H using the precomputed tables.
- * x and output are seen as elements of GF(2^128) as in [MGV].
- */
-static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
-                     unsigned char output[16])
+static void gcm_mult_smalltable(uint8_t *output, const uint8_t *x, uint64_t H[16][2])
 {
     int i = 0;
     unsigned char lo, hi, rem;
-    uint64_t zh, zl;
+    uint64_t u64z[2];
+    const uint64_t *pu64z = NULL;
+    uint8_t *u8z = (uint8_t *) u64z;
 
-#if defined(MBEDTLS_AESNI_HAVE_CODE)
-    if (mbedtls_aesni_has_support(MBEDTLS_AESNI_CLMUL)) {
-        unsigned char h[16];
-
-        /* mbedtls_aesni_gcm_mult needs big-endian input */
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
+    lo = x[15] & 0xf;
+    hi = (x[15] >> 4) & 0xf;
 
-        mbedtls_aesni_gcm_mult(output, x, h);
-        return;
-    }
-#endif /* MBEDTLS_AESNI_HAVE_CODE */
+    pu64z = H[lo];
 
-#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
-    if (mbedtls_aesce_has_support()) {
-        unsigned char h[16];
+    rem = (unsigned char) pu64z[1] & 0xf;
+    u64z[1] = (pu64z[0] << 60) | (pu64z[1] >> 4);
+    u64z[0] = (pu64z[0] >> 4);
+    u64z[0] ^= (uint64_t) last4[rem] << 48;
+    mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
 
-        /* mbedtls_aesce_gcm_mult needs big-endian input */
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8] >> 32, h,  0);
-        MBEDTLS_PUT_UINT32_BE(ctx->HH[8],       h,  4);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8] >> 32, h,  8);
-        MBEDTLS_PUT_UINT32_BE(ctx->HL[8],       h, 12);
+    for (i = 14; i >= 0; i--) {
+        lo = x[i] & 0xf;
+        hi = (x[i] >> 4) & 0xf;
 
-        mbedtls_aesce_gcm_mult(output, x, h);
-        return;
+        rem = (unsigned char) u64z[1] & 0xf;
+        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+        u64z[0] = (u64z[0] >> 4);
+        u64z[0] ^= (uint64_t) last4[rem] << 48;
+        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[lo], 16);
+
+        rem = (unsigned char) u64z[1] & 0xf;
+        u64z[1] = (u64z[0] << 60) | (u64z[1] >> 4);
+        u64z[0] = (u64z[0] >> 4);
+        u64z[0] ^= (uint64_t) last4[rem] << 48;
+        mbedtls_xor_no_simd(u8z, u8z, (uint8_t *) H[hi], 16);
     }
-#endif
 
-    lo = x[15] & 0xf;
-
-    zh = ctx->HH[lo];
-    zl = ctx->HL[lo];
-
-    for (i = 15; i >= 0; i--) {
-        lo = x[i] & 0xf;
-        hi = (x[i] >> 4) & 0xf;
+    MBEDTLS_PUT_UINT64_BE(u64z[0], output, 0);
+    MBEDTLS_PUT_UINT64_BE(u64z[1], output, 8);
+}
+#endif
 
-        if (i != 15) {
-            rem = (unsigned char) zl & 0xf;
-            zl = (zh << 60) | (zl >> 4);
-            zh = (zh >> 4);
-            zh ^= (uint64_t) last4[rem] << 48;
-            zh ^= ctx->HH[lo];
-            zl ^= ctx->HL[lo];
+/*
+ * Sets output to x times H using the precomputed tables.
+ * x and output are seen as elements of GF(2^128) as in [MGV].
+ */
+static void gcm_mult(mbedtls_gcm_context *ctx, const unsigned char x[16],
+                     unsigned char output[16])
+{
+    switch (ctx->acceleration) {
+#if defined(MBEDTLS_AESNI_HAVE_CODE)
+        case MBEDTLS_GCM_ACC_AESNI:
+            mbedtls_aesni_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+            break;
+#endif
 
-        }
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+        case MBEDTLS_GCM_ACC_AESCE:
+            mbedtls_aesce_gcm_mult(output, x, (uint8_t *) ctx->H[MBEDTLS_GCM_HTABLE_SIZE/2]);
+            break;
+#endif
 
-        rem = (unsigned char) zl & 0xf;
-        zl = (zh << 60) | (zl >> 4);
-        zh = (zh >> 4);
-        zh ^= (uint64_t) last4[rem] << 48;
-        zh ^= ctx->HH[hi];
-        zl ^= ctx->HL[hi];
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+        case MBEDTLS_GCM_ACC_LARGETABLE:
+            gcm_mult_largetable(output, x, ctx->H);
+            break;
+#else
+        case MBEDTLS_GCM_ACC_SMALLTABLE:
+            gcm_mult_smalltable(output, x, ctx->H);
+            break;
+#endif
     }
 
-    MBEDTLS_PUT_UINT32_BE(zh >> 32, output, 0);
-    MBEDTLS_PUT_UINT32_BE(zh, output, 4);
-    MBEDTLS_PUT_UINT32_BE(zl >> 32, output, 8);
-    MBEDTLS_PUT_UINT32_BE(zl, output, 12);
+    return;
 }
 
 int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
@@ -263,8 +381,11 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char work_buf[16];
     const unsigned char *p;
-    size_t use_len, olen = 0;
+    size_t use_len;
     uint64_t iv_bits;
+#if !defined(MBEDTLS_BLOCK_CIPHER_C)
+    size_t olen = 0;
+#endif
 
     /* IV is limited to 2^64 bits, so 2^61 bytes */
     /* IV is not allowed to be zero length */
@@ -291,8 +412,17 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
         while (iv_len > 0) {
             use_len = (iv_len < 16) ? iv_len : 16;
 
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wstringop-overflow=0"
+#endif
+
             mbedtls_xor(ctx->y, ctx->y, p, use_len);
 
+#if defined(MBEDTLS_COMPILER_IS_GCC) && (MBEDTLS_GCC_VERSION >= 70110)
+#pragma GCC diagnostic pop
+#endif
+
             gcm_mult(ctx, ctx->y, ctx->y);
 
             iv_len -= use_len;
@@ -304,8 +434,13 @@ int mbedtls_gcm_starts(mbedtls_gcm_context *ctx,
         gcm_mult(ctx, ctx->y, ctx->y);
     }
 
-    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16,
-                                     ctx->base_ectr, &olen)) != 0) {
+
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ctx->base_ectr);
+#else
+    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ctx->base_ectr, &olen);
+#endif
+    if (ret != 0) {
         return ret;
     }
 
@@ -334,9 +469,17 @@ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
 {
     const unsigned char *p;
     size_t use_len, offset;
+    uint64_t new_add_len;
 
-    /* IV is limited to 2^64 bits, so 2^61 bytes */
-    if ((uint64_t) add_len >> 61 != 0) {
+    /* AD is limited to 2^64 bits, ie 2^61 bytes
+     * Also check for possible overflow */
+#if SIZE_MAX > 0xFFFFFFFFFFFFFFFFULL
+    if (add_len > 0xFFFFFFFFFFFFFFFFULL) {
+        return MBEDTLS_ERR_GCM_BAD_INPUT;
+    }
+#endif
+    new_add_len = ctx->add_len + (uint64_t) add_len;
+    if (new_add_len < ctx->add_len || new_add_len >> 61 != 0) {
         return MBEDTLS_ERR_GCM_BAD_INPUT;
     }
 
@@ -381,12 +524,9 @@ int mbedtls_gcm_update_ad(mbedtls_gcm_context *ctx,
 /* Increment the counter. */
 static void gcm_incr(unsigned char y[16])
 {
-    size_t i;
-    for (i = 16; i > 12; i--) {
-        if (++y[i - 1] != 0) {
-            break;
-        }
-    }
+    uint32_t x = MBEDTLS_GET_UINT32_BE(y, 12);
+    x++;
+    MBEDTLS_PUT_UINT32_BE(x, y, 12);
 }
 
 /* Calculate and apply the encryption mask. Process use_len bytes of data,
@@ -397,11 +537,15 @@ static int gcm_mask(mbedtls_gcm_context *ctx,
                     const unsigned char *input,
                     unsigned char *output)
 {
-    size_t olen = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if ((ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr,
-                                     &olen)) != 0) {
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    ret = mbedtls_block_cipher_encrypt(&ctx->block_cipher_ctx, ctx->y, ectr);
+#else
+    size_t olen = 0;
+    ret = mbedtls_cipher_update(&ctx->cipher_ctx, ctx->y, 16, ectr, &olen);
+#endif
+    if (ret != 0) {
         mbedtls_platform_zeroize(ectr, 16);
         return ret;
     }
@@ -518,6 +662,9 @@ int mbedtls_gcm_finish(mbedtls_gcm_context *ctx,
     (void) output_size;
     *output_length = 0;
 
+    /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes
+     * and AD length is restricted to 2^64 bits, ie 2^61 bytes so neither of
+     * the two multiplications would overflow. */
     orig_len = ctx->len * 8;
     orig_add_len = ctx->add_len * 8;
 
@@ -601,7 +748,6 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char check_tag[16];
-    size_t i;
     int diff;
 
     if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length,
@@ -611,9 +757,7 @@ int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx,
     }
 
     /* Check tag in "constant-time" */
-    for (diff = 0, i = 0; i < tag_len; i++) {
-        diff |= tag[i] ^ check_tag[i];
-    }
+    diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
 
     if (diff != 0) {
         mbedtls_platform_zeroize(output, length);
@@ -628,13 +772,17 @@ void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
     if (ctx == NULL) {
         return;
     }
+#if defined(MBEDTLS_BLOCK_CIPHER_C)
+    mbedtls_block_cipher_free(&ctx->block_cipher_ctx);
+#else
     mbedtls_cipher_free(&ctx->cipher_ctx);
+#endif
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_gcm_context));
 }
 
 #endif /* !MBEDTLS_GCM_ALT */
 
-#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_CCM_GCM_CAN_AES)
 /*
  * AES-GCM test vectors from:
  *
@@ -645,7 +793,7 @@ void mbedtls_gcm_free(mbedtls_gcm_context *ctx)
 static const int key_index_test_data[MAX_TESTS] =
 { 0, 0, 1, 1, 1, 1 };
 
-static const unsigned char key_test_data[MAX_TESTS][32] =
+static const unsigned char key_test_data[][32] =
 {
     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -663,7 +811,7 @@ static const size_t iv_len_test_data[MAX_TESTS] =
 static const int iv_index_test_data[MAX_TESTS] =
 { 0, 0, 1, 1, 1, 2 };
 
-static const unsigned char iv_test_data[MAX_TESTS][64] =
+static const unsigned char iv_test_data[][64] =
 {
     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00 },
@@ -685,7 +833,7 @@ static const size_t add_len_test_data[MAX_TESTS] =
 static const int add_index_test_data[MAX_TESTS] =
 { 0, 0, 0, 1, 1, 1 };
 
-static const unsigned char additional_test_data[MAX_TESTS][64] =
+static const unsigned char additional_test_data[][64] =
 {
     { 0x00 },
     { 0xfe, 0xed, 0xfa, 0xce, 0xde, 0xad, 0xbe, 0xef,
@@ -699,7 +847,7 @@ static const size_t pt_len_test_data[MAX_TESTS] =
 static const int pt_index_test_data[MAX_TESTS] =
 { 0, 0, 1, 1, 1, 1 };
 
-static const unsigned char pt_test_data[MAX_TESTS][64] =
+static const unsigned char pt_test_data[][64] =
 {
     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -713,7 +861,7 @@ static const unsigned char pt_test_data[MAX_TESTS][64] =
       0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 },
 };
 
-static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
+static const unsigned char ct_test_data[][64] =
 {
     { 0x00 },
     { 0x03, 0x88, 0xda, 0xce, 0x60, 0xb6, 0xa3, 0x92,
@@ -750,6 +898,7 @@ static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
       0xcc, 0xdc, 0xb2, 0x81, 0xd4, 0x8c, 0x7c, 0x6f,
       0xd6, 0x28, 0x75, 0xd2, 0xac, 0xa4, 0x17, 0x03,
       0x4c, 0x34, 0xae, 0xe5 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x00 },
     { 0x98, 0xe7, 0x24, 0x7c, 0x07, 0xf0, 0xfe, 0x41,
       0x1c, 0x26, 0x7e, 0x43, 0x84, 0xb0, 0xf6, 0x00 },
@@ -820,9 +969,10 @@ static const unsigned char ct_test_data[MAX_TESTS * 3][64] =
       0x2d, 0xa3, 0xeb, 0xf1, 0xc5, 0xd8, 0x2c, 0xde,
       0xa2, 0x41, 0x89, 0x97, 0x20, 0x0e, 0xf8, 0x2e,
       0x44, 0xae, 0x7e, 0x3f },
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 };
 
-static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
+static const unsigned char tag_test_data[][16] =
 {
     { 0x58, 0xe2, 0xfc, 0xce, 0xfa, 0x7e, 0x30, 0x61,
       0x36, 0x7f, 0x1d, 0x57, 0xa4, 0xe7, 0x45, 0x5a },
@@ -836,6 +986,7 @@ static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
       0x56, 0x1b, 0xe1, 0x4a, 0xac, 0xa2, 0xfc, 0xcb },
     { 0x61, 0x9c, 0xc5, 0xae, 0xff, 0xfe, 0x0b, 0xfa,
       0x46, 0x2a, 0xf4, 0x3c, 0x16, 0x99, 0xd0, 0x50 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0xcd, 0x33, 0xb2, 0x8a, 0xc7, 0x73, 0xf7, 0x4b,
       0xa0, 0x0e, 0xd1, 0xf3, 0x12, 0x57, 0x24, 0x35 },
     { 0x2f, 0xf5, 0x8d, 0x80, 0x03, 0x39, 0x27, 0xab,
@@ -860,6 +1011,7 @@ static const unsigned char tag_test_data[MAX_TESTS * 3][16] =
       0x5e, 0x45, 0x49, 0x13, 0xfe, 0x2e, 0xa8, 0xf2 },
     { 0xa4, 0x4a, 0x82, 0x66, 0xee, 0x1c, 0x8e, 0xb0,
       0xc8, 0xb5, 0xd4, 0xcf, 0x5a, 0xe9, 0xf1, 0x9a },
+#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
 };
 
 int mbedtls_gcm_self_test(int verbose)
@@ -880,21 +1032,31 @@ int mbedtls_gcm_self_test(int verbose)
             mbedtls_printf("  GCM note: using AESNI.\n");
         } else
 #endif
+
+#if defined(MBEDTLS_AESCE_HAVE_CODE)
+        if (MBEDTLS_AESCE_HAS_SUPPORT()) {
+            mbedtls_printf("  GCM note: using AESCE.\n");
+        } else
+#endif
+
         mbedtls_printf("  GCM note: built-in implementation.\n");
 #endif /* MBEDTLS_GCM_ALT */
     }
 
-    for (j = 0; j < 3; j++) {
+    static const int loop_limit =
+        (sizeof(ct_test_data) / sizeof(*ct_test_data)) / MAX_TESTS;
+
+    for (j = 0; j < loop_limit; j++) {
         int key_len = 128 + 64 * j;
 
         for (i = 0; i < MAX_TESTS; i++) {
-            mbedtls_gcm_init(&ctx);
-
             if (verbose != 0) {
                 mbedtls_printf("  AES-GCM-%3d #%d (%s): ",
                                key_len, i, "enc");
             }
 
+            mbedtls_gcm_init(&ctx);
+
             ret = mbedtls_gcm_setkey(&ctx, cipher,
                                      key_test_data[key_index_test_data[i]],
                                      key_len);
diff --git a/lib/libmbedtls/mbedtls/library/hash_info.c b/lib/libmbedtls/mbedtls/library/hash_info.c
deleted file mode 100644
index 0e445b6cf8217ecadb2abd950f559b1e3548b03d..0000000000000000000000000000000000000000
--- a/lib/libmbedtls/mbedtls/library/hash_info.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Hash information that's independent from the crypto implementation.
- *
- * (See the corresponding header file for usage notes.)
- */
-/*
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-
-#include "hash_info.h"
-#include "mbedtls/legacy_or_psa.h"
-#include "mbedtls/error.h"
-
-typedef struct {
-    psa_algorithm_t psa_alg;
-    mbedtls_md_type_t md_type;
-    unsigned char size;
-    unsigned char block_size;
-} hash_entry;
-
-static const hash_entry hash_table[] = {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_MD5, MBEDTLS_MD_MD5, 16, 64 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_RIPEMD160, MBEDTLS_MD_RIPEMD160, 20, 64 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_SHA_1, MBEDTLS_MD_SHA1, 20, 64 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_SHA_224, MBEDTLS_MD_SHA224, 28, 64 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_SHA_256, MBEDTLS_MD_SHA256, 32, 64 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_SHA_384, MBEDTLS_MD_SHA384, 48, 128 },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
-    { PSA_ALG_SHA_512, MBEDTLS_MD_SHA512, 64, 128 },
-#endif
-    { PSA_ALG_NONE, MBEDTLS_MD_NONE, 0, 0 },
-};
-
-/* Get size from MD type */
-unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type)
-{
-    const hash_entry *entry = hash_table;
-    while (entry->md_type != MBEDTLS_MD_NONE &&
-           entry->md_type != md_type) {
-        entry++;
-    }
-
-    return entry->size;
-}
-
-/* Get block size from MD type */
-unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type)
-{
-    const hash_entry *entry = hash_table;
-    while (entry->md_type != MBEDTLS_MD_NONE &&
-           entry->md_type != md_type) {
-        entry++;
-    }
-
-    return entry->block_size;
-}
-
-/* Get PSA from MD */
-psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type)
-{
-    const hash_entry *entry = hash_table;
-    while (entry->md_type != MBEDTLS_MD_NONE &&
-           entry->md_type != md_type) {
-        entry++;
-    }
-
-    return entry->psa_alg;
-}
-
-/* Get MD from PSA */
-mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg)
-{
-    const hash_entry *entry = hash_table;
-    while (entry->md_type != MBEDTLS_MD_NONE &&
-           entry->psa_alg != psa_alg) {
-        entry++;
-    }
-
-    return entry->md_type;
-}
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-int mbedtls_md_error_from_psa(psa_status_t status)
-{
-    switch (status) {
-        case PSA_SUCCESS:
-            return 0;
-        case PSA_ERROR_NOT_SUPPORTED:
-            return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_INVALID_ARGUMENT:
-            return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
-        case PSA_ERROR_INSUFFICIENT_MEMORY:
-            return MBEDTLS_ERR_MD_ALLOC_FAILED;
-        default:
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-    }
-}
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
diff --git a/lib/libmbedtls/mbedtls/library/hash_info.h b/lib/libmbedtls/mbedtls/library/hash_info.h
deleted file mode 100644
index f984c82427ace03d1f9039133e4bb4e4f12a93b6..0000000000000000000000000000000000000000
--- a/lib/libmbedtls/mbedtls/library/hash_info.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * Hash information that's independent from the crypto implementation.
- *
- *  This can be used by:
- *  - code based on PSA
- *  - code based on the legacy API
- *  - code based on either of them depending on MBEDTLS_USE_PSA_CRYPTO
- *  - code based on either of them depending on what's available
- *
- *  Note: this internal module will go away when everything becomes based on
- *  PSA Crypto; it is a helper for the transition while hash algorithms are
- *  still represented using mbedtls_md_type_t in most places even when PSA is
- *  used for the actual crypto computations.
- *
- *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- */
-#ifndef MBEDTLS_HASH_INFO_H
-#define MBEDTLS_HASH_INFO_H
-
-#include "common.h"
-
-#include "mbedtls/md.h"
-#include "psa/crypto.h"
-#include "mbedtls/platform_util.h"
-
-/** \def MBEDTLS_HASH_MAX_SIZE
- *
- * Maximum size of a hash based on configuration.
- */
-#if defined(MBEDTLS_MD_C) && ( \
-    !defined(MBEDTLS_PSA_CRYPTO_C) || \
-    MBEDTLS_MD_MAX_SIZE >= PSA_HASH_MAX_SIZE)
-#define MBEDTLS_HASH_MAX_SIZE MBEDTLS_MD_MAX_SIZE
-#elif defined(MBEDTLS_PSA_CRYPTO_C) && ( \
-    !defined(MBEDTLS_MD_C) || \
-    PSA_HASH_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE)
-#define MBEDTLS_HASH_MAX_SIZE PSA_HASH_MAX_SIZE
-#endif
-
-/** Get the output length of the given hash type from its MD type.
- *
- * \note To get the output length from the PSA alg, use \c PSA_HASH_LENGTH().
- *
- * \param md_type   The hash MD type.
- *
- * \return          The output length in bytes, or 0 if not known.
- */
-unsigned char mbedtls_hash_info_get_size(mbedtls_md_type_t md_type);
-
-/** Get the block size of the given hash type from its MD type.
- *
- * \note To get the output length from the PSA alg, use
- *       \c PSA_HASH_BLOCK_LENGTH().
- *
- * \param md_type   The hash MD type.
- *
- * \return          The block size in bytes, or 0 if not known.
- */
-unsigned char mbedtls_hash_info_get_block_size(mbedtls_md_type_t md_type);
-
-/** Get the PSA alg from the MD type.
- *
- * \param md_type   The hash MD type.
- *
- * \return          The corresponding PSA algorithm identifier,
- *                  or PSA_ALG_NONE if not known.
- */
-psa_algorithm_t mbedtls_hash_info_psa_from_md(mbedtls_md_type_t md_type);
-
-/** Get the MD type alg from the PSA algorithm identifier.
- *
- * \param psa_alg   The PSA hash algorithm.
- *
- * \return          The corresponding MD type,
- *                  or MBEDTLS_MD_NONE if not known.
- */
-mbedtls_md_type_t mbedtls_hash_info_md_from_psa(psa_algorithm_t psa_alg);
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-/** Convert PSA status to MD error code.
- *
- * \param status    PSA status.
- *
- * \return          The corresponding MD error code,
- */
-int MBEDTLS_DEPRECATED mbedtls_md_error_from_psa(psa_status_t status);
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
-#endif /* MBEDTLS_HASH_INFO_H */
diff --git a/lib/libmbedtls/mbedtls/library/hkdf.c b/lib/libmbedtls/mbedtls/library/hkdf.c
index a3f071ecef4609566314458d78ffc8c86948d694..631ac24e53049bd21beea3147eabc72c4b0e7bab 100644
--- a/lib/libmbedtls/mbedtls/library/hkdf.c
+++ b/lib/libmbedtls/mbedtls/library/hkdf.c
@@ -2,19 +2,7 @@
  *  HKDF implementation -- RFC 5869
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #include "common.h"
 
diff --git a/lib/libmbedtls/mbedtls/library/hmac_drbg.c b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
index b15730235c309fb1306d21eeefe018c87217f5d2..90174d5d17d56324ed14029b8f58431b98b99848 100644
--- a/lib/libmbedtls/mbedtls/library/hmac_drbg.c
+++ b/lib/libmbedtls/mbedtls/library/hmac_drbg.c
@@ -2,19 +2,7 @@
  *  HMAC_DRBG implementation (NIST SP 800-90)
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -510,7 +498,7 @@ exit:
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#if !defined(MBEDTLS_SHA1_C)
+#if !defined(MBEDTLS_MD_CAN_SHA1)
 /* Dummy checkup routine */
 int mbedtls_hmac_drbg_self_test(int verbose)
 {
@@ -639,7 +627,7 @@ int mbedtls_hmac_drbg_self_test(int verbose)
 
     return 0;
 }
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_SELF_TEST */
 
 #endif /* MBEDTLS_HMAC_DRBG_C */
diff --git a/lib/libmbedtls/mbedtls/library/lmots.c b/lib/libmbedtls/mbedtls/library/lmots.c
index 4061edde04878a1ec1566203145f9a00aa39c9b5..c51cb41ece88dd34739d0934896dae5b86e573ca 100644
--- a/lib/libmbedtls/mbedtls/library/lmots.c
+++ b/lib/libmbedtls/mbedtls/library/lmots.c
@@ -2,19 +2,7 @@
  * The LM-OTS one-time public-key signature scheme
  *
  * Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -41,13 +29,19 @@
 #include "mbedtls/lms.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 
 #include "psa/crypto.h"
 
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_lms_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_lms_errors,
+                                 ARRAY_LENGTH(psa_to_lms_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 
 #define PUBLIC_KEY_TYPE_OFFSET     (0)
 #define PUBLIC_KEY_I_KEY_ID_OFFSET (PUBLIC_KEY_TYPE_OFFSET + \
@@ -75,29 +69,6 @@ static const unsigned char D_MESSAGE_CONSTANT_BYTES[D_CONST_LEN] = { 0x81, 0x81
 int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *) = NULL;
 #endif /* defined(MBEDTLS_TEST_HOOKS) */
 
-void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len,
-                                               unsigned char *bytes)
-{
-    size_t idx;
-
-    for (idx = 0; idx < len; idx++) {
-        bytes[idx] = (val >> ((len - 1 - idx) * 8)) & 0xFF;
-    }
-}
-
-unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len,
-                                                       const unsigned char *bytes)
-{
-    size_t idx;
-    unsigned int val = 0;
-
-    for (idx = 0; idx < len; idx++) {
-        val |= ((unsigned int) bytes[idx]) << (8 * (len - 1 - idx));
-    }
-
-    return val;
-}
-
 /* Calculate the checksum digits that are appended to the end of the LMOTS digit
  * string. See NIST SP800-208 section 3.1 or RFC8554 Algorithm 2 for details of
  * the checksum algorithm.
@@ -197,8 +168,7 @@ static int create_digit_array_with_checksum(const mbedtls_lmots_parameters_t *pa
     }
 
     checksum = lmots_checksum_calculate(params, out);
-    mbedtls_lms_unsigned_int_to_network_bytes(checksum, CHECKSUM_LEN,
-                                              out + MBEDTLS_LMOTS_N_HASH_LEN(params->type));
+    MBEDTLS_PUT_UINT16_BE(checksum, out, MBEDTLS_LMOTS_N_HASH_LEN(params->type));
 
 exit:
     psa_hash_abort(&op);
@@ -287,17 +257,13 @@ static int hash_digit_array(const mbedtls_lmots_parameters_t *params,
                 goto exit;
             }
 
-            mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx,
-                                                      I_DIGIT_IDX_LEN,
-                                                      i_digit_idx_bytes);
+            MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
             status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
             if (status != PSA_SUCCESS) {
                 goto exit;
             }
 
-            mbedtls_lms_unsigned_int_to_network_bytes(j_hash_idx,
-                                                      J_HASH_IDX_LEN,
-                                                      j_hash_idx_bytes);
+            j_hash_idx_bytes[0] = (uint8_t) j_hash_idx;
             status = psa_hash_update(&op, j_hash_idx_bytes, J_HASH_IDX_LEN);
             if (status != PSA_SUCCESS) {
                 goto exit;
@@ -421,6 +387,10 @@ void mbedtls_lmots_public_init(mbedtls_lmots_public_t *ctx)
 
 void mbedtls_lmots_public_free(mbedtls_lmots_public_t *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_platform_zeroize(ctx, sizeof(*ctx));
 }
 
@@ -431,9 +401,8 @@ int mbedtls_lmots_import_public_key(mbedtls_lmots_public_t *ctx,
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
 
-    ctx->params.type =
-        mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
-                                                  key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+    ctx->params.type = (mbedtls_lmots_algorithm_type_t)
+                       MBEDTLS_GET_UINT32_BE(key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 
     if (key_len != MBEDTLS_LMOTS_PUBLIC_KEY_LEN(ctx->params.type)) {
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
@@ -468,9 +437,7 @@ int mbedtls_lmots_export_public_key(const mbedtls_lmots_public_t *ctx,
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
-                                              MBEDTLS_LMOTS_TYPE_LEN,
-                                              key + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 
     memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
            ctx->params.I_key_identifier,
@@ -563,9 +530,7 @@ int mbedtls_lmots_verify(const mbedtls_lmots_public_t *ctx,
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
 
-    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
-                                                  sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET) !=
-        MBEDTLS_LMOTS_SHA256_N32_W8) {
+    if (MBEDTLS_GET_UINT32_BE(sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET) != MBEDTLS_LMOTS_SHA256_N32_W8) {
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
 
@@ -595,6 +560,10 @@ void mbedtls_lmots_private_init(mbedtls_lmots_private_t *ctx)
 
 void mbedtls_lmots_private_free(mbedtls_lmots_private_t *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_platform_zeroize(ctx,
                              sizeof(*ctx));
 }
@@ -611,7 +580,7 @@ int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
     size_t output_hash_len;
     unsigned int i_digit_idx;
     unsigned char i_digit_idx_bytes[2];
-    unsigned char const_bytes[1];
+    unsigned char const_bytes[1] = { 0xFF };
 
     if (ctx->have_private_key) {
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
@@ -627,12 +596,7 @@ int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
            I_key_identifier,
            sizeof(ctx->params.I_key_identifier));
 
-    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
-                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
-                                              ctx->params.q_leaf_identifier);
-
-    mbedtls_lms_unsigned_int_to_network_bytes(0xFF, sizeof(const_bytes),
-                                              const_bytes);
+    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ctx->params.q_leaf_identifier, 0);
 
     for (i_digit_idx = 0;
          i_digit_idx < MBEDTLS_LMOTS_P_SIG_DIGIT_COUNT(ctx->params.type);
@@ -656,8 +620,7 @@ int mbedtls_lmots_generate_private_key(mbedtls_lmots_private_t *ctx,
             goto exit;
         }
 
-        mbedtls_lms_unsigned_int_to_network_bytes(i_digit_idx, I_DIGIT_IDX_LEN,
-                                                  i_digit_idx_bytes);
+        MBEDTLS_PUT_UINT16_BE(i_digit_idx, i_digit_idx_bytes, 0);
         status = psa_hash_update(&op, i_digit_idx_bytes, I_DIGIT_IDX_LEN);
         if (status != PSA_SUCCESS) {
             goto exit;
@@ -778,9 +741,7 @@ int mbedtls_lmots_sign(mbedtls_lmots_private_t *ctx,
         goto exit;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
-                                              MBEDTLS_LMOTS_TYPE_LEN,
-                                              sig + MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
+    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, MBEDTLS_LMOTS_SIG_TYPE_OFFSET);
 
     /* Test hook to check if sig is being written to before we invalidate the
      * private key.
diff --git a/lib/libmbedtls/mbedtls/library/lmots.h b/lib/libmbedtls/mbedtls/library/lmots.h
index 98d1941d5343d13149887e53e4b4080ac47bb5a6..cf92d326c987b5abe869176d8923f50b74683f4f 100644
--- a/lib/libmbedtls/mbedtls/library/lmots.h
+++ b/lib/libmbedtls/mbedtls/library/lmots.h
@@ -8,19 +8,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_LMOTS_H
@@ -56,29 +44,6 @@ extern "C" {
 extern int (*mbedtls_lmots_sign_private_key_invalidated_hook)(unsigned char *);
 #endif /* defined(MBEDTLS_TEST_HOOKS) */
 
-/**
- * \brief                    This function converts an unsigned int into a
- *                           network-byte-order (big endian) string.
- *
- * \param val                The unsigned integer value
- * \param len                The length of the string.
- * \param bytes              The string to output into.
- */
-void mbedtls_lms_unsigned_int_to_network_bytes(unsigned int val, size_t len,
-                                               unsigned char *bytes);
-
-/**
- * \brief                    This function converts a network-byte-order
- *                           (big endian) string into an unsigned integer.
- *
- * \param len                The length of the string.
- * \param bytes              The string.
- *
- * \return                   The corresponding LMS error code.
- */
-unsigned int mbedtls_lms_network_bytes_to_unsigned_int(size_t len,
-                                                       const unsigned char *bytes);
-
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 /**
  * \brief                    This function converts a \ref psa_status_t to a
diff --git a/lib/libmbedtls/mbedtls/library/lms.c b/lib/libmbedtls/mbedtls/library/lms.c
index acc35233145807667a7d2620f1a22b35b618aad6..7f7bec068b4a717f287a69eb22716b2e84526282 100644
--- a/lib/libmbedtls/mbedtls/library/lms.c
+++ b/lib/libmbedtls/mbedtls/library/lms.c
@@ -2,19 +2,7 @@
  *  The LMS stateful-hash public-key signature scheme
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -39,16 +27,22 @@
 #include "lmots.h"
 
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 #include "mbedtls/lms.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 
 #include "mbedtls/platform.h"
 
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_lms_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_lms_errors,
+                                 ARRAY_LENGTH(psa_to_lms_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 
 #define SIG_Q_LEAF_ID_OFFSET     (0)
 #define SIG_OTS_SIG_OFFSET       (SIG_Q_LEAF_ID_OFFSET + \
@@ -71,7 +65,8 @@
 #define H_TREE_HEIGHT_MAX                  10
 #define MERKLE_TREE_NODE_AM(type)          ((size_t) 1 << (MBEDTLS_LMS_H_TREE_HEIGHT(type) + 1u))
 #define MERKLE_TREE_LEAF_NODE_AM(type)     ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
-#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((size_t) 1 << MBEDTLS_LMS_H_TREE_HEIGHT(type))
+#define MERKLE_TREE_INTERNAL_NODE_AM(type) ((unsigned int) \
+                                            (1u << MBEDTLS_LMS_H_TREE_HEIGHT(type)))
 
 #define D_CONST_LEN           (2)
 static const unsigned char D_LEAF_CONSTANT_BYTES[D_CONST_LEN] = { 0x82, 0x82 };
@@ -118,7 +113,7 @@ static int create_merkle_leaf_value(const mbedtls_lms_parameters_t *params,
         goto exit;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes);
+    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
     status = psa_hash_update(&op, r_node_idx_bytes, 4);
     if (status != PSA_SUCCESS) {
         goto exit;
@@ -192,7 +187,7 @@ static int create_merkle_internal_value(const mbedtls_lms_parameters_t *params,
         goto exit;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(r_node_idx, 4, r_node_idx_bytes);
+    MBEDTLS_PUT_UINT32_BE(r_node_idx, r_node_idx_bytes, 0);
     status = psa_hash_update(&op, r_node_idx_bytes, 4);
     if (status != PSA_SUCCESS) {
         goto exit;
@@ -234,6 +229,10 @@ void mbedtls_lms_public_init(mbedtls_lms_public_t *ctx)
 
 void mbedtls_lms_public_free(mbedtls_lms_public_t *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_platform_zeroize(ctx, sizeof(*ctx));
 }
 
@@ -243,8 +242,7 @@ int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
     mbedtls_lms_algorithm_type_t type;
     mbedtls_lmots_algorithm_type_t otstype;
 
-    type = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN,
-                                                     key + PUBLIC_KEY_TYPE_OFFSET);
+    type = (mbedtls_lms_algorithm_type_t) MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_TYPE_OFFSET);
     if (type != MBEDTLS_LMS_SHA256_M32_H10) {
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
@@ -254,8 +252,8 @@ int mbedtls_lms_import_public_key(mbedtls_lms_public_t *ctx,
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
 
-    otstype = mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
-                                                        key + PUBLIC_KEY_OTSTYPE_OFFSET);
+    otstype = (mbedtls_lmots_algorithm_type_t)
+              MBEDTLS_GET_UINT32_BE(key, PUBLIC_KEY_OTSTYPE_OFFSET);
     if (otstype != MBEDTLS_LMOTS_SHA256_N32_W8) {
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
@@ -284,12 +282,8 @@ int mbedtls_lms_export_public_key(const mbedtls_lms_public_t *ctx,
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(
-        ctx->params.type,
-        MBEDTLS_LMS_TYPE_LEN, key + PUBLIC_KEY_TYPE_OFFSET);
-    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.otstype,
-                                              MBEDTLS_LMOTS_TYPE_LEN,
-                                              key + PUBLIC_KEY_OTSTYPE_OFFSET);
+    MBEDTLS_PUT_UINT32_BE(ctx->params.type, key, PUBLIC_KEY_TYPE_OFFSET);
+    MBEDTLS_PUT_UINT32_BE(ctx->params.otstype, key, PUBLIC_KEY_OTSTYPE_OFFSET);
     memcpy(key + PUBLIC_KEY_I_KEY_ID_OFFSET,
            ctx->params.I_key_identifier,
            MBEDTLS_LMOTS_I_KEY_ID_LEN);
@@ -341,9 +335,7 @@ int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
 
-    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMOTS_TYPE_LEN,
-                                                  sig + SIG_OTS_SIG_OFFSET +
-                                                  MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
+    if (MBEDTLS_GET_UINT32_BE(sig, SIG_OTS_SIG_OFFSET + MBEDTLS_LMOTS_SIG_TYPE_OFFSET)
         != MBEDTLS_LMOTS_SHA256_N32_W8) {
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
@@ -352,15 +344,13 @@ int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
 
-    if (mbedtls_lms_network_bytes_to_unsigned_int(MBEDTLS_LMS_TYPE_LEN,
-                                                  sig + SIG_TYPE_OFFSET(ctx->params.otstype))
+    if (MBEDTLS_GET_UINT32_BE(sig, SIG_TYPE_OFFSET(ctx->params.otstype))
         != MBEDTLS_LMS_SHA256_M32_H10) {
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
     }
 
 
-    q_leaf_identifier = mbedtls_lms_network_bytes_to_unsigned_int(
-        MBEDTLS_LMOTS_Q_LEAF_ID_LEN, sig + SIG_Q_LEAF_ID_OFFSET);
+    q_leaf_identifier = MBEDTLS_GET_UINT32_BE(sig, SIG_Q_LEAF_ID_OFFSET);
 
     if (q_leaf_identifier >= MERKLE_TREE_LEAF_NODE_AM(ctx->params.type)) {
         return MBEDTLS_ERR_LMS_VERIFY_FAILED;
@@ -369,9 +359,7 @@ int mbedtls_lms_verify(const mbedtls_lms_public_t *ctx,
     memcpy(ots_params.I_key_identifier,
            ctx->params.I_key_identifier,
            MBEDTLS_LMOTS_I_KEY_ID_LEN);
-    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
-                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
-                                              ots_params.q_leaf_identifier);
+    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, ots_params.q_leaf_identifier, 0);
     ots_params.type = ctx->params.otstype;
 
     ret = mbedtls_lmots_calculate_public_key_candidate(&ots_params,
@@ -507,7 +495,7 @@ static int get_merkle_path(mbedtls_lms_private_t *ctx,
     unsigned int height;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(ctx->params.type),
+    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(ctx->params.type),
                           node_bytes);
     if (tree == NULL) {
         return MBEDTLS_ERR_LMS_ALLOC_FAILED;
@@ -531,9 +519,8 @@ static int get_merkle_path(mbedtls_lms_private_t *ctx,
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize(tree, node_bytes *
-                             MERKLE_TREE_NODE_AM(ctx->params.type));
-    mbedtls_free(tree);
+    mbedtls_zeroize_and_free(tree, node_bytes *
+                             (size_t) MERKLE_TREE_NODE_AM(ctx->params.type));
 
     return ret;
 }
@@ -545,6 +532,10 @@ void mbedtls_lms_private_init(mbedtls_lms_private_t *ctx)
 
 void mbedtls_lms_private_free(mbedtls_lms_private_t *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     unsigned int idx;
 
     if (ctx->have_private_key) {
@@ -672,7 +663,7 @@ int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
         return MBEDTLS_ERR_LMS_BAD_INPUT_DATA;
     }
 
-    tree = mbedtls_calloc(MERKLE_TREE_NODE_AM(priv_ctx->params.type),
+    tree = mbedtls_calloc((size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type),
                           node_bytes);
     if (tree == NULL) {
         return MBEDTLS_ERR_LMS_ALLOC_FAILED;
@@ -694,9 +685,8 @@ int mbedtls_lms_calculate_public_key(mbedtls_lms_public_t *ctx,
     ret = 0;
 
 exit:
-    mbedtls_platform_zeroize(tree, node_bytes *
-                             MERKLE_TREE_NODE_AM(priv_ctx->params.type));
-    mbedtls_free(tree);
+    mbedtls_zeroize_and_free(tree, node_bytes *
+                             (size_t) MERKLE_TREE_NODE_AM(priv_ctx->params.type));
 
     return ret;
 }
@@ -757,12 +747,8 @@ int mbedtls_lms_sign(mbedtls_lms_private_t *ctx,
         return ret;
     }
 
-    mbedtls_lms_unsigned_int_to_network_bytes(ctx->params.type,
-                                              MBEDTLS_LMS_TYPE_LEN,
-                                              sig + SIG_TYPE_OFFSET(ctx->params.otstype));
-    mbedtls_lms_unsigned_int_to_network_bytes(q_leaf_identifier,
-                                              MBEDTLS_LMOTS_Q_LEAF_ID_LEN,
-                                              sig + SIG_Q_LEAF_ID_OFFSET);
+    MBEDTLS_PUT_UINT32_BE(ctx->params.type, sig, SIG_TYPE_OFFSET(ctx->params.otstype));
+    MBEDTLS_PUT_UINT32_BE(q_leaf_identifier, sig, SIG_Q_LEAF_ID_OFFSET);
 
     ret = get_merkle_path(ctx,
                           MERKLE_TREE_INTERNAL_NODE_AM(ctx->params.type) + q_leaf_identifier,
diff --git a/lib/libmbedtls/mbedtls/library/md.c b/lib/libmbedtls/mbedtls/library/md.c
index 89295de755cf3eebc1f4a6f72faff26a0eeec4e8..f263dcbda673bc7ae29a5dcd8805f3e4436d43c0 100644
--- a/lib/libmbedtls/mbedtls/library/md.c
+++ b/lib/libmbedtls/mbedtls/library/md.c
@@ -1,24 +1,12 @@
 /**
  * \file md.c
  *
- * \brief Generic message digest wrapper for mbed TLS
+ * \brief Generic message digest wrapper for Mbed TLS
  *
  * \author Adriaan de Jong <dejong@fox-it.com>
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -51,9 +39,15 @@
 #include "mbedtls/sha1.h"
 #include "mbedtls/sha256.h"
 #include "mbedtls/sha512.h"
+#include "mbedtls/sha3.h"
 
-#if defined(MBEDTLS_MD_SOME_PSA)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
 #include <psa/crypto.h>
+#include "md_psa.h"
+#include "psa_util_internal.h"
+#endif
+
+#if defined(MBEDTLS_MD_SOME_PSA)
 #include "psa_crypto_core.h"
 #endif
 
@@ -65,66 +59,80 @@
 #include <stdio.h>
 #endif
 
+/* See comment above MBEDTLS_MD_MAX_SIZE in md.h */
+#if defined(MBEDTLS_PSA_CRYPTO_C) && MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE
+#error "Internal error: MBEDTLS_MD_MAX_SIZE < PSA_HASH_MAX_SIZE"
+#endif
+
+#if defined(MBEDTLS_MD_C)
+#define MD_INFO(type, out_size, block_size) type, out_size, block_size,
+#else
+#define MD_INFO(type, out_size, block_size) type, out_size,
+#endif
+
 #if defined(MBEDTLS_MD_CAN_MD5)
-const mbedtls_md_info_t mbedtls_md5_info = {
-    "MD5",
-    MBEDTLS_MD_MD5,
-    16,
-    64,
+static const mbedtls_md_info_t mbedtls_md5_info = {
+    MD_INFO(MBEDTLS_MD_MD5, 16, 64)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_RIPEMD160)
-const mbedtls_md_info_t mbedtls_ripemd160_info = {
-    "RIPEMD160",
-    MBEDTLS_MD_RIPEMD160,
-    20,
-    64,
+static const mbedtls_md_info_t mbedtls_ripemd160_info = {
+    MD_INFO(MBEDTLS_MD_RIPEMD160, 20, 64)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_SHA1)
-const mbedtls_md_info_t mbedtls_sha1_info = {
-    "SHA1",
-    MBEDTLS_MD_SHA1,
-    20,
-    64,
+static const mbedtls_md_info_t mbedtls_sha1_info = {
+    MD_INFO(MBEDTLS_MD_SHA1, 20, 64)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_SHA224)
-const mbedtls_md_info_t mbedtls_sha224_info = {
-    "SHA224",
-    MBEDTLS_MD_SHA224,
-    28,
-    64,
+static const mbedtls_md_info_t mbedtls_sha224_info = {
+    MD_INFO(MBEDTLS_MD_SHA224, 28, 64)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_SHA256)
-const mbedtls_md_info_t mbedtls_sha256_info = {
-    "SHA256",
-    MBEDTLS_MD_SHA256,
-    32,
-    64,
+static const mbedtls_md_info_t mbedtls_sha256_info = {
+    MD_INFO(MBEDTLS_MD_SHA256, 32, 64)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_SHA384)
-const mbedtls_md_info_t mbedtls_sha384_info = {
-    "SHA384",
-    MBEDTLS_MD_SHA384,
-    48,
-    128,
+static const mbedtls_md_info_t mbedtls_sha384_info = {
+    MD_INFO(MBEDTLS_MD_SHA384, 48, 128)
 };
 #endif
 
 #if defined(MBEDTLS_MD_CAN_SHA512)
-const mbedtls_md_info_t mbedtls_sha512_info = {
-    "SHA512",
-    MBEDTLS_MD_SHA512,
-    64,
-    128,
+static const mbedtls_md_info_t mbedtls_sha512_info = {
+    MD_INFO(MBEDTLS_MD_SHA512, 64, 128)
+};
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+static const mbedtls_md_info_t mbedtls_sha3_224_info = {
+    MD_INFO(MBEDTLS_MD_SHA3_224, 28, 144)
+};
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+static const mbedtls_md_info_t mbedtls_sha3_256_info = {
+    MD_INFO(MBEDTLS_MD_SHA3_256, 32, 136)
+};
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+static const mbedtls_md_info_t mbedtls_sha3_384_info = {
+    MD_INFO(MBEDTLS_MD_SHA3_384, 48, 104)
+};
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+static const mbedtls_md_info_t mbedtls_sha3_512_info = {
+    MD_INFO(MBEDTLS_MD_SHA3_512, 64, 72)
 };
 #endif
 
@@ -158,6 +166,22 @@ const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
 #if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_MD_SHA512:
             return &mbedtls_sha512_info;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+        case MBEDTLS_MD_SHA3_224:
+            return &mbedtls_sha3_224_info;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+        case MBEDTLS_MD_SHA3_256:
+            return &mbedtls_sha3_256_info;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+        case MBEDTLS_MD_SHA3_384:
+            return &mbedtls_sha3_384_info;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+        case MBEDTLS_MD_SHA3_512:
+            return &mbedtls_sha3_512_info;
 #endif
         default:
             return NULL;
@@ -195,6 +219,22 @@ static psa_algorithm_t psa_alg_of_md(const mbedtls_md_info_t *info)
 #if defined(MBEDTLS_MD_SHA512_VIA_PSA)
         case MBEDTLS_MD_SHA512:
             return PSA_ALG_SHA_512;
+#endif
+#if defined(MBEDTLS_MD_SHA3_224_VIA_PSA)
+        case MBEDTLS_MD_SHA3_224:
+            return PSA_ALG_SHA3_224;
+#endif
+#if defined(MBEDTLS_MD_SHA3_256_VIA_PSA)
+        case MBEDTLS_MD_SHA3_256:
+            return PSA_ALG_SHA3_256;
+#endif
+#if defined(MBEDTLS_MD_SHA3_384_VIA_PSA)
+        case MBEDTLS_MD_SHA3_384:
+            return PSA_ALG_SHA3_384;
+#endif
+#if defined(MBEDTLS_MD_SHA3_512_VIA_PSA)
+        case MBEDTLS_MD_SHA3_512:
+            return PSA_ALG_SHA3_512;
 #endif
         default:
             return PSA_ALG_NONE;
@@ -210,20 +250,6 @@ static int md_can_use_psa(const mbedtls_md_info_t *info)
 
     return psa_can_do_hash(alg);
 }
-
-static int mbedtls_md_error_from_psa(psa_status_t status)
-{
-    switch (status) {
-        case PSA_SUCCESS:
-            return 0;
-        case PSA_ERROR_NOT_SUPPORTED:
-            return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_INSUFFICIENT_MEMORY:
-            return MBEDTLS_ERR_MD_ALLOC_FAILED;
-        default:
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-    }
-}
 #endif /* MBEDTLS_MD_SOME_PSA */
 
 void mbedtls_md_init(mbedtls_md_context_t *ctx)
@@ -279,6 +305,14 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx)
             case MBEDTLS_MD_SHA512:
                 mbedtls_sha512_free(ctx->md_ctx);
                 break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+            case MBEDTLS_MD_SHA3_224:
+            case MBEDTLS_MD_SHA3_256:
+            case MBEDTLS_MD_SHA3_384:
+            case MBEDTLS_MD_SHA3_512:
+                mbedtls_sha3_free(ctx->md_ctx);
+                break;
 #endif
             default:
                 /* Shouldn't happen */
@@ -289,9 +323,8 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx)
 
 #if defined(MBEDTLS_MD_C)
     if (ctx->hmac_ctx != NULL) {
-        mbedtls_platform_zeroize(ctx->hmac_ctx,
+        mbedtls_zeroize_and_free(ctx->hmac_ctx,
                                  2 * ctx->md_info->block_size);
-        mbedtls_free(ctx->hmac_ctx);
     }
 #endif
 
@@ -357,6 +390,14 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst,
         case MBEDTLS_MD_SHA512:
             mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);
             break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+        case MBEDTLS_MD_SHA3_256:
+        case MBEDTLS_MD_SHA3_384:
+        case MBEDTLS_MD_SHA3_512:
+            mbedtls_sha3_clone(dst->md_ctx, src->md_ctx);
+            break;
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -379,7 +420,12 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst,
 
 int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac)
 {
-    if (md_info == NULL || ctx == NULL) {
+#if defined(MBEDTLS_MD_C)
+    if (ctx == NULL) {
+        return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+    }
+#endif
+    if (md_info == NULL) {
         return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
 
@@ -437,6 +483,14 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info
         case MBEDTLS_MD_SHA512:
             ALLOC(sha512);
             break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+        case MBEDTLS_MD_SHA3_256:
+        case MBEDTLS_MD_SHA3_384:
+        case MBEDTLS_MD_SHA3_512:
+            ALLOC(sha3);
+            break;
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -458,9 +512,11 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info
 
 int mbedtls_md_starts(mbedtls_md_context_t *ctx)
 {
+#if defined(MBEDTLS_MD_C)
     if (ctx == NULL || ctx->md_info == NULL) {
         return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
+#endif
 
 #if defined(MBEDTLS_MD_SOME_PSA)
     if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
@@ -499,6 +555,16 @@ int mbedtls_md_starts(mbedtls_md_context_t *ctx)
 #if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_MD_SHA512:
             return mbedtls_sha512_starts(ctx->md_ctx, 0);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224);
+        case MBEDTLS_MD_SHA3_256:
+            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256);
+        case MBEDTLS_MD_SHA3_384:
+            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384);
+        case MBEDTLS_MD_SHA3_512:
+            return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512);
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -507,9 +573,11 @@ int mbedtls_md_starts(mbedtls_md_context_t *ctx)
 
 int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen)
 {
+#if defined(MBEDTLS_MD_C)
     if (ctx == NULL || ctx->md_info == NULL) {
         return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
+#endif
 
 #if defined(MBEDTLS_MD_SOME_PSA)
     if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
@@ -546,6 +614,13 @@ int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, siz
 #if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_MD_SHA512:
             return mbedtls_sha512_update(ctx->md_ctx, input, ilen);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+        case MBEDTLS_MD_SHA3_256:
+        case MBEDTLS_MD_SHA3_384:
+        case MBEDTLS_MD_SHA3_512:
+            return mbedtls_sha3_update(ctx->md_ctx, input, ilen);
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -554,9 +629,11 @@ int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, siz
 
 int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output)
 {
+#if defined(MBEDTLS_MD_C)
     if (ctx == NULL || ctx->md_info == NULL) {
         return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
     }
+#endif
 
 #if defined(MBEDTLS_MD_SOME_PSA)
     if (ctx->engine == MBEDTLS_MD_ENGINE_PSA) {
@@ -595,6 +672,13 @@ int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output)
 #if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_MD_SHA512:
             return mbedtls_sha512_finish(ctx->md_ctx, output);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+        case MBEDTLS_MD_SHA3_256:
+        case MBEDTLS_MD_SHA3_384:
+        case MBEDTLS_MD_SHA3_512:
+            return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size);
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -646,6 +730,16 @@ int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, siz
 #if defined(MBEDTLS_SHA512_C)
         case MBEDTLS_MD_SHA512:
             return mbedtls_sha512(input, ilen, output, 0);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+        case MBEDTLS_MD_SHA3_224:
+            return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size);
+        case MBEDTLS_MD_SHA3_256:
+            return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size);
+        case MBEDTLS_MD_SHA3_384:
+            return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size);
+        case MBEDTLS_MD_SHA3_512:
+            return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size);
 #endif
         default:
             return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -670,6 +764,15 @@ mbedtls_md_type_t mbedtls_md_get_type(const mbedtls_md_info_t *md_info)
     return md_info->type;
 }
 
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+int mbedtls_md_error_from_psa(psa_status_t status)
+{
+    return PSA_TO_MBEDTLS_ERR_LIST(status, psa_to_md_errors,
+                                   psa_generic_status_to_mbedtls);
+}
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
+
 /************************************************************************
  * Functions above this separator are part of MBEDTLS_MD_LIGHT,         *
  * functions below are only available when MBEDTLS_MD_C is set.         *
@@ -708,6 +811,22 @@ static const int supported_digests[] = {
     MBEDTLS_MD_MD5,
 #endif
 
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+    MBEDTLS_MD_SHA3_224,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+    MBEDTLS_MD_SHA3_256,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+    MBEDTLS_MD_SHA3_384,
+#endif
+
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+    MBEDTLS_MD_SHA3_512,
+#endif
+
     MBEDTLS_MD_NONE
 };
 
@@ -716,49 +835,77 @@ const int *mbedtls_md_list(void)
     return supported_digests;
 }
 
-const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
-{
-    if (NULL == md_name) {
-        return NULL;
-    }
+typedef struct {
+    const char *md_name;
+    mbedtls_md_type_t md_type;
+} md_name_entry;
 
-    /* Get the appropriate digest information */
+static const md_name_entry md_names[] = {
 #if defined(MBEDTLS_MD_CAN_MD5)
-    if (!strcmp("MD5", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_MD5);
-    }
+    { "MD5", MBEDTLS_MD_MD5 },
 #endif
 #if defined(MBEDTLS_MD_CAN_RIPEMD160)
-    if (!strcmp("RIPEMD160", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160);
-    }
+    { "RIPEMD160", MBEDTLS_MD_RIPEMD160 },
 #endif
 #if defined(MBEDTLS_MD_CAN_SHA1)
-    if (!strcmp("SHA1", md_name) || !strcmp("SHA", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
-    }
+    { "SHA1", MBEDTLS_MD_SHA1 },
+    { "SHA", MBEDTLS_MD_SHA1 }, // compatibility fallback
 #endif
 #if defined(MBEDTLS_MD_CAN_SHA224)
-    if (!strcmp("SHA224", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA224);
-    }
+    { "SHA224", MBEDTLS_MD_SHA224 },
 #endif
 #if defined(MBEDTLS_MD_CAN_SHA256)
-    if (!strcmp("SHA256", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
-    }
+    { "SHA256", MBEDTLS_MD_SHA256 },
 #endif
 #if defined(MBEDTLS_MD_CAN_SHA384)
-    if (!strcmp("SHA384", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
-    }
+    { "SHA384", MBEDTLS_MD_SHA384 },
 #endif
 #if defined(MBEDTLS_MD_CAN_SHA512)
-    if (!strcmp("SHA512", md_name)) {
-        return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
-    }
+    { "SHA512", MBEDTLS_MD_SHA512 },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+    { "SHA3-224", MBEDTLS_MD_SHA3_224 },
 #endif
-    return NULL;
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+    { "SHA3-256", MBEDTLS_MD_SHA3_256 },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+    { "SHA3-384", MBEDTLS_MD_SHA3_384 },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+    { "SHA3-512", MBEDTLS_MD_SHA3_512 },
+#endif
+    { NULL, MBEDTLS_MD_NONE },
+};
+
+const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
+{
+    if (NULL == md_name) {
+        return NULL;
+    }
+
+    const md_name_entry *entry = md_names;
+    while (entry->md_name != NULL &&
+           strcmp(entry->md_name, md_name) != 0) {
+        ++entry;
+    }
+
+    return mbedtls_md_info_from_type(entry->md_type);
+}
+
+const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info)
+{
+    if (md_info == NULL) {
+        return NULL;
+    }
+
+    const md_name_entry *entry = md_names;
+    while (entry->md_type != MBEDTLS_MD_NONE &&
+           entry->md_type != md_info->type) {
+        ++entry;
+    }
+
+    return entry->md_name;
 }
 
 const mbedtls_md_info_t *mbedtls_md_info_from_ctx(
@@ -959,15 +1106,6 @@ cleanup:
     return ret;
 }
 
-const char *mbedtls_md_get_name(const mbedtls_md_info_t *md_info)
-{
-    if (md_info == NULL) {
-        return NULL;
-    }
-
-    return md_info->name;
-}
-
 #endif /* MBEDTLS_MD_C */
 
 #endif /* MBEDTLS_MD_LIGHT */
diff --git a/lib/libmbedtls/mbedtls/library/md5.c b/lib/libmbedtls/mbedtls/library/md5.c
index 138a3205734d5e8f7726831f6a28b30706d431a7..e4a87a2e093d08e733032b3a890fea7a6688a2bb 100644
--- a/lib/libmbedtls/mbedtls/library/md5.c
+++ b/lib/libmbedtls/mbedtls/library/md5.c
@@ -2,19 +2,7 @@
  *  RFC 1321 compliant MD5 implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The MD5 algorithm was designed by Ron Rivest in 1991.
@@ -286,7 +274,7 @@ int mbedtls_md5_finish(mbedtls_md5_context *ctx,
         memset(ctx->buffer + used, 0, 64 - used);
 
         if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
-            return ret;
+            goto exit;
         }
 
         memset(ctx->buffer, 0, 56);
@@ -303,7 +291,7 @@ int mbedtls_md5_finish(mbedtls_md5_context *ctx,
     MBEDTLS_PUT_UINT32_LE(high, ctx->buffer, 60);
 
     if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) {
-        return ret;
+        goto exit;
     }
 
     /*
@@ -314,7 +302,11 @@ int mbedtls_md5_finish(mbedtls_md5_context *ctx,
     MBEDTLS_PUT_UINT32_LE(ctx->state[2], output,  8);
     MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
 
-    return 0;
+    ret = 0;
+
+exit:
+    mbedtls_md5_free(ctx);
+    return ret;
 }
 
 #endif /* !MBEDTLS_MD5_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/md_psa.h b/lib/libmbedtls/mbedtls/library/md_psa.h
new file mode 100644
index 0000000000000000000000000000000000000000..028ba2409cd516d30c2bfcc3f9c8c6e9d9e1b545
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/md_psa.h
@@ -0,0 +1,26 @@
+/**
+ * Translation between MD and PSA identifiers (algorithms, errors).
+ *
+ *  Note: this internal module will go away when everything becomes based on
+ *  PSA Crypto; it is a helper for the transition period.
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_MD_PSA_H
+#define MBEDTLS_MD_PSA_H
+
+#include "common.h"
+
+#include "mbedtls/md.h"
+#include "psa/crypto.h"
+
+/** Convert PSA status to MD error code.
+ *
+ * \param status    PSA status.
+ *
+ * \return          The corresponding MD error code,
+ */
+int mbedtls_md_error_from_psa(psa_status_t status);
+
+#endif /* MBEDTLS_MD_PSA_H */
diff --git a/lib/libmbedtls/mbedtls/library/md_wrap.h b/lib/libmbedtls/mbedtls/library/md_wrap.h
index cd539b54be32d45d01672734c349e18858821fdd..dad123540a1d9497f47198383b9a6116ed1f95e5 100644
--- a/lib/libmbedtls/mbedtls/library/md_wrap.h
+++ b/lib/libmbedtls/mbedtls/library/md_wrap.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_MD_WRAP_H
 #define MBEDTLS_MD_WRAP_H
@@ -39,40 +27,17 @@ extern "C" {
  * Allows message digest functions to be called in a generic way.
  */
 struct mbedtls_md_info_t {
-    /** Name of the message digest */
-    const char *name;
-
     /** Digest identifier */
     mbedtls_md_type_t type;
 
     /** Output length of the digest function in bytes */
     unsigned char size;
 
+#if defined(MBEDTLS_MD_C)
     /** Block length of the digest function in bytes */
     unsigned char block_size;
-};
-
-#if defined(MBEDTLS_MD5_C)
-extern const mbedtls_md_info_t mbedtls_md5_info;
-#endif
-#if defined(MBEDTLS_RIPEMD160_C)
-extern const mbedtls_md_info_t mbedtls_ripemd160_info;
-#endif
-#if defined(MBEDTLS_SHA1_C)
-extern const mbedtls_md_info_t mbedtls_sha1_info;
-#endif
-#if defined(MBEDTLS_SHA224_C)
-extern const mbedtls_md_info_t mbedtls_sha224_info;
-#endif
-#if defined(MBEDTLS_SHA256_C)
-extern const mbedtls_md_info_t mbedtls_sha256_info;
-#endif
-#if defined(MBEDTLS_SHA384_C)
-extern const mbedtls_md_info_t mbedtls_sha384_info;
-#endif
-#if defined(MBEDTLS_SHA512_C)
-extern const mbedtls_md_info_t mbedtls_sha512_info;
 #endif
+};
 
 #ifdef __cplusplus
 }
diff --git a/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c b/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
index e5052ce5ac383c3c9922291e65e52e3901e81960..79b0a8b8fa975b6c960702c7a84b1dfbe2654bdc 100644
--- a/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
+++ b/lib/libmbedtls/mbedtls/library/memory_buffer_alloc.c
@@ -2,19 +2,7 @@
  *  Buffer-based memory allocator
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
diff --git a/lib/libmbedtls/mbedtls/library/net_sockets.c b/lib/libmbedtls/mbedtls/library/net_sockets.c
index e63d08b15dda887e3a62528f43505b64b7bbc99f..ef89a88ef05ecc25905f5c7a070d99bdd6a66f9e 100644
--- a/lib/libmbedtls/mbedtls/library/net_sockets.c
+++ b/lib/libmbedtls/mbedtls/library/net_sockets.c
@@ -2,19 +2,7 @@
  *  TCP/IP or UDP/IP networking functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /* Enable definition of getaddrinfo() even when compiling with -std=c99. Must
@@ -49,11 +37,6 @@
 
 #define IS_EINTR(ret) ((ret) == WSAEINTR)
 
-#if !defined(_WIN32_WINNT)
-/* Enables getaddrinfo() & Co */
-#define _WIN32_WINNT 0x0501
-#endif
-
 #include <ws2tcpip.h>
 
 #include <winsock2.h>
@@ -90,6 +73,7 @@ static int wsa_init_done = 0;
 #include <errno.h>
 
 #define IS_EINTR(ret) ((ret) == EINTR)
+#define SOCKET int
 
 #endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */
 
@@ -332,7 +316,7 @@ static int net_would_block(const mbedtls_net_context *ctx)
  */
 int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
                        mbedtls_net_context *client_ctx,
-                       void *client_ip, size_t buf_size, size_t *ip_len)
+                       void *client_ip, size_t buf_size, size_t *cip_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int type;
@@ -415,22 +399,22 @@ int mbedtls_net_accept(mbedtls_net_context *bind_ctx,
     if (client_ip != NULL) {
         if (client_addr.ss_family == AF_INET) {
             struct sockaddr_in *addr4 = (struct sockaddr_in *) &client_addr;
-            *ip_len = sizeof(addr4->sin_addr.s_addr);
+            *cip_len = sizeof(addr4->sin_addr.s_addr);
 
-            if (buf_size < *ip_len) {
+            if (buf_size < *cip_len) {
                 return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
             }
 
-            memcpy(client_ip, &addr4->sin_addr.s_addr, *ip_len);
+            memcpy(client_ip, &addr4->sin_addr.s_addr, *cip_len);
         } else {
             struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *) &client_addr;
-            *ip_len = sizeof(addr6->sin6_addr.s6_addr);
+            *cip_len = sizeof(addr6->sin6_addr.s6_addr);
 
-            if (buf_size < *ip_len) {
+            if (buf_size < *cip_len) {
                 return MBEDTLS_ERR_NET_BUFFER_TOO_SMALL;
             }
 
-            memcpy(client_ip, &addr6->sin6_addr.s6_addr, *ip_len);
+            memcpy(client_ip, &addr6->sin6_addr.s6_addr, *cip_len);
         }
     }
 
@@ -494,13 +478,13 @@ int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout)
     FD_ZERO(&read_fds);
     if (rw & MBEDTLS_NET_POLL_READ) {
         rw &= ~MBEDTLS_NET_POLL_READ;
-        FD_SET(fd, &read_fds);
+        FD_SET((SOCKET) fd, &read_fds);
     }
 
     FD_ZERO(&write_fds);
     if (rw & MBEDTLS_NET_POLL_WRITE) {
         rw &= ~MBEDTLS_NET_POLL_WRITE;
-        FD_SET(fd, &write_fds);
+        FD_SET((SOCKET) fd, &write_fds);
     }
 
     if (rw != 0) {
@@ -608,7 +592,7 @@ int mbedtls_net_recv_timeout(void *ctx, unsigned char *buf,
     }
 
     FD_ZERO(&read_fds);
-    FD_SET(fd, &read_fds);
+    FD_SET((SOCKET) fd, &read_fds);
 
     tv.tv_sec  = timeout / 1000;
     tv.tv_usec = (timeout % 1000) * 1000;
@@ -699,7 +683,7 @@ void mbedtls_net_close(mbedtls_net_context *ctx)
  */
 void mbedtls_net_free(mbedtls_net_context *ctx)
 {
-    if (ctx->fd == -1) {
+    if (ctx == NULL || ctx->fd == -1) {
         return;
     }
 
diff --git a/lib/libmbedtls/mbedtls/library/nist_kw.c b/lib/libmbedtls/mbedtls/library/nist_kw.c
index 5817bf4f4c281ed7476a4428bd518f0db99e3fde..8faafe43f1a030184d21dc33197952b3956dc33f 100644
--- a/lib/libmbedtls/mbedtls/library/nist_kw.c
+++ b/lib/libmbedtls/mbedtls/library/nist_kw.c
@@ -3,19 +3,7 @@
  *  only
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * Definition of Key Wrapping:
@@ -35,6 +23,7 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "mbedtls/constant_time.h"
+#include "constant_time_internal.h"
 
 #include <stdint.h>
 #include <string.h>
@@ -75,7 +64,7 @@ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
-    if (cipher_info->block_size != 16) {
+    if (mbedtls_cipher_info_get_block_size(cipher_info) != 16) {
         return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
     }
 
@@ -113,6 +102,10 @@ int mbedtls_nist_kw_setkey(mbedtls_nist_kw_context *ctx,
  */
 void mbedtls_nist_kw_free(mbedtls_nist_kw_context *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_cipher_free(&ctx->cipher_ctx);
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_nist_kw_context));
 }
@@ -333,9 +326,9 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
                            unsigned char *output, size_t *out_len, size_t out_size)
 {
     int ret = 0;
-    size_t i, olen;
+    size_t olen;
     unsigned char A[KW_SEMIBLOCK_LENGTH];
-    unsigned char diff, bad_padding = 0;
+    int diff;
 
     *out_len = 0;
     if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
@@ -420,19 +413,15 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx,
          * larger than 8, because of the type wrap around.
          */
         padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
-        if (padlen > 7) {
-            padlen &= 7;
-            ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
-        }
+        ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7),
+                                  MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret);
+        padlen &= 7;
 
         /* Check padding in "constant-time" */
-        for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
-            if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
-                diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
-            } else {
-                bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
-            }
-        }
+        const uint8_t zero[KW_SEMIBLOCK_LENGTH] = { 0 };
+        diff = mbedtls_ct_memcmp_partial(
+            &output[*out_len - KW_SEMIBLOCK_LENGTH], zero,
+            KW_SEMIBLOCK_LENGTH, KW_SEMIBLOCK_LENGTH - padlen, 0);
 
         if (diff != 0) {
             ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
@@ -454,7 +443,6 @@ cleanup:
         *out_len = 0;
     }
 
-    mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
     mbedtls_platform_zeroize(&diff, sizeof(diff));
     mbedtls_platform_zeroize(A, sizeof(A));
 
@@ -465,17 +453,22 @@ cleanup:
 
 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_AES_C)
 
-#define KW_TESTS 3
-
 /*
  * Test vectors taken from NIST
  * https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#KW
  */
-static const unsigned int key_len[KW_TESTS] = { 16, 24, 32 };
+static const unsigned int key_len[] = {
+    16,
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    24,
+    32
+#endif
+};
 
-static const unsigned char kw_key[KW_TESTS][32] = {
+static const unsigned char kw_key[][32] = {
     { 0x75, 0x75, 0xda, 0x3a, 0x93, 0x60, 0x7c, 0xc2,
       0xbf, 0xd8, 0xce, 0xc7, 0xaa, 0xdf, 0xd9, 0xa6 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x2d, 0x85, 0x26, 0x08, 0x1d, 0x02, 0xfb, 0x5b,
       0x85, 0xf6, 0x9a, 0xc2, 0x86, 0xec, 0xd5, 0x7d,
       0x40, 0xdf, 0x5d, 0xf3, 0x49, 0x47, 0x44, 0xd3 },
@@ -483,11 +476,13 @@ static const unsigned char kw_key[KW_TESTS][32] = {
       0x4a, 0x98, 0x48, 0xd3, 0x0f, 0xdd, 0x78, 0x33,
       0x5b, 0x03, 0x9a, 0x48, 0xa8, 0x96, 0x2c, 0x4d,
       0x1c, 0xb7, 0x8e, 0xab, 0xd5, 0xda, 0xd7, 0x88 }
+#endif
 };
 
-static const unsigned char kw_msg[KW_TESTS][40] = {
+static const unsigned char kw_msg[][40] = {
     { 0x42, 0x13, 0x6d, 0x3c, 0x38, 0x4a, 0x3e, 0xea,
       0xc9, 0x5a, 0x06, 0x6f, 0xd2, 0x8f, 0xed, 0x3f },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x95, 0xc1, 0x1b, 0xf5, 0x35, 0x3a, 0xfe, 0xdb,
       0x98, 0xfd, 0xd6, 0xc8, 0xca, 0x6f, 0xdb, 0x6d,
       0xa5, 0x4b, 0x74, 0xb4, 0x99, 0x0f, 0xdc, 0x45,
@@ -496,14 +491,28 @@ static const unsigned char kw_msg[KW_TESTS][40] = {
     { 0x1b, 0x20, 0xbf, 0x19, 0x90, 0xb0, 0x65, 0xd7,
       0x98, 0xe1, 0xb3, 0x22, 0x64, 0xad, 0x50, 0xa8,
       0x74, 0x74, 0x92, 0xba, 0x09, 0xa0, 0x4d, 0xd1 }
+#endif
 };
 
-static const size_t kw_msg_len[KW_TESTS] = { 16, 40, 24 };
-static const size_t kw_out_len[KW_TESTS] = { 24, 48, 32 };
-static const unsigned char kw_res[KW_TESTS][48] = {
+static const size_t kw_msg_len[] = {
+    16,
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    40,
+    24
+#endif
+};
+static const size_t kw_out_len[] = {
+    24,
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    48,
+    32
+#endif
+};
+static const unsigned char kw_res[][48] = {
     { 0x03, 0x1f, 0x6b, 0xd7, 0xe6, 0x1e, 0x64, 0x3d,
       0xf6, 0x85, 0x94, 0x81, 0x6f, 0x64, 0xca, 0xa3,
       0xf5, 0x6f, 0xab, 0xea, 0x25, 0x48, 0xf5, 0xfb },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x44, 0x3c, 0x6f, 0x15, 0x09, 0x83, 0x71, 0x91,
       0x3e, 0x5c, 0x81, 0x4c, 0xa1, 0xa0, 0x42, 0xec,
       0x68, 0x2f, 0x7b, 0x13, 0x6d, 0x24, 0x3a, 0x4d,
@@ -514,11 +523,13 @@ static const unsigned char kw_res[KW_TESTS][48] = {
       0xd5, 0xd5, 0x40, 0xec, 0x25, 0xd4, 0x3d, 0x87,
       0x20, 0x0f, 0xda, 0xdc, 0x6d, 0x1f, 0x05, 0xd9,
       0x16, 0x58, 0x4f, 0xa9, 0xf6, 0xcb, 0xf5, 0x12 }
+#endif
 };
 
-static const unsigned char kwp_key[KW_TESTS][32] = {
+static const unsigned char kwp_key[][32] = {
     { 0x78, 0x65, 0xe2, 0x0f, 0x3c, 0x21, 0x65, 0x9a,
       0xb4, 0x69, 0x0b, 0x62, 0x9c, 0xdf, 0x3c, 0xc4 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0xf5, 0xf8, 0x96, 0xa3, 0xbd, 0x2f, 0x4a, 0x98,
       0x23, 0xef, 0x16, 0x2b, 0x00, 0xb8, 0x05, 0xd7,
       0xde, 0x1e, 0xa4, 0x66, 0x26, 0x96, 0xa2, 0x58 },
@@ -526,23 +537,33 @@ static const unsigned char kwp_key[KW_TESTS][32] = {
       0x25, 0x54, 0xee, 0x2a, 0x8d, 0xf1, 0x38, 0x6f,
       0x5b, 0x94, 0xa1, 0xa6, 0x0e, 0xd8, 0xa4, 0xae,
       0xf6, 0x0a, 0x8d, 0x61, 0xab, 0x5f, 0x22, 0x5a }
+#endif
 };
 
-static const unsigned char kwp_msg[KW_TESTS][31] = {
+static const unsigned char kwp_msg[][31] = {
     { 0xbd, 0x68, 0x43, 0xd4, 0x20, 0x37, 0x8d, 0xc8,
       0x96 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x6c, 0xcd, 0xd5, 0x85, 0x18, 0x40, 0x97, 0xeb,
       0xd5, 0xc3, 0xaf, 0x3e, 0x47, 0xd0, 0x2c, 0x19,
       0x14, 0x7b, 0x4d, 0x99, 0x5f, 0x96, 0x43, 0x66,
       0x91, 0x56, 0x75, 0x8c, 0x13, 0x16, 0x8f },
     { 0xd1 }
+#endif
+};
+static const size_t kwp_msg_len[] = {
+    9,
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    31,
+    1
+#endif
 };
-static const size_t kwp_msg_len[KW_TESTS] = { 9, 31, 1 };
 
-static const unsigned char kwp_res[KW_TESTS][48] = {
+static const unsigned char kwp_res[][48] = {
     { 0x41, 0xec, 0xa9, 0x56, 0xd4, 0xaa, 0x04, 0x7e,
       0xb5, 0xcf, 0x4e, 0xfe, 0x65, 0x96, 0x61, 0xe7,
       0x4d, 0xb6, 0xf8, 0xc5, 0x64, 0xe2, 0x35, 0x00 },
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
     { 0x4e, 0x9b, 0xc2, 0xbc, 0xbc, 0x6c, 0x1e, 0x13,
       0xd3, 0x35, 0xbc, 0xc0, 0xf7, 0x73, 0x6a, 0x88,
       0xfa, 0x87, 0x53, 0x66, 0x15, 0xbb, 0x8e, 0x63,
@@ -550,8 +571,15 @@ static const unsigned char kwp_res[KW_TESTS][48] = {
       0x67, 0xcf, 0xa9, 0x8a, 0x9d, 0x0e, 0x33, 0x26 },
     { 0x06, 0xba, 0x7a, 0xe6, 0xf3, 0x24, 0x8c, 0xfd,
       0xcf, 0x26, 0x75, 0x07, 0xfa, 0x00, 0x1b, 0xc4  }
+#endif
+};
+static const size_t kwp_out_len[] = {
+    24,
+#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    40,
+    16
+#endif
 };
-static const size_t kwp_out_len[KW_TESTS] = { 24, 40, 16 };
 
 int mbedtls_nist_kw_self_test(int verbose)
 {
@@ -562,114 +590,128 @@ int mbedtls_nist_kw_self_test(int verbose)
     int ret = 0;
     mbedtls_nist_kw_init(&ctx);
 
-    for (i = 0; i < KW_TESTS; i++) {
-        if (verbose != 0) {
-            mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
-        }
+    /*
+     * KW mode
+     */
+    {
+        static const int num_tests = sizeof(kw_key) / sizeof(*kw_key);
 
-        ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
-                                     kw_key[i], key_len[i] * 8, 1);
-        if (ret != 0) {
+        for (i = 0; i < num_tests; i++) {
             if (verbose != 0) {
-                mbedtls_printf("  KW: setup failed ");
+                mbedtls_printf("  KW-AES-%u ", (unsigned int) key_len[i] * 8);
             }
 
-            goto end;
-        }
+            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                         kw_key[i], key_len[i] * 8, 1);
+            if (ret != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("  KW: setup failed ");
+                }
 
-        ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
-                                   kw_msg_len[i], out, &olen, sizeof(out));
-        if (ret != 0 || kw_out_len[i] != olen ||
-            memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
-            if (verbose != 0) {
-                mbedtls_printf("failed. ");
+                goto end;
             }
 
-            ret = 1;
-            goto end;
-        }
+            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, kw_msg[i],
+                                       kw_msg_len[i], out, &olen, sizeof(out));
+            if (ret != 0 || kw_out_len[i] != olen ||
+                memcmp(out, kw_res[i], kw_out_len[i]) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed. ");
+                }
 
-        if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
-                                          kw_key[i], key_len[i] * 8, 0))
-            != 0) {
-            if (verbose != 0) {
-                mbedtls_printf("  KW: setup failed ");
+                ret = 1;
+                goto end;
             }
 
-            goto end;
-        }
-
-        ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
-                                     out, olen, out, &olen, sizeof(out));
+            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                              kw_key[i], key_len[i] * 8, 0))
+                != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("  KW: setup failed ");
+                }
 
-        if (ret != 0 || olen != kw_msg_len[i] ||
-            memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
-            if (verbose != 0) {
-                mbedtls_printf("failed\n");
+                goto end;
             }
 
-            ret = 1;
-            goto end;
-        }
+            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW,
+                                         out, olen, out, &olen, sizeof(out));
 
-        if (verbose != 0) {
-            mbedtls_printf(" passed\n");
-        }
-    }
+            if (ret != 0 || olen != kw_msg_len[i] ||
+                memcmp(out, kw_msg[i], kw_msg_len[i]) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed\n");
+                }
 
-    for (i = 0; i < KW_TESTS; i++) {
-        olen = sizeof(out);
-        if (verbose != 0) {
-            mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
-        }
+                ret = 1;
+                goto end;
+            }
 
-        ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
-                                     key_len[i] * 8, 1);
-        if (ret  != 0) {
             if (verbose != 0) {
-                mbedtls_printf("  KWP: setup failed ");
+                mbedtls_printf(" passed\n");
             }
-
-            goto end;
         }
-        ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
-                                   kwp_msg_len[i], out, &olen, sizeof(out));
+    }
 
-        if (ret != 0 || kwp_out_len[i] != olen ||
-            memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
+    /*
+     * KWP mode
+     */
+    {
+        static const int num_tests = sizeof(kwp_key) / sizeof(*kwp_key);
+
+        for (i = 0; i < num_tests; i++) {
+            olen = sizeof(out);
             if (verbose != 0) {
-                mbedtls_printf("failed. ");
+                mbedtls_printf("  KWP-AES-%u ", (unsigned int) key_len[i] * 8);
             }
 
-            ret = 1;
-            goto end;
-        }
+            ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, kwp_key[i],
+                                         key_len[i] * 8, 1);
+            if (ret  != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("  KWP: setup failed ");
+                }
 
-        if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
-                                          kwp_key[i], key_len[i] * 8, 0))
-            != 0) {
-            if (verbose != 0) {
-                mbedtls_printf("  KWP: setup failed ");
+                goto end;
             }
+            ret = mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KWP, kwp_msg[i],
+                                       kwp_msg_len[i], out, &olen, sizeof(out));
 
-            goto end;
-        }
+            if (ret != 0 || kwp_out_len[i] != olen ||
+                memcmp(out, kwp_res[i], kwp_out_len[i]) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed. ");
+                }
 
-        ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
-                                     olen, out, &olen, sizeof(out));
+                ret = 1;
+                goto end;
+            }
 
-        if (ret != 0 || olen != kwp_msg_len[i] ||
-            memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
-            if (verbose != 0) {
-                mbedtls_printf("failed. ");
+            if ((ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
+                                              kwp_key[i], key_len[i] * 8, 0))
+                != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("  KWP: setup failed ");
+                }
+
+                goto end;
             }
 
-            ret = 1;
-            goto end;
-        }
+            ret = mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KWP, out,
+                                         olen, out, &olen, sizeof(out));
 
-        if (verbose != 0) {
-            mbedtls_printf(" passed\n");
+            if (ret != 0 || olen != kwp_msg_len[i] ||
+                memcmp(out, kwp_msg[i], kwp_msg_len[i]) != 0) {
+                if (verbose != 0) {
+                    mbedtls_printf("failed. ");
+                }
+
+                ret = 1;
+                goto end;
+            }
+
+            if (verbose != 0) {
+                mbedtls_printf(" passed\n");
+            }
         }
     }
 end:
diff --git a/lib/libmbedtls/mbedtls/library/oid.c b/lib/libmbedtls/mbedtls/library/oid.c
index 63b3df38800957f4786d840e4aff8ae5fddfe8cc..1d6b1eb866b9269041c069807581310bc5c2338f 100644
--- a/lib/libmbedtls/mbedtls/library/oid.c
+++ b/lib/libmbedtls/mbedtls/library/oid.c
@@ -4,19 +4,7 @@
  * \brief Object Identifier (OID) database
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -28,8 +16,6 @@
 #include "mbedtls/error.h"
 #include "mbedtls/pk.h"
 
-#include "mbedtls/legacy_or_psa.h"
-
 #include <stdio.h>
 #include <string.h>
 
@@ -320,6 +306,18 @@ static const oid_x509_ext_t oid_x509_ext[] =
                        "Certificate Policies"),
         MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
     },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER,
+                       "id-ce-subjectKeyIdentifier",
+                       "Subject Key Identifier"),
+        MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER,
+    },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER,
+                       "id-ce-authorityKeyIdentifier",
+                       "Authority Key Identifier"),
+        MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER,
+    },
     {
         NULL_OID_DESCRIPTOR,
         0,
@@ -381,84 +379,84 @@ typedef struct {
 static const oid_sig_alg_t oid_sig_alg[] =
 {
 #if defined(MBEDTLS_RSA_C)
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_MD5)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_MD5,        "md5WithRSAEncryption",     "RSA with MD5"),
         MBEDTLS_MD_MD5,      MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_MD5 */
+#if defined(MBEDTLS_MD_CAN_SHA1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA1,       "sha-1WithRSAEncryption",   "RSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA224)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA224,     "sha224WithRSAEncryption",
                        "RSA with SHA-224"),
         MBEDTLS_MD_SHA224,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA224 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA256,     "sha256WithRSAEncryption",
                        "RSA with SHA-256"),
         MBEDTLS_MD_SHA256,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA384,     "sha384WithRSAEncryption",
                        "RSA with SHA-384"),
         MBEDTLS_MD_SHA384,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA512)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_PKCS1_SHA512,     "sha512WithRSAEncryption",
                        "RSA with SHA-512"),
         MBEDTLS_MD_SHA512,   MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA512 */
+#if defined(MBEDTLS_MD_CAN_SHA1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_RSA_SHA_OBS,      "sha-1WithRSAEncryption",   "RSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_RSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA1,       "ecdsa-with-SHA1",      "ECDSA with SHA1"),
         MBEDTLS_MD_SHA1,     MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA224)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA224,     "ecdsa-with-SHA224",    "ECDSA with SHA224"),
         MBEDTLS_MD_SHA224,   MBEDTLS_PK_ECDSA,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA256,     "ecdsa-with-SHA256",    "ECDSA with SHA256"),
         MBEDTLS_MD_SHA256,   MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA384,     "ecdsa-with-SHA384",    "ECDSA with SHA384"),
         MBEDTLS_MD_SHA384,   MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA512)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_ECDSA_SHA512,     "ecdsa-with-SHA512",    "ECDSA with SHA512"),
         MBEDTLS_MD_SHA512,   MBEDTLS_PK_ECDSA,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA512 */
 #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
 #if defined(MBEDTLS_RSA_C)
     {
@@ -533,9 +531,9 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg,
                         mbedtls_pk_type_t,
                         pk_alg)
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 /*
- * For namedCurve (RFC 5480)
+ * For elliptic curves that use namedCurve inside ECParams (RFC 5480)
  */
 typedef struct {
     mbedtls_oid_descriptor_t    descriptor;
@@ -544,72 +542,72 @@ typedef struct {
 
 static const oid_ecp_grp_t oid_ecp_grp[] =
 {
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
+#if defined(MBEDTLS_ECP_HAVE_SECP192R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1",    "secp192r1"),
         MBEDTLS_ECP_DP_SECP192R1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP192R1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP224R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1",    "secp224r1"),
         MBEDTLS_ECP_DP_SECP224R1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP224R1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1",    "secp256r1"),
         MBEDTLS_ECP_DP_SECP256R1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP256R1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1",    "secp384r1"),
         MBEDTLS_ECP_DP_SECP384R1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP384R1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1",    "secp521r1"),
         MBEDTLS_ECP_DP_SECP521R1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP521R1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP192K1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1",    "secp192k1"),
         MBEDTLS_ECP_DP_SECP192K1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP192K1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP224K1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1",    "secp224k1"),
         MBEDTLS_ECP_DP_SECP224K1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP224K1 */
+#if defined(MBEDTLS_ECP_HAVE_SECP256K1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1",    "secp256k1"),
         MBEDTLS_ECP_DP_SECP256K1,
     },
-#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_SECP256K1 */
+#if defined(MBEDTLS_ECP_HAVE_BP256R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP256R1,   "brainpoolP256r1", "brainpool256r1"),
         MBEDTLS_ECP_DP_BP256R1,
     },
-#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_BP256R1 */
+#if defined(MBEDTLS_ECP_HAVE_BP384R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP384R1,   "brainpoolP384r1", "brainpool384r1"),
         MBEDTLS_ECP_DP_BP384R1,
     },
-#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
+#endif /* MBEDTLS_ECP_HAVE_BP384R1 */
+#if defined(MBEDTLS_ECP_HAVE_BP512R1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_EC_GRP_BP512R1,   "brainpoolP512r1", "brainpool512r1"),
         MBEDTLS_ECP_DP_BP512R1,
     },
-#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
+#endif /* MBEDTLS_ECP_HAVE_BP512R1 */
     {
         NULL_OID_DESCRIPTOR,
         MBEDTLS_ECP_DP_NONE,
@@ -623,7 +621,48 @@ FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp,
                         oid_ecp_grp,
                         mbedtls_ecp_group_id,
                         grp_id)
-#endif /* MBEDTLS_ECP_C */
+
+/*
+ * For Elliptic Curve algorithms that are directly
+ * encoded in the AlgorithmIdentifier (RFC 8410)
+ */
+typedef struct {
+    mbedtls_oid_descriptor_t    descriptor;
+    mbedtls_ecp_group_id        grp_id;
+} oid_ecp_grp_algid_t;
+
+static const oid_ecp_grp_algid_t oid_ecp_grp_algid[] =
+{
+#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_X25519,               "X25519",       "X25519"),
+        MBEDTLS_ECP_DP_CURVE25519,
+    },
+#endif /* MBEDTLS_ECP_HAVE_CURVE25519 */
+#if defined(MBEDTLS_ECP_HAVE_CURVE448)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_X448,                 "X448",         "X448"),
+        MBEDTLS_ECP_DP_CURVE448,
+    },
+#endif /* MBEDTLS_ECP_HAVE_CURVE448 */
+    {
+        NULL_OID_DESCRIPTOR,
+        MBEDTLS_ECP_DP_NONE,
+    },
+};
+
+FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_algid_t, grp_id_algid, oid_ecp_grp_algid)
+FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp_algid,
+                 oid_ecp_grp_algid_t,
+                 grp_id_algid,
+                 mbedtls_ecp_group_id,
+                 grp_id)
+FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp_algid,
+                        oid_ecp_grp_algid_t,
+                        oid_ecp_grp_algid,
+                        mbedtls_ecp_group_id,
+                        grp_id)
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 #if defined(MBEDTLS_CIPHER_C)
 /*
@@ -644,6 +683,18 @@ static const oid_cipher_alg_t oid_cipher_alg[] =
         OID_DESCRIPTOR(MBEDTLS_OID_DES_EDE3_CBC,         "des-ede3-cbc", "DES-EDE3-CBC"),
         MBEDTLS_CIPHER_DES_EDE3_CBC,
     },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_AES_128_CBC,          "aes128-cbc", "AES128-CBC"),
+        MBEDTLS_CIPHER_AES_128_CBC,
+    },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_AES_192_CBC,          "aes192-cbc", "AES192-CBC"),
+        MBEDTLS_CIPHER_AES_192_CBC,
+    },
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_AES_256_CBC,          "aes256-cbc", "AES256-CBC"),
+        MBEDTLS_CIPHER_AES_256_CBC,
+    },
     {
         NULL_OID_DESCRIPTOR,
         MBEDTLS_CIPHER_NONE,
@@ -668,47 +719,71 @@ typedef struct {
 
 static const oid_md_alg_t oid_md_alg[] =
 {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_MD5)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_MD5,       "id-md5",       "MD5"),
         MBEDTLS_MD_MD5,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA1,      "id-sha1",      "SHA-1"),
         MBEDTLS_MD_SHA1,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA224)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA224,    "id-sha224",    "SHA-224"),
         MBEDTLS_MD_SHA224,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA256,    "id-sha256",    "SHA-256"),
         MBEDTLS_MD_SHA256,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA384,    "id-sha384",    "SHA-384"),
         MBEDTLS_MD_SHA384,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA512)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA512,    "id-sha512",    "SHA-512"),
         MBEDTLS_MD_SHA512,
     },
 #endif
-#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160"),
         MBEDTLS_MD_RIPEMD160,
     },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_224,    "id-sha3-224",    "SHA-3-224"),
+        MBEDTLS_MD_SHA3_224,
+    },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_256,    "id-sha3-256",    "SHA-3-256"),
+        MBEDTLS_MD_SHA3_256,
+    },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_384,    "id-sha3-384",    "SHA-3-384"),
+        MBEDTLS_MD_SHA3_384,
+    },
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_DIGEST_ALG_SHA3_512,    "id-sha3-512",    "SHA-3-512"),
+        MBEDTLS_MD_SHA3_512,
+    },
 #endif
     {
         NULL_OID_DESCRIPTOR,
@@ -734,36 +809,66 @@ typedef struct {
 
 static const oid_md_hmac_t oid_md_hmac[] =
 {
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA1,      "hmacSHA1",      "HMAC-SHA-1"),
         MBEDTLS_MD_SHA1,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA224)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA224,    "hmacSHA224",    "HMAC-SHA-224"),
         MBEDTLS_MD_SHA224,
     },
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA224 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA256,    "hmacSHA256",    "HMAC-SHA-256"),
         MBEDTLS_MD_SHA256,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA384,    "hmacSHA384",    "HMAC-SHA-384"),
         MBEDTLS_MD_SHA384,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA512)
     {
         OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA512,    "hmacSHA512",    "HMAC-SHA-512"),
         MBEDTLS_MD_SHA512,
     },
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_LOWLEVEL_OR_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA512 */
+#if defined(MBEDTLS_MD_CAN_SHA3_224)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_224,    "hmacSHA3-224",    "HMAC-SHA3-224"),
+        MBEDTLS_MD_SHA3_224,
+    },
+#endif /* MBEDTLS_MD_CAN_SHA3_224 */
+#if defined(MBEDTLS_MD_CAN_SHA3_256)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_256,    "hmacSHA3-256",    "HMAC-SHA3-256"),
+        MBEDTLS_MD_SHA3_256,
+    },
+#endif /* MBEDTLS_MD_CAN_SHA3_256 */
+#if defined(MBEDTLS_MD_CAN_SHA3_384)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_384,    "hmacSHA3-384",    "HMAC-SHA3-384"),
+        MBEDTLS_MD_SHA3_384,
+    },
+#endif /* MBEDTLS_MD_CAN_SHA3_384 */
+#if defined(MBEDTLS_MD_CAN_SHA3_512)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_SHA3_512,    "hmacSHA3-512",    "HMAC-SHA3-512"),
+        MBEDTLS_MD_SHA3_512,
+    },
+#endif /* MBEDTLS_MD_CAN_SHA3_512 */
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
+    {
+        OID_DESCRIPTOR(MBEDTLS_OID_HMAC_RIPEMD160,    "hmacRIPEMD160",    "HMAC-RIPEMD160"),
+        MBEDTLS_MD_RIPEMD160,
+    },
+#endif /* MBEDTLS_MD_CAN_RIPEMD160 */
     {
         NULL_OID_DESCRIPTOR,
         MBEDTLS_MD_NONE,
@@ -773,7 +878,7 @@ static const oid_md_hmac_t oid_md_hmac[] =
 FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac)
 FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac)
 
-#if defined(MBEDTLS_PKCS12_C)
+#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_C)
 /*
  * For PKCS#12 PBEs
  */
@@ -811,7 +916,7 @@ FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg,
                  md_alg,
                  mbedtls_cipher_type_t,
                  cipher_alg)
-#endif /* MBEDTLS_PKCS12_C */
+#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_C */
 
 /* Return the x.y.z.... style numeric string for the given OID */
 int mbedtls_oid_get_numeric_string(char *buf, size_t size,
@@ -882,4 +987,180 @@ int mbedtls_oid_get_numeric_string(char *buf, size_t size,
     return (int) (size - n);
 }
 
+static int oid_parse_number(unsigned int *num, const char **p, const char *bound)
+{
+    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+
+    *num = 0;
+
+    while (*p < bound && **p >= '0' && **p <= '9') {
+        ret = 0;
+        if (*num > (UINT_MAX / 10)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+        *num *= 10;
+        *num += **p - '0';
+        (*p)++;
+    }
+    return ret;
+}
+
+static size_t oid_subidentifier_num_bytes(unsigned int value)
+{
+    size_t num_bytes = 0;
+
+    do {
+        value >>= 7;
+        num_bytes++;
+    } while (value != 0);
+
+    return num_bytes;
+}
+
+static int oid_subidentifier_encode_into(unsigned char **p,
+                                         unsigned char *bound,
+                                         unsigned int value)
+{
+    size_t num_bytes = oid_subidentifier_num_bytes(value);
+
+    if ((size_t) (bound - *p) < num_bytes) {
+        return MBEDTLS_ERR_OID_BUF_TOO_SMALL;
+    }
+    (*p)[num_bytes - 1] = (unsigned char) (value & 0x7f);
+    value >>= 7;
+
+    for (size_t i = 2; i <= num_bytes; i++) {
+        (*p)[num_bytes - i] = 0x80 | (unsigned char) (value & 0x7f);
+        value >>= 7;
+    }
+    *p += num_bytes;
+
+    return 0;
+}
+
+/* Return the OID for the given x.y.z.... style numeric string  */
+int mbedtls_oid_from_numeric_string(mbedtls_asn1_buf *oid,
+                                    const char *oid_str, size_t size)
+{
+    int ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+    const char *str_ptr = oid_str;
+    const char *str_bound = oid_str + size;
+    unsigned int val = 0;
+    unsigned int component1, component2;
+    size_t encoded_len;
+    unsigned char *resized_mem;
+
+    /* Count the number of dots to get a worst-case allocation size. */
+    size_t num_dots = 0;
+    for (size_t i = 0; i < size; i++) {
+        if (oid_str[i] == '.') {
+            num_dots++;
+        }
+    }
+    /* Allocate maximum possible required memory:
+     * There are (num_dots + 1) integer components, but the first 2 share the
+     * same subidentifier, so we only need num_dots subidentifiers maximum. */
+    if (num_dots == 0 || (num_dots > MBEDTLS_OID_MAX_COMPONENTS - 1)) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    /* Each byte can store 7 bits, calculate number of bytes for a
+     * subidentifier:
+     *
+     * bytes = ceil(subidentifer_size * 8 / 7)
+     */
+    size_t bytes_per_subidentifier = (((sizeof(unsigned int) * 8) - 1) / 7)
+                                     + 1;
+    size_t max_possible_bytes = num_dots * bytes_per_subidentifier;
+    oid->p = mbedtls_calloc(max_possible_bytes, 1);
+    if (oid->p == NULL) {
+        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+    }
+    unsigned char *out_ptr = oid->p;
+    unsigned char *out_bound = oid->p + max_possible_bytes;
+
+    ret = oid_parse_number(&component1, &str_ptr, str_bound);
+    if (ret != 0) {
+        goto error;
+    }
+    if (component1 > 2) {
+        /* First component can't be > 2 */
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    if (str_ptr >= str_bound || *str_ptr != '.') {
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    str_ptr++;
+
+    ret = oid_parse_number(&component2, &str_ptr, str_bound);
+    if (ret != 0) {
+        goto error;
+    }
+    if ((component1 < 2) && (component2 > 39)) {
+        /* Root nodes 0 and 1 may have up to 40 children, numbered 0-39 */
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    if (str_ptr < str_bound) {
+        if (*str_ptr == '.') {
+            str_ptr++;
+        } else {
+            ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+            goto error;
+        }
+    }
+
+    if (component2 > (UINT_MAX - (component1 * 40))) {
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto error;
+    }
+    ret = oid_subidentifier_encode_into(&out_ptr, out_bound,
+                                        (component1 * 40) + component2);
+    if (ret != 0) {
+        goto error;
+    }
+
+    while (str_ptr < str_bound) {
+        ret = oid_parse_number(&val, &str_ptr, str_bound);
+        if (ret != 0) {
+            goto error;
+        }
+        if (str_ptr < str_bound) {
+            if (*str_ptr == '.') {
+                str_ptr++;
+            } else {
+                ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+                goto error;
+            }
+        }
+
+        ret = oid_subidentifier_encode_into(&out_ptr, out_bound, val);
+        if (ret != 0) {
+            goto error;
+        }
+    }
+
+    encoded_len = (size_t) (out_ptr - oid->p);
+    resized_mem = mbedtls_calloc(encoded_len, 1);
+    if (resized_mem == NULL) {
+        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+        goto error;
+    }
+    memcpy(resized_mem, oid->p, encoded_len);
+    mbedtls_free(oid->p);
+    oid->p = resized_mem;
+    oid->len = encoded_len;
+
+    oid->tag = MBEDTLS_ASN1_OID;
+
+    return 0;
+
+error:
+    mbedtls_free(oid->p);
+    oid->p = NULL;
+    oid->len = 0;
+    return ret;
+}
+
 #endif /* MBEDTLS_OID_C */
diff --git a/lib/libmbedtls/mbedtls/library/padlock.c b/lib/libmbedtls/mbedtls/library/padlock.c
index f42c40ff93e5246e913d9704c1629c7baea4f030..1f006910c2e90d810a16b48807295817fab2597b 100644
--- a/lib/libmbedtls/mbedtls/library/padlock.c
+++ b/lib/libmbedtls/mbedtls/library/padlock.c
@@ -2,19 +2,7 @@
  *  VIA PadLock support functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  This implementation is based on the VIA PadLock Programming Guide:
@@ -31,7 +19,7 @@
 
 #include <string.h>
 
-#if defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
 
 /*
  * PadLock detection routine
@@ -108,6 +96,7 @@ int mbedtls_padlock_xcryptecb(mbedtls_aes_context *ctx,
     return 0;
 }
 
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
 /*
  * PadLock AES-CBC buffer en(de)cryption
  */
@@ -161,7 +150,8 @@ int mbedtls_padlock_xcryptcbc(mbedtls_aes_context *ctx,
 
     return 0;
 }
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
 
-#endif /* MBEDTLS_HAVE_X86 */
+#endif /* MBEDTLS_VIA_PADLOCK_HAVE_CODE */
 
 #endif /* MBEDTLS_PADLOCK_C */
diff --git a/lib/libmbedtls/mbedtls/library/padlock.h b/lib/libmbedtls/mbedtls/library/padlock.h
index b5f0d7d7a3d40962534b85073fc90157ae1f8cef..92d72af516e7c1b851eb8f5d075ff0a808c5d15d 100644
--- a/lib/libmbedtls/mbedtls/library/padlock.h
+++ b/lib/libmbedtls/mbedtls/library/padlock.h
@@ -9,19 +9,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_PADLOCK_H
 #define MBEDTLS_PADLOCK_H
@@ -38,13 +26,16 @@
 #endif
 #endif
 
-/* Some versions of ASan result in errors about not enough registers */
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \
+/*
+ * - `padlock` is implements with GNUC assembly for x86 target.
+ * - Some versions of ASan result in errors about not enough registers.
+ */
+#if defined(MBEDTLS_PADLOCK_C) && \
+    defined(__GNUC__) && defined(MBEDTLS_ARCH_IS_X86) && \
+    defined(MBEDTLS_HAVE_ASM) && \
     !defined(MBEDTLS_HAVE_ASAN)
 
-#ifndef MBEDTLS_HAVE_X86
-#define MBEDTLS_HAVE_X86
-#endif
+#define MBEDTLS_VIA_PADLOCK_HAVE_CODE
 
 #include <stdint.h>
 
diff --git a/lib/libmbedtls/mbedtls/library/pem.c b/lib/libmbedtls/mbedtls/library/pem.c
index 84bbb3df10a4d9259ac8e83db788721b150c9ac7..02076014563bb04eda571491097f9c039879749b 100644
--- a/lib/libmbedtls/mbedtls/library/pem.c
+++ b/lib/libmbedtls/mbedtls/library/pem.c
@@ -2,19 +2,7 @@
  *  Privacy Enhanced Mail (PEM) decoding
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -29,7 +17,6 @@
 #include "mbedtls/cipher.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
-#include "hash_info.h"
 
 #include <string.h>
 
@@ -39,20 +26,11 @@
 #include "psa/crypto.h"
 #endif
 
-#if !defined(MBEDTLS_MD5_C)
-#include "mbedtls/psa_util.h"
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,          \
-                                                           psa_to_md_errors,                     \
-                                                           psa_generic_status_to_mbedtls)
-#endif
-
-#include "mbedtls/legacy_or_psa.h"
-
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA) &&  \
+#if defined(MBEDTLS_MD_CAN_MD5) &&  \
     defined(MBEDTLS_CIPHER_MODE_CBC) &&                             \
     (defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C))
 #define PEM_RFC1421
-#endif /* MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
+#endif /* MBEDTLS_MD_CAN_MD5 &&
           MBEDTLS_CIPHER_MODE_CBC &&
           ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */
 
@@ -94,7 +72,6 @@ static int pem_get_iv(const unsigned char *s, unsigned char *iv,
     return 0;
 }
 
-#if defined(MBEDTLS_MD5_C)
 static int pem_pbkdf1(unsigned char *key, size_t keylen,
                       unsigned char *iv,
                       const unsigned char *pwd, size_t pwdlen)
@@ -168,91 +145,6 @@ exit:
 
     return ret;
 }
-#else
-static int pem_pbkdf1(unsigned char *key, size_t keylen,
-                      unsigned char *iv,
-                      const unsigned char *pwd, size_t pwdlen)
-{
-    unsigned char md5sum[16];
-    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
-    size_t output_length = 0;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-
-
-    if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_finish(&operation, md5sum,
-                                  PSA_HASH_LENGTH(PSA_ALG_MD5),
-                                  &output_length)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    /*
-     * key[ 0..15] = MD5(pwd || IV)
-     */
-    if (keylen <= 16) {
-        memcpy(key, md5sum, keylen);
-        goto exit;
-    }
-
-    memcpy(key, md5sum, 16);
-
-    /*
-     * key[16..23] = MD5(key[ 0..15] || pwd || IV])
-     */
-    if ((status = psa_hash_setup(&operation, PSA_ALG_MD5)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_update(&operation, md5sum, 16)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_update(&operation, pwd, pwdlen)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_update(&operation, iv, 8)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_finish(&operation, md5sum,
-                                  PSA_HASH_LENGTH(PSA_ALG_MD5),
-                                  &output_length)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if ((status = psa_hash_abort(&operation)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    size_t use_len = 16;
-    if (keylen < 32) {
-        use_len = keylen - 16;
-    }
-
-    memcpy(key + 16, md5sum, use_len);
-
-exit:
-    mbedtls_platform_zeroize(md5sum, 16);
-
-    return PSA_TO_MBEDTLS_ERR(status);
-}
-#endif /* MBEDTLS_MD5_C */
 
 #if defined(MBEDTLS_DES_C)
 /*
@@ -348,6 +240,29 @@ exit:
 }
 #endif /* MBEDTLS_AES_C */
 
+#if defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C)
+static int pem_check_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len)
+{
+    /* input_len > 0 is guaranteed by mbedtls_pem_read_buffer(). */
+    size_t pad_len = input[input_len - 1];
+    size_t i;
+
+    if (pad_len > input_len) {
+        return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+    }
+
+    *data_len = input_len - pad_len;
+
+    for (i = *data_len; i < input_len; i++) {
+        if (input[i] != pad_len) {
+            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+        }
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_DES_C || MBEDTLS_AES_C */
+
 #endif /* PEM_RFC1421 */
 
 int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const char *footer,
@@ -406,7 +321,7 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
     if (*end == '\n') {
         end++;
     }
-    *use_len = end - data;
+    *use_len = (size_t) (end - data);
 
     enc = 0;
 
@@ -491,27 +406,29 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
         return MBEDTLS_ERR_PEM_INVALID_DATA;
     }
 
-    ret = mbedtls_base64_decode(NULL, 0, &len, s1, s2 - s1);
+    ret = mbedtls_base64_decode(NULL, 0, &len, s1, (size_t) (s2 - s1));
 
     if (ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER) {
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     }
 
+    if (len == 0) {
+        return MBEDTLS_ERR_PEM_BAD_INPUT_DATA;
+    }
+
     if ((buf = mbedtls_calloc(1, len)) == NULL) {
         return MBEDTLS_ERR_PEM_ALLOC_FAILED;
     }
 
-    if ((ret = mbedtls_base64_decode(buf, len, &len, s1, s2 - s1)) != 0) {
-        mbedtls_platform_zeroize(buf, len);
-        mbedtls_free(buf);
+    if ((ret = mbedtls_base64_decode(buf, len, &len, s1, (size_t) (s2 - s1))) != 0) {
+        mbedtls_zeroize_and_free(buf, len);
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PEM_INVALID_DATA, ret);
     }
 
     if (enc != 0) {
 #if defined(PEM_RFC1421)
         if (pwd == NULL) {
-            mbedtls_platform_zeroize(buf, len);
-            mbedtls_free(buf);
+            mbedtls_zeroize_and_free(buf, len);
             return MBEDTLS_ERR_PEM_PASSWORD_REQUIRED;
         }
 
@@ -536,24 +453,22 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
 #endif /* MBEDTLS_AES_C */
 
         if (ret != 0) {
-            mbedtls_free(buf);
+            mbedtls_zeroize_and_free(buf, len);
             return ret;
         }
 
-        /*
-         * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3
-         * length bytes (allow 4 to be sure) in all known use cases.
-         *
-         * Use that as a heuristic to try to detect password mismatches.
-         */
-        if (len <= 2 || buf[0] != 0x30 || buf[1] > 0x83) {
-            mbedtls_platform_zeroize(buf, len);
-            mbedtls_free(buf);
-            return MBEDTLS_ERR_PEM_PASSWORD_MISMATCH;
+        /* Check PKCS padding and update data length based on padding info.
+         * This can be used to detect invalid padding data and password
+         * mismatches. */
+        size_t unpadded_len;
+        ret = pem_check_pkcs_padding(buf, len, &unpadded_len);
+        if (ret != 0) {
+            mbedtls_zeroize_and_free(buf, len);
+            return ret;
         }
+        len = unpadded_len;
 #else
-        mbedtls_platform_zeroize(buf, len);
-        mbedtls_free(buf);
+        mbedtls_zeroize_and_free(buf, len);
         return MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE;
 #endif /* PEM_RFC1421 */
     }
@@ -566,9 +481,12 @@ int mbedtls_pem_read_buffer(mbedtls_pem_context *ctx, const char *header, const
 
 void mbedtls_pem_free(mbedtls_pem_context *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     if (ctx->buf != NULL) {
-        mbedtls_platform_zeroize(ctx->buf, ctx->buflen);
-        mbedtls_free(ctx->buf);
+        mbedtls_zeroize_and_free(ctx->buf, ctx->buflen);
     }
     mbedtls_free(ctx->info);
 
@@ -586,7 +504,7 @@ int mbedtls_pem_write_buffer(const char *header, const char *footer,
     size_t len = 0, use_len, add_len = 0;
 
     mbedtls_base64_encode(NULL, 0, &use_len, der_data, der_len);
-    add_len = strlen(header) + strlen(footer) + (use_len / 64) + 1;
+    add_len = strlen(header) + strlen(footer) + (((use_len > 2) ? (use_len - 2) : 0) / 64) + 1;
 
     if (use_len + add_len > buf_len) {
         *olen = use_len + add_len;
@@ -621,7 +539,7 @@ int mbedtls_pem_write_buffer(const char *header, const char *footer,
     p += strlen(footer);
 
     *p++ = '\0';
-    *olen = p - buf;
+    *olen = (size_t) (p - buf);
 
     /* Clean any remaining data previously written to the buffer */
     memset(buf + *olen, 0, buf_len - *olen);
diff --git a/lib/libmbedtls/mbedtls/library/pk.c b/lib/libmbedtls/mbedtls/library/pk.c
index 5e18ad29827040478f0db3a9c59183f46438deb4..3fe51ea34fae79ec79cfe05b0fb5e4eed2275b51 100644
--- a/lib/libmbedtls/mbedtls/library/pk.c
+++ b/lib/libmbedtls/mbedtls/library/pk.c
@@ -2,19 +2,7 @@
  *  Public Key abstraction layer
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -23,36 +11,34 @@
 #include "mbedtls/pk.h"
 #include "pk_wrap.h"
 #include "pkwrite.h"
-
-#include "hash_info.h"
+#include "pk_internal.h"
 
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
 #if defined(MBEDTLS_RSA_C)
 #include "mbedtls/rsa.h"
+#include "rsa_internal.h"
 #endif
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 #include "mbedtls/ecp.h"
 #endif
 #if defined(MBEDTLS_ECDSA_C)
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#include "psa_util_internal.h"
 #include "mbedtls/psa_util.h"
-#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
-#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
-                                                                  psa_to_pk_rsa_errors,            \
-                                                                  psa_pk_status_to_mbedtls)
-#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                                    psa_to_pk_ecdsa_errors,        \
-                                                                    psa_pk_status_to_mbedtls)
 #endif
 
 #include <limits.h>
 #include <stdint.h>
 
+#define PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE \
+    (PSA_EXPORT_KEY_PAIR_MAX_SIZE > PSA_EXPORT_PUBLIC_KEY_MAX_SIZE) ? \
+    PSA_EXPORT_KEY_PAIR_MAX_SIZE : PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+
 /*
  * Initialise a mbedtls_pk_context
  */
@@ -60,6 +46,15 @@ void mbedtls_pk_init(mbedtls_pk_context *ctx)
 {
     ctx->pk_info = NULL;
     ctx->pk_ctx = NULL;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    ctx->priv_id = MBEDTLS_SVC_KEY_ID_INIT;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    memset(ctx->pub_raw, 0, sizeof(ctx->pub_raw));
+    ctx->pub_raw_len = 0;
+    ctx->ec_family = 0;
+    ctx->ec_bits = 0;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 }
 
 /*
@@ -71,10 +66,18 @@ void mbedtls_pk_free(mbedtls_pk_context *ctx)
         return;
     }
 
-    if (ctx->pk_info != NULL) {
+    if ((ctx->pk_info != NULL) && (ctx->pk_info->ctx_free_func != NULL)) {
         ctx->pk_info->ctx_free_func(ctx->pk_ctx);
     }
 
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    /* The ownership of the priv_id key for opaque keys is external of the PK
+     * module. It's the user responsibility to clear it after use. */
+    if ((ctx->pk_info != NULL) && (ctx->pk_info->type != MBEDTLS_PK_OPAQUE)) {
+        psa_destroy_key(ctx->priv_id);
+    }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
     mbedtls_platform_zeroize(ctx, sizeof(mbedtls_pk_context));
 }
 
@@ -114,17 +117,17 @@ const mbedtls_pk_info_t *mbedtls_pk_info_from_type(mbedtls_pk_type_t pk_type)
 #if defined(MBEDTLS_RSA_C)
         case MBEDTLS_PK_RSA:
             return &mbedtls_rsa_info;
-#endif
-#if defined(MBEDTLS_ECP_C)
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
         case MBEDTLS_PK_ECKEY:
             return &mbedtls_eckey_info;
         case MBEDTLS_PK_ECKEY_DH:
             return &mbedtls_eckeydh_info;
-#endif
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
         case MBEDTLS_PK_ECDSA:
             return &mbedtls_ecdsa_info;
-#endif
+#endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
         /* MBEDTLS_PK_RSA_ALT omitted on purpose */
         default:
             return NULL;
@@ -140,7 +143,8 @@ int mbedtls_pk_setup(mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info)
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
-    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
+    if ((info->ctx_alloc_func != NULL) &&
+        ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL)) {
         return MBEDTLS_ERR_PK_ALLOC_FAILED;
     }
 
@@ -158,7 +162,6 @@ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
 {
     const mbedtls_pk_info_t *info = NULL;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    mbedtls_svc_key_id_t *pk_ctx;
     psa_key_type_t type;
 
     if (ctx == NULL || ctx->pk_info != NULL) {
@@ -171,22 +174,19 @@ int mbedtls_pk_setup_opaque(mbedtls_pk_context *ctx,
     type = psa_get_key_type(&attributes);
     psa_reset_key_attributes(&attributes);
 
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
-        info = &mbedtls_pk_ecdsa_opaque_info;
-    } else if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
-        info = &mbedtls_pk_rsa_opaque_info;
+        info = &mbedtls_ecdsa_opaque_info;
+    } else
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        info = &mbedtls_rsa_opaque_info;
     } else {
         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
 
-    if ((ctx->pk_ctx = info->ctx_alloc_func()) == NULL) {
-        return MBEDTLS_ERR_PK_ALLOC_FAILED;
-    }
-
     ctx->pk_info = info;
-
-    pk_ctx = (mbedtls_svc_key_id_t *) ctx->pk_ctx;
-    *pk_ctx = key;
+    ctx->priv_id = key;
 
     return 0;
 }
@@ -315,18 +315,23 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
         return (key_usage & usage) == usage;
     }
 
-    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_algorithm_t key_alg, key_alg2;
     psa_status_t status;
 
-    status = psa_get_key_attributes(*key, &attributes);
+    status = psa_get_key_attributes(ctx->priv_id, &attributes);
     if (status != PSA_SUCCESS) {
         return 0;
     }
 
-    key_alg = psa_get_key_algorithm(&attributes);
-    key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
+    psa_algorithm_t key_alg = psa_get_key_algorithm(&attributes);
+    /* Key's enrollment is available only when an Mbed TLS implementation of PSA
+     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
+     * Even though we don't officially support using other implementations of PSA
+     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
+     * separated. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+    psa_algorithm_t key_alg2 = psa_get_key_enrollment_algorithm(&attributes);
+#endif /* MBEDTLS_PSA_CRYPTO_C */
     key_usage = psa_get_key_usage_flags(&attributes);
     psa_reset_key_attributes(&attributes);
 
@@ -335,40 +340,657 @@ int mbedtls_pk_can_do_ext(const mbedtls_pk_context *ctx, psa_algorithm_t alg,
     }
 
     /*
-     * Common case: the key alg or alg2 only allows alg.
+     * Common case: the key alg [or alg2] only allows alg.
      * This will match PSA_ALG_RSA_PKCS1V15_CRYPT & PSA_ALG_IS_ECDH
      * directly.
      * This would also match ECDSA/RSA_PKCS1V15_SIGN/RSA_PSS with
-     * a fixed hash on key_alg/key_alg2.
+     * a fixed hash on key_alg [or key_alg2].
      */
-    if (alg == key_alg || alg == key_alg2) {
+    if (alg == key_alg) {
+        return 1;
+    }
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+    if (alg == key_alg2) {
         return 1;
     }
+#endif /* MBEDTLS_PSA_CRYPTO_C */
 
     /*
-     * If key_alg or key_alg2 is a hash-and-sign with a wildcard for the hash,
+     * If key_alg [or key_alg2] is a hash-and-sign with a wildcard for the hash,
      * and alg is the same hash-and-sign family with any hash,
      * then alg is compliant with this key alg
      */
     if (PSA_ALG_IS_SIGN_HASH(alg)) {
-
         if (PSA_ALG_IS_SIGN_HASH(key_alg) &&
             PSA_ALG_SIGN_GET_HASH(key_alg) == PSA_ALG_ANY_HASH &&
             (alg & ~PSA_ALG_HASH_MASK) == (key_alg & ~PSA_ALG_HASH_MASK)) {
             return 1;
         }
-
+#if defined(MBEDTLS_PSA_CRYPTO_C)
         if (PSA_ALG_IS_SIGN_HASH(key_alg2) &&
             PSA_ALG_SIGN_GET_HASH(key_alg2) == PSA_ALG_ANY_HASH &&
             (alg & ~PSA_ALG_HASH_MASK) == (key_alg2 & ~PSA_ALG_HASH_MASK)) {
             return 1;
         }
+#endif /* MBEDTLS_PSA_CRYPTO_C */
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#if defined(MBEDTLS_RSA_C)
+static psa_algorithm_t psa_algorithm_for_rsa(const mbedtls_rsa_context *rsa,
+                                             int want_crypt)
+{
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        if (want_crypt) {
+            mbedtls_md_type_t md_type = (mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa);
+            return PSA_ALG_RSA_OAEP(mbedtls_md_psa_alg_from_type(md_type));
+        } else {
+            return PSA_ALG_RSA_PSS_ANY_SALT(PSA_ALG_ANY_HASH);
+        }
+    } else {
+        if (want_crypt) {
+            return PSA_ALG_RSA_PKCS1V15_CRYPT;
+        } else {
+            return PSA_ALG_RSA_PKCS1V15_SIGN(PSA_ALG_ANY_HASH);
+        }
+    }
+}
+#endif /* MBEDTLS_RSA_C */
+
+int mbedtls_pk_get_psa_attributes(const mbedtls_pk_context *pk,
+                                  psa_key_usage_t usage,
+                                  psa_key_attributes_t *attributes)
+{
+    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+
+    psa_key_usage_t more_usage = usage;
+    if (usage == PSA_KEY_USAGE_SIGN_MESSAGE) {
+        more_usage |= PSA_KEY_USAGE_VERIFY_MESSAGE;
+    } else if (usage == PSA_KEY_USAGE_SIGN_HASH) {
+        more_usage |= PSA_KEY_USAGE_VERIFY_HASH;
+    } else if (usage == PSA_KEY_USAGE_DECRYPT) {
+        more_usage |= PSA_KEY_USAGE_ENCRYPT;
+    }
+    more_usage |= PSA_KEY_USAGE_EXPORT | PSA_KEY_USAGE_COPY;
+
+    int want_private = !(usage == PSA_KEY_USAGE_VERIFY_MESSAGE ||
+                         usage == PSA_KEY_USAGE_VERIFY_HASH ||
+                         usage == PSA_KEY_USAGE_ENCRYPT);
+
+    switch (pk_type) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            int want_crypt = 0; /* 0: sign/verify; 1: encrypt/decrypt */
+            switch (usage) {
+                case PSA_KEY_USAGE_SIGN_MESSAGE:
+                case PSA_KEY_USAGE_SIGN_HASH:
+                case PSA_KEY_USAGE_VERIFY_MESSAGE:
+                case PSA_KEY_USAGE_VERIFY_HASH:
+                    /* Nothing to do. */
+                    break;
+                case PSA_KEY_USAGE_DECRYPT:
+                case PSA_KEY_USAGE_ENCRYPT:
+                    want_crypt = 1;
+                    break;
+                default:
+                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            /* Detect the presence of a private key in a way that works both
+             * in CRT and non-CRT configurations. */
+            mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*pk);
+            int has_private = (mbedtls_rsa_check_privkey(rsa) == 0);
+            if (want_private && !has_private) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            psa_set_key_type(attributes, (want_private ?
+                                          PSA_KEY_TYPE_RSA_KEY_PAIR :
+                                          PSA_KEY_TYPE_RSA_PUBLIC_KEY));
+            psa_set_key_bits(attributes, mbedtls_pk_get_bitlen(pk));
+            psa_set_key_algorithm(attributes,
+                                  psa_algorithm_for_rsa(rsa, want_crypt));
+            break;
+        }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+            int sign_ok = (pk_type != MBEDTLS_PK_ECKEY_DH);
+            int derive_ok = (pk_type != MBEDTLS_PK_ECDSA);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            psa_ecc_family_t family = pk->ec_family;
+            size_t bits = pk->ec_bits;
+            int has_private = 0;
+            if (pk->priv_id != MBEDTLS_SVC_KEY_ID_INIT) {
+                has_private = 1;
+            }
+#else
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+            int has_private = (ec->d.n != 0);
+            size_t bits = 0;
+            psa_ecc_family_t family =
+                mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
+#endif
+            psa_algorithm_t alg = 0;
+            switch (usage) {
+                case PSA_KEY_USAGE_SIGN_MESSAGE:
+                case PSA_KEY_USAGE_SIGN_HASH:
+                case PSA_KEY_USAGE_VERIFY_MESSAGE:
+                case PSA_KEY_USAGE_VERIFY_HASH:
+                    if (!sign_ok) {
+                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+                    }
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+                    alg = PSA_ALG_DETERMINISTIC_ECDSA(PSA_ALG_ANY_HASH);
+#else
+                    alg = PSA_ALG_ECDSA(PSA_ALG_ANY_HASH);
+#endif
+                    break;
+                case PSA_KEY_USAGE_DERIVE:
+                    alg = PSA_ALG_ECDH;
+                    if (!derive_ok) {
+                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+                    }
+                    break;
+                default:
+                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            if (want_private && !has_private) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            psa_set_key_type(attributes, (want_private ?
+                                          PSA_KEY_TYPE_ECC_KEY_PAIR(family) :
+                                          PSA_KEY_TYPE_ECC_PUBLIC_KEY(family)));
+            psa_set_key_bits(attributes, bits);
+            psa_set_key_algorithm(attributes, alg);
+            break;
+        }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+        case MBEDTLS_PK_RSA_ALT:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+        {
+            psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+            psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+            status = psa_get_key_attributes(pk->priv_id, &old_attributes);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+            }
+            psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+            switch (usage) {
+                case PSA_KEY_USAGE_SIGN_MESSAGE:
+                case PSA_KEY_USAGE_SIGN_HASH:
+                case PSA_KEY_USAGE_VERIFY_MESSAGE:
+                case PSA_KEY_USAGE_VERIFY_HASH:
+                    if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type) ||
+                          old_type == PSA_KEY_TYPE_RSA_KEY_PAIR)) {
+                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+                    }
+                    break;
+                case PSA_KEY_USAGE_DECRYPT:
+                case PSA_KEY_USAGE_ENCRYPT:
+                    if (old_type != PSA_KEY_TYPE_RSA_KEY_PAIR) {
+                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+                    }
+                    break;
+                case PSA_KEY_USAGE_DERIVE:
+                    if (!(PSA_KEY_TYPE_IS_ECC_KEY_PAIR(old_type))) {
+                        return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+                    }
+                    break;
+                default:
+                    return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            psa_key_type_t new_type = old_type;
+            /* Opaque keys are always key pairs, so we don't need a check
+             * on the input if the required usage is private. We just need
+             * to adjust the type correctly if the required usage is public. */
+            if (!want_private) {
+                new_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(new_type);
+            }
+            more_usage = psa_get_key_usage_flags(&old_attributes);
+            if ((usage & more_usage) == 0) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            psa_set_key_type(attributes, new_type);
+            psa_set_key_bits(attributes, psa_get_key_bits(&old_attributes));
+            psa_set_key_algorithm(attributes, psa_get_key_algorithm(&old_attributes));
+            break;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        default:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
+    psa_set_key_usage_flags(attributes, more_usage);
+    /* Key's enrollment is available only when an Mbed TLS implementation of PSA
+     * Crypto is being used, i.e. when MBEDTLS_PSA_CRYPTO_C is defined.
+     * Even though we don't officially support using other implementations of PSA
+     * Crypto with TLS and X.509 (yet), we try to keep vendor's customizations
+     * separated. */
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+    psa_set_key_enrollment_algorithm(attributes, PSA_ALG_NONE);
+#endif
+
     return 0;
 }
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA) || defined(MBEDTLS_USE_PSA_CRYPTO)
+static psa_status_t export_import_into_psa(mbedtls_svc_key_id_t old_key_id,
+                                           const psa_key_attributes_t *attributes,
+                                           mbedtls_svc_key_id_t *new_key_id)
+{
+    unsigned char key_buffer[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
+    size_t key_length = 0;
+    psa_status_t status = psa_export_key(old_key_id,
+                                         key_buffer, sizeof(key_buffer),
+                                         &key_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    status = psa_import_key(attributes, key_buffer, key_length, new_key_id);
+    mbedtls_platform_zeroize(key_buffer, key_length);
+    return status;
+}
+
+static int copy_into_psa(mbedtls_svc_key_id_t old_key_id,
+                         const psa_key_attributes_t *attributes,
+                         mbedtls_svc_key_id_t *new_key_id)
+{
+    /* Normally, we prefer copying: it's more efficient and works even
+     * for non-exportable keys. */
+    psa_status_t status = psa_copy_key(old_key_id, attributes, new_key_id);
+    if (status == PSA_ERROR_NOT_PERMITTED /*missing COPY usage*/ ||
+        status == PSA_ERROR_INVALID_ARGUMENT /*incompatible policy*/) {
+        /* There are edge cases where copying won't work, but export+import
+         * might:
+         * - If the old key does not allow PSA_KEY_USAGE_COPY.
+         * - If the old key's usage does not allow what attributes wants.
+         *   Because the key was intended for use in the pk module, and may
+         *   have had a policy chosen solely for what pk needs rather than
+         *   based on a detailed understanding of PSA policies, we are a bit
+         *   more liberal than psa_copy_key() here.
+         */
+        /* Here we need to check that the types match, otherwise we risk
+         * importing nonsensical data. */
+        psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+        status = psa_get_key_attributes(old_key_id, &old_attributes);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+        psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+        psa_reset_key_attributes(&old_attributes);
+        if (old_type != psa_get_key_type(attributes)) {
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        }
+        status = export_import_into_psa(old_key_id, attributes, new_key_id);
+    }
+    return PSA_PK_TO_MBEDTLS_ERR(status);
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA || MBEDTLS_USE_PSA_CRYPTO */
+
+static int import_pair_into_psa(const mbedtls_pk_context *pk,
+                                const psa_key_attributes_t *attributes,
+                                mbedtls_svc_key_id_t *key_id)
+{
+    switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            if (psa_get_key_type(attributes) != PSA_KEY_TYPE_RSA_KEY_PAIR) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char key_buffer[
+                PSA_KEY_EXPORT_RSA_KEY_PAIR_MAX_SIZE(PSA_VENDOR_RSA_MAX_KEY_BITS)];
+            unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+            unsigned char *key_data = key_end;
+            int ret = mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk),
+                                            key_buffer, &key_data);
+            if (ret < 0) {
+                return ret;
+            }
+            size_t key_length = key_end - key_data;
+            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                       key_data, key_length,
+                                                       key_id));
+            mbedtls_platform_zeroize(key_data, key_length);
+            return ret;
+        }
+#endif /* MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+            /* We need to check the curve family, otherwise the import could
+             * succeed with nonsensical data.
+             * We don't check the bit-size: it's optional in attributes,
+             * and if it's specified, psa_import_key() will know from the key
+             * data length and will check that the bit-size matches. */
+            psa_key_type_t to_type = psa_get_key_type(attributes);
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            psa_ecc_family_t from_family = pk->ec_family;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+            size_t from_bits = 0;
+            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+                                                                    &from_bits);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            if (to_type != PSA_KEY_TYPE_ECC_KEY_PAIR(from_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (mbedtls_svc_key_id_is_null(pk->priv_id)) {
+                /* We have a public key and want a key pair. */
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            return copy_into_psa(pk->priv_id, attributes, key_id);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            if (ec->d.n == 0) {
+                /* Private key not set. Assume the input is a public key only.
+                 * (The other possibility is that it's an incomplete object
+                 * where the group is set but neither the public key nor
+                 * the private key. This is not possible through ecp.h
+                 * functions, so we don't bother reporting a more suitable
+                 * error in that case.) */
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char key_buffer[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+            size_t key_length = 0;
+            int ret = mbedtls_ecp_write_key_ext(ec, &key_length,
+                                                key_buffer, sizeof(key_buffer));
+            if (ret < 0) {
+                return ret;
+            }
+            ret = PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                       key_buffer, key_length,
+                                                       key_id));
+            mbedtls_platform_zeroize(key_buffer, key_length);
+            return ret;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+        }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+            return copy_into_psa(pk->priv_id, attributes, key_id);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+        default:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+}
+
+static int import_public_into_psa(const mbedtls_pk_context *pk,
+                                  const psa_key_attributes_t *attributes,
+                                  mbedtls_svc_key_id_t *key_id)
+{
+    psa_key_type_t psa_type = psa_get_key_type(attributes);
+
+#if defined(MBEDTLS_RSA_C) ||                                           \
+    (defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)) || \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+    unsigned char key_buffer[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+#endif
+    unsigned char *key_data = NULL;
+    size_t key_length = 0;
+
+    switch (mbedtls_pk_get_type(pk)) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_PK_RSA:
+        {
+            if (psa_type != PSA_KEY_TYPE_RSA_PUBLIC_KEY) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            unsigned char *const key_end = key_buffer + sizeof(key_buffer);
+            key_data = key_end;
+            int ret = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*pk),
+                                               key_buffer, &key_data);
+            if (ret < 0) {
+                return ret;
+            }
+            key_length = (size_t) ret;
+            break;
+        }
+#endif /*MBEDTLS_RSA_C */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+        {
+            /* We need to check the curve family, otherwise the import could
+             * succeed with nonsensical data.
+             * We don't check the bit-size: it's optional in attributes,
+             * and if it's specified, psa_import_key() will know from the key
+             * data length and will check that the bit-size matches. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            key_data = (unsigned char *) pk->pub_raw;
+            key_length = pk->pub_raw_len;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec_ro(*pk);
+            size_t from_bits = 0;
+            psa_ecc_family_t from_family = mbedtls_ecc_group_to_psa(ec->grp.id,
+                                                                    &from_bits);
+            if (psa_type != PSA_KEY_TYPE_ECC_PUBLIC_KEY(from_family)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            int ret = mbedtls_ecp_write_public_key(
+                ec, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                &key_length, key_buffer, sizeof(key_buffer));
+            if (ret < 0) {
+                return ret;
+            }
+            key_data = key_buffer;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+            break;
+        }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        case MBEDTLS_PK_OPAQUE:
+        {
+            psa_key_attributes_t old_attributes = PSA_KEY_ATTRIBUTES_INIT;
+            psa_status_t status =
+                psa_get_key_attributes(pk->priv_id, &old_attributes);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+            }
+            psa_key_type_t old_type = psa_get_key_type(&old_attributes);
+            psa_reset_key_attributes(&old_attributes);
+            if (psa_type != PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(old_type)) {
+                return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+            }
+            status = psa_export_public_key(pk->priv_id,
+                                           key_buffer, sizeof(key_buffer),
+                                           &key_length);
+            if (status != PSA_SUCCESS) {
+                return PSA_PK_TO_MBEDTLS_ERR(status);
+            }
+            key_data = key_buffer;
+            break;
+        }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+        default:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    return PSA_PK_TO_MBEDTLS_ERR(psa_import_key(attributes,
+                                                key_data, key_length,
+                                                key_id));
+}
+
+int mbedtls_pk_import_into_psa(const mbedtls_pk_context *pk,
+                               const psa_key_attributes_t *attributes,
+                               mbedtls_svc_key_id_t *key_id)
+{
+    /* Set the output immediately so that it won't contain garbage even
+     * if we error out before calling psa_import_key(). */
+    *key_id = MBEDTLS_SVC_KEY_ID_INIT;
+
+#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA_ALT) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
+
+    int want_public = PSA_KEY_TYPE_IS_PUBLIC_KEY(psa_get_key_type(attributes));
+    if (want_public) {
+        return import_public_into_psa(pk, attributes, key_id);
+    } else {
+        return import_pair_into_psa(pk, attributes, key_id);
+    }
+}
+
+static int copy_from_psa(mbedtls_svc_key_id_t key_id,
+                         mbedtls_pk_context *pk,
+                         int public_only)
+{
+    psa_status_t status;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_type_t key_type;
+    size_t key_bits;
+    /* Use a buffer size large enough to contain either a key pair or public key. */
+    unsigned char exp_key[PSA_EXPORT_KEY_PAIR_OR_PUBLIC_MAX_SIZE];
+    size_t exp_key_len;
+    int ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+
+    if (pk == NULL) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    status = psa_get_key_attributes(key_id, &key_attr);
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    if (public_only) {
+        status = psa_export_public_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
+    } else {
+        status = psa_export_key(key_id, exp_key, sizeof(exp_key), &exp_key_len);
+    }
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_TO_MBEDTLS_ERR(status);
+        goto exit;
+    }
+
+    key_type = psa_get_key_type(&key_attr);
+    if (public_only) {
+        key_type = PSA_KEY_TYPE_PUBLIC_KEY_OF_KEY_PAIR(key_type);
+    }
+    key_bits = psa_get_key_bits(&key_attr);
+
+#if defined(MBEDTLS_RSA_C)
+    if ((key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) ||
+        (key_type == PSA_KEY_TYPE_RSA_PUBLIC_KEY)) {
+
+        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
+        if (ret != 0) {
+            goto exit;
+        }
+
+        if (key_type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+            ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
+        } else {
+            ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), exp_key, exp_key_len);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+
+        psa_algorithm_t alg_type = psa_get_key_algorithm(&key_attr);
+        mbedtls_md_type_t md_type = MBEDTLS_MD_NONE;
+        if (PSA_ALG_GET_HASH(alg_type) != PSA_ALG_ANY_HASH) {
+            md_type = mbedtls_md_type_from_psa_alg(alg_type);
+        }
+
+        if (PSA_ALG_IS_RSA_OAEP(alg_type) || PSA_ALG_IS_RSA_PSS(alg_type)) {
+            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V21, md_type);
+        } else if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg_type) ||
+                   alg_type == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+            ret = mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk), MBEDTLS_RSA_PKCS_V15, md_type);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+    } else
+#endif /* MBEDTLS_RSA_C */
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type) ||
+        PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(key_type)) {
+        mbedtls_ecp_group_id grp_id;
+
+        ret = mbedtls_pk_setup(pk, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
+        if (ret != 0) {
+            goto exit;
+        }
+
+        grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(key_type), key_bits);
+        ret = mbedtls_pk_ecc_set_group(pk, grp_id);
+        if (ret != 0) {
+            goto exit;
+        }
+
+        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
+            ret = mbedtls_pk_ecc_set_key(pk, exp_key, exp_key_len);
+            if (ret != 0) {
+                goto exit;
+            }
+            ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, exp_key, exp_key_len,
+                                                     mbedtls_psa_get_random,
+                                                     MBEDTLS_PSA_RANDOM_STATE);
+        } else {
+            ret = mbedtls_pk_ecc_set_pubkey(pk, exp_key, exp_key_len);
+        }
+        if (ret != 0) {
+            goto exit;
+        }
+    } else
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+    {
+        (void) key_bits;
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+exit:
+    psa_reset_key_attributes(&key_attr);
+    mbedtls_platform_zeroize(exp_key, sizeof(exp_key));
+
+    return ret;
+}
+
+int mbedtls_pk_copy_from_psa(mbedtls_svc_key_id_t key_id,
+                             mbedtls_pk_context *pk)
+{
+    return copy_from_psa(key_id, pk, 0);
+}
+
+int mbedtls_pk_copy_public_from_psa(mbedtls_svc_key_id_t key_id,
+                                    mbedtls_pk_context *pk)
+{
+    return copy_from_psa(key_id, pk, 1);
+}
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
 /*
  * Helper for mbedtls_pk_sign and mbedtls_pk_verify
  */
@@ -378,7 +1000,7 @@ static inline int pk_hashlen_helper(mbedtls_md_type_t md_alg, size_t *hash_len)
         return 0;
     }
 
-    *hash_len = mbedtls_hash_info_get_size(md_alg);
+    *hash_len = mbedtls_md_get_size_from_type(md_alg);
 
     if (*hash_len == 0) {
         return -1;
@@ -443,7 +1065,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
             return ret;
         }
 
-        ret = ctx->pk_info->verify_rs_func(ctx->pk_ctx,
+        ret = ctx->pk_info->verify_rs_func(ctx,
                                            md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx);
 
         if (ret != MBEDTLS_ERR_ECP_IN_PROGRESS) {
@@ -460,7 +1082,7 @@ int mbedtls_pk_verify_restartable(mbedtls_pk_context *ctx,
         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
     }
 
-    return ctx->pk_info->verify_func(ctx->pk_ctx, md_alg, hash, hash_len,
+    return ctx->pk_info->verify_func(ctx, md_alg, hash, hash_len,
                                      sig, sig_len);
 }
 
@@ -504,13 +1126,21 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
         return mbedtls_pk_verify(ctx, md_alg, hash, hash_len, sig, sig_len);
     }
 
+    /* Ensure the PK context is of the right type otherwise mbedtls_pk_rsa()
+     * below would return a NULL pointer. */
+    if (mbedtls_pk_get_type(ctx) != MBEDTLS_PK_RSA) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+
 #if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const mbedtls_pk_rsassa_pss_options *pss_opts;
 
+#if SIZE_MAX > UINT_MAX
     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+#endif
 
     if (options == NULL) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
@@ -527,12 +1157,12 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
         psa_status_t status = PSA_ERROR_DATA_CORRUPT;
         psa_status_t destruction_status = PSA_ERROR_DATA_CORRUPT;
 
-        psa_algorithm_t psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+        psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
         mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
         psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
         psa_algorithm_t psa_sig_alg = PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg);
         p = buf + sizeof(buf);
-        key_len = mbedtls_pk_write_pubkey(&p, buf, ctx);
+        key_len = mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*ctx), buf, &p);
 
         if (key_len < 0) {
             return key_len;
@@ -571,7 +1201,7 @@ int mbedtls_pk_verify_ext(mbedtls_pk_type_t type, const void *options,
 
         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     } else
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
     {
         if (sig_len < mbedtls_pk_get_len(ctx)) {
             return MBEDTLS_ERR_RSA_VERIFY_FAILED;
@@ -626,7 +1256,7 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
             return ret;
         }
 
-        ret = ctx->pk_info->sign_rs_func(ctx->pk_ctx, md_alg,
+        ret = ctx->pk_info->sign_rs_func(ctx, md_alg,
                                          hash, hash_len,
                                          sig, sig_size, sig_len,
                                          f_rng, p_rng, rs_ctx->rs_ctx);
@@ -645,7 +1275,7 @@ int mbedtls_pk_sign_restartable(mbedtls_pk_context *ctx,
         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
     }
 
-    return ctx->pk_info->sign_func(ctx->pk_ctx, md_alg,
+    return ctx->pk_info->sign_func(ctx, md_alg,
                                    hash, hash_len,
                                    sig, sig_size, sig_len,
                                    f_rng, p_rng);
@@ -664,7 +1294,6 @@ int mbedtls_pk_sign(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                                        f_rng, p_rng, NULL);
 }
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
 /*
  * Make a signature given a signature type.
  */
@@ -676,11 +1305,6 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng)
 {
-#if defined(MBEDTLS_RSA_C)
-    psa_algorithm_t psa_md_alg;
-#endif /* MBEDTLS_RSA_C */
-    *sig_len = 0;
-
     if (ctx->pk_info == NULL) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
@@ -694,31 +1318,59 @@ int mbedtls_pk_sign_ext(mbedtls_pk_type_t pk_type,
                                sig, sig_size, sig_len, f_rng, p_rng);
     }
 
-#if defined(MBEDTLS_RSA_C)
-    psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    const psa_algorithm_t psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
     if (psa_md_alg == 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
     if (mbedtls_pk_get_type(ctx) == MBEDTLS_PK_OPAQUE) {
-        const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx->pk_ctx;
         psa_status_t status;
 
-        status = psa_sign_hash(*key, PSA_ALG_RSA_PSS(psa_md_alg),
+        /* PSA_ALG_RSA_PSS() behaves the same as PSA_ALG_RSA_PSS_ANY_SALT() when
+         * performing a signature, but they are encoded differently. Instead of
+         * extracting the proper one from the wrapped key policy, just try both. */
+        status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS(psa_md_alg),
                                hash, hash_len,
                                sig, sig_size, sig_len);
+        if (status == PSA_ERROR_NOT_PERMITTED) {
+            status = psa_sign_hash(ctx->priv_id, PSA_ALG_RSA_PSS_ANY_SALT(psa_md_alg),
+                                   hash, hash_len,
+                                   sig, sig_size, sig_len);
+        }
         return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
 
     return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PSS(psa_md_alg),
                                        ctx->pk_ctx, hash, hash_len,
                                        sig, sig_size, sig_len);
-#else /* MBEDTLS_RSA_C */
-    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-#endif /* !MBEDTLS_RSA_C */
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+    if (sig_size < mbedtls_pk_get_len(ctx)) {
+        return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+    }
+
+    if (pk_hashlen_helper(md_alg, &hash_len) != 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
 
+    mbedtls_rsa_context *const rsa_ctx = mbedtls_pk_rsa(*ctx);
+
+    const int ret = mbedtls_rsa_rsassa_pss_sign_no_mode_check(rsa_ctx, f_rng, p_rng, md_alg,
+                                                              (unsigned int) hash_len, hash, sig);
+    if (ret == 0) {
+        *sig_len = rsa_ctx->len;
+    }
+    return ret;
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#else
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */
 }
-#endif /* MBEDTLS_PSA_CRYPTO_C */
 
 /*
  * Decrypt message
@@ -736,7 +1388,7 @@ int mbedtls_pk_decrypt(mbedtls_pk_context *ctx,
         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
     }
 
-    return ctx->pk_info->decrypt_func(ctx->pk_ctx, input, ilen,
+    return ctx->pk_info->decrypt_func(ctx, input, ilen,
                                       output, olen, osize, f_rng, p_rng);
 }
 
@@ -756,7 +1408,7 @@ int mbedtls_pk_encrypt(mbedtls_pk_context *ctx,
         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
     }
 
-    return ctx->pk_info->encrypt_func(ctx->pk_ctx, input, ilen,
+    return ctx->pk_info->encrypt_func(ctx, input, ilen,
                                       output, olen, osize, f_rng, p_rng);
 }
 
@@ -786,12 +1438,15 @@ int mbedtls_pk_check_pair(const mbedtls_pk_context *pub,
             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
         }
     } else {
-        if (pub->pk_info != prv->pk_info) {
+        if ((prv->pk_info->type != MBEDTLS_PK_OPAQUE) &&
+            (pub->pk_info != prv->pk_info)) {
             return MBEDTLS_ERR_PK_TYPE_MISMATCH;
         }
     }
 
-    return prv->pk_info->check_pair_func(pub->pk_ctx, prv->pk_ctx, f_rng, p_rng);
+    return prv->pk_info->check_pair_func((mbedtls_pk_context *) pub,
+                                         (mbedtls_pk_context *) prv,
+                                         f_rng, p_rng);
 }
 
 /*
@@ -805,7 +1460,7 @@ size_t mbedtls_pk_get_bitlen(const mbedtls_pk_context *ctx)
         return 0;
     }
 
-    return ctx->pk_info->get_bitlen(ctx->pk_ctx);
+    return ctx->pk_info->get_bitlen((mbedtls_pk_context *) ctx);
 }
 
 /*
@@ -821,7 +1476,7 @@ int mbedtls_pk_debug(const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items
         return MBEDTLS_ERR_PK_TYPE_MISMATCH;
     }
 
-    ctx->pk_info->debug_func(ctx->pk_ctx, items);
+    ctx->pk_info->debug_func((mbedtls_pk_context *) ctx, items);
     return 0;
 }
 
@@ -849,112 +1504,4 @@ mbedtls_pk_type_t mbedtls_pk_get_type(const mbedtls_pk_context *ctx)
     return ctx->pk_info->type;
 }
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Load the key to a PSA key slot,
- * then turn the PK context into a wrapper for that key slot.
- *
- * Currently only works for EC & RSA private keys.
- */
-int mbedtls_pk_wrap_as_opaque(mbedtls_pk_context *pk,
-                              mbedtls_svc_key_id_t *key,
-                              psa_algorithm_t alg,
-                              psa_key_usage_t usage,
-                              psa_algorithm_t alg2)
-{
-#if !defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_RSA_C)
-    ((void) pk);
-    ((void) key);
-    ((void) alg);
-    ((void) usage);
-    ((void) alg2);
-#else
-#if defined(MBEDTLS_ECP_C)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_ECKEY) {
-        const mbedtls_ecp_keypair *ec;
-        unsigned char d[MBEDTLS_ECP_MAX_BYTES];
-        size_t d_len;
-        psa_ecc_family_t curve_id;
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        psa_key_type_t key_type;
-        size_t bits;
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        psa_status_t status;
-
-        /* export the private key material in the format PSA wants */
-        ec = mbedtls_pk_ec(*pk);
-        d_len = PSA_BITS_TO_BYTES(ec->grp.nbits);
-        if ((ret = mbedtls_mpi_write_binary(&ec->d, d, d_len)) != 0) {
-            return ret;
-        }
-
-        curve_id = mbedtls_ecc_group_to_psa(ec->grp.id, &bits);
-        key_type = PSA_KEY_TYPE_ECC_KEY_PAIR(curve_id);
-
-        /* prepare the key attributes */
-        psa_set_key_type(&attributes, key_type);
-        psa_set_key_bits(&attributes, bits);
-        psa_set_key_usage_flags(&attributes, usage);
-        psa_set_key_algorithm(&attributes, alg);
-        if (alg2 != PSA_ALG_NONE) {
-            psa_set_key_enrollment_algorithm(&attributes, alg2);
-        }
-
-        /* import private key into PSA */
-        status = psa_import_key(&attributes, d, d_len, key);
-        if (status != PSA_SUCCESS) {
-            return PSA_PK_TO_MBEDTLS_ERR(status);
-        }
-
-        /* make PK context wrap the key slot */
-        mbedtls_pk_free(pk);
-        mbedtls_pk_init(pk);
-
-        return mbedtls_pk_setup_opaque(pk, *key);
-    } else
-#endif /* MBEDTLS_ECP_C */
-#if defined(MBEDTLS_RSA_C)
-    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_RSA) {
-        unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        int key_len;
-        psa_status_t status;
-
-        /* export the private key material in the format PSA wants */
-        key_len = mbedtls_pk_write_key_der(pk, buf, sizeof(buf));
-        if (key_len <= 0) {
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        }
-
-        /* prepare the key attributes */
-        psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
-        psa_set_key_bits(&attributes, mbedtls_pk_get_bitlen(pk));
-        psa_set_key_usage_flags(&attributes, usage);
-        psa_set_key_algorithm(&attributes, alg);
-        if (alg2 != PSA_ALG_NONE) {
-            psa_set_key_enrollment_algorithm(&attributes, alg2);
-        }
-
-        /* import private key into PSA */
-        status = psa_import_key(&attributes,
-                                buf + sizeof(buf) - key_len,
-                                key_len, key);
-
-        mbedtls_platform_zeroize(buf, sizeof(buf));
-
-        if (status != PSA_SUCCESS) {
-            return PSA_PK_TO_MBEDTLS_ERR(status);
-        }
-
-        /* make PK context wrap the key slot */
-        mbedtls_pk_free(pk);
-        mbedtls_pk_init(pk);
-
-        return mbedtls_pk_setup_opaque(pk, *key);
-    } else
-#endif /* MBEDTLS_RSA_C */
-#endif /* !MBEDTLS_ECP_C && !MBEDTLS_RSA_C */
-    return MBEDTLS_ERR_PK_TYPE_MISMATCH;
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif /* MBEDTLS_PK_C */
diff --git a/lib/libmbedtls/mbedtls/library/pk_ecc.c b/lib/libmbedtls/mbedtls/library/pk_ecc.c
new file mode 100644
index 0000000000000000000000000000000000000000..86218fffc898952e191e277fed3e46172c4068e2
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/pk_ecc.c
@@ -0,0 +1,255 @@
+/*
+ *  ECC setters for PK.
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#include "mbedtls/pk.h"
+#include "mbedtls/error.h"
+#include "mbedtls/ecp.h"
+#include "pk_internal.h"
+
+#if defined(MBEDTLS_PK_C) && defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+
+int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    size_t ec_bits;
+    psa_ecc_family_t ec_family = mbedtls_ecc_group_to_psa(grp_id, &ec_bits);
+
+    /* group may already be initialized; if so, make sure IDs match */
+    if ((pk->ec_family != 0 && pk->ec_family != ec_family) ||
+        (pk->ec_bits != 0 && pk->ec_bits != ec_bits)) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
+
+    /* set group */
+    pk->ec_family = ec_family;
+    pk->ec_bits = ec_bits;
+
+    return 0;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    mbedtls_ecp_keypair *ecp = mbedtls_pk_ec_rw(*pk);
+
+    /* grp may already be initialized; if so, make sure IDs match */
+    if (mbedtls_pk_ec_ro(*pk)->grp.id != MBEDTLS_ECP_DP_NONE &&
+        mbedtls_pk_ec_ro(*pk)->grp.id != grp_id) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+    }
+
+    /* set group */
+    return mbedtls_ecp_group_load(&(ecp->grp), grp_id);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_usage_t flags;
+    psa_status_t status;
+
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(pk->ec_family));
+    if (pk->ec_family == PSA_ECC_FAMILY_MONTGOMERY) {
+        /* Do not set algorithm here because Montgomery keys cannot do ECDSA and
+         * the PK module cannot do ECDH. When the key will be used in TLS for
+         * ECDH, it will be exported and then re-imported with proper flags
+         * and algorithm. */
+        flags = PSA_KEY_USAGE_EXPORT;
+    } else {
+        psa_set_key_algorithm(&attributes,
+                              MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(PSA_ALG_ANY_HASH));
+        flags = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE |
+                PSA_KEY_USAGE_EXPORT;
+    }
+    psa_set_key_usage_flags(&attributes, flags);
+
+    status = psa_import_key(&attributes, key, key_len, &pk->priv_id);
+    return psa_pk_status_to_mbedtls(status);
+
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    mbedtls_ecp_keypair *eck = mbedtls_pk_ec_rw(*pk);
+    int ret = mbedtls_ecp_read_key(eck->grp.id, eck, key, key_len);
+    if (ret != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
+    return 0;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
+                                       const unsigned char *prv, size_t prv_len,
+                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+
+    (void) f_rng;
+    (void) p_rng;
+    (void) prv;
+    (void) prv_len;
+    psa_status_t status;
+
+    status = psa_export_public_key(pk->priv_id, pk->pub_raw, sizeof(pk->pub_raw),
+                                   &pk->pub_raw_len);
+    return psa_pk_status_to_mbedtls(status);
+
+#elif defined(MBEDTLS_USE_PSA_CRYPTO) /* && !MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    (void) f_rng;
+    (void) p_rng;
+    psa_status_t status;
+
+    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    size_t curve_bits;
+    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(eck->grp.id, &curve_bits);
+
+    /* Import private key into PSA, from serialized input */
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
+    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
+    status = psa_import_key(&key_attr, prv, prv_len, &key_id);
+    if (status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(status);
+    }
+
+    /* Export public key from PSA */
+    unsigned char pub[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t pub_len;
+    status = psa_export_public_key(key_id, pub, sizeof(pub), &pub_len);
+    psa_status_t destruction_status = psa_destroy_key(key_id);
+    if (status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(status);
+    } else if (destruction_status != PSA_SUCCESS) {
+        return psa_pk_status_to_mbedtls(destruction_status);
+    }
+
+    /* Load serialized public key into ecp_keypair structure */
+    return mbedtls_ecp_point_read_binary(&eck->grp, &eck->Q, pub, pub_len);
+
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+
+    (void) prv;
+    (void) prv_len;
+
+    mbedtls_ecp_keypair *eck = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    return mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G, f_rng, p_rng);
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+/*
+ * Set the public key: fallback using ECP_LIGHT in the USE_PSA_EC_DATA case.
+ *
+ * Normally, when MBEDTLS_PK_USE_PSA_EC_DATA is enabled, we only use PSA
+ * functions to handle keys. However, currently psa_import_key() does not
+ * support compressed points. In case that support was explicitly requested,
+ * this fallback uses ECP functions to get the job done. This is the reason
+ * why MBEDTLS_PK_PARSE_EC_COMPRESSED auto-enables MBEDTLS_ECP_LIGHT.
+ *
+ * [in/out] pk: in: must have the group set, see mbedtls_pk_ecc_set_group().
+ *              out: will have the public key set.
+ * [in] pub, pub_len: the public key as an ECPoint,
+ *                    in any format supported by ECP.
+ *
+ * Return:
+ * - 0 on success;
+ * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
+ *   but not supported;
+ * - another error code otherwise.
+ */
+static int pk_ecc_set_pubkey_psa_ecp_fallback(mbedtls_pk_context *pk,
+                                              const unsigned char *pub,
+                                              size_t pub_len)
+{
+#if !defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
+    (void) pk;
+    (void) pub;
+    (void) pub_len;
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+#else /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
+    mbedtls_ecp_keypair ecp_key;
+    mbedtls_ecp_group_id ecp_group_id;
+    int ret;
+
+    ecp_group_id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
+
+    mbedtls_ecp_keypair_init(&ecp_key);
+    ret = mbedtls_ecp_group_load(&(ecp_key.grp), ecp_group_id);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_ecp_point_read_binary(&(ecp_key.grp), &ecp_key.Q,
+                                        pub, pub_len);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_ecp_point_write_binary(&(ecp_key.grp), &ecp_key.Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &pk->pub_raw_len, pk->pub_raw,
+                                         sizeof(pk->pub_raw));
+
+exit:
+    mbedtls_ecp_keypair_free(&ecp_key);
+    return ret;
+#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len)
+{
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+
+    /* Load the key */
+    if (!PSA_ECC_FAMILY_IS_WEIERSTRASS(pk->ec_family) || *pub == 0x04) {
+        /* Format directly supported by PSA:
+         * - non-Weierstrass curves that only have one format;
+         * - uncompressed format for Weierstrass curves. */
+        if (pub_len > sizeof(pk->pub_raw)) {
+            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+        }
+        memcpy(pk->pub_raw, pub, pub_len);
+        pk->pub_raw_len = pub_len;
+    } else {
+        /* Other format, try the fallback */
+        int ret = pk_ecc_set_pubkey_psa_ecp_fallback(pk, pub, pub_len);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+
+    /* Validate the key by trying to import it */
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t key_attrs = PSA_KEY_ATTRIBUTES_INIT;
+
+    psa_set_key_usage_flags(&key_attrs, 0);
+    psa_set_key_type(&key_attrs, PSA_KEY_TYPE_ECC_PUBLIC_KEY(pk->ec_family));
+    psa_set_key_bits(&key_attrs, pk->ec_bits);
+
+    if ((psa_import_key(&key_attrs, pk->pub_raw, pk->pub_raw_len,
+                        &key_id) != PSA_SUCCESS) ||
+        (psa_destroy_key(key_id) != PSA_SUCCESS)) {
+        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    }
+
+    return 0;
+
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+    int ret;
+    mbedtls_ecp_keypair *ec_key = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    ret = mbedtls_ecp_point_read_binary(&ec_key->grp, &ec_key->Q, pub, pub_len);
+    if (ret != 0) {
+        return ret;
+    }
+    return mbedtls_ecp_check_pubkey(&ec_key->grp, &ec_key->Q);
+
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+}
+
+#endif /* MBEDTLS_PK_C && MBEDTLS_PK_HAVE_ECC_KEYS */
diff --git a/lib/libmbedtls/mbedtls/library/pk_internal.h b/lib/libmbedtls/mbedtls/library/pk_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..e86a3a09d2c57e0bcf45bf4caff019740f0e9033
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/pk_internal.h
@@ -0,0 +1,207 @@
+/**
+ * \file pk_internal.h
+ *
+ * \brief Public Key abstraction layer: internal (i.e. library only) functions
+ *        and definitions.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_PK_INTERNAL_H
+#define MBEDTLS_PK_INTERNAL_H
+
+#include "mbedtls/pk.h"
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#include "mbedtls/ecp.h"
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+#include "psa/crypto.h"
+
+#include "psa_util_internal.h"
+#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
+#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
+                                                                  psa_to_pk_rsa_errors,            \
+                                                                  psa_pk_status_to_mbedtls)
+#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
+                                                                    psa_to_pk_ecdsa_errors,        \
+                                                                    psa_pk_status_to_mbedtls)
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
+/* Headers/footers for PEM files */
+#define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----"
+#define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----"
+#define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----"
+#define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----"
+#define PEM_BEGIN_PUBLIC_KEY_RSA     "-----BEGIN RSA PUBLIC KEY-----"
+#define PEM_END_PUBLIC_KEY_RSA     "-----END RSA PUBLIC KEY-----"
+#define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----"
+#define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----"
+#define PEM_BEGIN_PRIVATE_KEY_PKCS8 "-----BEGIN PRIVATE KEY-----"
+#define PEM_END_PRIVATE_KEY_PKCS8   "-----END PRIVATE KEY-----"
+#define PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8 "-----BEGIN ENCRYPTED PRIVATE KEY-----"
+#define PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8   "-----END ENCRYPTED PRIVATE KEY-----"
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS) && !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+/**
+ * Public function mbedtls_pk_ec() can be used to get direct access to the
+ * wrapped ecp_keypair structure pointed to the pk_ctx. However this is not
+ * ideal because it bypasses the PK module on the control of its internal
+ * structure (pk_context) fields.
+ * For backward compatibility we keep mbedtls_pk_ec() when ECP_C is defined, but
+ * we provide 2 very similar functions when only ECP_LIGHT is enabled and not
+ * ECP_C.
+ * These variants embed the "ro" or "rw" keywords in their name to make the
+ * usage of the returned pointer explicit. Of course the returned value is
+ * const or non-const accordingly.
+ */
+static inline const mbedtls_ecp_keypair *mbedtls_pk_ec_ro(const mbedtls_pk_context pk)
+{
+    switch (mbedtls_pk_get_type(&pk)) {
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            return (const mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);
+        default:
+            return NULL;
+    }
+}
+
+static inline mbedtls_ecp_keypair *mbedtls_pk_ec_rw(const mbedtls_pk_context pk)
+{
+    switch (mbedtls_pk_get_type(&pk)) {
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+            return (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx);
+        default:
+            return NULL;
+    }
+}
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS && !MBEDTLS_PK_USE_PSA_EC_DATA */
+
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+static inline mbedtls_ecp_group_id mbedtls_pk_get_ec_group_id(const mbedtls_pk_context *pk)
+{
+    mbedtls_ecp_group_id id;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
+        psa_key_type_t opaque_key_type;
+        psa_ecc_family_t curve;
+
+        if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
+            return MBEDTLS_ECP_DP_NONE;
+        }
+        opaque_key_type = psa_get_key_type(&opaque_attrs);
+        curve = PSA_KEY_TYPE_ECC_GET_FAMILY(opaque_key_type);
+        id = mbedtls_ecc_group_from_psa(curve, psa_get_key_bits(&opaque_attrs));
+        psa_reset_key_attributes(&opaque_attrs);
+    } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    {
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        id = mbedtls_ecc_group_from_psa(pk->ec_family, pk->ec_bits);
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+        id = mbedtls_pk_ec_ro(*pk)->grp.id;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    }
+
+    return id;
+}
+
+/* Helper for Montgomery curves */
+#if defined(MBEDTLS_ECP_HAVE_CURVE25519) || defined(MBEDTLS_ECP_HAVE_CURVE448)
+#define MBEDTLS_PK_HAVE_RFC8410_CURVES
+#endif /* MBEDTLS_ECP_HAVE_CURVE25519 || MBEDTLS_ECP_DP_CURVE448 */
+
+#define MBEDTLS_PK_IS_RFC8410_GROUP_ID(id)  \
+    ((id == MBEDTLS_ECP_DP_CURVE25519) || (id == MBEDTLS_ECP_DP_CURVE448))
+
+static inline int mbedtls_pk_is_rfc8410(const mbedtls_pk_context *pk)
+{
+    mbedtls_ecp_group_id id = mbedtls_pk_get_ec_group_id(pk);
+
+    return MBEDTLS_PK_IS_RFC8410_GROUP_ID(id);
+}
+
+/*
+ * Set the group used by this key.
+ *
+ * [in/out] pk: in: must have been pk_setup() to an ECC type
+ *              out: will have group (curve) information set
+ * [in] grp_in: a supported group ID (not NONE)
+ */
+int mbedtls_pk_ecc_set_group(mbedtls_pk_context *pk, mbedtls_ecp_group_id grp_id);
+
+/*
+ * Set the private key material
+ *
+ * [in/out] pk: in: must have the group set already, see mbedtls_pk_ecc_set_group().
+ *              out: will have the private key set.
+ * [in] key, key_len: the raw private key (no ASN.1 wrapping).
+ */
+int mbedtls_pk_ecc_set_key(mbedtls_pk_context *pk, unsigned char *key, size_t key_len);
+
+/*
+ * Set the public key.
+ *
+ * [in/out] pk: in: must have its group set, see mbedtls_pk_ecc_set_group().
+ *              out: will have the public key set.
+ * [in] pub, pub_len: the raw public key (an ECPoint).
+ *
+ * Return:
+ * - 0 on success;
+ * - MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the format is potentially valid
+ *   but not supported;
+ * - another error code otherwise.
+ */
+int mbedtls_pk_ecc_set_pubkey(mbedtls_pk_context *pk, const unsigned char *pub, size_t pub_len);
+
+/*
+ * Derive a public key from its private counterpart.
+ * Computationally intensive, only use when public key is not available.
+ *
+ * [in/out] pk: in: must have the private key set, see mbedtls_pk_ecc_set_key().
+ *              out: will have the public key set.
+ * [in] prv, prv_len: the raw private key (see note below).
+ * [in] f_rng, p_rng: RNG function and context.
+ *
+ * Note: the private key information is always available from pk,
+ * however for convenience the serialized version is also passed,
+ * as it's available at each calling site, and useful in some configs
+ * (as otherwise we would have to re-serialize it from the pk context).
+ *
+ * There are three implementations of this function:
+ * 1. MBEDTLS_PK_USE_PSA_EC_DATA,
+ * 2. MBEDTLS_USE_PSA_CRYPTO but not MBEDTLS_PK_USE_PSA_EC_DATA,
+ * 3. not MBEDTLS_USE_PSA_CRYPTO.
+ */
+int mbedtls_pk_ecc_set_pubkey_from_prv(mbedtls_pk_context *pk,
+                                       const unsigned char *prv, size_t prv_len,
+                                       int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/* Helper for (deterministic) ECDSA */
+#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
+#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET  PSA_ALG_DETERMINISTIC_ECDSA
+#else
+#define MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET  PSA_ALG_ECDSA
+#endif
+
+#if defined(MBEDTLS_TEST_HOOKS)
+MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
+    mbedtls_pk_context *pk,
+    unsigned char *key, size_t keylen,
+    const unsigned char *pwd, size_t pwdlen,
+    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng);
+#endif
+
+#if defined(MBEDTLS_FS_IO)
+int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n);
+#endif
+
+#endif /* MBEDTLS_PK_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/pk_wrap.c b/lib/libmbedtls/mbedtls/library/pk_wrap.c
index 4d91f22b2e5076449a594935122bb6fedec5f0bf..19196b559ae95ed75bc0ecfa6f38055b695a6b02 100644
--- a/lib/libmbedtls/mbedtls/library/pk_wrap.c
+++ b/lib/libmbedtls/mbedtls/library/pk_wrap.c
@@ -2,19 +2,7 @@
  *  Public Key abstraction layer: wrapper functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -23,7 +11,9 @@
 
 #if defined(MBEDTLS_PK_C)
 #include "pk_wrap.h"
+#include "pk_internal.h"
 #include "mbedtls/error.h"
+#include "mbedtls/psa_util.h"
 
 /* Even if RSA not activated, for the sake of RSA-alt */
 #include "mbedtls/rsa.h"
@@ -36,24 +26,15 @@
 #include "mbedtls/ecdsa.h"
 #endif
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PSA_CRYPTO_C)
-#include "pkwrite.h"
-#endif
-
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#include "mbedtls/psa_util.h"
-#define PSA_PK_TO_MBEDTLS_ERR(status) psa_pk_status_to_mbedtls(status)
-#define PSA_PK_RSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,     \
-                                                                  psa_to_pk_rsa_errors,            \
-                                                                  psa_pk_status_to_mbedtls)
-#define PSA_PK_ECDSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                                    psa_to_pk_ecdsa_errors,        \
-                                                                    psa_pk_status_to_mbedtls)
-#endif
-
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa_util_internal.h"
 #include "psa/crypto.h"
-#include "hash_info.h"
+#include "mbedtls/psa_util.h"
+
+#if defined(MBEDTLS_RSA_C)
+#include "pkwrite.h"
+#include "rsa_internal.h"
+#endif
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
 #include "mbedtls/asn1write.h"
@@ -67,123 +48,6 @@
 #include <stdint.h>
 #include <string.h>
 
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-int mbedtls_pk_error_from_psa(psa_status_t status)
-{
-    switch (status) {
-        case PSA_SUCCESS:
-            return 0;
-        case PSA_ERROR_INVALID_HANDLE:
-            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-        case PSA_ERROR_NOT_PERMITTED:
-            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-        case PSA_ERROR_BUFFER_TOO_SMALL:
-            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
-        case PSA_ERROR_NOT_SUPPORTED:
-            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_INVALID_ARGUMENT:
-            return MBEDTLS_ERR_PK_INVALID_ALG;
-        case PSA_ERROR_INSUFFICIENT_MEMORY:
-            return MBEDTLS_ERR_PK_ALLOC_FAILED;
-        case PSA_ERROR_BAD_STATE:
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        case PSA_ERROR_COMMUNICATION_FAILURE:
-        case PSA_ERROR_HARDWARE_FAILURE:
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-        case PSA_ERROR_DATA_CORRUPT:
-        case PSA_ERROR_DATA_INVALID:
-        case PSA_ERROR_STORAGE_FAILURE:
-            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-        case PSA_ERROR_CORRUPTION_DETECTED:
-            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        default:
-            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-    }
-}
-
-#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
-    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-int mbedtls_pk_error_from_psa_rsa(psa_status_t status)
-{
-    switch (status) {
-        case PSA_ERROR_NOT_PERMITTED:
-        case PSA_ERROR_INVALID_ARGUMENT:
-        case PSA_ERROR_INVALID_HANDLE:
-            return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-        case PSA_ERROR_BUFFER_TOO_SMALL:
-            return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
-        case PSA_ERROR_INSUFFICIENT_ENTROPY:
-            return MBEDTLS_ERR_RSA_RNG_FAILED;
-        case PSA_ERROR_INVALID_SIGNATURE:
-            return MBEDTLS_ERR_RSA_VERIFY_FAILED;
-        case PSA_ERROR_INVALID_PADDING:
-            return MBEDTLS_ERR_RSA_INVALID_PADDING;
-        case PSA_SUCCESS:
-            return 0;
-        case PSA_ERROR_NOT_SUPPORTED:
-            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_INSUFFICIENT_MEMORY:
-            return MBEDTLS_ERR_PK_ALLOC_FAILED;
-        case PSA_ERROR_BAD_STATE:
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        case PSA_ERROR_COMMUNICATION_FAILURE:
-        case PSA_ERROR_HARDWARE_FAILURE:
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-        case PSA_ERROR_DATA_CORRUPT:
-        case PSA_ERROR_DATA_INVALID:
-        case PSA_ERROR_STORAGE_FAILURE:
-            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-        case PSA_ERROR_CORRUPTION_DETECTED:
-            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        default:
-            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-    }
-}
-#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
-#endif /* MBEDTLS_PSA_CRYPTO_C */
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-int mbedtls_pk_error_from_psa_ecdsa(psa_status_t status)
-{
-    switch (status) {
-        case PSA_ERROR_NOT_PERMITTED:
-        case PSA_ERROR_INVALID_ARGUMENT:
-            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
-        case PSA_ERROR_INVALID_HANDLE:
-            return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_BUFFER_TOO_SMALL:
-            return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
-        case PSA_ERROR_INSUFFICIENT_ENTROPY:
-            return MBEDTLS_ERR_ECP_RANDOM_FAILED;
-        case PSA_ERROR_INVALID_SIGNATURE:
-            return MBEDTLS_ERR_ECP_VERIFY_FAILED;
-        case PSA_SUCCESS:
-            return 0;
-        case PSA_ERROR_NOT_SUPPORTED:
-            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-        case PSA_ERROR_INSUFFICIENT_MEMORY:
-            return MBEDTLS_ERR_PK_ALLOC_FAILED;
-        case PSA_ERROR_BAD_STATE:
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        case PSA_ERROR_COMMUNICATION_FAILURE:
-        case PSA_ERROR_HARDWARE_FAILURE:
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-        case PSA_ERROR_DATA_CORRUPT:
-        case PSA_ERROR_DATA_INVALID:
-        case PSA_ERROR_STORAGE_FAILURE:
-            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-        case PSA_ERROR_CORRUPTION_DETECTED:
-            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        default:
-            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-    }
-}
-#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
-
 #if defined(MBEDTLS_RSA_C)
 static int rsa_can_do(mbedtls_pk_type_t type)
 {
@@ -191,42 +55,45 @@ static int rsa_can_do(mbedtls_pk_type_t type)
            type == MBEDTLS_PK_RSASSA_PSS;
 }
 
-static size_t rsa_get_bitlen(const void *ctx)
+static size_t rsa_get_bitlen(mbedtls_pk_context *pk)
 {
-    const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) ctx;
-    return 8 * mbedtls_rsa_get_len(rsa);
+    const mbedtls_rsa_context *rsa = (const mbedtls_rsa_context *) pk->pk_ctx;
+    return mbedtls_rsa_get_bitlen(rsa);
 }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hash_len,
                            const unsigned char *sig, size_t sig_len)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
-    mbedtls_pk_context key;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
-    psa_algorithm_t psa_alg_md =
-        PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
+    unsigned char *p = buf + sizeof(buf);
+    psa_algorithm_t psa_alg_md;
     size_t rsa_len = mbedtls_rsa_get_len(rsa);
 
+#if SIZE_MAX > UINT_MAX
     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+#endif
+
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_alg_md = PSA_ALG_RSA_PSS(mbedtls_md_psa_alg_from_type(md_alg));
+    } else {
+        psa_alg_md = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_md_psa_alg_from_type(md_alg));
+    }
 
     if (sig_len < rsa_len) {
         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
     }
 
-    /* mbedtls_pk_write_pubkey_der() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &mbedtls_rsa_info;
-    key.pk_ctx = ctx;
-    key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+    key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
     if (key_len <= 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
@@ -259,18 +126,20 @@ cleanup:
 
     return ret;
 }
-#else
-static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int rsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hash_len,
                            const unsigned char *sig, size_t sig_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
     size_t rsa_len = mbedtls_rsa_get_len(rsa);
 
+#if SIZE_MAX > UINT_MAX
     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+#endif
 
     if (sig_len < rsa_len) {
         return MBEDTLS_ERR_RSA_VERIFY_FAILED;
@@ -293,9 +162,9 @@ static int rsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
 
     return 0;
 }
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
 int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
                                  mbedtls_rsa_context *rsa_ctx,
                                  const unsigned char *hash, size_t hash_len,
@@ -306,22 +175,25 @@ int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
-    mbedtls_pk_context key;
     int key_len;
-    unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
-    mbedtls_pk_info_t pk_info = mbedtls_rsa_info;
+    unsigned char *buf = NULL;
+    unsigned char *p;
+
+    buf = mbedtls_calloc(1, MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES);
+    if (buf == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
+    p = buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES;
 
     *sig_len = mbedtls_rsa_get_len(rsa_ctx);
     if (sig_size < *sig_len) {
+        mbedtls_free(buf);
         return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
     }
 
-    /* mbedtls_pk_write_key_der() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &pk_info;
-    key.pk_ctx = rsa_ctx;
-    key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
+    key_len = mbedtls_rsa_write_key(rsa_ctx, buf, &p);
     if (key_len <= 0) {
+        mbedtls_free(buf);
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
@@ -329,7 +201,7 @@ int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
 
     status = psa_import_key(&attributes,
-                            buf + sizeof(buf) - key_len, key_len,
+                            buf + MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES - key_len, key_len,
                             &key_id);
     if (status != PSA_SUCCESS) {
         ret = PSA_PK_TO_MBEDTLS_ERR(status);
@@ -345,16 +217,17 @@ int  mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t alg,
     ret = 0;
 
 cleanup:
+    mbedtls_free(buf);
     status = psa_destroy_key(key_id);
     if (ret == 0 && status != PSA_SUCCESS) {
         ret = PSA_PK_TO_MBEDTLS_ERR(status);
     }
     return ret;
 }
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                          const unsigned char *hash, size_t hash_len,
                          unsigned char *sig, size_t sig_size, size_t *sig_len,
                          int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
@@ -363,27 +236,33 @@ static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
     ((void) p_rng);
 
     psa_algorithm_t psa_md_alg;
-    psa_md_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    psa_md_alg = mbedtls_md_psa_alg_from_type(md_alg);
     if (psa_md_alg == 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+    psa_algorithm_t psa_alg;
+    if (mbedtls_rsa_get_padding_mode(mbedtls_pk_rsa(*pk)) == MBEDTLS_RSA_PKCS_V21) {
+        psa_alg = PSA_ALG_RSA_PSS(psa_md_alg);
+    } else {
+        psa_alg = PSA_ALG_RSA_PKCS1V15_SIGN(psa_md_alg);
+    }
 
-    return mbedtls_pk_psa_rsa_sign_ext(PSA_ALG_RSA_PKCS1V15_SIGN(
-                                           psa_md_alg),
-                                       ctx, hash, hash_len,
+    return mbedtls_pk_psa_rsa_sign_ext(psa_alg, pk->pk_ctx, hash, hash_len,
                                        sig, sig_size, sig_len);
 }
-#else
-static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int rsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                          const unsigned char *hash, size_t hash_len,
                          unsigned char *sig, size_t sig_size, size_t *sig_len,
                          int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
 
+#if SIZE_MAX > UINT_MAX
     if (md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+#endif
 
     *sig_len = mbedtls_rsa_get_len(rsa);
     if (sig_size < *sig_len) {
@@ -394,48 +273,45 @@ static int rsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
                                   md_alg, (unsigned int) hash_len,
                                   hash, sig);
 }
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-static int rsa_decrypt_wrap(void *ctx,
+static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
                             const unsigned char *input, size_t ilen,
                             unsigned char *output, size_t *olen, size_t osize,
                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_algorithm_t psa_md_alg, decrypt_alg;
     psa_status_t status;
-    mbedtls_pk_context key;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PRV_DER_MAX_BYTES];
+    unsigned char *p = buf + sizeof(buf);
 
     ((void) f_rng);
     ((void) p_rng);
 
-#if !defined(MBEDTLS_RSA_ALT)
-    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
-        return MBEDTLS_ERR_RSA_INVALID_PADDING;
-    }
-#endif /* !MBEDTLS_RSA_ALT */
-
     if (ilen != mbedtls_rsa_get_len(rsa)) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
-    /* mbedtls_pk_write_key_der() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &mbedtls_rsa_info;
-    key.pk_ctx = ctx;
-    key_len = mbedtls_pk_write_key_der(&key, buf, sizeof(buf));
+    key_len = mbedtls_rsa_write_key(rsa, buf, &p);
     if (key_len <= 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
-    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+        decrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
+    } else {
+        decrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
+    }
+    psa_set_key_algorithm(&attributes, decrypt_alg);
 
     status = psa_import_key(&attributes,
                             buf + sizeof(buf) - key_len, key_len,
@@ -445,7 +321,7 @@ static int rsa_decrypt_wrap(void *ctx,
         goto cleanup;
     }
 
-    status = psa_asymmetric_decrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+    status = psa_asymmetric_decrypt(key_id, decrypt_alg,
                                     input, ilen,
                                     NULL, 0,
                                     output, osize, olen);
@@ -465,13 +341,13 @@ cleanup:
 
     return ret;
 }
-#else
-static int rsa_decrypt_wrap(void *ctx,
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int rsa_decrypt_wrap(mbedtls_pk_context *pk,
                             const unsigned char *input, size_t ilen,
                             unsigned char *output, size_t *olen, size_t osize,
                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
 
     if (ilen != mbedtls_rsa_get_len(rsa)) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
@@ -480,47 +356,44 @@ static int rsa_decrypt_wrap(void *ctx,
     return mbedtls_rsa_pkcs1_decrypt(rsa, f_rng, p_rng,
                                      olen, input, output, osize);
 }
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-static int rsa_encrypt_wrap(void *ctx,
+static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
                             const unsigned char *input, size_t ilen,
                             unsigned char *output, size_t *olen, size_t osize,
                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_algorithm_t psa_md_alg, psa_encrypt_alg;
     psa_status_t status;
-    mbedtls_pk_context key;
     int key_len;
     unsigned char buf[MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES];
+    unsigned char *p = buf + sizeof(buf);
 
     ((void) f_rng);
     ((void) p_rng);
 
-#if !defined(MBEDTLS_RSA_ALT)
-    if (rsa->padding != MBEDTLS_RSA_PKCS_V15) {
-        return MBEDTLS_ERR_RSA_INVALID_PADDING;
-    }
-#endif
-
     if (mbedtls_rsa_get_len(rsa) > osize) {
         return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
     }
 
-    /* mbedtls_pk_write_pubkey_der() expects a full PK context;
-     * re-construct one to make it happy */
-    key.pk_info = &mbedtls_rsa_info;
-    key.pk_ctx = ctx;
-    key_len = mbedtls_pk_write_pubkey_der(&key, buf, sizeof(buf));
+    key_len = mbedtls_rsa_write_pubkey(rsa, buf, &p);
     if (key_len <= 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
 
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
-    psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
+    if (mbedtls_rsa_get_padding_mode(rsa) == MBEDTLS_RSA_PKCS_V21) {
+        psa_md_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) mbedtls_rsa_get_md_alg(rsa));
+        psa_encrypt_alg = PSA_ALG_RSA_OAEP(psa_md_alg);
+    } else {
+        psa_encrypt_alg = PSA_ALG_RSA_PKCS1V15_CRYPT;
+    }
+    psa_set_key_algorithm(&attributes, psa_encrypt_alg);
     psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_PUBLIC_KEY);
 
     status = psa_import_key(&attributes,
@@ -531,7 +404,7 @@ static int rsa_encrypt_wrap(void *ctx,
         goto cleanup;
     }
 
-    status = psa_asymmetric_encrypt(key_id, PSA_ALG_RSA_PKCS1V15_CRYPT,
+    status = psa_asymmetric_encrypt(key_id, psa_encrypt_alg,
                                     input, ilen,
                                     NULL, 0,
                                     output, osize, olen);
@@ -550,13 +423,13 @@ cleanup:
 
     return ret;
 }
-#else
-static int rsa_encrypt_wrap(void *ctx,
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int rsa_encrypt_wrap(mbedtls_pk_context *pk,
                             const unsigned char *input, size_t ilen,
                             unsigned char *output, size_t *olen, size_t osize,
                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) ctx;
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
     *olen = mbedtls_rsa_get_len(rsa);
 
     if (*olen > osize) {
@@ -566,16 +439,16 @@ static int rsa_encrypt_wrap(void *ctx,
     return mbedtls_rsa_pkcs1_encrypt(rsa, f_rng, p_rng,
                                      ilen, input, output);
 }
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-static int rsa_check_pair_wrap(const void *pub, const void *prv,
+static int rsa_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
                                int (*f_rng)(void *, unsigned char *, size_t),
                                void *p_rng)
 {
     (void) f_rng;
     (void) p_rng;
-    return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub,
-                                      (const mbedtls_rsa_context *) prv);
+    return mbedtls_rsa_check_pub_priv((const mbedtls_rsa_context *) pub->pk_ctx,
+                                      (const mbedtls_rsa_context *) prv->pk_ctx);
 }
 
 static void *rsa_alloc_wrap(void)
@@ -595,50 +468,50 @@ static void rsa_free_wrap(void *ctx)
     mbedtls_free(ctx);
 }
 
-static void rsa_debug(const void *ctx, mbedtls_pk_debug_item *items)
+static void rsa_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items)
 {
 #if defined(MBEDTLS_RSA_ALT)
     /* Not supported */
-    (void) ctx;
+    (void) pk;
     (void) items;
 #else
+    mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) pk->pk_ctx;
+
     items->type = MBEDTLS_PK_DEBUG_MPI;
     items->name = "rsa.N";
-    items->value = &(((mbedtls_rsa_context *) ctx)->N);
+    items->value = &(rsa->N);
 
     items++;
 
     items->type = MBEDTLS_PK_DEBUG_MPI;
     items->name = "rsa.E";
-    items->value = &(((mbedtls_rsa_context *) ctx)->E);
+    items->value = &(rsa->E);
 #endif
 }
 
 const mbedtls_pk_info_t mbedtls_rsa_info = {
-    MBEDTLS_PK_RSA,
-    "RSA",
-    rsa_get_bitlen,
-    rsa_can_do,
-    rsa_verify_wrap,
-    rsa_sign_wrap,
+    .type = MBEDTLS_PK_RSA,
+    .name = "RSA",
+    .get_bitlen = rsa_get_bitlen,
+    .can_do = rsa_can_do,
+    .verify_func = rsa_verify_wrap,
+    .sign_func = rsa_sign_wrap,
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    rsa_decrypt_wrap,
-    rsa_encrypt_wrap,
-    rsa_check_pair_wrap,
-    rsa_alloc_wrap,
-    rsa_free_wrap,
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    rsa_debug,
+    .verify_rs_func = NULL,
+    .sign_rs_func = NULL,
+    .rs_alloc_func = NULL,
+    .rs_free_func = NULL,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = rsa_decrypt_wrap,
+    .encrypt_func = rsa_encrypt_wrap,
+    .check_pair_func = rsa_check_pair_wrap,
+    .ctx_alloc_func = rsa_alloc_wrap,
+    .ctx_free_func = rsa_free_wrap,
+    .debug_func = rsa_debug,
 };
 #endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 /*
  * Generic EC key
  */
@@ -649,96 +522,33 @@ static int eckey_can_do(mbedtls_pk_type_t type)
            type == MBEDTLS_PK_ECDSA;
 }
 
-static size_t eckey_get_bitlen(const void *ctx)
+static size_t eckey_get_bitlen(mbedtls_pk_context *pk)
 {
-    return ((mbedtls_ecp_keypair *) ctx)->grp.pbits;
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    return pk->ec_bits;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx;
+    return ecp->grp.pbits;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 }
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of
- * those integers and convert it to the fixed-length encoding expected by PSA.
- */
-static int extract_ecdsa_sig_int(unsigned char **from, const unsigned char *end,
-                                 unsigned char *to, size_t to_len)
+/* Common helper for ECDSA verify using PSA functions. */
+static int ecdsa_verify_psa(unsigned char *key, size_t key_len,
+                            psa_ecc_family_t curve, size_t curve_bits,
+                            const unsigned char *hash, size_t hash_len,
+                            const unsigned char *sig, size_t sig_len)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t unpadded_len, padding_len;
-
-    if ((ret = mbedtls_asn1_get_tag(from, end, &unpadded_len,
-                                    MBEDTLS_ASN1_INTEGER)) != 0) {
-        return ret;
-    }
-
-    while (unpadded_len > 0 && **from == 0x00) {
-        (*from)++;
-        unpadded_len--;
-    }
-
-    if (unpadded_len > to_len || unpadded_len == 0) {
-        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
-    }
-
-    padding_len = to_len - unpadded_len;
-    memset(to, 0x00, padding_len);
-    memcpy(to + padding_len, *from, unpadded_len);
-    (*from) += unpadded_len;
-
-    return 0;
-}
-
-/*
- * Convert a signature from an ASN.1 sequence of two integers
- * to a raw {r,s} buffer. Note: the provided sig buffer must be at least
- * twice as big as int_size.
- */
-static int extract_ecdsa_sig(unsigned char **p, const unsigned char *end,
-                             unsigned char *sig, size_t int_size)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t tmp_size;
-
-    if ((ret = mbedtls_asn1_get_tag(p, end, &tmp_size,
-                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return ret;
-    }
-
-    /* Extract r */
-    if ((ret = extract_ecdsa_sig_int(p, end, sig, int_size)) != 0) {
-        return ret;
-    }
-    /* Extract s */
-    if ((ret = extract_ecdsa_sig_int(p, end, sig + int_size, int_size)) != 0) {
-        return ret;
-    }
-
-    return 0;
-}
-
-static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
-                             const unsigned char *hash, size_t hash_len,
-                             const unsigned char *sig, size_t sig_len)
-{
-    mbedtls_ecp_keypair *ctx = ctx_arg;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_status_t status;
-    size_t key_len;
-    /* This buffer will initially contain the public key and then the signature
-     * but at different points in time. For all curves except secp224k1, which
-     * is not currently supported in PSA, the public key is one byte longer
-     * (header byte + 2 numbers, while the signature is only 2 numbers),
-     * so use that as the buffer size. */
-    unsigned char buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
-    unsigned char *p;
     psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY;
-    size_t curve_bits;
-    psa_ecc_family_t curve =
-        mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
-    const size_t signature_part_size = (ctx->grp.nbits + 7) / 8;
-    ((void) md_alg);
+    size_t signature_len = PSA_ECDSA_SIGNATURE_SIZE(curve_bits);
+    size_t converted_sig_len;
+    unsigned char extracted_sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
+    unsigned char *p;
+    psa_status_t status;
 
     if (curve == 0) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
@@ -748,46 +558,36 @@ static int ecdsa_verify_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
     psa_set_key_algorithm(&attributes, psa_sig_md);
 
-    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,
-                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
-                                         &key_len, buf, sizeof(buf));
-    if (ret != 0) {
-        goto cleanup;
-    }
-
-    status = psa_import_key(&attributes,
-                            buf, key_len,
-                            &key_id);
+    status = psa_import_key(&attributes, key, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
-    /* We don't need the exported key anymore and can
-     * reuse its buffer for signature extraction. */
-    if (2 * signature_part_size > sizeof(buf)) {
+    if (signature_len > sizeof(extracted_sig)) {
         ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
         goto cleanup;
     }
 
     p = (unsigned char *) sig;
-    if ((ret = extract_ecdsa_sig(&p, sig + sig_len, buf,
-                                 signature_part_size)) != 0) {
+    ret = mbedtls_ecdsa_der_to_raw(curve_bits, p, sig_len, extracted_sig,
+                                   sizeof(extracted_sig), &converted_sig_len);
+    if (ret != 0) {
         goto cleanup;
     }
 
-    status = psa_verify_hash(key_id, psa_sig_md,
-                             hash, hash_len,
-                             buf, 2 * signature_part_size);
-    if (status != PSA_SUCCESS) {
-        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+    if (converted_sig_len != signature_len) {
+        ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA;
         goto cleanup;
     }
 
-    if (p != sig + sig_len) {
-        ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH;
+    status = psa_verify_hash(key_id, psa_sig_md, hash, hash_len,
+                             extracted_sig, signature_len);
+    if (status != PSA_SUCCESS) {
+        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
+
     ret = 0;
 
 cleanup:
@@ -798,15 +598,84 @@ cleanup:
 
     return ret;
 }
+
+static int ecdsa_opaque_verify_wrap(mbedtls_pk_context *pk,
+                                    mbedtls_md_type_t md_alg,
+                                    const unsigned char *hash, size_t hash_len,
+                                    const unsigned char *sig, size_t sig_len)
+{
+    (void) md_alg;
+    unsigned char key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];
+    size_t key_len;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_ecc_family_t curve;
+    size_t curve_bits;
+    psa_status_t status;
+
+    status = psa_get_key_attributes(pk->priv_id, &key_attr);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+    }
+    curve = PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(&key_attr));
+    curve_bits = psa_get_key_bits(&key_attr);
+    psa_reset_key_attributes(&key_attr);
+
+    status = psa_export_public_key(pk->priv_id, key, sizeof(key), &key_len);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+    }
+
+    return ecdsa_verify_psa(key, key_len, curve, curve_bits,
+                            hash, hash_len, sig, sig_len);
+}
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static int ecdsa_verify_wrap(mbedtls_pk_context *pk,
+                             mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             const unsigned char *sig, size_t sig_len)
+{
+    (void) md_alg;
+    psa_ecc_family_t curve = pk->ec_family;
+    size_t curve_bits = pk->ec_bits;
+
+    return ecdsa_verify_psa(pk->pub_raw, pk->pub_raw_len, curve, curve_bits,
+                            hash, hash_len, sig, sig_len);
+}
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int ecdsa_verify_wrap(mbedtls_pk_context *pk,
+                             mbedtls_md_type_t md_alg,
+                             const unsigned char *hash, size_t hash_len,
+                             const unsigned char *sig, size_t sig_len)
+{
+    (void) md_alg;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_keypair *ctx = pk->pk_ctx;
+    unsigned char key[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t key_len;
+    size_t curve_bits;
+    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
+
+    ret = mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &key_len, key, sizeof(key));
+    if (ret != 0) {
+        return ret;
+    }
+
+    return ecdsa_verify_psa(key, key_len, curve, curve_bits,
+                            hash, hash_len, sig, sig_len);
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 #else /* MBEDTLS_USE_PSA_CRYPTO */
-static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_verify_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                              const unsigned char *hash, size_t hash_len,
                              const unsigned char *sig, size_t sig_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     ((void) md_alg);
 
-    ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) ctx,
+    ret = mbedtls_ecdsa_read_signature((mbedtls_ecdsa_context *) pk->pk_ctx,
                                        hash, hash_len, sig, sig_len);
 
     if (ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) {
@@ -820,114 +689,85 @@ static int ecdsa_verify_wrap(void *ctx, mbedtls_md_type_t md_alg,
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-/*
- * Simultaneously convert and move raw MPI from the beginning of a buffer
- * to an ASN.1 MPI at the end of the buffer.
- * See also mbedtls_asn1_write_mpi().
- *
- * p: pointer to the end of the output buffer
- * start: start of the output buffer, and also of the mpi to write at the end
- * n_len: length of the mpi to read from start
+/* Common helper for ECDSA sign using PSA functions.
+ * Instead of extracting key's properties in order to check which kind of ECDSA
+ * signature it supports, we try both deterministic and non-deterministic.
  */
-static int asn1_write_mpibuf(unsigned char **p, unsigned char *start,
-                             size_t n_len)
+static int ecdsa_sign_psa(mbedtls_svc_key_id_t key_id, mbedtls_md_type_t md_alg,
+                          const unsigned char *hash, size_t hash_len,
+                          unsigned char *sig, size_t sig_size, size_t *sig_len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-
-    if ((size_t) (*p - start) < n_len) {
-        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-    }
-
-    len = n_len;
-    *p -= len;
-    memmove(*p, start, len);
+    psa_status_t status;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    size_t key_bits = 0;
 
-    /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
-     * Neither r nor s should be 0, but as a failsafe measure, still detect
-     * that rather than overflowing the buffer in case of a PSA error. */
-    while (len > 0 && **p == 0x00) {
-        ++(*p);
-        --len;
+    status = psa_get_key_attributes(key_id, &key_attr);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     }
+    key_bits = psa_get_key_bits(&key_attr);
+    psa_reset_key_attributes(&key_attr);
 
-    /* this is only reached if the signature was invalid */
-    if (len == 0) {
-        return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    status = psa_sign_hash(key_id,
+                           PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),
+                           hash, hash_len, sig, sig_size, sig_len);
+    if (status == PSA_SUCCESS) {
+        goto done;
+    } else if (status != PSA_ERROR_NOT_PERMITTED) {
+        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     }
 
-    /* if the msb is 1, ASN.1 requires that we prepend a 0.
-     * Neither r nor s can be 0, so we can assume len > 0 at all times. */
-    if (**p & 0x80) {
-        if (*p - start < 1) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
-        }
-
-        *--(*p) = 0x00;
-        len += 1;
+    status = psa_sign_hash(key_id,
+                           PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type(md_alg)),
+                           hash, hash_len, sig, sig_size, sig_len);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
     }
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
-                                                     MBEDTLS_ASN1_INTEGER));
+done:
+    ret = mbedtls_ecdsa_raw_to_der(key_bits, sig, *sig_len, sig, sig_size, sig_len);
 
-    return (int) len;
+    return ret;
 }
 
-/* Transcode signature from PSA format to ASN.1 sequence.
- * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of
- * MPIs, and in-place.
- *
- * [in/out] sig: the signature pre- and post-transcoding
- * [in/out] sig_len: signature length pre- and post-transcoding
- * [int] buf_len: the available size the in/out buffer
- */
-static int pk_ecdsa_sig_asn1_from_psa(unsigned char *sig, size_t *sig_len,
-                                      size_t buf_len)
+static int ecdsa_opaque_sign_wrap(mbedtls_pk_context *pk,
+                                  mbedtls_md_type_t md_alg,
+                                  const unsigned char *hash, size_t hash_len,
+                                  unsigned char *sig, size_t sig_size,
+                                  size_t *sig_len,
+                                  int (*f_rng)(void *, unsigned char *, size_t),
+                                  void *p_rng)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-    const size_t rs_len = *sig_len / 2;
-    unsigned char *p = sig + buf_len;
-
-    MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig + rs_len, rs_len));
-    MBEDTLS_ASN1_CHK_ADD(len, asn1_write_mpibuf(&p, sig, rs_len));
-
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, sig, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, sig,
-                                                     MBEDTLS_ASN1_CONSTRUCTED |
-                                                     MBEDTLS_ASN1_SEQUENCE));
-
-    memmove(sig, p, len);
-    *sig_len = len;
+    ((void) f_rng);
+    ((void) p_rng);
 
-    return 0;
+    return ecdsa_sign_psa(pk->priv_id, md_alg, hash, hash_len, sig, sig_size,
+                          sig_len);
 }
 
-static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up
+ * using the same function. */
+#define ecdsa_sign_wrap     ecdsa_opaque_sign_wrap
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hash_len,
                            unsigned char *sig, size_t sig_size, size_t *sig_len,
                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_ecp_keypair *ctx = ctx_arg;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
     psa_status_t status;
+    mbedtls_ecp_keypair *ctx = pk->pk_ctx;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     unsigned char buf[MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH];
-#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    psa_algorithm_t psa_sig_md =
-        PSA_ALG_DETERMINISTIC_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
-#else
-    psa_algorithm_t psa_sig_md =
-        PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
-#endif
     size_t curve_bits;
     psa_ecc_family_t curve =
         mbedtls_ecc_group_to_psa(ctx->grp.id, &curve_bits);
     size_t key_len = PSA_BITS_TO_BYTES(curve_bits);
-
-    /* PSA has its own RNG */
+    psa_algorithm_t psa_hash = mbedtls_md_psa_alg_from_type(md_alg);
+    psa_algorithm_t psa_sig_md = MBEDTLS_PK_PSA_ALG_ECDSA_MAYBE_DET(psa_hash);
     ((void) f_rng);
     ((void) p_rng);
 
@@ -947,22 +787,13 @@ static int ecdsa_sign_wrap(void *ctx_arg, mbedtls_md_type_t md_alg,
     psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
     psa_set_key_algorithm(&attributes, psa_sig_md);
 
-    status = psa_import_key(&attributes,
-                            buf, key_len,
-                            &key_id);
+    status = psa_import_key(&attributes, buf, key_len, &key_id);
     if (status != PSA_SUCCESS) {
         ret = PSA_PK_TO_MBEDTLS_ERR(status);
         goto cleanup;
     }
 
-    status = psa_sign_hash(key_id, psa_sig_md, hash, hash_len,
-                           sig, sig_size, sig_len);
-    if (status != PSA_SUCCESS) {
-        ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
-        goto cleanup;
-    }
-
-    ret = pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+    ret = ecdsa_sign_psa(key_id, md_alg, hash, hash_len, sig, sig_size, sig_len);
 
 cleanup:
     mbedtls_platform_zeroize(buf, sizeof(buf));
@@ -973,13 +804,14 @@ cleanup:
 
     return ret;
 }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 #else /* MBEDTLS_USE_PSA_CRYPTO */
-static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                            const unsigned char *hash, size_t hash_len,
                            unsigned char *sig, size_t sig_size, size_t *sig_len,
                            int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) ctx,
+    return mbedtls_ecdsa_write_signature((mbedtls_ecdsa_context *) pk->pk_ctx,
                                          md_alg, hash, hash_len,
                                          sig, sig_size, sig_len,
                                          f_rng, p_rng);
@@ -989,12 +821,12 @@ static int ecdsa_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
 /* Forward declarations */
-static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_verify_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                                 const unsigned char *hash, size_t hash_len,
                                 const unsigned char *sig, size_t sig_len,
                                 void *rs_ctx);
 
-static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_sign_rs_wrap(mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg,
                               const unsigned char *hash, size_t hash_len,
                               unsigned char *sig, size_t sig_size, size_t *sig_len,
                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
@@ -1041,7 +873,7 @@ static void eckey_rs_free(void *ctx)
     mbedtls_free(ctx);
 }
 
-static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int eckey_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                                 const unsigned char *hash, size_t hash_len,
                                 const unsigned char *sig, size_t sig_len,
                                 void *rs_ctx)
@@ -1056,10 +888,10 @@ static int eckey_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
 
     /* set up our own sub-context if needed (that is, on first run) */
     if (rs->ecdsa_ctx.grp.pbits == 0) {
-        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx));
     }
 
-    MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(&rs->ecdsa_ctx,
+    MBEDTLS_MPI_CHK(ecdsa_verify_rs_wrap(pk,
                                          md_alg, hash, hash_len,
                                          sig, sig_len, &rs->ecdsa_rs));
 
@@ -1067,7 +899,7 @@ cleanup:
     return ret;
 }
 
-static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int eckey_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                               const unsigned char *hash, size_t hash_len,
                               unsigned char *sig, size_t sig_size, size_t *sig_len,
                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
@@ -1083,10 +915,10 @@ static int eckey_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
 
     /* set up our own sub-context if needed (that is, on first run) */
     if (rs->ecdsa_ctx.grp.pbits == 0) {
-        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, ctx));
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_from_keypair(&rs->ecdsa_ctx, pk->pk_ctx));
     }
 
-    MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(&rs->ecdsa_ctx, md_alg,
+    MBEDTLS_MPI_CHK(ecdsa_sign_rs_wrap(pk, md_alg,
                                        hash, hash_len, sig, sig_size, sig_len,
                                        f_rng, p_rng, &rs->ecdsa_rs));
 
@@ -1095,15 +927,157 @@ cleanup:
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
-static int eckey_check_pair(const void *pub, const void *prv,
-                            int (*f_rng)(void *, unsigned char *, size_t),
-                            void *p_rng)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv)
 {
-    return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub,
-                                      (const mbedtls_ecp_keypair *) prv,
+    psa_status_t status;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t prv_key_len;
+    mbedtls_svc_key_id_t key_id = prv->priv_id;
+
+    status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf),
+                                   &prv_key_len);
+    ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (memcmp(prv_key_buf, pub->pub_raw, pub->pub_raw_len) != 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    return 0;
+}
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int eckey_check_pair_psa(mbedtls_pk_context *pub, mbedtls_pk_context *prv)
+{
+    psa_status_t status;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    uint8_t prv_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t prv_key_len;
+    psa_status_t destruction_status;
+    mbedtls_svc_key_id_t key_id = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
+    uint8_t pub_key_buf[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
+    size_t pub_key_len;
+    size_t curve_bits;
+    const psa_ecc_family_t curve =
+        mbedtls_ecc_group_to_psa(mbedtls_pk_ec_ro(*prv)->grp.id, &curve_bits);
+    const size_t curve_bytes = PSA_BITS_TO_BYTES(curve_bits);
+
+    if (curve == 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_KEY_PAIR(curve));
+    psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_EXPORT);
+
+    ret = mbedtls_mpi_write_binary(&mbedtls_pk_ec_ro(*prv)->d,
+                                   prv_key_buf, curve_bytes);
+    if (ret != 0) {
+        mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf));
+        return ret;
+    }
+
+    status = psa_import_key(&key_attr, prv_key_buf, curve_bytes, &key_id);
+    mbedtls_platform_zeroize(prv_key_buf, sizeof(prv_key_buf));
+    ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    if (ret != 0) {
+        return ret;
+    }
+
+    // From now on prv_key_buf is used to store the public key of prv.
+    status = psa_export_public_key(key_id, prv_key_buf, sizeof(prv_key_buf),
+                                   &prv_key_len);
+    ret = PSA_PK_TO_MBEDTLS_ERR(status);
+    destruction_status = psa_destroy_key(key_id);
+    if (ret != 0) {
+        return ret;
+    } else if (destruction_status != PSA_SUCCESS) {
+        return PSA_PK_TO_MBEDTLS_ERR(destruction_status);
+    }
+
+    ret = mbedtls_ecp_point_write_binary(&mbedtls_pk_ec_rw(*pub)->grp,
+                                         &mbedtls_pk_ec_rw(*pub)->Q,
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &pub_key_len, pub_key_buf,
+                                         sizeof(pub_key_buf));
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (memcmp(prv_key_buf, pub_key_buf, curve_bytes) != 0) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng)
+{
+    (void) f_rng;
+    (void) p_rng;
+    return eckey_check_pair_psa(pub, prv);
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+static int eckey_check_pair_wrap(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
+                                 int (*f_rng)(void *, unsigned char *, size_t),
+                                 void *p_rng)
+{
+    return mbedtls_ecp_check_pub_priv((const mbedtls_ecp_keypair *) pub->pk_ctx,
+                                      (const mbedtls_ecp_keypair *) prv->pk_ctx,
                                       f_rng, p_rng);
 }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+/* When PK_USE_PSA_EC_DATA is defined opaque and non-opaque keys end up
+ * using the same function. */
+#define ecdsa_opaque_check_pair_wrap    eckey_check_pair_wrap
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int ecdsa_opaque_check_pair_wrap(mbedtls_pk_context *pub,
+                                        mbedtls_pk_context *prv,
+                                        int (*f_rng)(void *, unsigned char *, size_t),
+                                        void *p_rng)
+{
+    psa_status_t status;
+    uint8_t exp_pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];
+    size_t exp_pub_key_len = 0;
+    uint8_t pub_key[MBEDTLS_PK_MAX_EC_PUBKEY_RAW_LEN];
+    size_t pub_key_len = 0;
+    int ret;
+    (void) f_rng;
+    (void) p_rng;
+
+    status = psa_export_public_key(prv->priv_id, exp_pub_key, sizeof(exp_pub_key),
+                                   &exp_pub_key_len);
+    if (status != PSA_SUCCESS) {
+        ret = psa_pk_status_to_mbedtls(status);
+        return ret;
+    }
+    ret = mbedtls_ecp_point_write_binary(&(mbedtls_pk_ec_ro(*pub)->grp),
+                                         &(mbedtls_pk_ec_ro(*pub)->Q),
+                                         MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                         &pub_key_len, pub_key, sizeof(pub_key));
+    if (ret != 0) {
+        return ret;
+    }
+    if ((exp_pub_key_len != pub_key_len) ||
+        memcmp(exp_pub_key, pub_key, exp_pub_key_len)) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+    return 0;
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
 static void *eckey_alloc_wrap(void)
 {
     void *ctx = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
@@ -1120,43 +1094,54 @@ static void eckey_free_wrap(void *ctx)
     mbedtls_ecp_keypair_free((mbedtls_ecp_keypair *) ctx);
     mbedtls_free(ctx);
 }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 
-static void eckey_debug(const void *ctx, mbedtls_pk_debug_item *items)
+static void eckey_debug(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items)
 {
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    items->type = MBEDTLS_PK_DEBUG_PSA_EC;
+    items->name = "eckey.Q";
+    items->value = pk;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    mbedtls_ecp_keypair *ecp = (mbedtls_ecp_keypair *) pk->pk_ctx;
     items->type = MBEDTLS_PK_DEBUG_ECP;
     items->name = "eckey.Q";
-    items->value = &(((mbedtls_ecp_keypair *) ctx)->Q);
+    items->value = &(ecp->Q);
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 }
 
 const mbedtls_pk_info_t mbedtls_eckey_info = {
-    MBEDTLS_PK_ECKEY,
-    "EC",
-    eckey_get_bitlen,
-    eckey_can_do,
+    .type = MBEDTLS_PK_ECKEY,
+    .name = "EC",
+    .get_bitlen = eckey_get_bitlen,
+    .can_do = eckey_can_do,
 #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
-    ecdsa_verify_wrap,   /* Compatible key structures */
-#else
-    NULL,
-#endif
+    .verify_func = ecdsa_verify_wrap,   /* Compatible key structures */
+#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+    .verify_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-    ecdsa_sign_wrap,   /* Compatible key structures */
-#else
-    NULL,
-#endif
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    eckey_verify_rs_wrap,
-    eckey_sign_rs_wrap,
-#endif
-    NULL,
-    NULL,
-    eckey_check_pair,
-    eckey_alloc_wrap,
-    eckey_free_wrap,
+    .sign_func = ecdsa_sign_wrap,   /* Compatible key structures */
+#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+    .sign_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    eckey_rs_alloc,
-    eckey_rs_free,
-#endif
-    eckey_debug,
+    .verify_rs_func = eckey_verify_rs_wrap,
+    .sign_rs_func = eckey_sign_rs_wrap,
+    .rs_alloc_func = eckey_rs_alloc,
+    .rs_free_func = eckey_rs_free,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = NULL,
+    .encrypt_func = NULL,
+    .check_pair_func = eckey_check_pair_wrap,
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    .ctx_alloc_func = NULL,
+    .ctx_free_func = NULL,
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .ctx_alloc_func = eckey_alloc_wrap,
+    .ctx_free_func = eckey_free_wrap,
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .debug_func = eckey_debug,
 };
 
 /*
@@ -1169,28 +1154,28 @@ static int eckeydh_can_do(mbedtls_pk_type_t type)
 }
 
 const mbedtls_pk_info_t mbedtls_eckeydh_info = {
-    MBEDTLS_PK_ECKEY_DH,
-    "EC_DH",
-    eckey_get_bitlen,         /* Same underlying key structure */
-    eckeydh_can_do,
-    NULL,
-    NULL,
+    .type = MBEDTLS_PK_ECKEY_DH,
+    .name = "EC_DH",
+    .get_bitlen = eckey_get_bitlen,         /* Same underlying key structure */
+    .can_do = eckeydh_can_do,
+    .verify_func = NULL,
+    .sign_func = NULL,
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    NULL,
-    NULL,
-    eckey_check_pair,
-    eckey_alloc_wrap,       /* Same underlying key structure */
-    eckey_free_wrap,        /* Same underlying key structure */
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    eckey_debug,            /* Same underlying key structure */
+    .verify_rs_func = NULL,
+    .sign_rs_func = NULL,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = NULL,
+    .encrypt_func = NULL,
+    .check_pair_func = eckey_check_pair_wrap,
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    .ctx_alloc_func = NULL,
+    .ctx_free_func = NULL,
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .ctx_alloc_func = eckey_alloc_wrap,   /* Same underlying key structure */
+    .ctx_free_func = eckey_free_wrap,    /* Same underlying key structure */
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .debug_func = eckey_debug,            /* Same underlying key structure */
 };
-#endif /* MBEDTLS_ECP_C */
 
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
 static int ecdsa_can_do(mbedtls_pk_type_t type)
@@ -1199,7 +1184,7 @@ static int ecdsa_can_do(mbedtls_pk_type_t type)
 }
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_verify_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                                 const unsigned char *hash, size_t hash_len,
                                 const unsigned char *sig, size_t sig_len,
                                 void *rs_ctx)
@@ -1208,7 +1193,7 @@ static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
     ((void) md_alg);
 
     ret = mbedtls_ecdsa_read_signature_restartable(
-        (mbedtls_ecdsa_context *) ctx,
+        (mbedtls_ecdsa_context *) pk->pk_ctx,
         hash, hash_len, sig, sig_len,
         (mbedtls_ecdsa_restart_ctx *) rs_ctx);
 
@@ -1219,14 +1204,14 @@ static int ecdsa_verify_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
     return ret;
 }
 
-static int ecdsa_sign_rs_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int ecdsa_sign_rs_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                               const unsigned char *hash, size_t hash_len,
                               unsigned char *sig, size_t sig_size, size_t *sig_len,
                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
                               void *rs_ctx)
 {
     return mbedtls_ecdsa_write_signature_restartable(
-        (mbedtls_ecdsa_context *) ctx,
+        (mbedtls_ecdsa_context *) pk->pk_ctx,
         md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng,
         (mbedtls_ecdsa_restart_ctx *) rs_ctx);
 
@@ -1251,36 +1236,40 @@ static void ecdsa_rs_free(void *ctx)
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
 const mbedtls_pk_info_t mbedtls_ecdsa_info = {
-    MBEDTLS_PK_ECDSA,
-    "ECDSA",
-    eckey_get_bitlen,     /* Compatible key structures */
-    ecdsa_can_do,
+    .type = MBEDTLS_PK_ECDSA,
+    .name = "ECDSA",
+    .get_bitlen = eckey_get_bitlen,     /* Compatible key structures */
+    .can_do = ecdsa_can_do,
 #if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
-    ecdsa_verify_wrap,   /* Compatible key structures */
-#else
-    NULL,
-#endif
+    .verify_func = ecdsa_verify_wrap,   /* Compatible key structures */
+#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+    .verify_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
 #if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-    ecdsa_sign_wrap,   /* Compatible key structures */
-#else
-    NULL,
-#endif
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    ecdsa_verify_rs_wrap,
-    ecdsa_sign_rs_wrap,
-#endif
-    NULL,
-    NULL,
-    eckey_check_pair,   /* Compatible key structures */
-    eckey_alloc_wrap,   /* Compatible key structures */
-    eckey_free_wrap,   /* Compatible key structures */
+    .sign_func = ecdsa_sign_wrap,   /* Compatible key structures */
+#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+    .sign_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    ecdsa_rs_alloc,
-    ecdsa_rs_free,
-#endif
-    eckey_debug,        /* Compatible key structures */
+    .verify_rs_func = ecdsa_verify_rs_wrap,
+    .sign_rs_func = ecdsa_sign_rs_wrap,
+    .rs_alloc_func = ecdsa_rs_alloc,
+    .rs_free_func = ecdsa_rs_free,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = NULL,
+    .encrypt_func = NULL,
+    .check_pair_func = eckey_check_pair_wrap,   /* Compatible key structures */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    .ctx_alloc_func = NULL,
+    .ctx_free_func = NULL,
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .ctx_alloc_func = eckey_alloc_wrap,   /* Compatible key structures */
+    .ctx_free_func = eckey_free_wrap,   /* Compatible key structures */
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    .debug_func = eckey_debug,        /* Compatible key structures */
 };
 #endif /* MBEDTLS_PK_CAN_ECDSA_SOME */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
 /*
@@ -1292,23 +1281,25 @@ static int rsa_alt_can_do(mbedtls_pk_type_t type)
     return type == MBEDTLS_PK_RSA;
 }
 
-static size_t rsa_alt_get_bitlen(const void *ctx)
+static size_t rsa_alt_get_bitlen(mbedtls_pk_context *pk)
 {
-    const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx;
+    const mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;
 
     return 8 * rsa_alt->key_len_func(rsa_alt->key);
 }
 
-static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
+static int rsa_alt_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                              const unsigned char *hash, size_t hash_len,
                              unsigned char *sig, size_t sig_size, size_t *sig_len,
                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
+    mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;
 
+#if SIZE_MAX > UINT_MAX
     if (UINT_MAX < hash_len) {
         return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
     }
+#endif
 
     *sig_len = rsa_alt->key_len_func(rsa_alt->key);
     if (*sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE) {
@@ -1322,12 +1313,12 @@ static int rsa_alt_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
                               md_alg, (unsigned int) hash_len, hash, sig);
 }
 
-static int rsa_alt_decrypt_wrap(void *ctx,
+static int rsa_alt_decrypt_wrap(mbedtls_pk_context *pk,
                                 const unsigned char *input, size_t ilen,
                                 unsigned char *output, size_t *olen, size_t osize,
                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx;
+    mbedtls_rsa_alt_context *rsa_alt = pk->pk_ctx;
 
     ((void) f_rng);
     ((void) p_rng);
@@ -1341,7 +1332,7 @@ static int rsa_alt_decrypt_wrap(void *ctx,
 }
 
 #if defined(MBEDTLS_RSA_C)
-static int rsa_alt_check_pair(const void *pub, const void *prv,
+static int rsa_alt_check_pair(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
                               int (*f_rng)(void *, unsigned char *, size_t),
                               void *p_rng)
 {
@@ -1356,14 +1347,14 @@ static int rsa_alt_check_pair(const void *pub, const void *prv,
 
     memset(hash, 0x2a, sizeof(hash));
 
-    if ((ret = rsa_alt_sign_wrap((void *) prv, MBEDTLS_MD_NONE,
+    if ((ret = rsa_alt_sign_wrap(prv, MBEDTLS_MD_NONE,
                                  hash, sizeof(hash),
                                  sig, sizeof(sig), &sig_len,
                                  f_rng, p_rng)) != 0) {
         return ret;
     }
 
-    if (rsa_verify_wrap((void *) pub, MBEDTLS_MD_NONE,
+    if (rsa_verify_wrap(pub, MBEDTLS_MD_NONE,
                         hash, sizeof(hash), sig, sig_len) != 0) {
         return MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     }
@@ -1385,63 +1376,42 @@ static void *rsa_alt_alloc_wrap(void)
 
 static void rsa_alt_free_wrap(void *ctx)
 {
-    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_rsa_alt_context));
-    mbedtls_free(ctx);
+    mbedtls_zeroize_and_free(ctx, sizeof(mbedtls_rsa_alt_context));
 }
 
 const mbedtls_pk_info_t mbedtls_rsa_alt_info = {
-    MBEDTLS_PK_RSA_ALT,
-    "RSA-alt",
-    rsa_alt_get_bitlen,
-    rsa_alt_can_do,
-    NULL,
-    rsa_alt_sign_wrap,
+    .type = MBEDTLS_PK_RSA_ALT,
+    .name = "RSA-alt",
+    .get_bitlen = rsa_alt_get_bitlen,
+    .can_do = rsa_alt_can_do,
+    .verify_func = NULL,
+    .sign_func = rsa_alt_sign_wrap,
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    rsa_alt_decrypt_wrap,
-    NULL,
+    .verify_rs_func = NULL,
+    .sign_rs_func = NULL,
+    .rs_alloc_func = NULL,
+    .rs_free_func = NULL,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = rsa_alt_decrypt_wrap,
+    .encrypt_func = NULL,
 #if defined(MBEDTLS_RSA_C)
-    rsa_alt_check_pair,
+    .check_pair_func = rsa_alt_check_pair,
 #else
-    NULL,
+    .check_pair_func = NULL,
 #endif
-    rsa_alt_alloc_wrap,
-    rsa_alt_free_wrap,
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL,
-    NULL,
-#endif
-    NULL,
+    .ctx_alloc_func = rsa_alt_alloc_wrap,
+    .ctx_free_func = rsa_alt_free_wrap,
+    .debug_func = NULL,
 };
-
 #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-static void *pk_opaque_alloc_wrap(void)
-{
-    void *ctx = mbedtls_calloc(1, sizeof(mbedtls_svc_key_id_t));
-
-    /* no _init() function to call, as calloc() already zeroized */
-
-    return ctx;
-}
-
-static void pk_opaque_free_wrap(void *ctx)
+static size_t opaque_get_bitlen(mbedtls_pk_context *pk)
 {
-    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_svc_key_id_t));
-    mbedtls_free(ctx);
-}
-
-static size_t pk_opaque_get_bitlen(const void *ctx)
-{
-    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
     size_t bits;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-    if (PSA_SUCCESS != psa_get_key_attributes(*key, &attributes)) {
+    if (PSA_SUCCESS != psa_get_key_attributes(pk->priv_id, &attributes)) {
         return 0;
     }
 
@@ -1450,36 +1420,55 @@ static size_t pk_opaque_get_bitlen(const void *ctx)
     return bits;
 }
 
-static int pk_opaque_ecdsa_can_do(mbedtls_pk_type_t type)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+static int ecdsa_opaque_can_do(mbedtls_pk_type_t type)
 {
     return type == MBEDTLS_PK_ECKEY ||
            type == MBEDTLS_PK_ECDSA;
 }
 
-static int pk_opaque_rsa_can_do(mbedtls_pk_type_t type)
+const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info = {
+    .type = MBEDTLS_PK_OPAQUE,
+    .name = "Opaque",
+    .get_bitlen = opaque_get_bitlen,
+    .can_do = ecdsa_opaque_can_do,
+#if defined(MBEDTLS_PK_CAN_ECDSA_VERIFY)
+    .verify_func = ecdsa_opaque_verify_wrap,
+#else /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+    .verify_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_VERIFY */
+#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
+    .sign_func = ecdsa_opaque_sign_wrap,
+#else /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+    .sign_func = NULL,
+#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
+#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
+    .verify_rs_func = NULL,
+    .sign_rs_func = NULL,
+    .rs_alloc_func = NULL,
+    .rs_free_func = NULL,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+    .decrypt_func = NULL,
+    .encrypt_func = NULL,
+    .check_pair_func = ecdsa_opaque_check_pair_wrap,
+    .ctx_alloc_func = NULL,
+    .ctx_free_func = NULL,
+    .debug_func = NULL,
+};
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+static int rsa_opaque_can_do(mbedtls_pk_type_t type)
 {
     return type == MBEDTLS_PK_RSA ||
            type == MBEDTLS_PK_RSASSA_PSS;
 }
 
-static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
-                               const unsigned char *hash, size_t hash_len,
-                               unsigned char *sig, size_t sig_size, size_t *sig_len,
-                               int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+static int rsa_opaque_decrypt(mbedtls_pk_context *pk,
+                              const unsigned char *input, size_t ilen,
+                              unsigned char *output, size_t *olen, size_t osize,
+                              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-#if !defined(MBEDTLS_PK_CAN_ECDSA_SIGN) && !defined(MBEDTLS_RSA_C)
-    ((void) ctx);
-    ((void) md_alg);
-    ((void) hash);
-    ((void) hash_len);
-    ((void) sig);
-    ((void) sig_size);
-    ((void) sig_len);
-    ((void) f_rng);
-    ((void) p_rng);
-    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-#else /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
-    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
     psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
     psa_algorithm_t alg;
     psa_key_type_t type;
@@ -1489,127 +1478,105 @@ static int pk_opaque_sign_wrap(void *ctx, mbedtls_md_type_t md_alg,
     (void) f_rng;
     (void) p_rng;
 
-    status = psa_get_key_attributes(*key, &attributes);
+    status = psa_get_key_attributes(pk->priv_id, &attributes);
     if (status != PSA_SUCCESS) {
         return PSA_PK_TO_MBEDTLS_ERR(status);
     }
 
     type = psa_get_key_type(&attributes);
+    alg = psa_get_key_algorithm(&attributes);
     psa_reset_key_attributes(&attributes);
 
-#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
-        alg = PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(md_alg));
-    } else
-#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
-#if defined(MBEDTLS_RSA_C)
-    if (PSA_KEY_TYPE_IS_RSA(type)) {
-        alg = PSA_ALG_RSA_PKCS1V15_SIGN(mbedtls_hash_info_psa_from_md(md_alg));
-    } else
-#endif /* MBEDTLS_RSA_C */
-    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-
-    /* make the signature */
-    status = psa_sign_hash(*key, alg, hash, hash_len,
-                           sig, sig_size, sig_len);
-    if (status != PSA_SUCCESS) {
-#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
-            return PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
-        } else
-#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
-#if defined(MBEDTLS_RSA_C)
-        if (PSA_KEY_TYPE_IS_RSA(type)) {
-            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
-        } else
-#endif /* MBEDTLS_RSA_C */
-        return PSA_PK_TO_MBEDTLS_ERR(status);
+    if (!PSA_KEY_TYPE_IS_RSA(type)) {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
 
-#if defined(MBEDTLS_PK_CAN_ECDSA_SIGN)
-    if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(type)) {
-        /* transcode it to ASN.1 sequence */
-        return pk_ecdsa_sig_asn1_from_psa(sig, sig_len, sig_size);
+    status = psa_asymmetric_decrypt(pk->priv_id, alg, input, ilen, NULL, 0, output, osize, olen);
+    if (status != PSA_SUCCESS) {
+        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
     }
-#endif /* MBEDTLS_PK_CAN_ECDSA_SIGN */
 
     return 0;
-#endif /* !MBEDTLS_PK_CAN_ECDSA_SIGN && !MBEDTLS_RSA_C */
 }
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */
 
-const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info = {
-    MBEDTLS_PK_OPAQUE,
-    "Opaque",
-    pk_opaque_get_bitlen,
-    pk_opaque_ecdsa_can_do,
-    NULL, /* verify - will be done later */
-    pk_opaque_sign_wrap,
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL, /* restartable verify - not relevant */
-    NULL, /* restartable sign - not relevant */
-#endif
-    NULL, /* decrypt - not relevant */
-    NULL, /* encrypt - not relevant */
-    NULL, /* check_pair - could be done later or left NULL */
-    pk_opaque_alloc_wrap,
-    pk_opaque_free_wrap,
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL, /* restart alloc - not relevant */
-    NULL, /* restart free - not relevant */
-#endif
-    NULL, /* debug - could be done later, or even left NULL */
-};
-
-#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-static int pk_opaque_rsa_decrypt(void *ctx,
-                                 const unsigned char *input, size_t ilen,
-                                 unsigned char *output, size_t *olen, size_t osize,
-                                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+static int rsa_opaque_sign_wrap(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
+                                const unsigned char *hash, size_t hash_len,
+                                unsigned char *sig, size_t sig_size, size_t *sig_len,
+                                int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
-    const mbedtls_svc_key_id_t *key = (const mbedtls_svc_key_id_t *) ctx;
+#if defined(MBEDTLS_RSA_C)
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    psa_key_type_t type;
     psa_status_t status;
 
     /* PSA has its own RNG */
     (void) f_rng;
     (void) p_rng;
 
-    status = psa_asymmetric_decrypt(*key, PSA_ALG_RSA_PKCS1V15_CRYPT,
-                                    input, ilen,
-                                    NULL, 0,
-                                    output, osize, olen);
+    status = psa_get_key_attributes(pk->priv_id, &attributes);
     if (status != PSA_SUCCESS) {
-        return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        return PSA_PK_TO_MBEDTLS_ERR(status);
+    }
+
+    type = psa_get_key_type(&attributes);
+    alg = psa_get_key_algorithm(&attributes);
+    psa_reset_key_attributes(&attributes);
+
+    if (PSA_KEY_TYPE_IS_RSA(type)) {
+        alg = (alg & ~PSA_ALG_HASH_MASK) | mbedtls_md_psa_alg_from_type(md_alg);
+    } else {
+        return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+    }
+
+    status = psa_sign_hash(pk->priv_id, alg, hash, hash_len, sig, sig_size, sig_len);
+    if (status != PSA_SUCCESS) {
+        if (PSA_KEY_TYPE_IS_RSA(type)) {
+            return PSA_PK_RSA_TO_MBEDTLS_ERR(status);
+        } else {
+            return PSA_PK_TO_MBEDTLS_ERR(status);
+        }
     }
 
     return 0;
+#else /* !MBEDTLS_RSA_C */
+    ((void) pk);
+    ((void) md_alg);
+    ((void) hash);
+    ((void) hash_len);
+    ((void) sig);
+    ((void) sig_size);
+    ((void) sig_len);
+    ((void) f_rng);
+    ((void) p_rng);
+    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* !MBEDTLS_RSA_C */
 }
-#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
-
-const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info = {
-    MBEDTLS_PK_OPAQUE,
-    "Opaque",
-    pk_opaque_get_bitlen,
-    pk_opaque_rsa_can_do,
-    NULL, /* verify - will be done later */
-    pk_opaque_sign_wrap,
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL, /* restartable verify - not relevant */
-    NULL, /* restartable sign - not relevant */
-#endif
-#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-    pk_opaque_rsa_decrypt,
-#else
-    NULL, /* decrypt - not available */
-#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY */
-    NULL, /* encrypt - will be done later */
-    NULL, /* check_pair - could be done later or left NULL */
-    pk_opaque_alloc_wrap,
-    pk_opaque_free_wrap,
+
+const mbedtls_pk_info_t mbedtls_rsa_opaque_info = {
+    .type = MBEDTLS_PK_OPAQUE,
+    .name = "Opaque",
+    .get_bitlen = opaque_get_bitlen,
+    .can_do = rsa_opaque_can_do,
+    .verify_func = NULL,
+    .sign_func = rsa_opaque_sign_wrap,
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
-    NULL, /* restart alloc - not relevant */
-    NULL, /* restart free - not relevant */
-#endif
-    NULL, /* debug - could be done later, or even left NULL */
+    .verify_rs_func = NULL,
+    .sign_rs_func = NULL,
+    .rs_alloc_func = NULL,
+    .rs_free_func = NULL,
+#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+    .decrypt_func = rsa_opaque_decrypt,
+#else /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */
+    .decrypt_func = NULL,
+#endif /* PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC */
+    .encrypt_func = NULL,
+    .check_pair_func = NULL,
+    .ctx_alloc_func = NULL,
+    .ctx_free_func = NULL,
+    .debug_func = NULL,
 };
 
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
diff --git a/lib/libmbedtls/mbedtls/library/pk_wrap.h b/lib/libmbedtls/mbedtls/library/pk_wrap.h
index c5cd4df151b49f997149732f71407517d269fc53..be096da53ac8cc4f88a230633684d06085ddb5d4 100644
--- a/lib/libmbedtls/mbedtls/library/pk_wrap.h
+++ b/lib/libmbedtls/mbedtls/library/pk_wrap.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_PK_WRAP_H
@@ -27,9 +15,9 @@
 
 #include "mbedtls/pk.h"
 
-#if defined(MBEDTLS_PSA_CRYPTO_C)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif
 
 struct mbedtls_pk_info_t {
     /** Public key type */
@@ -39,18 +27,18 @@ struct mbedtls_pk_info_t {
     const char *name;
 
     /** Get key size in bits */
-    size_t (*get_bitlen)(const void *);
+    size_t (*get_bitlen)(mbedtls_pk_context *pk);
 
     /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */
     int (*can_do)(mbedtls_pk_type_t type);
 
     /** Verify signature */
-    int (*verify_func)(void *ctx, mbedtls_md_type_t md_alg,
+    int (*verify_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                        const unsigned char *hash, size_t hash_len,
                        const unsigned char *sig, size_t sig_len);
 
     /** Make signature */
-    int (*sign_func)(void *ctx, mbedtls_md_type_t md_alg,
+    int (*sign_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                      const unsigned char *hash, size_t hash_len,
                      unsigned char *sig, size_t sig_size, size_t *sig_len,
                      int (*f_rng)(void *, unsigned char *, size_t),
@@ -58,13 +46,13 @@ struct mbedtls_pk_info_t {
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /** Verify signature (restartable) */
-    int (*verify_rs_func)(void *ctx, mbedtls_md_type_t md_alg,
+    int (*verify_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                           const unsigned char *hash, size_t hash_len,
                           const unsigned char *sig, size_t sig_len,
                           void *rs_ctx);
 
     /** Make signature (restartable) */
-    int (*sign_rs_func)(void *ctx, mbedtls_md_type_t md_alg,
+    int (*sign_rs_func)(mbedtls_pk_context *pk, mbedtls_md_type_t md_alg,
                         const unsigned char *hash, size_t hash_len,
                         unsigned char *sig, size_t sig_size, size_t *sig_len,
                         int (*f_rng)(void *, unsigned char *, size_t),
@@ -72,19 +60,19 @@ struct mbedtls_pk_info_t {
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
     /** Decrypt message */
-    int (*decrypt_func)(void *ctx, const unsigned char *input, size_t ilen,
+    int (*decrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,
                         unsigned char *output, size_t *olen, size_t osize,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng);
 
     /** Encrypt message */
-    int (*encrypt_func)(void *ctx, const unsigned char *input, size_t ilen,
+    int (*encrypt_func)(mbedtls_pk_context *pk, const unsigned char *input, size_t ilen,
                         unsigned char *output, size_t *olen, size_t osize,
                         int (*f_rng)(void *, unsigned char *, size_t),
                         void *p_rng);
 
     /** Check public-private key pair */
-    int (*check_pair_func)(const void *pub, const void *prv,
+    int (*check_pair_func)(mbedtls_pk_context *pub, mbedtls_pk_context *prv,
                            int (*f_rng)(void *, unsigned char *, size_t),
                            void *p_rng);
 
@@ -103,7 +91,7 @@ struct mbedtls_pk_info_t {
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
     /** Interface with the debug module */
-    void (*debug_func)(const void *ctx, mbedtls_pk_debug_item *items);
+    void (*debug_func)(mbedtls_pk_context *pk, mbedtls_pk_debug_item *items);
 
 };
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
@@ -120,7 +108,7 @@ typedef struct {
 extern const mbedtls_pk_info_t mbedtls_rsa_info;
 #endif
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 extern const mbedtls_pk_info_t mbedtls_eckey_info;
 extern const mbedtls_pk_info_t mbedtls_eckeydh_info;
 #endif
@@ -134,26 +122,8 @@ extern const mbedtls_pk_info_t mbedtls_rsa_alt_info;
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-extern const mbedtls_pk_info_t mbedtls_pk_ecdsa_opaque_info;
-extern const mbedtls_pk_info_t mbedtls_pk_rsa_opaque_info;
-
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
-int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_ecdsa(psa_status_t status);
-#endif
-#endif
-
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#if defined(MBEDTLS_PSA_CRYPTO_C)
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa(psa_status_t status);
-
-#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
-    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR)
-int MBEDTLS_DEPRECATED mbedtls_pk_error_from_psa_rsa(psa_status_t status);
-#endif /* PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY || PSA_WANT_KEY_TYPE_RSA_KEY_PAIR */
-#endif /* !MBEDTLS_DEPRECATED_REMOVED */
+extern const mbedtls_pk_info_t mbedtls_ecdsa_opaque_info;
+extern const mbedtls_pk_info_t mbedtls_rsa_opaque_info;
 
 #if defined(MBEDTLS_RSA_C)
 int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
@@ -163,6 +133,6 @@ int mbedtls_pk_psa_rsa_sign_ext(psa_algorithm_t psa_alg_md,
                                 size_t *sig_len);
 #endif /* MBEDTLS_RSA_C */
 
-#endif /* MBEDTLS_PSA_CRYPTO_C */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #endif /* MBEDTLS_PK_WRAP_H */
diff --git a/lib/libmbedtls/mbedtls/library/pkcs12.c b/lib/libmbedtls/mbedtls/library/pkcs12.c
index 8521483941fb57ecef757c80274b08c81ec02a91..a3467b98208926c19060cd9c8eb2a9f30ad7e893 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs12.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs12.c
@@ -2,19 +2,7 @@
  *  PKCS#12 Personal Information Exchange Syntax
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The PKCS #12 Personal Information Exchange Syntax Standard v1.1
@@ -29,27 +17,21 @@
 
 #include "mbedtls/pkcs12.h"
 #include "mbedtls/asn1.h"
+#if defined(MBEDTLS_CIPHER_C)
 #include "mbedtls/cipher.h"
+#endif /* MBEDTLS_CIPHER_C */
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 
 #include <string.h>
 
-#if !defined(MBEDTLS_MD_C)
-#include "mbedtls/psa_util.h"
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_md_errors,              \
-                                                           psa_generic_status_to_mbedtls)
-#endif
-
 #if defined(MBEDTLS_DES_C)
 #include "mbedtls/des.h"
 #endif
 
-#include "hash_info.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 
-#if defined(MBEDTLS_ASN1_PARSE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
 
 static int pkcs12_parse_pbe_params(mbedtls_asn1_buf *params,
                                    mbedtls_asn1_buf *salt, int *iterations)
@@ -137,18 +119,49 @@ static int pkcs12_pbe_derive_key_iv(mbedtls_asn1_buf *pbe_params, mbedtls_md_typ
 
 #undef PKCS12_MAX_PWDLEN
 
+#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,
+                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
+                           const unsigned char *pwd,  size_t pwdlen,
+                           const unsigned char *data, size_t len,
+                           unsigned char *output, size_t output_size,
+                           size_t *output_len);
+#endif
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
                        mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
                        const unsigned char *pwd,  size_t pwdlen,
                        const unsigned char *data, size_t len,
                        unsigned char *output)
+{
+    size_t output_len = 0;
+
+    /* We assume caller of the function is providing a big enough output buffer
+     * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
+     * for the output size actually being correct.
+     */
+    return mbedtls_pkcs12_pbe_ext(pbe_params, mode, cipher_type, md_type,
+                                  pwd, pwdlen, data, len, output, SIZE_MAX,
+                                  &output_len);
+}
+#endif
+
+int mbedtls_pkcs12_pbe_ext(mbedtls_asn1_buf *pbe_params, int mode,
+                           mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type,
+                           const unsigned char *pwd,  size_t pwdlen,
+                           const unsigned char *data, size_t len,
+                           unsigned char *output, size_t output_size,
+                           size_t *output_len)
 {
     int ret, keylen = 0;
     unsigned char key[32];
     unsigned char iv[16];
     const mbedtls_cipher_info_t *cipher_info;
     mbedtls_cipher_context_t cipher_ctx;
-    size_t olen = 0;
+    size_t iv_len = 0;
+    size_t finish_olen = 0;
+    unsigned int padlen = 0;
 
     if (pwd == NULL && pwdlen != 0) {
         return MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA;
@@ -159,11 +172,25 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
         return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
     }
 
-    keylen = cipher_info->key_bitlen / 8;
+    keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
+
+    if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {
+        if (output_size < len) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+    }
 
+    if (mode == MBEDTLS_PKCS12_PBE_ENCRYPT) {
+        padlen = cipher_info->block_size - (len % cipher_info->block_size);
+        if (output_size < (len + padlen)) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+    }
+
+    iv_len = mbedtls_cipher_info_get_iv_size(cipher_info);
     if ((ret = pkcs12_pbe_derive_key_iv(pbe_params, md_type, pwd, pwdlen,
                                         key, keylen,
-                                        iv, cipher_info->iv_size)) != 0) {
+                                        iv, iv_len)) != 0) {
         return ret;
     }
 
@@ -173,29 +200,38 @@ int mbedtls_pkcs12_pbe(mbedtls_asn1_buf *pbe_params, int mode,
         goto exit;
     }
 
-    if ((ret =
-             mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
-                                   (mbedtls_operation_t) mode)) != 0) {
-        goto exit;
-    }
-
-    if ((ret = mbedtls_cipher_set_iv(&cipher_ctx, iv, cipher_info->iv_size)) != 0) {
+    if ((ret = mbedtls_cipher_setkey(&cipher_ctx, key, 8 * keylen,
+                                     (mbedtls_operation_t) mode)) != 0) {
         goto exit;
     }
 
-    if ((ret = mbedtls_cipher_reset(&cipher_ctx)) != 0) {
-        goto exit;
-    }
-
-    if ((ret = mbedtls_cipher_update(&cipher_ctx, data, len,
-                                     output, &olen)) != 0) {
-        goto exit;
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    {
+        /* PKCS12 uses CBC with PKCS7 padding */
+        mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
+#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+        /* For historical reasons, when decrypting, this function works when
+         * decrypting even when support for PKCS7 padding is disabled. In this
+         * case, it ignores the padding, and so will never report a
+         * password mismatch.
+         */
+        if (mode == MBEDTLS_PKCS12_PBE_DECRYPT) {
+            padding = MBEDTLS_PADDING_NONE;
+        }
+#endif
+        if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
+            goto exit;
+        }
     }
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
 
-    if ((ret = mbedtls_cipher_finish(&cipher_ctx, output + olen, &olen)) != 0) {
+    ret = mbedtls_cipher_crypt(&cipher_ctx, iv, iv_len, data, len, output, &finish_olen);
+    if (ret == MBEDTLS_ERR_CIPHER_INVALID_PADDING) {
         ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH;
     }
 
+    *output_len += finish_olen;
+
 exit:
     mbedtls_platform_zeroize(key, sizeof(key));
     mbedtls_platform_zeroize(iv,  sizeof(iv));
@@ -204,7 +240,7 @@ exit:
     return ret;
 }
 
-#endif /* MBEDTLS_ASN1_PARSE_C */
+#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */
 
 static void pkcs12_fill_buffer(unsigned char *data, size_t data_len,
                                const unsigned char *filler, size_t fill_len)
@@ -234,7 +270,6 @@ static int calculate_hashes(mbedtls_md_type_t md_type, int iterations,
                             unsigned char *pwd_block, unsigned char *hash_output, int use_salt,
                             int use_password, size_t hlen, size_t v)
 {
-#if defined(MBEDTLS_MD_C)
     int ret = -1;
     size_t i;
     const mbedtls_md_info_t *md_info;
@@ -285,58 +320,6 @@ static int calculate_hashes(mbedtls_md_type_t md_type, int iterations,
 exit:
     mbedtls_md_free(&md_ctx);
     return ret;
-#else
-    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t alg = mbedtls_psa_translate_md(md_type);
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_status_t status_abort = PSA_ERROR_CORRUPTION_DETECTED;
-    size_t i, out_len, out_size = PSA_HASH_LENGTH(alg);
-
-    if (alg == PSA_ALG_NONE) {
-        return MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE;
-    }
-
-    if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    // Calculate hash( diversifier || salt_block || pwd_block )
-    if ((status = psa_hash_update(&op, diversifier, v)) != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    if (use_salt != 0) {
-        if ((status = psa_hash_update(&op, salt_block, v)) != PSA_SUCCESS) {
-            goto exit;
-        }
-    }
-
-    if (use_password != 0) {
-        if ((status = psa_hash_update(&op, pwd_block, v)) != PSA_SUCCESS) {
-            goto exit;
-        }
-    }
-
-    if ((status = psa_hash_finish(&op, hash_output, out_size, &out_len))
-        != PSA_SUCCESS) {
-        goto exit;
-    }
-
-    // Perform remaining ( iterations - 1 ) recursive hash calculations
-    for (i = 1; i < (size_t) iterations; i++) {
-        if ((status = psa_hash_compute(alg, hash_output, hlen, hash_output,
-                                       out_size, &out_len)) != PSA_SUCCESS) {
-            goto exit;
-        }
-    }
-
-exit:
-    status_abort = psa_hash_abort(&op);
-    if (status == PSA_SUCCESS) {
-        status = status_abort;
-    }
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif /* !MBEDTLS_MD_C */
 }
 
 
@@ -350,7 +333,7 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,
 
     unsigned char diversifier[128];
     unsigned char salt_block[128], pwd_block[128], hash_block[128] = { 0 };
-    unsigned char hash_output[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash_output[MBEDTLS_MD_MAX_SIZE];
     unsigned char *p;
     unsigned char c;
     int           use_password = 0;
@@ -374,7 +357,7 @@ int mbedtls_pkcs12_derivation(unsigned char *data, size_t datalen,
     use_password = (pwd && pwdlen != 0);
     use_salt = (salt && saltlen != 0);
 
-    hlen = mbedtls_hash_info_get_size(md_type);
+    hlen = mbedtls_md_get_size_from_type(md_type);
 
     if (hlen <= 32) {
         v = 64;
diff --git a/lib/libmbedtls/mbedtls/library/pkcs5.c b/lib/libmbedtls/mbedtls/library/pkcs5.c
index f471b6378b79a9981fc2e5d70632defc984460da..c6c53054b62127272b82eda572e50eab01f8b917 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs5.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs5.c
@@ -6,19 +6,7 @@
  * \author Mathias Olsson <mathias@kompetensum.com>
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * PKCS#5 includes PBKDF2 and more
@@ -36,7 +24,9 @@
 
 #if defined(MBEDTLS_ASN1_PARSE_C)
 #include "mbedtls/asn1.h"
+#if defined(MBEDTLS_CIPHER_C)
 #include "mbedtls/cipher.h"
+#endif /* MBEDTLS_CIPHER_C */
 #include "mbedtls/oid.h"
 #endif /* MBEDTLS_ASN1_PARSE_C */
 
@@ -44,16 +34,9 @@
 
 #include "mbedtls/platform.h"
 
-#include "hash_info.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 
-#if !defined(MBEDTLS_MD_C)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_md_errors,              \
-                                                           psa_generic_status_to_mbedtls)
-#endif
-
-#if defined(MBEDTLS_ASN1_PARSE_C)
+#if defined(MBEDTLS_ASN1_PARSE_C) && defined(MBEDTLS_CIPHER_C)
 static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
                                      mbedtls_asn1_buf *salt, int *iterations,
                                      int *keylen, mbedtls_md_type_t *md_type)
@@ -118,10 +101,36 @@ static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
     return 0;
 }
 
+#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
+                            const unsigned char *pwd,  size_t pwdlen,
+                            const unsigned char *data, size_t datalen,
+                            unsigned char *output, size_t output_size,
+                            size_t *output_len);
+#endif
+
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
 int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
                         const unsigned char *pwd,  size_t pwdlen,
                         const unsigned char *data, size_t datalen,
                         unsigned char *output)
+{
+    size_t output_len = 0;
+
+    /* We assume caller of the function is providing a big enough output buffer
+     * so we pass output_size as SIZE_MAX to pass checks, However, no guarantees
+     * for the output size actually being correct.
+     */
+    return mbedtls_pkcs5_pbes2_ext(pbe_params, mode, pwd, pwdlen, data,
+                                   datalen, output, SIZE_MAX, &output_len);
+}
+#endif
+
+int mbedtls_pkcs5_pbes2_ext(const mbedtls_asn1_buf *pbe_params, int mode,
+                            const unsigned char *pwd,  size_t pwdlen,
+                            const unsigned char *data, size_t datalen,
+                            unsigned char *output, size_t output_size,
+                            size_t *output_len)
 {
     int ret, iterations = 0, keylen = 0;
     unsigned char *p, *end;
@@ -129,10 +138,10 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
     mbedtls_asn1_buf salt;
     mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1;
     unsigned char key[32], iv[32];
-    size_t olen = 0;
     const mbedtls_cipher_info_t *cipher_info;
     mbedtls_cipher_type_t cipher_alg;
     mbedtls_cipher_context_t cipher_ctx;
+    unsigned int padlen = 0;
 
     p = pbe_params->p;
     end = p + pbe_params->len;
@@ -183,13 +192,26 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
      * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored
      * since it is optional and we don't know if it was set or not
      */
-    keylen = cipher_info->key_bitlen / 8;
+    keylen = (int) mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
 
     if (enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING ||
-        enc_scheme_params.len != cipher_info->iv_size) {
+        enc_scheme_params.len != mbedtls_cipher_info_get_iv_size(cipher_info)) {
         return MBEDTLS_ERR_PKCS5_INVALID_FORMAT;
     }
 
+    if (mode == MBEDTLS_PKCS5_DECRYPT) {
+        if (output_size < datalen) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+    }
+
+    if (mode == MBEDTLS_PKCS5_ENCRYPT) {
+        padlen = cipher_info->block_size - (datalen % cipher_info->block_size);
+        if (output_size < (datalen + padlen)) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+    }
+
     mbedtls_cipher_init(&cipher_ctx);
 
     memcpy(iv, enc_scheme_params.p, enc_scheme_params.len);
@@ -209,8 +231,30 @@ int mbedtls_pkcs5_pbes2(const mbedtls_asn1_buf *pbe_params, int mode,
         goto exit;
     }
 
+#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING)
+    {
+        /* PKCS5 uses CBC with PKCS7 padding (which is the same as
+         * "PKCS5 padding" except that it's typically only called PKCS5
+         * with 64-bit-block ciphers).
+         */
+        mbedtls_cipher_padding_t padding = MBEDTLS_PADDING_PKCS7;
+#if !defined(MBEDTLS_CIPHER_PADDING_PKCS7)
+        /* For historical reasons, when decrypting, this function works when
+         * decrypting even when support for PKCS7 padding is disabled. In this
+         * case, it ignores the padding, and so will never report a
+         * password mismatch.
+         */
+        if (mode == MBEDTLS_DECRYPT) {
+            padding = MBEDTLS_PADDING_NONE;
+        }
+#endif
+        if ((ret = mbedtls_cipher_set_padding_mode(&cipher_ctx, padding)) != 0) {
+            goto exit;
+        }
+    }
+#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */
     if ((ret = mbedtls_cipher_crypt(&cipher_ctx, iv, enc_scheme_params.len,
-                                    data, datalen, output, &olen)) != 0) {
+                                    data, datalen, output, output_len)) != 0) {
         ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH;
     }
 
@@ -219,9 +263,8 @@ exit:
 
     return ret;
 }
-#endif /* MBEDTLS_ASN1_PARSE_C */
+#endif /* MBEDTLS_ASN1_PARSE_C && MBEDTLS_CIPHER_C */
 
-#if defined(MBEDTLS_MD_C)
 static int pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
                              const unsigned char *password,
                              size_t plen, const unsigned char *salt, size_t slen,
@@ -322,7 +365,6 @@ int mbedtls_pkcs5_pbkdf2_hmac(mbedtls_md_context_t *ctx,
                              key_length, output);
 }
 #endif
-#endif /* MBEDTLS_MD_C */
 
 int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
                                   const unsigned char *password,
@@ -330,7 +372,6 @@ int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
                                   unsigned int iteration_count,
                                   uint32_t key_length, unsigned char *output)
 {
-#if defined(MBEDTLS_MD_C)
     mbedtls_md_context_t md_ctx;
     const mbedtls_md_info_t *md_info = NULL;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
@@ -350,121 +391,11 @@ int mbedtls_pkcs5_pbkdf2_hmac_ext(mbedtls_md_type_t md_alg,
 exit:
     mbedtls_md_free(&md_ctx);
     return ret;
-#else
-    unsigned int i;
-    unsigned char md1[PSA_HASH_MAX_SIZE];
-    unsigned char work[PSA_HASH_MAX_SIZE];
-    const unsigned char md_size = mbedtls_hash_info_get_size(md_alg);
-    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
-
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_status_t status_destruction = PSA_ERROR_CORRUPTION_DETECTED;
-    size_t use_len, out_len;
-    unsigned char *out_p = output;
-    unsigned char counter[4];
-    mbedtls_svc_key_id_t psa_hmac_key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    const psa_algorithm_t alg = PSA_ALG_HMAC(mbedtls_hash_info_psa_from_md(md_alg));
-    const size_t out_size = PSA_MAC_LENGTH(PSA_KEY_TYPE_HMAC, 0, alg);
-
-    memset(counter, 0, sizeof(counter));
-    counter[3] = 1;
-
-    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
-    psa_set_key_algorithm(&attributes,  alg);
-    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
-
-    if (key_length == 0) {
-        return 0;
-    }
-    if ((status = psa_import_key(&attributes,
-                                 password, plen,
-                                 &psa_hmac_key)) != PSA_SUCCESS) {
-        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
-    }
-
-#if UINT_MAX > 0xFFFFFFFF
-    if (iteration_count > 0xFFFFFFFF) {
-        return MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA;
-    }
-#endif
-
-    while (key_length) {
-        status = psa_mac_sign_setup(&operation, psa_hmac_key,
-                                    PSA_ALG_HMAC(alg));
-        if (status != PSA_SUCCESS) {
-            goto cleanup;
-        }
-        // U1 ends up in work
-        if ((status = psa_mac_update(&operation, salt, slen)) != PSA_SUCCESS) {
-            goto cleanup;
-        }
-
-        if ((status = psa_mac_update(&operation, counter, sizeof(counter))) != PSA_SUCCESS) {
-            goto cleanup;
-        }
-
-        if ((status = psa_mac_sign_finish(&operation, work, out_size, &out_len))
-            != PSA_SUCCESS) {
-            goto cleanup;
-        }
-
-        memcpy(md1, work, out_len);
-
-        for (i = 1; i < iteration_count; i++) {
-            // U2 ends up in md1
-            //
-            status = psa_mac_sign_setup(&operation, psa_hmac_key,
-                                        PSA_ALG_HMAC(alg));
-            if (status != PSA_SUCCESS) {
-                goto cleanup;
-            }
-            if ((status = psa_mac_update(&operation, md1, md_size)) != PSA_SUCCESS) {
-                goto cleanup;
-            }
-            if ((status =
-                     psa_mac_sign_finish(&operation, md1, out_size, &out_len)) != PSA_SUCCESS) {
-                goto cleanup;
-            }
-
-            // U1 xor U2
-            //
-            mbedtls_xor(work, work, md1, md_size);
-        }
-
-        use_len = (key_length < md_size) ? key_length : md_size;
-        memcpy(out_p, work, use_len);
-
-        key_length -= (uint32_t) use_len;
-        out_p += use_len;
-
-        for (i = 4; i > 0; i--) {
-            if (++counter[i - 1] != 0) {
-                break;
-            }
-        }
-    }
-
-cleanup:
-    /* Zeroise buffers to clear sensitive data from memory. */
-    mbedtls_platform_zeroize(work, PSA_HASH_MAX_SIZE);
-    mbedtls_platform_zeroize(md1, PSA_HASH_MAX_SIZE);
-    status_destruction = psa_destroy_key(psa_hmac_key);
-    if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) {
-        status = status_destruction;
-    }
-    status_destruction = psa_mac_abort(&operation);
-    if (status == PSA_SUCCESS && status_destruction != PSA_SUCCESS) {
-        status = status_destruction;
-    }
-
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif /* !MBEDTLS_MD_C */
 }
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#if !defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
+#if !defined(MBEDTLS_MD_CAN_SHA1)
 int mbedtls_pkcs5_self_test(int verbose)
 {
     if (verbose != 0) {
@@ -562,7 +493,7 @@ int mbedtls_pkcs5_self_test(int verbose)
 exit:
     return ret;
 }
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
 #endif /* MBEDTLS_SELF_TEST */
 
diff --git a/lib/libmbedtls/mbedtls/library/pkcs7.c b/lib/libmbedtls/mbedtls/library/pkcs7.c
index cf05afd2c9f7eafc865a392cb44c67ee0a0efa9e..3aac662ba69839bf3ab74727e6ec2f9ed13147c2 100644
--- a/lib/libmbedtls/mbedtls/library/pkcs7.c
+++ b/lib/libmbedtls/mbedtls/library/pkcs7.c
@@ -1,25 +1,13 @@
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #include "common.h"
 
 #include "mbedtls/build_info.h"
 #if defined(MBEDTLS_PKCS7_C)
 #include "mbedtls/pkcs7.h"
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/x509_crt.h"
 #include "mbedtls/x509_crl.h"
@@ -328,7 +316,7 @@ static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
         goto out;
     }
 
-    signer->issuer_raw.len =  *p - signer->issuer_raw.p;
+    signer->issuer_raw.len =  (size_t) (*p - signer->issuer_raw.p);
 
     ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
     if (ret != 0) {
diff --git a/lib/libmbedtls/mbedtls/library/pkparse.c b/lib/libmbedtls/mbedtls/library/pkparse.c
index ccca692b7e1190c81e635d77fe97c5978b1b0eb9..4f6ee139862d6f1d11d6ed6c5edbd1fd1da7b0f9 100644
--- a/lib/libmbedtls/mbedtls/library/pkparse.c
+++ b/lib/libmbedtls/mbedtls/library/pkparse.c
@@ -2,19 +2,7 @@
  *  Public Key layer for parsing key files and structures
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -25,19 +13,25 @@
 #include "mbedtls/asn1.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
+#include "mbedtls/platform.h"
 #include "mbedtls/error.h"
+#include "mbedtls/ecp.h"
+#include "pk_internal.h"
 
 #include <string.h>
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#include "psa/crypto.h"
+#endif
+
+/* Key types */
 #if defined(MBEDTLS_RSA_C)
 #include "mbedtls/rsa.h"
+#include "rsa_internal.h"
 #endif
-#if defined(MBEDTLS_ECP_C)
-#include "mbedtls/ecp.h"
-#endif
-#if defined(MBEDTLS_ECDSA_C)
-#include "mbedtls/ecdsa.h"
-#endif
+
+/* Extended formats */
 #if defined(MBEDTLS_PEM_PARSE_C)
 #include "mbedtls/pem.h"
 #endif
@@ -48,163 +42,55 @@
 #include "mbedtls/pkcs12.h"
 #endif
 
-#include "mbedtls/platform.h"
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 
-#if defined(MBEDTLS_FS_IO)
-/*
- * Load all data from a file into a given buffer.
+/***********************************************************************
  *
- * The file is expected to contain either PEM or DER encoded data.
- * A terminating null byte is always appended. It is included in the announced
- * length only if the data looks like it is PEM encoded.
- */
-int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
-{
-    FILE *f;
-    long size;
-
-    if ((f = fopen(path, "rb")) == NULL) {
-        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-    }
-
-    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
-    mbedtls_setbuf(f, NULL);
-
-    fseek(f, 0, SEEK_END);
-    if ((size = ftell(f)) == -1) {
-        fclose(f);
-        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-    }
-    fseek(f, 0, SEEK_SET);
-
-    *n = (size_t) size;
-
-    if (*n + 1 == 0 ||
-        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
-        fclose(f);
-        return MBEDTLS_ERR_PK_ALLOC_FAILED;
-    }
-
-    if (fread(*buf, 1, *n, f) != *n) {
-        fclose(f);
-
-        mbedtls_platform_zeroize(*buf, *n);
-        mbedtls_free(*buf);
-
-        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
-    }
-
-    fclose(f);
-
-    (*buf)[*n] = '\0';
-
-    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
-        ++*n;
-    }
+ *      Low-level ECC parsing: optional support for SpecifiedECDomain
+ *
+ * There are two functions here that are used by the rest of the code:
+ * - pk_ecc_tag_is_speficied_ec_domain()
+ * - pk_ecc_group_id_from_specified()
+ *
+ * All the other functions are internal to this section.
+ *
+ * The two "public" functions have a dummy variant provided
+ * in configs without MBEDTLS_PK_PARSE_EC_EXTENDED. This acts as an
+ * abstraction layer for this macro, which should not appear outside
+ * this section.
+ *
+ **********************************************************************/
 
+#if !defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
+/* See the "real" version for documentation */
+static int pk_ecc_tag_is_specified_ec_domain(int tag)
+{
+    (void) tag;
     return 0;
 }
 
-/*
- * Load and parse a private key
- */
-int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
-                             const char *path, const char *pwd,
-                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+/* See the "real" version for documentation */
+static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
+                                          mbedtls_ecp_group_id *grp_id)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n;
-    unsigned char *buf;
-
-    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
-        return ret;
-    }
-
-    if (pwd == NULL) {
-        ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
-    } else {
-        ret = mbedtls_pk_parse_key(ctx, buf, n,
-                                   (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
-    }
-
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
-
-    return ret;
+    (void) params;
+    (void) grp_id;
+    return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
 }
-
+#else /* MBEDTLS_PK_PARSE_EC_EXTENDED */
 /*
- * Load and parse a public key
+ * Tell if the passed tag might be the start of SpecifiedECDomain
+ * (that is, a sequence).
  */
-int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
+static int pk_ecc_tag_is_specified_ec_domain(int tag)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n;
-    unsigned char *buf;
-
-    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
-        return ret;
-    }
-
-    ret = mbedtls_pk_parse_public_key(ctx, buf, n);
-
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
-
-    return ret;
+    return tag == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
 }
-#endif /* MBEDTLS_FS_IO */
-
-#if defined(MBEDTLS_ECP_C)
-/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
- *
- * ECParameters ::= CHOICE {
- *   namedCurve         OBJECT IDENTIFIER
- *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
- *   -- implicitCurve   NULL
- * }
- */
-static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
-                           mbedtls_asn1_buf *params)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if (end - *p < 1) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
-    }
-
-    /* Tag may be either OID or SEQUENCE */
-    params->tag = **p;
-    if (params->tag != MBEDTLS_ASN1_OID
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-        && params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
-#endif
-        ) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
-    }
-
-    if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
-
-    params->p = *p;
-    *p += params->len;
-
-    if (*p != end) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
-
-    return 0;
-}
-
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
 /*
  * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
  * WARNING: the resulting group should only be used with
- * pk_group_id_from_specified(), since its base point may not be set correctly
+ * pk_ecc_group_id_from_specified(), since its base point may not be set correctly
  * if it was encoded compressed.
  *
  *  SpecifiedECDomain ::= SEQUENCE {
@@ -224,7 +110,7 @@ static int pk_group_from_specified(const mbedtls_asn1_buf *params, mbedtls_ecp_g
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *p = params->p;
-    const unsigned char * const end = params->p + params->len;
+    const unsigned char *const end = params->p + params->len;
     const unsigned char *end_field, *end_curve;
     size_t len;
     int ver;
@@ -396,7 +282,6 @@ static int pk_group_id_from_group(const mbedtls_ecp_group *grp, mbedtls_ecp_grou
             mbedtls_mpi_get_bit(&grp->G.Y, 0) == mbedtls_mpi_get_bit(&ref.G.Y, 0)) {
             break;
         }
-
     }
 
 cleanup:
@@ -414,8 +299,8 @@ cleanup:
 /*
  * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID
  */
-static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
-                                      mbedtls_ecp_group_id *grp_id)
+static int pk_ecc_group_id_from_specified(const mbedtls_asn1_buf *params,
+                                          mbedtls_ecp_group_id *grp_id)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group grp;
@@ -430,7 +315,7 @@ static int pk_group_id_from_specified(const mbedtls_asn1_buf *params,
 
 cleanup:
     /* The API respecting lifecycle for mbedtls_ecp_group struct is
-     * _init(), _load() and _free(). In pk_group_id_from_specified() the
+     * _init(), _load() and _free(). In pk_ecc_group_id_from_specified() the
      * temporary grp breaks that flow and it's members are populated
      * by pk_group_id_from_group(). As such mbedtls_ecp_group_free()
      * which is assuming a group populated by _setup() may not clean-up
@@ -446,6 +331,53 @@ cleanup:
 }
 #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
 
+/***********************************************************************
+ *
+ * Unsorted (yet!) from this point on until the next section header
+ *
+ **********************************************************************/
+
+/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf
+ *
+ * ECParameters ::= CHOICE {
+ *   namedCurve         OBJECT IDENTIFIER
+ *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
+ *   -- implicitCurve   NULL
+ * }
+ */
+static int pk_get_ecparams(unsigned char **p, const unsigned char *end,
+                           mbedtls_asn1_buf *params)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (end - *p < 1) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_OUT_OF_DATA);
+    }
+
+    /* Acceptable tags: OID for namedCurve, or specifiedECDomain */
+    params->tag = **p;
+    if (params->tag != MBEDTLS_ASN1_OID &&
+        !pk_ecc_tag_is_specified_ec_domain(params->tag)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
+    }
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &params->len, params->tag)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
+    }
+
+    params->p = *p;
+    *p += params->len;
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
+}
+
 /*
  * Use EC parameters to initialise an EC group
  *
@@ -454,7 +386,7 @@ cleanup:
  *   specifiedCurve     SpecifiedECDomain -- = SEQUENCE { ... }
  *   -- implicitCurve   NULL
  */
-static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp)
+static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_pk_context *pk)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ecp_group_id grp_id;
@@ -464,116 +396,71 @@ static int pk_use_ecparams(const mbedtls_asn1_buf *params, mbedtls_ecp_group *gr
             return MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE;
         }
     } else {
-#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-        if ((ret = pk_group_id_from_specified(params, &grp_id)) != 0) {
+        ret = pk_ecc_group_id_from_specified(params, &grp_id);
+        if (ret != 0) {
             return ret;
         }
-#else
-        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-#endif
-    }
-
-    /*
-     * grp may already be initialized; if so, make sure IDs match
-     */
-    if (grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id) {
-        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-    }
-
-    if ((ret = mbedtls_ecp_group_load(grp, grp_id)) != 0) {
-        return ret;
     }
 
-    return 0;
+    return mbedtls_pk_ecc_set_group(pk, grp_id);
 }
 
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+
 /*
- * EC public key is an EC point
- *
- * The caller is responsible for clearing the structure upon failure if
- * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
- * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
+ * Load an RFC8410 EC key, which doesn't have any parameters
  */
-static int pk_get_ecpubkey(unsigned char **p, const unsigned char *end,
-                           mbedtls_ecp_keypair *key)
+static int pk_use_ecparams_rfc8410(const mbedtls_asn1_buf *params,
+                                   mbedtls_ecp_group_id grp_id,
+                                   mbedtls_pk_context *pk)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-
-    if ((ret = mbedtls_ecp_point_read_binary(&key->grp, &key->Q,
-                                             (const unsigned char *) *p, end - *p)) == 0) {
-        ret = mbedtls_ecp_check_pubkey(&key->grp, &key->Q);
+    if (params->tag != 0 || params->len != 0) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
     }
 
-    /*
-     * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
-     */
-    *p = (unsigned char *) end;
-
-    return ret;
+    return mbedtls_pk_ecc_set_group(pk, grp_id);
 }
-#endif /* MBEDTLS_ECP_C */
 
-#if defined(MBEDTLS_RSA_C)
 /*
- *  RSAPublicKey ::= SEQUENCE {
- *      modulus           INTEGER,  -- n
- *      publicExponent    INTEGER   -- e
- *  }
+ * Parse an RFC 8410 encoded private EC key
+ *
+ * CurvePrivateKey ::= OCTET STRING
  */
-static int pk_get_rsapubkey(unsigned char **p,
-                            const unsigned char *end,
-                            mbedtls_rsa_context *rsa)
+static int pk_parse_key_rfc8410_der(mbedtls_pk_context *pk,
+                                    unsigned char *key, size_t keylen, const unsigned char *end,
+                                    int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
 
-    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
-                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
-    }
-
-    if (*p + len != end) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
-
-    /* Import N */
-    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
-    }
-
-    if ((ret = mbedtls_rsa_import_raw(rsa, *p, len, NULL, 0, NULL, 0,
-                                      NULL, 0, NULL, 0)) != 0) {
-        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
-    }
-
-    *p += len;
-
-    /* Import E */
-    if ((ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+    if ((ret = mbedtls_asn1_get_tag(&key, (key + keylen), &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
-    if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
-                                      NULL, 0, *p, len)) != 0) {
-        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    if (key + len != end) {
+        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
     }
 
-    *p += len;
-
-    if (mbedtls_rsa_complete(rsa) != 0 ||
-        mbedtls_rsa_check_pubkey(rsa) != 0) {
-        return MBEDTLS_ERR_PK_INVALID_PUBKEY;
+    /*
+     * Load the private key
+     */
+    ret = mbedtls_pk_ecc_set_key(pk, key, len);
+    if (ret != 0) {
+        return ret;
     }
 
-    if (*p != end) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    /* pk_parse_key_pkcs8_unencrypted_der() only supports version 1 PKCS8 keys,
+     * which never contain a public key. As such, derive the public key
+     * unconditionally. */
+    if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, key, len, f_rng, p_rng)) != 0) {
+        return ret;
     }
 
     return 0;
 }
-#endif /* MBEDTLS_RSA_C */
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 /* Get a PK algorithm identifier
  *
@@ -583,7 +470,8 @@ static int pk_get_rsapubkey(unsigned char **p,
  */
 static int pk_get_pk_alg(unsigned char **p,
                          const unsigned char *end,
-                         mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params)
+                         mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params,
+                         mbedtls_ecp_group_id *ec_grp_id)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_asn1_buf alg_oid;
@@ -594,7 +482,18 @@ static int pk_get_pk_alg(unsigned char **p,
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_ALG, ret);
     }
 
-    if (mbedtls_oid_get_pk_alg(&alg_oid, pk_alg) != 0) {
+    ret = mbedtls_oid_get_pk_alg(&alg_oid, pk_alg);
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (ret == MBEDTLS_ERR_OID_NOT_FOUND) {
+        ret = mbedtls_oid_get_ec_grp_algid(&alg_oid, ec_grp_id);
+        if (ret == 0) {
+            *pk_alg = MBEDTLS_PK_ECKEY;
+        }
+    }
+#else
+    (void) ec_grp_id;
+#endif
+    if (ret != 0) {
         return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
     }
 
@@ -622,6 +521,7 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
     size_t len;
     mbedtls_asn1_buf alg_params;
     mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
+    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
     const mbedtls_pk_info_t *pk_info;
 
     if ((ret = mbedtls_asn1_get_tag(p, end, &len,
@@ -631,7 +531,7 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
 
     end = *p + len;
 
-    if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params)) != 0) {
+    if ((ret = pk_get_pk_alg(p, end, &pk_alg, &alg_params, &ec_grp_id)) != 0) {
         return ret;
     }
 
@@ -654,17 +554,35 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
 
 #if defined(MBEDTLS_RSA_C)
     if (pk_alg == MBEDTLS_PK_RSA) {
-        ret = pk_get_rsapubkey(p, end, mbedtls_pk_rsa(*pk));
+        ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*pk), *p, (size_t) (end - *p));
+        if (ret == 0) {
+            /* On success all the input has been consumed by the parsing function. */
+            *p += end - *p;
+        } else if ((ret <= MBEDTLS_ERR_ASN1_OUT_OF_DATA) &&
+                   (ret >= MBEDTLS_ERR_ASN1_BUF_TOO_SMALL)) {
+            /* In case of ASN1 error codes add MBEDTLS_ERR_PK_INVALID_PUBKEY. */
+            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY, ret);
+        } else {
+            ret = MBEDTLS_ERR_PK_INVALID_PUBKEY;
+        }
     } else
 #endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     if (pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY) {
-        ret = pk_use_ecparams(&alg_params, &mbedtls_pk_ec(*pk)->grp);
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
+            ret = pk_use_ecparams_rfc8410(&alg_params, ec_grp_id, pk);
+        } else
+#endif
+        {
+            ret = pk_use_ecparams(&alg_params, pk);
+        }
         if (ret == 0) {
-            ret = pk_get_ecpubkey(p, end, mbedtls_pk_ec(*pk));
+            ret = mbedtls_pk_ecc_set_pubkey(pk, *p, (size_t) (end - *p));
+            *p += end - *p;
         }
     } else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
     if (ret == 0 && *p != end) {
@@ -679,208 +597,20 @@ int mbedtls_pk_parse_subpubkey(unsigned char **p, const unsigned char *end,
     return ret;
 }
 
-#if defined(MBEDTLS_RSA_C)
-/*
- * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
- *
- * The value zero is:
- * - never a valid value for an RSA parameter
- * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
- *
- * Since values can't be omitted in PKCS#1, passing a zero value to
- * rsa_complete() would be incorrect, so reject zero values early.
- */
-static int asn1_get_nonzero_mpi(unsigned char **p,
-                                const unsigned char *end,
-                                mbedtls_mpi *X)
-{
-    int ret;
-
-    ret = mbedtls_asn1_get_mpi(p, end, X);
-    if (ret != 0) {
-        return ret;
-    }
-
-    if (mbedtls_mpi_cmp_int(X, 0) == 0) {
-        return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-    }
-
-    return 0;
-}
-
-/*
- * Parse a PKCS#1 encoded private RSA key
- */
-static int pk_parse_key_pkcs1_der(mbedtls_rsa_context *rsa,
-                                  const unsigned char *key,
-                                  size_t keylen)
-{
-    int ret, version;
-    size_t len;
-    unsigned char *p, *end;
-
-    mbedtls_mpi T;
-    mbedtls_mpi_init(&T);
-
-    p = (unsigned char *) key;
-    end = p + keylen;
-
-    /*
-     * This function parses the RSAPrivateKey (PKCS#1)
-     *
-     *  RSAPrivateKey ::= SEQUENCE {
-     *      version           Version,
-     *      modulus           INTEGER,  -- n
-     *      publicExponent    INTEGER,  -- e
-     *      privateExponent   INTEGER,  -- d
-     *      prime1            INTEGER,  -- p
-     *      prime2            INTEGER,  -- q
-     *      exponent1         INTEGER,  -- d mod (p-1)
-     *      exponent2         INTEGER,  -- d mod (q-1)
-     *      coefficient       INTEGER,  -- (inverse of q) mod p
-     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
-     *  }
-     */
-    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
-                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
-
-    end = p + len;
-
-    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
-
-    if (version != 0) {
-        return MBEDTLS_ERR_PK_KEY_INVALID_VERSION;
-    }
-
-    /* Import N */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
-                                  NULL, NULL)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import E */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
-                                  NULL, &T)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import D */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
-                                  &T, NULL)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import P */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
-                                  NULL, NULL)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import Q */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
-                                  NULL, NULL)) != 0) {
-        goto cleanup;
-    }
-
-#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
-    /*
-     * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
-     * that they can be easily recomputed from D, P and Q. However by
-     * parsing them from the PKCS1 structure it is possible to avoid
-     * recalculating them which both reduces the overhead of loading
-     * RSA private keys into memory and also avoids side channels which
-     * can arise when computing those values, since all of D, P, and Q
-     * are secret. See https://eprint.iacr.org/2020/055 for a
-     * description of one such attack.
-     */
-
-    /* Import DP */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import DQ */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
-        goto cleanup;
-    }
-
-    /* Import QP */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
-        goto cleanup;
-    }
-
-#else
-    /* Verify existence of the CRT params */
-    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
-        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
-        goto cleanup;
-    }
-#endif
-
-    /* rsa_complete() doesn't complete anything with the default
-     * implementation but is still called:
-     * - for the benefit of alternative implementation that may want to
-     *   pre-compute stuff beyond what's provided (eg Montgomery factors)
-     * - as is also sanity-checks the key
-     *
-     * Furthermore, we also check the public part for consistency with
-     * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
-     */
-    if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
-        (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
-        goto cleanup;
-    }
-
-    if (p != end) {
-        ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
-                                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
-
-cleanup:
-
-    mbedtls_mpi_free(&T);
-
-    if (ret != 0) {
-        /* Wrap error code if it's coming from a lower level */
-        if ((ret & 0xff80) == 0) {
-            ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-        } else {
-            ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
-        }
-
-        mbedtls_rsa_free(rsa);
-    }
-
-    return ret;
-}
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 /*
  * Parse a SEC1 encoded private EC key
  */
-static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
+static int pk_parse_key_sec1_der(mbedtls_pk_context *pk,
                                  const unsigned char *key, size_t keylen,
                                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     int version, pubkey_done;
-    size_t len;
+    size_t len, d_len;
     mbedtls_asn1_buf params = { 0, 0, NULL };
     unsigned char *p = (unsigned char *) key;
+    unsigned char *d;
     unsigned char *end = p + keylen;
     unsigned char *end2;
 
@@ -913,10 +643,10 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
     }
 
-    if ((ret = mbedtls_mpi_read_binary(&eck->d, p, len)) != 0) {
-        mbedtls_ecp_keypair_free(eck);
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
+    /* Keep a reference to the position fo the private key. It will be used
+     * later in this function. */
+    d = p;
+    d_len = len;
 
     p += len;
 
@@ -929,16 +659,22 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
                                         MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
                                         0)) == 0) {
             if ((ret = pk_get_ecparams(&p, p + len, &params)) != 0 ||
-                (ret = pk_use_ecparams(&params, &eck->grp)) != 0) {
-                mbedtls_ecp_keypair_free(eck);
+                (ret = pk_use_ecparams(&params, pk)) != 0) {
                 return ret;
             }
         } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
-            mbedtls_ecp_keypair_free(eck);
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
         }
     }
 
+    /*
+     * Load the private key
+     */
+    ret = mbedtls_pk_ecc_set_key(pk, d, d_len);
+    if (ret != 0) {
+        return ret;
+    }
+
     if (p != end) {
         /*
          * Is 'publickey' present? If not, or if we can't read it (eg because it
@@ -958,11 +694,11 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
                                          MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
             }
 
-            if ((ret = pk_get_ecpubkey(&p, end2, eck)) == 0) {
+            if ((ret = mbedtls_pk_ecc_set_pubkey(pk, p, (size_t) (end2 - p))) == 0) {
                 pubkey_done = 1;
             } else {
                 /*
-                 * The only acceptable failure mode of pk_get_ecpubkey() above
+                 * The only acceptable failure mode of mbedtls_pk_ecc_set_pubkey() above
                  * is if the point format is not recognized.
                  */
                 if (ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
@@ -970,26 +706,25 @@ static int pk_parse_key_sec1_der(mbedtls_ecp_keypair *eck,
                 }
             }
         } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
-            mbedtls_ecp_keypair_free(eck);
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
         }
     }
 
-    if (!pubkey_done &&
-        (ret = mbedtls_ecp_mul(&eck->grp, &eck->Q, &eck->d, &eck->grp.G,
-                               f_rng, p_rng)) != 0) {
-        mbedtls_ecp_keypair_free(eck);
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret);
-    }
-
-    if ((ret = mbedtls_ecp_check_privkey(&eck->grp, &eck->d)) != 0) {
-        mbedtls_ecp_keypair_free(eck);
-        return ret;
+    if (!pubkey_done) {
+        if ((ret = mbedtls_pk_ecc_set_pubkey_from_prv(pk, d, d_len, f_rng, p_rng)) != 0) {
+            return ret;
+        }
     }
 
     return 0;
 }
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/***********************************************************************
+ *
+ *      PKCS#8 parsing functions
+ *
+ **********************************************************************/
 
 /*
  * Parse an unencrypted PKCS#8 encoded private key
@@ -1015,9 +750,10 @@ static int pk_parse_key_pkcs8_unencrypted_der(
     unsigned char *p = (unsigned char *) key;
     unsigned char *end = p + keylen;
     mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
+    mbedtls_ecp_group_id ec_grp_id = MBEDTLS_ECP_DP_NONE;
     const mbedtls_pk_info_t *pk_info;
 
-#if !defined(MBEDTLS_ECP_C)
+#if !defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     (void) f_rng;
     (void) p_rng;
 #endif
@@ -1053,7 +789,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret);
     }
 
-    if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params)) != 0) {
+    if ((ret = pk_get_pk_alg(&p, end, &pk_alg, &params, &ec_grp_id)) != 0) {
         return ret;
     }
 
@@ -1076,23 +812,43 @@ static int pk_parse_key_pkcs8_unencrypted_der(
 
 #if defined(MBEDTLS_RSA_C)
     if (pk_alg == MBEDTLS_PK_RSA) {
-        if ((ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), p, len)) != 0) {
+        if ((ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), p, len)) != 0) {
             mbedtls_pk_free(pk);
             return ret;
         }
     } else
 #endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     if (pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH) {
-        if ((ret = pk_use_ecparams(&params, &mbedtls_pk_ec(*pk)->grp)) != 0 ||
-            (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk), p, len, f_rng, p_rng)) != 0) {
-            mbedtls_pk_free(pk);
-            return ret;
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
+            if ((ret =
+                     pk_use_ecparams_rfc8410(&params, ec_grp_id, pk)) != 0 ||
+                (ret =
+                     pk_parse_key_rfc8410_der(pk, p, len, end, f_rng,
+                                              p_rng)) != 0) {
+                mbedtls_pk_free(pk);
+                return ret;
+            }
+        } else
+#endif
+        {
+            if ((ret = pk_use_ecparams(&params, pk)) != 0 ||
+                (ret = pk_parse_key_sec1_der(pk, p, len, f_rng, p_rng)) != 0) {
+                mbedtls_pk_free(pk);
+                return ret;
+            }
         }
     } else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     return MBEDTLS_ERR_PK_UNKNOWN_PK_ALG;
 
+    end = p + len;
+    if (end != (key + keylen)) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
     return 0;
 }
 
@@ -1106,7 +862,7 @@ static int pk_parse_key_pkcs8_unencrypted_der(
  *
  */
 #if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C)
-static int pk_parse_key_pkcs8_encrypted_der(
+MBEDTLS_STATIC_TESTABLE int mbedtls_pk_parse_key_pkcs8_encrypted_der(
     mbedtls_pk_context *pk,
     unsigned char *key, size_t keylen,
     const unsigned char *pwd, size_t pwdlen,
@@ -1117,10 +873,11 @@ static int pk_parse_key_pkcs8_encrypted_der(
     unsigned char *buf;
     unsigned char *p, *end;
     mbedtls_asn1_buf pbe_alg_oid, pbe_params;
-#if defined(MBEDTLS_PKCS12_C)
+#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
     mbedtls_cipher_type_t cipher_alg;
     mbedtls_md_type_t md_alg;
 #endif
+    size_t outlen = 0;
 
     p = key;
     end = p + keylen;
@@ -1164,11 +921,11 @@ static int pk_parse_key_pkcs8_encrypted_der(
     /*
      * Decrypt EncryptedData with appropriate PBE
      */
-#if defined(MBEDTLS_PKCS12_C)
+#if defined(MBEDTLS_PKCS12_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
     if (mbedtls_oid_get_pkcs12_pbe_alg(&pbe_alg_oid, &md_alg, &cipher_alg) == 0) {
-        if ((ret = mbedtls_pkcs12_pbe(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
-                                      cipher_alg, md_alg,
-                                      pwd, pwdlen, p, len, buf)) != 0) {
+        if ((ret = mbedtls_pkcs12_pbe_ext(&pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT,
+                                          cipher_alg, md_alg,
+                                          pwd, pwdlen, p, len, buf, len, &outlen)) != 0) {
             if (ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) {
                 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
             }
@@ -1178,11 +935,11 @@ static int pk_parse_key_pkcs8_encrypted_der(
 
         decrypted = 1;
     } else
-#endif /* MBEDTLS_PKCS12_C */
-#if defined(MBEDTLS_PKCS5_C)
+#endif /* MBEDTLS_PKCS12_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
+#if defined(MBEDTLS_PKCS5_C) && defined(MBEDTLS_CIPHER_PADDING_PKCS7) && defined(MBEDTLS_CIPHER_C)
     if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid) == 0) {
-        if ((ret = mbedtls_pkcs5_pbes2(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
-                                       p, len, buf)) != 0) {
+        if ((ret = mbedtls_pkcs5_pbes2_ext(&pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen,
+                                           p, len, buf, len, &outlen)) != 0) {
             if (ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) {
                 return MBEDTLS_ERR_PK_PASSWORD_MISMATCH;
             }
@@ -1192,7 +949,7 @@ static int pk_parse_key_pkcs8_encrypted_der(
 
         decrypted = 1;
     } else
-#endif /* MBEDTLS_PKCS5_C */
+#endif /* MBEDTLS_PKCS5_C && MBEDTLS_CIPHER_PADDING_PKCS7 && MBEDTLS_CIPHER_C */
     {
         ((void) pwd);
     }
@@ -1200,11 +957,16 @@ static int pk_parse_key_pkcs8_encrypted_der(
     if (decrypted == 0) {
         return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
     }
-
-    return pk_parse_key_pkcs8_unencrypted_der(pk, buf, len, f_rng, p_rng);
+    return pk_parse_key_pkcs8_unencrypted_der(pk, buf, outlen, f_rng, p_rng);
 }
 #endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */
 
+/***********************************************************************
+ *
+ *      Top-level functions, with format auto-discovery
+ *
+ **********************************************************************/
+
 /*
  * Parse a private key
  */
@@ -1233,16 +995,15 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN RSA PRIVATE KEY-----",
-                                      "-----END RSA PRIVATE KEY-----",
+                                      PEM_BEGIN_PRIVATE_KEY_RSA, PEM_END_PRIVATE_KEY_RSA,
                                       key, pwd, pwdlen, &len);
     }
 
     if (ret == 0) {
         pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
         if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
-            (ret = pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk),
-                                          pem.buf, pem.buflen)) != 0) {
+            (ret = mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk),
+                                         pem.buf, pem.buflen)) != 0) {
             mbedtls_pk_free(pk);
         }
 
@@ -1257,21 +1018,21 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
     }
 #endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
     if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN EC PRIVATE KEY-----",
-                                      "-----END EC PRIVATE KEY-----",
+                                      PEM_BEGIN_PRIVATE_KEY_EC,
+                                      PEM_END_PRIVATE_KEY_EC,
                                       key, pwd, pwdlen, &len);
     }
     if (ret == 0) {
         pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
 
         if ((ret = mbedtls_pk_setup(pk, pk_info)) != 0 ||
-            (ret = pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+            (ret = pk_parse_key_sec1_der(pk,
                                          pem.buf, pem.buflen,
                                          f_rng, p_rng)) != 0) {
             mbedtls_pk_free(pk);
@@ -1286,15 +1047,14 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
     } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
         return ret;
     }
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
     if (key[keylen - 1] != '\0') {
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN PRIVATE KEY-----",
-                                      "-----END PRIVATE KEY-----",
+                                      PEM_BEGIN_PRIVATE_KEY_PKCS8, PEM_END_PRIVATE_KEY_PKCS8,
                                       key, NULL, 0, &len);
     }
     if (ret == 0) {
@@ -1315,13 +1075,13 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN ENCRYPTED PRIVATE KEY-----",
-                                      "-----END ENCRYPTED PRIVATE KEY-----",
+                                      PEM_BEGIN_ENCRYPTED_PRIVATE_KEY_PKCS8,
+                                      PEM_END_ENCRYPTED_PRIVATE_KEY_PKCS8,
                                       key, NULL, 0, &len);
     }
     if (ret == 0) {
-        if ((ret = pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
-                                                    pwd, pwdlen, f_rng, p_rng)) != 0) {
+        if ((ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, pem.buf, pem.buflen,
+                                                            pwd, pwdlen, f_rng, p_rng)) != 0) {
             mbedtls_pk_free(pk);
         }
 
@@ -1353,11 +1113,10 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
 
         memcpy(key_copy, key, keylen);
 
-        ret = pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
-                                               pwd, pwdlen, f_rng, p_rng);
+        ret = mbedtls_pk_parse_key_pkcs8_encrypted_der(pk, key_copy, keylen,
+                                                       pwd, pwdlen, f_rng, p_rng);
 
-        mbedtls_platform_zeroize(key_copy, keylen);
-        mbedtls_free(key_copy);
+        mbedtls_zeroize_and_free(key_copy, keylen);
     }
 
     if (ret == 0) {
@@ -1384,7 +1143,7 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
 
     pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_RSA);
     if (mbedtls_pk_setup(pk, pk_info) == 0 &&
-        pk_parse_key_pkcs1_der(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
+        mbedtls_rsa_parse_key(mbedtls_pk_rsa(*pk), key, keylen) == 0) {
         return 0;
     }
 
@@ -1392,21 +1151,21 @@ int mbedtls_pk_parse_key(mbedtls_pk_context *pk,
     mbedtls_pk_init(pk);
 #endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     pk_info = mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
     if (mbedtls_pk_setup(pk, pk_info) == 0 &&
-        pk_parse_key_sec1_der(mbedtls_pk_ec(*pk),
+        pk_parse_key_sec1_der(pk,
                               key, keylen, f_rng, p_rng) == 0) {
         return 0;
     }
     mbedtls_pk_free(pk);
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
-    /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't,
+    /* If MBEDTLS_RSA_C is defined but MBEDTLS_PK_HAVE_ECC_KEYS isn't,
      * it is ok to leave the PK context initialized but not
      * freed: It is the caller's responsibility to call pk_init()
      * before calling this function, and to call pk_free()
-     * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C
+     * when it fails. If MBEDTLS_PK_HAVE_ECC_KEYS is defined but MBEDTLS_RSA_C
      * isn't, this leads to mbedtls_pk_free() being called
      * twice, once here and once by the caller, but this is
      * also ok and in line with the mbedtls_pk_free() calls
@@ -1443,8 +1202,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN RSA PUBLIC KEY-----",
-                                      "-----END RSA PUBLIC KEY-----",
+                                      PEM_BEGIN_PUBLIC_KEY_RSA, PEM_END_PUBLIC_KEY_RSA,
                                       key, NULL, 0, &len);
     }
 
@@ -1460,7 +1218,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
             return ret;
         }
 
-        if ((ret = pk_get_rsapubkey(&p, p + pem.buflen, mbedtls_pk_rsa(*ctx))) != 0) {
+        if ((ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, pem.buflen)) != 0) {
             mbedtls_pk_free(ctx);
         }
 
@@ -1477,8 +1235,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
     } else {
         ret = mbedtls_pem_read_buffer(&pem,
-                                      "-----BEGIN PUBLIC KEY-----",
-                                      "-----END PUBLIC KEY-----",
+                                      PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
                                       key, NULL, 0, &len);
     }
 
@@ -1488,7 +1245,7 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
          */
         p = pem.buf;
 
-        ret = mbedtls_pk_parse_subpubkey(&p,  p + pem.buflen, ctx);
+        ret = mbedtls_pk_parse_subpubkey(&p, p + pem.buflen, ctx);
         mbedtls_pem_free(&pem);
         return ret;
     } else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
@@ -1508,13 +1265,12 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
     }
 
     p = (unsigned char *) key;
-    ret = pk_get_rsapubkey(&p, p + keylen, mbedtls_pk_rsa(*ctx));
+    ret = mbedtls_rsa_parse_pubkey(mbedtls_pk_rsa(*ctx), p, keylen);
     if (ret == 0) {
         return ret;
     }
     mbedtls_pk_free(ctx);
-    if (ret != (MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PK_INVALID_PUBKEY,
-                                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG))) {
+    if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
         return ret;
     }
 #endif /* MBEDTLS_RSA_C */
@@ -1525,4 +1281,112 @@ int mbedtls_pk_parse_public_key(mbedtls_pk_context *ctx,
     return ret;
 }
 
+/***********************************************************************
+ *
+ *      Top-level functions, with filesystem support
+ *
+ **********************************************************************/
+
+#if defined(MBEDTLS_FS_IO)
+/*
+ * Load all data from a file into a given buffer.
+ *
+ * The file is expected to contain either PEM or DER encoded data.
+ * A terminating null byte is always appended. It is included in the announced
+ * length only if the data looks like it is PEM encoded.
+ */
+int mbedtls_pk_load_file(const char *path, unsigned char **buf, size_t *n)
+{
+    FILE *f;
+    long size;
+
+    if ((f = fopen(path, "rb")) == NULL) {
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+    }
+
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(f, NULL);
+
+    fseek(f, 0, SEEK_END);
+    if ((size = ftell(f)) == -1) {
+        fclose(f);
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+    }
+    fseek(f, 0, SEEK_SET);
+
+    *n = (size_t) size;
+
+    if (*n + 1 == 0 ||
+        (*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
+        fclose(f);
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
+
+    if (fread(*buf, 1, *n, f) != *n) {
+        fclose(f);
+
+        mbedtls_zeroize_and_free(*buf, *n);
+
+        return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+    }
+
+    fclose(f);
+
+    (*buf)[*n] = '\0';
+
+    if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
+        ++*n;
+    }
+
+    return 0;
+}
+
+/*
+ * Load and parse a private key
+ */
+int mbedtls_pk_parse_keyfile(mbedtls_pk_context *ctx,
+                             const char *path, const char *pwd,
+                             int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t n;
+    unsigned char *buf;
+
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
+
+    if (pwd == NULL) {
+        ret = mbedtls_pk_parse_key(ctx, buf, n, NULL, 0, f_rng, p_rng);
+    } else {
+        ret = mbedtls_pk_parse_key(ctx, buf, n,
+                                   (const unsigned char *) pwd, strlen(pwd), f_rng, p_rng);
+    }
+
+    mbedtls_zeroize_and_free(buf, n);
+
+    return ret;
+}
+
+/*
+ * Load and parse a public key
+ */
+int mbedtls_pk_parse_public_keyfile(mbedtls_pk_context *ctx, const char *path)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t n;
+    unsigned char *buf;
+
+    if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
+        return ret;
+    }
+
+    ret = mbedtls_pk_parse_public_key(ctx, buf, n);
+
+    mbedtls_zeroize_and_free(buf, n);
+
+    return ret;
+}
+#endif /* MBEDTLS_FS_IO */
+
 #endif /* MBEDTLS_PK_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.c b/lib/libmbedtls/mbedtls/library/pkwrite.c
index 2194c97e3b6c81c061e55a2003f48d8c26f9b384..2a698448bee647add928d6e7b85d738c3f48fcaf 100644
--- a/lib/libmbedtls/mbedtls/library/pkwrite.c
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.c
@@ -2,19 +2,7 @@
  *  Public Key layer for writing key files and structures
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -26,93 +14,136 @@
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+#include "pk_internal.h"
 
 #include <string.h>
 
-#if defined(MBEDTLS_RSA_C)
-#include "mbedtls/rsa.h"
-#endif
 #if defined(MBEDTLS_ECP_C)
 #include "mbedtls/bignum.h"
 #include "mbedtls/ecp.h"
 #include "mbedtls/platform_util.h"
 #endif
-#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C)
-#include "pkwrite.h"
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#include "pk_internal.h"
 #endif
-#if defined(MBEDTLS_ECDSA_C)
-#include "mbedtls/ecdsa.h"
+#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#include "pkwrite.h"
 #endif
 #if defined(MBEDTLS_PEM_WRITE_C)
 #include "mbedtls/pem.h"
 #endif
+#if defined(MBEDTLS_RSA_C)
+#include "rsa_internal.h"
+#endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 #endif
 #include "mbedtls/platform.h"
 
+/* Helpers for properly sizing buffers aimed at holding public keys or
+ * key-pairs based on build symbols. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+#define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
+#elif defined(MBEDTLS_USE_PSA_CRYPTO)
+#define PK_MAX_EC_PUBLIC_KEY_SIZE       PSA_EXPORT_PUBLIC_KEY_MAX_SIZE
+#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH
+#else
+#define PK_MAX_EC_PUBLIC_KEY_SIZE       MBEDTLS_ECP_MAX_PT_LEN
+#define PK_MAX_EC_KEY_PAIR_SIZE         MBEDTLS_ECP_MAX_BYTES
+#endif
+
+/******************************************************************************
+ * Internal functions for RSA keys.
+ ******************************************************************************/
 #if defined(MBEDTLS_RSA_C)
-/*
- *  RSAPublicKey ::= SEQUENCE {
- *      modulus           INTEGER,  -- n
- *      publicExponent    INTEGER   -- e
- *  }
- */
-static int pk_write_rsa_pubkey(unsigned char **p, unsigned char *start,
-                               mbedtls_rsa_context *rsa)
+static int pk_write_rsa_der(unsigned char **p, unsigned char *buf,
+                            const mbedtls_pk_context *pk)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len = 0;
-    mbedtls_mpi T;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        uint8_t tmp[PSA_EXPORT_KEY_PAIR_MAX_SIZE];
+        size_t tmp_len = 0;
 
-    mbedtls_mpi_init(&T);
+        if (psa_export_key(pk->priv_id, tmp, sizeof(tmp), &tmp_len) != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+        /* Ensure there's enough space in the provided buffer before copying data into it. */
+        if (tmp_len > (size_t) (*p - buf)) {
+            mbedtls_platform_zeroize(tmp, sizeof(tmp));
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+        *p -= tmp_len;
+        memcpy(*p, tmp, tmp_len);
+        mbedtls_platform_zeroize(tmp, sizeof(tmp));
 
-    /* Export E */
-    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
-        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
-        goto end_of_export;
+        return (int) tmp_len;
     }
-    len += ret;
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    return mbedtls_rsa_write_key(mbedtls_pk_rsa(*pk), buf, p);
+}
+#endif /* MBEDTLS_RSA_C */
 
-    /* Export N */
-    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
-        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
-        goto end_of_export;
-    }
-    len += ret;
+/******************************************************************************
+ * Internal functions for EC keys.
+ ******************************************************************************/
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
+                              const mbedtls_pk_context *pk)
+{
+    size_t len = 0;
+    uint8_t buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
 
-end_of_export:
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+    } else {
+        len = pk->pub_raw_len;
+        memcpy(buf, pk->pub_raw, len);
+    }
 
-    mbedtls_mpi_free(&T);
-    if (ret < 0) {
-        return ret;
+    if (*p < start || (size_t) (*p - start) < len) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
     }
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
-                                                     MBEDTLS_ASN1_SEQUENCE));
+    *p -= len;
+    memcpy(*p, buf, len);
 
     return (int) len;
 }
-#endif /* MBEDTLS_RSA_C */
-
-#if defined(MBEDTLS_ECP_C)
-/*
- * EC public key is an EC point
- */
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
 static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
-                              mbedtls_ecp_keypair *ec)
+                              const mbedtls_pk_context *pk)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
-    unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN];
+    unsigned char buf[PK_MAX_EC_PUBLIC_KEY_SIZE];
+    mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
-                                              MBEDTLS_ECP_PF_UNCOMPRESSED,
-                                              &len, buf, sizeof(buf))) != 0) {
-        return ret;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        if (psa_export_public_key(pk->priv_id, buf, sizeof(buf), &len) != PSA_SUCCESS) {
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        }
+        /* Ensure there's enough space in the provided buffer before copying data into it. */
+        if (len > (size_t) (*p - start)) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+        *p -= len;
+        memcpy(*p, buf, len);
+        return (int) len;
+    } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    {
+        if ((ret = mbedtls_ecp_point_write_binary(&ec->grp, &ec->Q,
+                                                  MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                                  &len, buf, sizeof(buf))) != 0) {
+            return ret;
+        }
     }
 
     if (*p < start || (size_t) (*p - start) < len) {
@@ -124,6 +155,72 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
 
     return (int) len;
 }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+
+/*
+ * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
+ */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+static int pk_write_ec_private(unsigned char **p, unsigned char *start,
+                               const mbedtls_pk_context *pk)
+{
+    size_t byte_length;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
+    psa_status_t status;
+
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+            return ret;
+        }
+    } else {
+        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+            goto exit;
+        }
+    }
+
+    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+exit:
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    return ret;
+}
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+static int pk_write_ec_private(unsigned char **p, unsigned char *start,
+                               const mbedtls_pk_context *pk)
+{
+    size_t byte_length;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char tmp[PK_MAX_EC_KEY_PAIR_SIZE];
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_status_t status;
+    if (mbedtls_pk_get_type(pk) == MBEDTLS_PK_OPAQUE) {
+        status = psa_export_key(pk->priv_id, tmp, sizeof(tmp), &byte_length);
+        if (status != PSA_SUCCESS) {
+            ret = PSA_PK_ECDSA_TO_MBEDTLS_ERR(status);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    {
+        mbedtls_ecp_keypair *ec = mbedtls_pk_ec_rw(*pk);
+        byte_length = (ec->grp.pbits + 7) / 8;
+
+        ret = mbedtls_ecp_write_key_ext(ec, &byte_length, tmp, sizeof(tmp));
+        if (ret != 0) {
+            goto exit;
+        }
+    }
+    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+exit:
+    mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    return ret;
+}
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 
 /*
  * ECParameters ::= CHOICE {
@@ -131,14 +228,14 @@ static int pk_write_ec_pubkey(unsigned char **p, unsigned char *start,
  * }
  */
 static int pk_write_ec_param(unsigned char **p, unsigned char *start,
-                             mbedtls_ecp_keypair *ec)
+                             mbedtls_ecp_group_id grp_id)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len = 0;
     const char *oid;
     size_t oid_len;
 
-    if ((ret = mbedtls_oid_get_oid_by_ec_grp(ec->grp.id, &oid, &oid_len)) != 0) {
+    if ((ret = mbedtls_oid_get_oid_by_ec_grp(grp_id, &oid, &oid_len)) != 0) {
         return ret;
     }
 
@@ -147,28 +244,178 @@ static int pk_write_ec_param(unsigned char **p, unsigned char *start,
     return (int) len;
 }
 
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
 /*
- * privateKey  OCTET STRING -- always of length ceil(log2(n)/8)
+ * RFC8410 section 7
+ *
+ * OneAsymmetricKey ::= SEQUENCE {
+ *    version Version,
+ *    privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+ *    privateKey PrivateKey,
+ *    attributes [0] IMPLICIT Attributes OPTIONAL,
+ *    ...,
+ *    [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]],
+ *    ...
+ * }
+ * ...
+ * CurvePrivateKey ::= OCTET STRING
  */
-static int pk_write_ec_private(unsigned char **p, unsigned char *start,
-                               mbedtls_ecp_keypair *ec)
+static int pk_write_ec_rfc8410_der(unsigned char **p, unsigned char *buf,
+                                   const mbedtls_pk_context *pk)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t byte_length = (ec->grp.pbits + 7) / 8;
-    unsigned char tmp[MBEDTLS_ECP_MAX_BYTES];
+    size_t len = 0;
+    size_t oid_len = 0;
+    const char *oid;
+    mbedtls_ecp_group_id grp_id;
 
-    ret = mbedtls_ecp_write_key(ec, tmp, byte_length);
-    if (ret != 0) {
-        goto exit;
+    /* privateKey */
+    MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_OCTET_STRING));
+
+    grp_id = mbedtls_pk_get_ec_group_id(pk);
+    /* privateKeyAlgorithm */
+    if ((ret = mbedtls_oid_get_oid_by_ec_grp_algid(grp_id, &oid, &oid_len)) != 0) {
+        return ret;
     }
-    ret = mbedtls_asn1_write_octet_string(p, start, tmp, byte_length);
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_algorithm_identifier_ext(p, buf, oid, oid_len, 0, 0));
 
-exit:
-    mbedtls_platform_zeroize(tmp, byte_length);
-    return ret;
+    /* version */
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 0));
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    return (int) len;
+}
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+
+/*
+ * RFC 5915, or SEC1 Appendix C.4
+ *
+ * ECPrivateKey ::= SEQUENCE {
+ *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+ *      privateKey     OCTET STRING,
+ *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
+ *      publicKey  [1] BIT STRING OPTIONAL
+ *    }
+ */
+static int pk_write_ec_der(unsigned char **p, unsigned char *buf,
+                           const mbedtls_pk_context *pk)
+{
+    size_t len = 0;
+    int ret;
+    size_t pub_len = 0, par_len = 0;
+    mbedtls_ecp_group_id grp_id;
+
+    /* publicKey */
+    MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(p, buf, pk));
+
+    if (*p - buf < 1) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+    (*p)--;
+    **p = 0;
+    pub_len += 1;
+
+    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
+    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_BIT_STRING));
+
+    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(p, buf, pub_len));
+    MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(p, buf,
+                                                         MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                         MBEDTLS_ASN1_CONSTRUCTED | 1));
+    len += pub_len;
+
+    /* parameters */
+    grp_id = mbedtls_pk_get_ec_group_id(pk);
+    MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(p, buf, grp_id));
+    MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(p, buf, par_len));
+    MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(p, buf,
+                                                         MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                         MBEDTLS_ASN1_CONSTRUCTED | 0));
+    len += par_len;
+
+    /* privateKey */
+    MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(p, buf, pk));
+
+    /* version */
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, buf, 1));
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, buf, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, buf, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    return (int) len;
+}
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/******************************************************************************
+ * Internal functions for Opaque keys.
+ ******************************************************************************/
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int pk_write_opaque_pubkey(unsigned char **p, unsigned char *start,
+                                  const mbedtls_pk_context *pk)
+{
+    size_t buffer_size;
+    size_t len = 0;
+
+    if (*p < start) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    buffer_size = (size_t) (*p - start);
+    if (psa_export_public_key(pk->priv_id, start, buffer_size,
+                              &len) != PSA_SUCCESS) {
+        return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+    }
+
+    *p -= len;
+    memmove(*p, start, len);
+
+    return (int) len;
 }
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+/******************************************************************************
+ * Generic helpers
+ ******************************************************************************/
+
+/* Extend the public mbedtls_pk_get_type() by getting key type also in case of
+ * opaque keys. */
+static mbedtls_pk_type_t pk_get_type_ext(const mbedtls_pk_context *pk)
+{
+    mbedtls_pk_type_t pk_type = mbedtls_pk_get_type(pk);
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (pk_type == MBEDTLS_PK_OPAQUE) {
+        psa_key_attributes_t opaque_attrs = PSA_KEY_ATTRIBUTES_INIT;
+        psa_key_type_t opaque_key_type;
 
+        if (psa_get_key_attributes(pk->priv_id, &opaque_attrs) != PSA_SUCCESS) {
+            return MBEDTLS_PK_NONE;
+        }
+        opaque_key_type = psa_get_key_type(&opaque_attrs);
+        psa_reset_key_attributes(&opaque_attrs);
+
+        if (PSA_KEY_TYPE_IS_ECC(opaque_key_type)) {
+            return MBEDTLS_PK_ECKEY;
+        } else if (PSA_KEY_TYPE_IS_RSA(opaque_key_type)) {
+            return MBEDTLS_PK_RSA;
+        } else {
+            return MBEDTLS_PK_NONE;
+        }
+    } else
+#endif
+    return pk_type;
+}
+
+/******************************************************************************
+ * Public functions for writing private/public DER keys.
+ ******************************************************************************/
 int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
                             const mbedtls_pk_context *key)
 {
@@ -177,31 +424,17 @@ int mbedtls_pk_write_pubkey(unsigned char **p, unsigned char *start,
 
 #if defined(MBEDTLS_RSA_C)
     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
-        MBEDTLS_ASN1_CHK_ADD(len, pk_write_rsa_pubkey(p, start, mbedtls_pk_rsa(*key)));
+        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_rsa_write_pubkey(mbedtls_pk_rsa(*key), start, p));
     } else
 #endif
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
-        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, mbedtls_pk_ec(*key)));
+        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_pubkey(p, start, key));
     } else
 #endif
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     if (mbedtls_pk_get_type(key) == MBEDTLS_PK_OPAQUE) {
-        size_t buffer_size;
-        mbedtls_svc_key_id_t *key_id = (mbedtls_svc_key_id_t *) key->pk_ctx;
-
-        if (*p < start) {
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        }
-
-        buffer_size = (size_t) (*p - start);
-        if (psa_export_public_key(*key_id, start, buffer_size, &len)
-            != PSA_SUCCESS) {
-            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
-        } else {
-            *p -= len;
-            memmove(*p, start, len);
-        }
+        MBEDTLS_ASN1_CHK_ADD(len, pk_write_opaque_pubkey(p, start, key));
     } else
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
@@ -213,9 +446,10 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *c;
-    size_t len = 0, par_len = 0, oid_len;
+    int has_par = 1;
+    size_t len = 0, par_len = 0, oid_len = 0;
     mbedtls_pk_type_t pk_type;
-    const char *oid;
+    const char *oid = NULL;
 
     if (size == 0) {
         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
@@ -240,64 +474,33 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
 
-    pk_type = mbedtls_pk_get_type(key);
-#if defined(MBEDTLS_ECP_C)
-    if (pk_type == MBEDTLS_PK_ECKEY) {
-        MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, mbedtls_pk_ec(*key)));
-    }
-#endif
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if (pk_type == MBEDTLS_PK_OPAQUE) {
-        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-        psa_key_type_t key_type;
-        mbedtls_svc_key_id_t key_id;
-        psa_ecc_family_t curve;
-        size_t bits;
-
-        key_id = *((mbedtls_svc_key_id_t *) key->pk_ctx);
-        if (PSA_SUCCESS != psa_get_key_attributes(key_id, &attributes)) {
-            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
-        }
-        key_type = psa_get_key_type(&attributes);
-        bits = psa_get_key_bits(&attributes);
-        psa_reset_key_attributes(&attributes);
-
-        if (PSA_KEY_TYPE_IS_ECC_KEY_PAIR(key_type)) {
-            curve = PSA_KEY_TYPE_ECC_GET_FAMILY(key_type);
-            if (curve == 0) {
-                return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-            }
+    pk_type = pk_get_type_ext(key);
 
-            ret = mbedtls_psa_get_ecc_oid_from_id(curve, bits,
-                                                  &oid, &oid_len);
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+        mbedtls_ecp_group_id ec_grp_id = mbedtls_pk_get_ec_group_id(key);
+        if (MBEDTLS_PK_IS_RFC8410_GROUP_ID(ec_grp_id)) {
+            ret = mbedtls_oid_get_oid_by_ec_grp_algid(ec_grp_id, &oid, &oid_len);
             if (ret != 0) {
-                return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+                return ret;
             }
-
-            /* Write EC algorithm parameters; that's akin
-             * to pk_write_ec_param() above. */
-            MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_oid(&c, buf,
-                                                                 oid,
-                                                                 oid_len));
-
-            /* The rest of the function works as for legacy EC contexts. */
-            pk_type = MBEDTLS_PK_ECKEY;
-        } else if (PSA_KEY_TYPE_IS_RSA(key_type)) {
-            /* The rest of the function works as for legacy RSA contexts. */
-            pk_type = MBEDTLS_PK_RSA;
+            has_par = 0;
         } else {
-            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+            MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec_grp_id));
         }
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
-    if ((ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid,
-                                             &oid_len)) != 0) {
-        return ret;
+    /* At this point oid_len is not null only for EC Montgomery keys. */
+    if (oid_len == 0) {
+        ret = mbedtls_oid_get_oid_by_pk_alg(pk_type, &oid, &oid_len);
+        if (ret != 0) {
+            return ret;
+        }
     }
 
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(&c, buf, oid, oid_len,
-                                                                      par_len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier_ext(&c, buf, oid, oid_len,
+                                                                          par_len, has_par));
 
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
     MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
@@ -308,9 +511,7 @@ int mbedtls_pk_write_pubkey_der(const mbedtls_pk_context *key, unsigned char *bu
 
 int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *c;
-    size_t len = 0;
 
     if (size == 0) {
         return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
@@ -319,160 +520,28 @@ int mbedtls_pk_write_key_der(const mbedtls_pk_context *key, unsigned char *buf,
     c = buf + size;
 
 #if defined(MBEDTLS_RSA_C)
-    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
-        mbedtls_mpi T; /* Temporary holding the exported parameters */
-        mbedtls_rsa_context *rsa = mbedtls_pk_rsa(*key);
-
-        /*
-         * Export the parameters one after another to avoid simultaneous copies.
-         */
-
-        mbedtls_mpi_init(&T);
-
-        /* Export QP */
-        if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export DQ */
-        if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export DP */
-        if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export Q */
-        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
-                                      &T, NULL, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export P */
-        if ((ret = mbedtls_rsa_export(rsa, NULL, &T,
-                                      NULL, NULL, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export D */
-        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
-                                      NULL, &T, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export E */
-        if ((ret = mbedtls_rsa_export(rsa, NULL, NULL,
-                                      NULL, NULL, &T)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-        /* Export N */
-        if ((ret = mbedtls_rsa_export(rsa, &T, NULL,
-                                      NULL, NULL, NULL)) != 0 ||
-            (ret = mbedtls_asn1_write_mpi(&c, buf, &T)) < 0) {
-            goto end_of_export;
-        }
-        len += ret;
-
-end_of_export:
-
-        mbedtls_mpi_free(&T);
-        if (ret < 0) {
-            return ret;
-        }
-
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 0));
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c,
-                                                         buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                                         MBEDTLS_ASN1_SEQUENCE));
+    if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
+        return pk_write_rsa_der(&c, buf, key);
     } else
 #endif /* MBEDTLS_RSA_C */
-#if defined(MBEDTLS_ECP_C)
-    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
-        mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*key);
-        size_t pub_len = 0, par_len = 0;
-
-        /*
-         * RFC 5915, or SEC1 Appendix C.4
-         *
-         * ECPrivateKey ::= SEQUENCE {
-         *      version        INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
-         *      privateKey     OCTET STRING,
-         *      parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
-         *      publicKey  [1] BIT STRING OPTIONAL
-         *    }
-         */
-
-        /* publicKey */
-        MBEDTLS_ASN1_CHK_ADD(pub_len, pk_write_ec_pubkey(&c, buf, ec));
-
-        if (c - buf < 1) {
-            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+#if defined(MBEDTLS_PK_HAVE_RFC8410_CURVES)
+        if (mbedtls_pk_is_rfc8410(key)) {
+            return pk_write_ec_rfc8410_der(&c, buf, key);
         }
-        *--c = 0;
-        pub_len += 1;
-
-        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
-        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_BIT_STRING));
-
-        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_len(&c, buf, pub_len));
-        MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_asn1_write_tag(&c, buf,
-                                                             MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                                             MBEDTLS_ASN1_CONSTRUCTED | 1));
-        len += pub_len;
-
-        /* parameters */
-        MBEDTLS_ASN1_CHK_ADD(par_len, pk_write_ec_param(&c, buf, ec));
-
-        MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_len(&c, buf, par_len));
-        MBEDTLS_ASN1_CHK_ADD(par_len, mbedtls_asn1_write_tag(&c, buf,
-                                                             MBEDTLS_ASN1_CONTEXT_SPECIFIC |
-                                                             MBEDTLS_ASN1_CONSTRUCTED | 0));
-        len += par_len;
-
-        /* privateKey */
-        MBEDTLS_ASN1_CHK_ADD(len, pk_write_ec_private(&c, buf, ec));
-
-        /* version */
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(&c, buf, 1));
-
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&c, buf, len));
-        MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&c, buf, MBEDTLS_ASN1_CONSTRUCTED |
-                                                         MBEDTLS_ASN1_SEQUENCE));
+#endif /* MBEDTLS_PK_HAVE_RFC8410_CURVES */
+        return pk_write_ec_der(&c, buf, key);
     } else
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
-
-    return (int) len;
 }
 
+/******************************************************************************
+ * Public functions for wrinting private/public PEM keys.
+ ******************************************************************************/
 #if defined(MBEDTLS_PEM_WRITE_C)
 
-#define PEM_BEGIN_PUBLIC_KEY    "-----BEGIN PUBLIC KEY-----\n"
-#define PEM_END_PUBLIC_KEY      "-----END PUBLIC KEY-----\n"
-
-#define PEM_BEGIN_PRIVATE_KEY_RSA   "-----BEGIN RSA PRIVATE KEY-----\n"
-#define PEM_END_PRIVATE_KEY_RSA     "-----END RSA PRIVATE KEY-----\n"
-#define PEM_BEGIN_PRIVATE_KEY_EC    "-----BEGIN EC PRIVATE KEY-----\n"
-#define PEM_END_PRIVATE_KEY_EC      "-----END EC PRIVATE KEY-----\n"
-
 #define PUB_DER_MAX_BYTES                                                   \
     (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ? \
      MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES : MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
@@ -483,55 +552,77 @@ end_of_export:
 int mbedtls_pk_write_pubkey_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char output_buf[PUB_DER_MAX_BYTES];
+    unsigned char *output_buf = NULL;
+    output_buf = mbedtls_calloc(1, PUB_DER_MAX_BYTES);
+    if (output_buf == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
     size_t olen = 0;
 
     if ((ret = mbedtls_pk_write_pubkey_der(key, output_buf,
-                                           sizeof(output_buf))) < 0) {
-        return ret;
+                                           PUB_DER_MAX_BYTES)) < 0) {
+        goto cleanup;
     }
 
-    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY,
-                                        output_buf + sizeof(output_buf) - ret,
+    if ((ret = mbedtls_pem_write_buffer(PEM_BEGIN_PUBLIC_KEY "\n", PEM_END_PUBLIC_KEY "\n",
+                                        output_buf + PUB_DER_MAX_BYTES - ret,
                                         ret, buf, size, &olen)) != 0) {
-        return ret;
+        goto cleanup;
     }
 
-    return 0;
+    ret = 0;
+cleanup:
+    mbedtls_free(output_buf);
+    return ret;
 }
 
 int mbedtls_pk_write_key_pem(const mbedtls_pk_context *key, unsigned char *buf, size_t size)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char output_buf[PRV_DER_MAX_BYTES];
+    unsigned char *output_buf = NULL;
+    output_buf = mbedtls_calloc(1, PRV_DER_MAX_BYTES);
+    if (output_buf == NULL) {
+        return MBEDTLS_ERR_PK_ALLOC_FAILED;
+    }
     const char *begin, *end;
     size_t olen = 0;
 
-    if ((ret = mbedtls_pk_write_key_der(key, output_buf, sizeof(output_buf))) < 0) {
-        return ret;
+    if ((ret = mbedtls_pk_write_key_der(key, output_buf, PRV_DER_MAX_BYTES)) < 0) {
+        goto cleanup;
     }
 
 #if defined(MBEDTLS_RSA_C)
-    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_RSA) {
-        begin = PEM_BEGIN_PRIVATE_KEY_RSA;
-        end = PEM_END_PRIVATE_KEY_RSA;
+    if (pk_get_type_ext(key) == MBEDTLS_PK_RSA) {
+        begin = PEM_BEGIN_PRIVATE_KEY_RSA "\n";
+        end = PEM_END_PRIVATE_KEY_RSA "\n";
     } else
 #endif
-#if defined(MBEDTLS_ECP_C)
-    if (mbedtls_pk_get_type(key) == MBEDTLS_PK_ECKEY) {
-        begin = PEM_BEGIN_PRIVATE_KEY_EC;
-        end = PEM_END_PRIVATE_KEY_EC;
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (pk_get_type_ext(key) == MBEDTLS_PK_ECKEY) {
+        if (mbedtls_pk_is_rfc8410(key)) {
+            begin = PEM_BEGIN_PRIVATE_KEY_PKCS8 "\n";
+            end = PEM_END_PRIVATE_KEY_PKCS8 "\n";
+        } else {
+            begin = PEM_BEGIN_PRIVATE_KEY_EC "\n";
+            end = PEM_END_PRIVATE_KEY_EC "\n";
+        }
     } else
-#endif
-    return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+    {
+        ret = MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        goto cleanup;
+    }
 
     if ((ret = mbedtls_pem_write_buffer(begin, end,
-                                        output_buf + sizeof(output_buf) - ret,
+                                        output_buf + PRV_DER_MAX_BYTES - ret,
                                         ret, buf, size, &olen)) != 0) {
-        return ret;
+        goto cleanup;
     }
 
-    return 0;
+    ret = 0;
+cleanup:
+    mbedtls_zeroize_and_free(output_buf, PRV_DER_MAX_BYTES);
+    return ret;
 }
 #endif /* MBEDTLS_PEM_WRITE_C */
 
diff --git a/lib/libmbedtls/mbedtls/library/pkwrite.h b/lib/libmbedtls/mbedtls/library/pkwrite.h
index 8aebd0c24dc69bd22e3e239728555db48a313fa4..01dc3d2f0ffa71268a04b26187e69baf0c9865d7 100644
--- a/lib/libmbedtls/mbedtls/library/pkwrite.h
+++ b/lib/libmbedtls/mbedtls/library/pkwrite.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_PK_WRITE_H
@@ -27,6 +15,10 @@
 
 #include "mbedtls/pk.h"
 
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 /*
  * Max sizes of key per types. Shown as tag + len (+ content).
  */
@@ -73,7 +65,20 @@
 
 #endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+
+/* Find the maximum number of bytes necessary to store an EC point. When USE_PSA
+ * is defined this means looking for the maximum between PSA and built-in
+ * supported curves. */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#define MBEDTLS_PK_MAX_ECC_BYTES   (PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) > \
+                                    MBEDTLS_ECP_MAX_BYTES ? \
+                                    PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS) : \
+                                    MBEDTLS_ECP_MAX_BYTES)
+#else /* MBEDTLS_USE_PSA_CRYPTO */
+#define MBEDTLS_PK_MAX_ECC_BYTES   MBEDTLS_ECP_MAX_BYTES
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
 /*
  * EC public keys:
  *  SubjectPublicKeyInfo  ::=  SEQUENCE  {      1 + 2
@@ -85,7 +90,7 @@
  *                                            + 2 * ECP_MAX (coords)    [1]
  *  }
  */
-#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES    (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
+#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES    (30 + 2 * MBEDTLS_PK_MAX_ECC_BYTES)
 
 /*
  * EC private keys:
@@ -96,13 +101,21 @@
  *      publicKey  [1] BIT STRING OPTIONAL      1 + 2 + [1] above
  *    }
  */
-#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES    (29 + 3 * MBEDTLS_ECP_MAX_BYTES)
+#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES    (29 + 3 * MBEDTLS_PK_MAX_ECC_BYTES)
 
-#else /* MBEDTLS_ECP_C */
+#else /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 #define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES   0
 #define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES   0
 
-#endif /* MBEDTLS_ECP_C */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
+
+/* Define the maximum available public key DER length based on the supported
+ * key types (EC and/or RSA). */
+#if (MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES > MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES)
+#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_RSA_PUB_DER_MAX_BYTES
+#else
+#define MBEDTLS_PK_WRITE_PUBKEY_MAX_SIZE    MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES
+#endif
 
 #endif /* MBEDTLS_PK_WRITE_H */
diff --git a/lib/libmbedtls/mbedtls/library/platform.c b/lib/libmbedtls/mbedtls/library/platform.c
index b15b7b29adc3fbbc44d2ef869609a4a7db6b85a5..890c4cbaba7fd5f8d8f9b8d3de3239a3c66d34ba 100644
--- a/lib/libmbedtls/mbedtls/library/platform.c
+++ b/lib/libmbedtls/mbedtls/library/platform.c
@@ -2,19 +2,7 @@
  *  Platform abstraction layer
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
diff --git a/lib/libmbedtls/mbedtls/library/platform_util.c b/lib/libmbedtls/mbedtls/library/platform_util.c
index f891cd48a3cf86b14007c813aa0ae0eaf6ff69b7..19ef07aead79d57b786474af25653dddb36d0778 100644
--- a/lib/libmbedtls/mbedtls/library/platform_util.c
+++ b/lib/libmbedtls/mbedtls/library/platform_util.c
@@ -3,19 +3,7 @@
  * library.
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -97,15 +85,14 @@
  * mbedtls_platform_zeroize() to use a suitable implementation for their
  * platform and needs.
  */
-#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !defined(__STDC_LIB_EXT1__) \
+#if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \
+    !defined(__IAR_SYSTEMS_ICC__)) \
     && !defined(_WIN32)
 static void *(*const volatile memset_func)(void *, int, size_t) = memset;
 #endif
 
 void mbedtls_platform_zeroize(void *buf, size_t len)
 {
-    MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
-
     if (len > 0) {
 #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
         explicit_bzero(buf, len);
@@ -118,25 +105,54 @@ void mbedtls_platform_zeroize(void *buf, size_t len)
          */
         __msan_unpoison(buf, len);
 #endif
-#elif defined(__STDC_LIB_EXT1__)
+#elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__)
         memset_s(buf, len, 0, len);
 #elif defined(_WIN32)
         SecureZeroMemory(buf, len);
 #else
         memset_func(buf, 0, len);
+#endif
+
+#if defined(__GNUC__)
+        /* For clang and recent gcc, pretend that we have some assembly that reads the
+         * zero'd memory as an additional protection against being optimised away. */
+#if defined(__clang__) || (__GNUC__ >= 10)
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wvla"
+#elif defined(MBEDTLS_COMPILER_IS_GCC)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wvla"
+#endif
+        asm volatile ("" : : "m" (*(char (*)[len]) buf) :);
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#elif defined(MBEDTLS_COMPILER_IS_GCC)
+#pragma GCC diagnostic pop
+#endif
+#endif
 #endif
     }
 }
 #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
 
+void mbedtls_zeroize_and_free(void *buf, size_t len)
+{
+    if (buf != NULL) {
+        mbedtls_platform_zeroize(buf, len);
+    }
+
+    mbedtls_free(buf);
+}
+
 #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
 #include <time.h>
 #if !defined(_WIN32) && (defined(unix) || \
     defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
-    defined(__MACH__)))
+    defined(__MACH__)) || defined(__midipix__))
 #include <unistd.h>
 #endif /* !_WIN32 && (unix || __unix || __unix__ ||
-        * (__APPLE__ && __MACH__)) */
+        * (__APPLE__ && __MACH__) || __midipix__) */
 
 #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \
     (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \
@@ -199,23 +215,49 @@ struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,
 void (*mbedtls_test_hook_test_fail)(const char *, int, const char *);
 #endif /* MBEDTLS_TEST_HOOKS */
 
-/*
- * Provide external definitions of some inline functions so that the compiler
- * has the option to not inline them
- */
-extern inline void mbedtls_xor(unsigned char *r,
-                               const unsigned char *a,
-                               const unsigned char *b,
-                               size_t n);
-
-extern inline uint16_t mbedtls_get_unaligned_uint16(const void *p);
+#if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT)
 
-extern inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x);
+#include <time.h>
+#if !defined(_WIN32) && \
+    (defined(unix) || defined(__unix) || defined(__unix__) || \
+    (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))
+#include <unistd.h>
+#endif \
+    /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */
+#if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__)
+mbedtls_ms_time_t mbedtls_ms_time(void)
+{
+    int ret;
+    struct timespec tv;
+    mbedtls_ms_time_t current_ms;
 
-extern inline uint32_t mbedtls_get_unaligned_uint32(const void *p);
+#if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__)
+    ret = clock_gettime(CLOCK_BOOTTIME, &tv);
+#else
+    ret = clock_gettime(CLOCK_MONOTONIC, &tv);
+#endif
+    if (ret) {
+        return time(NULL) * 1000;
+    }
 
-extern inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x);
+    current_ms = tv.tv_sec;
 
-extern inline uint64_t mbedtls_get_unaligned_uint64(const void *p);
+    return current_ms*1000 + tv.tv_nsec / 1000000;
+}
+#elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
+    defined(__MINGW32__) || defined(_WIN64)
+#include <windows.h>
+mbedtls_ms_time_t mbedtls_ms_time(void)
+{
+    FILETIME ct;
+    mbedtls_ms_time_t current_ms;
 
-extern inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x);
+    GetSystemTimeAsFileTime(&ct);
+    current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime +
+                  ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000;
+    return current_ms;
+}
+#else
+#error "No mbedtls_ms_time available"
+#endif
+#endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/poly1305.c b/lib/libmbedtls/mbedtls/library/poly1305.c
index f4e1d3f8807c55b532e75f2b9f39ee4d8f0186bf..c9ebe9e1daa6835b20a5d36d8c89051b4d49390b 100644
--- a/lib/libmbedtls/mbedtls/library/poly1305.c
+++ b/lib/libmbedtls/mbedtls/library/poly1305.c
@@ -4,19 +4,7 @@
  * \brief Poly1305 authentication algorithm.
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #include "common.h"
 
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto.c b/lib/libmbedtls/mbedtls/library/psa_crypto.c
new file mode 100644
index 0000000000000000000000000000000000000000..c4f41db10b60b26972394d633327d13829ee6c6f
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto.c
@@ -0,0 +1,9233 @@
+/*
+ *  PSA crypto layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+#include "psa_crypto_core_common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
+#include "check_crypto_config.h"
+#endif
+
+#include "psa/crypto.h"
+#include "psa/crypto_values.h"
+
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_invasive.h"
+#include "psa_crypto_driver_wrappers.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
+#include "psa_crypto_ecp.h"
+#include "psa_crypto_ffdh.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
+#include "psa_crypto_rsa.h"
+#include "psa_crypto_ecp.h"
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+#include "psa_crypto_se.h"
+#endif
+#include "psa_crypto_slot_management.h"
+/* Include internal declarations that are useful for implementing persistently
+ * stored keys. */
+#include "psa_crypto_storage.h"
+
+#include "psa_crypto_random_impl.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+
+#include "mbedtls/aes.h"
+#include "mbedtls/asn1.h"
+#include "mbedtls/asn1write.h"
+#include "mbedtls/bignum.h"
+#include "mbedtls/camellia.h"
+#include "mbedtls/chacha20.h"
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/ccm.h"
+#include "mbedtls/cmac.h"
+#include "mbedtls/constant_time.h"
+#include "mbedtls/des.h"
+#include "mbedtls/ecdh.h"
+#include "mbedtls/ecp.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/error.h"
+#include "mbedtls/gcm.h"
+#include "mbedtls/md5.h"
+#include "mbedtls/pk.h"
+#include "pk_wrap.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+#include "mbedtls/ripemd160.h"
+#include "mbedtls/rsa.h"
+#include "mbedtls/sha1.h"
+#include "mbedtls/sha256.h"
+#include "mbedtls/sha512.h"
+#include "mbedtls/psa_util.h"
+#include "mbedtls/threading.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF) ||          \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT) ||  \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+#define BUILTIN_ALG_ANY_HKDF 1
+#endif
+
+/****************************************************************/
+/* Global data, support functions and library management */
+/****************************************************************/
+
+static int key_type_is_raw_bytes(psa_key_type_t type)
+{
+    return PSA_KEY_TYPE_IS_UNSTRUCTURED(type);
+}
+
+/* Values for psa_global_data_t::rng_state */
+#define RNG_NOT_INITIALIZED 0
+#define RNG_INITIALIZED 1
+#define RNG_SEEDED 2
+
+/* IDs for PSA crypto subsystems. Starts at 1 to catch potential uninitialized
+ * variables as arguments. */
+typedef enum {
+    PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS = 1,
+    PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS,
+    PSA_CRYPTO_SUBSYSTEM_RNG,
+    PSA_CRYPTO_SUBSYSTEM_TRANSACTION,
+} mbedtls_psa_crypto_subsystem;
+
+/* Initialization flags for global_data::initialized */
+#define PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED    0x01
+#define PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED          0x02
+#define PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED        0x04
+
+#define PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED                ( \
+        PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED | \
+        PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED | \
+        PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)
+
+typedef struct {
+    uint8_t initialized;
+    uint8_t rng_state;
+    mbedtls_psa_random_context_t rng;
+} psa_global_data_t;
+
+static psa_global_data_t global_data;
+
+static uint8_t psa_get_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = global_data.rng_state == RNG_SEEDED;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized =
+        (initialized && (global_data.initialized == PSA_CRYPTO_SUBSYSTEM_ALL_INITIALISED));
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
+
+static uint8_t psa_get_drivers_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) != 0;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
+
+#define GUARD_MODULE_INITIALIZED        \
+    if (psa_get_initialized() == 0)     \
+    return PSA_ERROR_BAD_STATE;
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+
+/* Declare a local copy of an input buffer and a variable that will be used
+ * to store a pointer to the start of the buffer.
+ *
+ * Note: This macro must be called before any operations which may jump to
+ * the exit label, so that the local input copy object is safe to be freed.
+ *
+ * Assumptions:
+ * - input is the name of a pointer to the buffer to be copied
+ * - The name LOCAL_INPUT_COPY_OF_input is unused in the current scope
+ * - input_copy_name is a name that is unused in the current scope
+ */
+#define LOCAL_INPUT_DECLARE(input, input_copy_name) \
+    psa_crypto_local_input_t LOCAL_INPUT_COPY_OF_##input = PSA_CRYPTO_LOCAL_INPUT_INIT; \
+    const uint8_t *input_copy_name = NULL;
+
+/* Allocate a copy of the buffer input and set the pointer input_copy to
+ * point to the start of the copy.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - An exit label is declared
+ * - input is the name of a pointer to the buffer to be copied
+ * - LOCAL_INPUT_DECLARE(input, input_copy) has previously been called
+ */
+#define LOCAL_INPUT_ALLOC(input, length, input_copy) \
+    status = psa_crypto_local_input_alloc(input, length, \
+                                          &LOCAL_INPUT_COPY_OF_##input); \
+    if (status != PSA_SUCCESS) { \
+        goto exit; \
+    } \
+    input_copy = LOCAL_INPUT_COPY_OF_##input.buffer;
+
+/* Free the local input copy allocated previously by LOCAL_INPUT_ALLOC()
+ *
+ * Assumptions:
+ * - input_copy is the name of the input copy pointer set by LOCAL_INPUT_ALLOC()
+ * - input is the name of the original buffer that was copied
+ */
+#define LOCAL_INPUT_FREE(input, input_copy) \
+    input_copy = NULL; \
+    psa_crypto_local_input_free(&LOCAL_INPUT_COPY_OF_##input);
+
+/* Declare a local copy of an output buffer and a variable that will be used
+ * to store a pointer to the start of the buffer.
+ *
+ * Note: This macro must be called before any operations which may jump to
+ * the exit label, so that the local output copy object is safe to be freed.
+ *
+ * Assumptions:
+ * - output is the name of a pointer to the buffer to be copied
+ * - The name LOCAL_OUTPUT_COPY_OF_output is unused in the current scope
+ * - output_copy_name is a name that is unused in the current scope
+ */
+#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
+    psa_crypto_local_output_t LOCAL_OUTPUT_COPY_OF_##output = PSA_CRYPTO_LOCAL_OUTPUT_INIT; \
+    uint8_t *output_copy_name = NULL;
+
+/* Allocate a copy of the buffer output and set the pointer output_copy to
+ * point to the start of the copy.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - An exit label is declared
+ * - output is the name of a pointer to the buffer to be copied
+ * - LOCAL_OUTPUT_DECLARE(output, output_copy) has previously been called
+ */
+#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
+    status = psa_crypto_local_output_alloc(output, length, \
+                                           &LOCAL_OUTPUT_COPY_OF_##output); \
+    if (status != PSA_SUCCESS) { \
+        goto exit; \
+    } \
+    output_copy = LOCAL_OUTPUT_COPY_OF_##output.buffer;
+
+/* Free the local output copy allocated previously by LOCAL_OUTPUT_ALLOC()
+ * after first copying back its contents to the original buffer.
+ *
+ * Assumptions:
+ * - psa_status_t status exists
+ * - output_copy is the name of the output copy pointer set by LOCAL_OUTPUT_ALLOC()
+ * - output is the name of the original buffer that was copied
+ */
+#define LOCAL_OUTPUT_FREE(output, output_copy) \
+    output_copy = NULL; \
+    do { \
+        psa_status_t local_output_status; \
+        local_output_status = psa_crypto_local_output_free(&LOCAL_OUTPUT_COPY_OF_##output); \
+        if (local_output_status != PSA_SUCCESS) { \
+            /* Since this error case is an internal error, it's more serious than \
+             * any existing error code and so it's fine to overwrite the existing \
+             * status. */ \
+            status = local_output_status; \
+        } \
+    } while (0)
+#else /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
+#define LOCAL_INPUT_DECLARE(input, input_copy_name) \
+    const uint8_t *input_copy_name = NULL;
+#define LOCAL_INPUT_ALLOC(input, length, input_copy) \
+    input_copy = input;
+#define LOCAL_INPUT_FREE(input, input_copy) \
+    input_copy = NULL;
+#define LOCAL_OUTPUT_DECLARE(output, output_copy_name) \
+    uint8_t *output_copy_name = NULL;
+#define LOCAL_OUTPUT_ALLOC(output, length, output_copy) \
+    output_copy = output;
+#define LOCAL_OUTPUT_FREE(output, output_copy) \
+    output_copy = NULL;
+#endif /* !MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
+
+
+int psa_can_do_hash(psa_algorithm_t hash_alg)
+{
+    (void) hash_alg;
+    return psa_get_drivers_initialized();
+}
+
+int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg)
+{
+    (void) key_type;
+    (void) cipher_alg;
+    return psa_get_drivers_initialized();
+}
+
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||       \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) ||     \
+    defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+static int psa_is_dh_key_size_valid(size_t bits)
+{
+    switch (bits) {
+#if defined(PSA_WANT_DH_RFC7919_2048)
+        case 2048:
+            return 1;
+#endif /* PSA_WANT_DH_RFC7919_2048 */
+#if defined(PSA_WANT_DH_RFC7919_3072)
+        case 3072:
+            return 1;
+#endif /* PSA_WANT_DH_RFC7919_3072 */
+#if defined(PSA_WANT_DH_RFC7919_4096)
+        case 4096:
+            return 1;
+#endif /* PSA_WANT_DH_RFC7919_4096 */
+#if defined(PSA_WANT_DH_RFC7919_6144)
+        case 6144:
+            return 1;
+#endif /* PSA_WANT_DH_RFC7919_6144 */
+#if defined(PSA_WANT_DH_RFC7919_8192)
+        case 8192:
+            return 1;
+#endif /* PSA_WANT_DH_RFC7919_8192 */
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT ||
+          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
+          PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE */
+
+psa_status_t mbedtls_to_psa_error(int ret)
+{
+    /* Mbed TLS error codes can combine a high-level error code and a
+     * low-level error code. The low-level error usually reflects the
+     * root cause better, so dispatch on that preferably. */
+    int low_level_ret = -(-ret & 0x007f);
+    switch (low_level_ret != 0 ? low_level_ret : ret) {
+        case 0:
+            return PSA_SUCCESS;
+
+#if defined(MBEDTLS_AES_C)
+        case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH:
+        case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_AES_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+#endif
+
+#if defined(MBEDTLS_ASN1_PARSE_C) || defined(MBEDTLS_ASN1_WRITE_C)
+        case MBEDTLS_ERR_ASN1_OUT_OF_DATA:
+        case MBEDTLS_ERR_ASN1_UNEXPECTED_TAG:
+        case MBEDTLS_ERR_ASN1_INVALID_LENGTH:
+        case MBEDTLS_ERR_ASN1_LENGTH_MISMATCH:
+        case MBEDTLS_ERR_ASN1_INVALID_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_ASN1_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        case MBEDTLS_ERR_ASN1_BUF_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+#endif
+
+#if defined(MBEDTLS_CAMELLIA_C)
+        case MBEDTLS_ERR_CAMELLIA_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH:
+            return PSA_ERROR_NOT_SUPPORTED;
+#endif
+
+#if defined(MBEDTLS_CCM_C)
+        case MBEDTLS_ERR_CCM_BAD_INPUT:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_CCM_AUTH_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+#endif
+
+#if defined(MBEDTLS_CHACHA20_C)
+        case MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+#endif
+
+#if defined(MBEDTLS_CHACHAPOLY_C)
+        case MBEDTLS_ERR_CHACHAPOLY_BAD_STATE:
+            return PSA_ERROR_BAD_STATE;
+        case MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+#endif
+
+#if defined(MBEDTLS_CIPHER_C)
+        case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        case MBEDTLS_ERR_CIPHER_INVALID_PADDING:
+            return PSA_ERROR_INVALID_PADDING;
+        case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_CIPHER_AUTH_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT:
+            return PSA_ERROR_CORRUPTION_DETECTED;
+#endif
+
+#if !(defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ||      \
+            defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE))
+        /* Only check CTR_DRBG error codes if underlying mbedtls_xxx
+         * functions are passed a CTR_DRBG instance. */
+        case MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+        case MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG:
+        case MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+#endif
+
+#if defined(MBEDTLS_DES_C)
+        case MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH:
+            return PSA_ERROR_NOT_SUPPORTED;
+#endif
+
+        case MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED:
+        case MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE:
+        case MBEDTLS_ERR_ENTROPY_SOURCE_FAILED:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+
+#if defined(MBEDTLS_GCM_C)
+        case MBEDTLS_ERR_GCM_AUTH_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case MBEDTLS_ERR_GCM_BUFFER_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        case MBEDTLS_ERR_GCM_BAD_INPUT:
+            return PSA_ERROR_INVALID_ARGUMENT;
+#endif
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) &&        \
+            defined(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE)
+        /* Only check HMAC_DRBG error codes if underlying mbedtls_xxx
+         * functions are passed a HMAC_DRBG instance. */
+        case MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+        case MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG:
+        case MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+#endif
+
+#if defined(MBEDTLS_MD_LIGHT)
+        case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MD_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+#if defined(MBEDTLS_FS_IO)
+        case MBEDTLS_ERR_MD_FILE_IO_ERROR:
+            return PSA_ERROR_STORAGE_FAILURE;
+#endif
+#endif
+
+#if defined(MBEDTLS_BIGNUM_C)
+#if defined(MBEDTLS_FS_IO)
+        case MBEDTLS_ERR_MPI_FILE_IO_ERROR:
+            return PSA_ERROR_STORAGE_FAILURE;
+#endif
+        case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MPI_INVALID_CHARACTER:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        case MBEDTLS_ERR_MPI_NEGATIVE_VALUE:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MPI_DIVISION_BY_ZERO:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MPI_NOT_ACCEPTABLE:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_MPI_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+#endif
+
+#if defined(MBEDTLS_PK_C)
+        case MBEDTLS_ERR_PK_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        case MBEDTLS_ERR_PK_TYPE_MISMATCH:
+        case MBEDTLS_ERR_PK_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || defined(MBEDTLS_FS_IO) || \
+            defined(MBEDTLS_PSA_ITS_FILE_C)
+        case MBEDTLS_ERR_PK_FILE_IO_ERROR:
+            return PSA_ERROR_STORAGE_FAILURE;
+#endif
+        case MBEDTLS_ERR_PK_KEY_INVALID_VERSION:
+        case MBEDTLS_ERR_PK_KEY_INVALID_FORMAT:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_PK_UNKNOWN_PK_ALG:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_PK_PASSWORD_REQUIRED:
+        case MBEDTLS_ERR_PK_PASSWORD_MISMATCH:
+            return PSA_ERROR_NOT_PERMITTED;
+        case MBEDTLS_ERR_PK_INVALID_PUBKEY:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_PK_INVALID_ALG:
+        case MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE:
+        case MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_PK_SIG_LEN_MISMATCH:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case MBEDTLS_ERR_PK_BUFFER_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+#endif
+
+        case MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED:
+            return PSA_ERROR_HARDWARE_FAILURE;
+        case MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
+            return PSA_ERROR_NOT_SUPPORTED;
+
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_RSA_INVALID_PADDING:
+            return PSA_ERROR_INVALID_PADDING;
+        case MBEDTLS_ERR_RSA_KEY_GEN_FAILED:
+            return PSA_ERROR_HARDWARE_FAILURE;
+        case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_RSA_PUBLIC_FAILED:
+        case MBEDTLS_ERR_RSA_PRIVATE_FAILED:
+            return PSA_ERROR_CORRUPTION_DETECTED;
+        case MBEDTLS_ERR_RSA_VERIFY_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        case MBEDTLS_ERR_RSA_RNG_FAILED:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+#endif
+
+#if defined(MBEDTLS_ECP_LIGHT)
+        case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_ECP_INVALID_KEY:
+            return PSA_ERROR_INVALID_ARGUMENT;
+        case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        case MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:
+        case MBEDTLS_ERR_ECP_VERIFY_FAILED:
+            return PSA_ERROR_INVALID_SIGNATURE;
+        case MBEDTLS_ERR_ECP_ALLOC_FAILED:
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        case MBEDTLS_ERR_ECP_RANDOM_FAILED:
+            return PSA_ERROR_INSUFFICIENT_ENTROPY;
+
+#if defined(MBEDTLS_ECP_RESTARTABLE)
+        case MBEDTLS_ERR_ECP_IN_PROGRESS:
+            return PSA_OPERATION_INCOMPLETE;
+#endif
+#endif
+
+        case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
+            return PSA_ERROR_CORRUPTION_DETECTED;
+
+        default:
+            return PSA_ERROR_GENERIC_ERROR;
+    }
+}
+
+/**
+ * \brief                       For output buffers which contain "tags"
+ *                              (outputs that may be checked for validity like
+ *                              hashes, MACs and signatures), fill the unused
+ *                              part of the output buffer (the whole buffer on
+ *                              error, the trailing part on success) with
+ *                              something that isn't a valid tag (barring an
+ *                              attack on the tag and deliberately-crafted
+ *                              input), in case the caller doesn't check the
+ *                              return status properly.
+ *
+ * \param output_buffer         Pointer to buffer to wipe. May not be NULL
+ *                              unless \p output_buffer_size is zero.
+ * \param status                Status of function called to generate
+ *                              output_buffer originally
+ * \param output_buffer_size    Size of output buffer. If zero, \p output_buffer
+ *                              could be NULL.
+ * \param output_buffer_length  Length of data written to output_buffer, must be
+ *                              less than \p output_buffer_size
+ */
+static void psa_wipe_tag_output_buffer(uint8_t *output_buffer, psa_status_t status,
+                                       size_t output_buffer_size, size_t output_buffer_length)
+{
+    size_t offset = 0;
+
+    if (output_buffer_size == 0) {
+        /* If output_buffer_size is 0 then we have nothing to do. We must not
+           call memset because output_buffer may be NULL in this case */
+        return;
+    }
+
+    if (status == PSA_SUCCESS) {
+        offset = output_buffer_length;
+    }
+
+    memset(output_buffer + offset, '!', output_buffer_size - offset);
+}
+
+
+psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,
+                                                    size_t bits)
+{
+    /* Check that the bit size is acceptable for the key type */
+    switch (type) {
+        case PSA_KEY_TYPE_RAW_DATA:
+        case PSA_KEY_TYPE_HMAC:
+        case PSA_KEY_TYPE_DERIVE:
+        case PSA_KEY_TYPE_PASSWORD:
+        case PSA_KEY_TYPE_PASSWORD_HASH:
+            break;
+#if defined(PSA_WANT_KEY_TYPE_AES)
+        case PSA_KEY_TYPE_AES:
+            if (bits != 128 && bits != 192 && bits != 256) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif
+#if defined(PSA_WANT_KEY_TYPE_ARIA)
+        case PSA_KEY_TYPE_ARIA:
+            if (bits != 128 && bits != 192 && bits != 256) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif
+#if defined(PSA_WANT_KEY_TYPE_CAMELLIA)
+        case PSA_KEY_TYPE_CAMELLIA:
+            if (bits != 128 && bits != 192 && bits != 256) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif
+#if defined(PSA_WANT_KEY_TYPE_DES)
+        case PSA_KEY_TYPE_DES:
+            if (bits != 64 && bits != 128 && bits != 192) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif
+#if defined(PSA_WANT_KEY_TYPE_CHACHA20)
+        case PSA_KEY_TYPE_CHACHA20:
+            if (bits != 256) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+    if (bits % 8 != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return PSA_SUCCESS;
+}
+
+/** Check whether a given key type is valid for use with a given MAC algorithm
+ *
+ * Upon successful return of this function, the behavior of #PSA_MAC_LENGTH
+ * when called with the validated \p algorithm and \p key_type is well-defined.
+ *
+ * \param[in] algorithm     The specific MAC algorithm (can be wildcard).
+ * \param[in] key_type      The key type of the key to be used with the
+ *                          \p algorithm.
+ *
+ * \retval #PSA_SUCCESS
+ *         The \p key_type is valid for use with the \p algorithm
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The \p key_type is not valid for use with the \p algorithm
+ */
+MBEDTLS_STATIC_TESTABLE psa_status_t psa_mac_key_can_do(
+    psa_algorithm_t algorithm,
+    psa_key_type_t key_type)
+{
+    if (PSA_ALG_IS_HMAC(algorithm)) {
+        if (key_type == PSA_KEY_TYPE_HMAC) {
+            return PSA_SUCCESS;
+        }
+    }
+
+    if (PSA_ALG_IS_BLOCK_CIPHER_MAC(algorithm)) {
+        /* Check that we're calling PSA_BLOCK_CIPHER_BLOCK_LENGTH with a cipher
+         * key. */
+        if ((key_type & PSA_KEY_TYPE_CATEGORY_MASK) ==
+            PSA_KEY_TYPE_CATEGORY_SYMMETRIC) {
+            /* PSA_BLOCK_CIPHER_BLOCK_LENGTH returns 1 for stream ciphers and
+             * the block length (larger than 1) for block ciphers. */
+            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type) > 1) {
+                return PSA_SUCCESS;
+            }
+        }
+    }
+
+    return PSA_ERROR_INVALID_ARGUMENT;
+}
+
+psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,
+                                         size_t buffer_length)
+{
+    if (slot->key.data != NULL) {
+        return PSA_ERROR_ALREADY_EXISTS;
+    }
+
+    slot->key.data = mbedtls_calloc(1, buffer_length);
+    if (slot->key.data == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    slot->key.bytes = buffer_length;
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,
+                                             const uint8_t *data,
+                                             size_t data_length)
+{
+    psa_status_t status = psa_allocate_buffer_to_slot(slot,
+                                                      data_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    memcpy(slot->key.data, data, data_length);
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_import_key_into_slot(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t type = attributes->type;
+
+    /* zero-length keys are never supported. */
+    if (data_length == 0) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (key_type_is_raw_bytes(type)) {
+        *bits = PSA_BYTES_TO_BITS(data_length);
+
+        status = psa_validate_unstructured_key_bit_size(attributes->type,
+                                                        *bits);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        /* Copy the key material. */
+        memcpy(key_buffer, data, data_length);
+        *key_buffer_length = data_length;
+        (void) key_buffer_size;
+
+        return PSA_SUCCESS;
+    } else if (PSA_KEY_TYPE_IS_ASYMMETRIC(type)) {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
+        if (PSA_KEY_TYPE_IS_DH(type)) {
+            if (psa_is_dh_key_size_valid(PSA_BYTES_TO_BITS(data_length)) == 0) {
+                return PSA_ERROR_NOT_SUPPORTED;
+            }
+            return mbedtls_psa_ffdh_import_key(attributes,
+                                               data, data_length,
+                                               key_buffer, key_buffer_size,
+                                               key_buffer_length,
+                                               bits);
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
+        if (PSA_KEY_TYPE_IS_ECC(type)) {
+            return mbedtls_psa_ecp_import_key(attributes,
+                                              data, data_length,
+                                              key_buffer, key_buffer_size,
+                                              key_buffer_length,
+                                              bits);
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+        if (PSA_KEY_TYPE_IS_RSA(type)) {
+            return mbedtls_psa_rsa_import_key(attributes,
+                                              data, data_length,
+                                              key_buffer, key_buffer_size,
+                                              key_buffer_length,
+                                              bits);
+        }
+#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
+           defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+    }
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+/** Calculate the intersection of two algorithm usage policies.
+ *
+ * Return 0 (which allows no operation) on incompatibility.
+ */
+static psa_algorithm_t psa_key_policy_algorithm_intersection(
+    psa_key_type_t key_type,
+    psa_algorithm_t alg1,
+    psa_algorithm_t alg2)
+{
+    /* Common case: both sides actually specify the same policy. */
+    if (alg1 == alg2) {
+        return alg1;
+    }
+    /* If the policies are from the same hash-and-sign family, check
+     * if one is a wildcard. If so the other has the specific algorithm. */
+    if (PSA_ALG_IS_SIGN_HASH(alg1) &&
+        PSA_ALG_IS_SIGN_HASH(alg2) &&
+        (alg1 & ~PSA_ALG_HASH_MASK) == (alg2 & ~PSA_ALG_HASH_MASK)) {
+        if (PSA_ALG_SIGN_GET_HASH(alg1) == PSA_ALG_ANY_HASH) {
+            return alg2;
+        }
+        if (PSA_ALG_SIGN_GET_HASH(alg2) == PSA_ALG_ANY_HASH) {
+            return alg1;
+        }
+    }
+    /* If the policies are from the same AEAD family, check whether
+     * one of them is a minimum-tag-length wildcard. Calculate the most
+     * restrictive tag length. */
+    if (PSA_ALG_IS_AEAD(alg1) && PSA_ALG_IS_AEAD(alg2) &&
+        (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg1, 0) ==
+         PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg2, 0))) {
+        size_t alg1_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg1);
+        size_t alg2_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg2);
+        size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;
+
+        /* If both are wildcards, return most restrictive wildcard */
+        if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
+            ((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
+            return PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(
+                alg1, restricted_len);
+        }
+        /* If only one is a wildcard, return specific algorithm if compatible. */
+        if (((alg1 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
+            (alg1_len <= alg2_len)) {
+            return alg2;
+        }
+        if (((alg2 & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
+            (alg2_len <= alg1_len)) {
+            return alg1;
+        }
+    }
+    /* If the policies are from the same MAC family, check whether one
+     * of them is a minimum-MAC-length policy. Calculate the most
+     * restrictive tag length. */
+    if (PSA_ALG_IS_MAC(alg1) && PSA_ALG_IS_MAC(alg2) &&
+        (PSA_ALG_FULL_LENGTH_MAC(alg1) ==
+         PSA_ALG_FULL_LENGTH_MAC(alg2))) {
+        /* Validate the combination of key type and algorithm. Since the base
+         * algorithm of alg1 and alg2 are the same, we only need this once. */
+        if (PSA_SUCCESS != psa_mac_key_can_do(alg1, key_type)) {
+            return 0;
+        }
+
+        /* Get the (exact or at-least) output lengths for both sides of the
+         * requested intersection. None of the currently supported algorithms
+         * have an output length dependent on the actual key size, so setting it
+         * to a bogus value of 0 is currently OK.
+         *
+         * Note that for at-least-this-length wildcard algorithms, the output
+         * length is set to the shortest allowed length, which allows us to
+         * calculate the most restrictive tag length for the intersection. */
+        size_t alg1_len = PSA_MAC_LENGTH(key_type, 0, alg1);
+        size_t alg2_len = PSA_MAC_LENGTH(key_type, 0, alg2);
+        size_t restricted_len = alg1_len > alg2_len ? alg1_len : alg2_len;
+
+        /* If both are wildcards, return most restrictive wildcard */
+        if (((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) &&
+            ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
+            return PSA_ALG_AT_LEAST_THIS_LENGTH_MAC(alg1, restricted_len);
+        }
+
+        /* If only one is an at-least-this-length policy, the intersection would
+         * be the other (fixed-length) policy as long as said fixed length is
+         * equal to or larger than the shortest allowed length. */
+        if ((alg1 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
+            return (alg1_len <= alg2_len) ? alg2 : 0;
+        }
+        if ((alg2 & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
+            return (alg2_len <= alg1_len) ? alg1 : 0;
+        }
+
+        /* If none of them are wildcards, check whether they define the same tag
+         * length. This is still possible here when one is default-length and
+         * the other specific-length. Ensure to always return the
+         * specific-length version for the intersection. */
+        if (alg1_len == alg2_len) {
+            return PSA_ALG_TRUNCATED_MAC(alg1, alg1_len);
+        }
+    }
+    /* If the policies are incompatible, allow nothing. */
+    return 0;
+}
+
+static int psa_key_algorithm_permits(psa_key_type_t key_type,
+                                     psa_algorithm_t policy_alg,
+                                     psa_algorithm_t requested_alg)
+{
+    /* Common case: the policy only allows requested_alg. */
+    if (requested_alg == policy_alg) {
+        return 1;
+    }
+    /* If policy_alg is a hash-and-sign with a wildcard for the hash,
+     * and requested_alg is the same hash-and-sign family with any hash,
+     * then requested_alg is compliant with policy_alg. */
+    if (PSA_ALG_IS_SIGN_HASH(requested_alg) &&
+        PSA_ALG_SIGN_GET_HASH(policy_alg) == PSA_ALG_ANY_HASH) {
+        return (policy_alg & ~PSA_ALG_HASH_MASK) ==
+               (requested_alg & ~PSA_ALG_HASH_MASK);
+    }
+    /* If policy_alg is a wildcard AEAD algorithm of the same base as
+     * the requested algorithm, check the requested tag length to be
+     * equal-length or longer than the wildcard-specified length. */
+    if (PSA_ALG_IS_AEAD(policy_alg) &&
+        PSA_ALG_IS_AEAD(requested_alg) &&
+        (PSA_ALG_AEAD_WITH_SHORTENED_TAG(policy_alg, 0) ==
+         PSA_ALG_AEAD_WITH_SHORTENED_TAG(requested_alg, 0)) &&
+        ((policy_alg & PSA_ALG_AEAD_AT_LEAST_THIS_LENGTH_FLAG) != 0)) {
+        return PSA_ALG_AEAD_GET_TAG_LENGTH(policy_alg) <=
+               PSA_ALG_AEAD_GET_TAG_LENGTH(requested_alg);
+    }
+    /* If policy_alg is a MAC algorithm of the same base as the requested
+     * algorithm, check whether their MAC lengths are compatible. */
+    if (PSA_ALG_IS_MAC(policy_alg) &&
+        PSA_ALG_IS_MAC(requested_alg) &&
+        (PSA_ALG_FULL_LENGTH_MAC(policy_alg) ==
+         PSA_ALG_FULL_LENGTH_MAC(requested_alg))) {
+        /* Validate the combination of key type and algorithm. Since the policy
+         * and requested algorithms are the same, we only need this once. */
+        if (PSA_SUCCESS != psa_mac_key_can_do(policy_alg, key_type)) {
+            return 0;
+        }
+
+        /* Get both the requested output length for the algorithm which is to be
+         * verified, and the default output length for the base algorithm.
+         * Note that none of the currently supported algorithms have an output
+         * length dependent on actual key size, so setting it to a bogus value
+         * of 0 is currently OK. */
+        size_t requested_output_length = PSA_MAC_LENGTH(
+            key_type, 0, requested_alg);
+        size_t default_output_length = PSA_MAC_LENGTH(
+            key_type, 0,
+            PSA_ALG_FULL_LENGTH_MAC(requested_alg));
+
+        /* If the policy is default-length, only allow an algorithm with
+         * a declared exact-length matching the default. */
+        if (PSA_MAC_TRUNCATED_LENGTH(policy_alg) == 0) {
+            return requested_output_length == default_output_length;
+        }
+
+        /* If the requested algorithm is default-length, allow it if the policy
+         * length exactly matches the default length. */
+        if (PSA_MAC_TRUNCATED_LENGTH(requested_alg) == 0 &&
+            PSA_MAC_TRUNCATED_LENGTH(policy_alg) == default_output_length) {
+            return 1;
+        }
+
+        /* If policy_alg is an at-least-this-length wildcard MAC algorithm,
+         * check for the requested MAC length to be equal to or longer than the
+         * minimum allowed length. */
+        if ((policy_alg & PSA_ALG_MAC_AT_LEAST_THIS_LENGTH_FLAG) != 0) {
+            return PSA_MAC_TRUNCATED_LENGTH(policy_alg) <=
+                   requested_output_length;
+        }
+    }
+    /* If policy_alg is a generic key agreement operation, then using it for
+     * a key derivation with that key agreement should also be allowed. This
+     * behaviour is expected to be defined in a future specification version. */
+    if (PSA_ALG_IS_RAW_KEY_AGREEMENT(policy_alg) &&
+        PSA_ALG_IS_KEY_AGREEMENT(requested_alg)) {
+        return PSA_ALG_KEY_AGREEMENT_GET_BASE(requested_alg) ==
+               policy_alg;
+    }
+    /* If it isn't explicitly permitted, it's forbidden. */
+    return 0;
+}
+
+/** Test whether a policy permits an algorithm.
+ *
+ * The caller must test usage flags separately.
+ *
+ * \note This function requires providing the key type for which the policy is
+ *       being validated, since some algorithm policy definitions (e.g. MAC)
+ *       have different properties depending on what kind of cipher it is
+ *       combined with.
+ *
+ * \retval PSA_SUCCESS                  When \p alg is a specific algorithm
+ *                                      allowed by the \p policy.
+ * \retval PSA_ERROR_INVALID_ARGUMENT   When \p alg is not a specific algorithm
+ * \retval PSA_ERROR_NOT_PERMITTED      When \p alg is a specific algorithm, but
+ *                                      the \p policy does not allow it.
+ */
+static psa_status_t psa_key_policy_permits(const psa_key_policy_t *policy,
+                                           psa_key_type_t key_type,
+                                           psa_algorithm_t alg)
+{
+    /* '0' is not a valid algorithm */
+    if (alg == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* A requested algorithm cannot be a wildcard. */
+    if (PSA_ALG_IS_WILDCARD(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (psa_key_algorithm_permits(key_type, policy->alg, alg) ||
+        psa_key_algorithm_permits(key_type, policy->alg2, alg)) {
+        return PSA_SUCCESS;
+    } else {
+        return PSA_ERROR_NOT_PERMITTED;
+    }
+}
+
+/** Restrict a key policy based on a constraint.
+ *
+ * \note This function requires providing the key type for which the policy is
+ *       being restricted, since some algorithm policy definitions (e.g. MAC)
+ *       have different properties depending on what kind of cipher it is
+ *       combined with.
+ *
+ * \param[in] key_type      The key type for which to restrict the policy
+ * \param[in,out] policy    The policy to restrict.
+ * \param[in] constraint    The policy constraint to apply.
+ *
+ * \retval #PSA_SUCCESS
+ *         \c *policy contains the intersection of the original value of
+ *         \c *policy and \c *constraint.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \c key_type, \c *policy and \c *constraint are incompatible.
+ *         \c *policy is unchanged.
+ */
+static psa_status_t psa_restrict_key_policy(
+    psa_key_type_t key_type,
+    psa_key_policy_t *policy,
+    const psa_key_policy_t *constraint)
+{
+    psa_algorithm_t intersection_alg =
+        psa_key_policy_algorithm_intersection(key_type, policy->alg,
+                                              constraint->alg);
+    psa_algorithm_t intersection_alg2 =
+        psa_key_policy_algorithm_intersection(key_type, policy->alg2,
+                                              constraint->alg2);
+    if (intersection_alg == 0 && policy->alg != 0 && constraint->alg != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (intersection_alg2 == 0 && policy->alg2 != 0 && constraint->alg2 != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    policy->usage &= constraint->usage;
+    policy->alg = intersection_alg;
+    policy->alg2 = intersection_alg2;
+    return PSA_SUCCESS;
+}
+
+/** Get the description of a key given its identifier and policy constraints
+ *  and lock it.
+ *
+ * The key must have allow all the usage flags set in \p usage. If \p alg is
+ * nonzero, the key must allow operations with this algorithm. If \p alg is
+ * zero, the algorithm is not checked.
+ *
+ * In case of a persistent key, the function loads the description of the key
+ * into a key slot if not already done.
+ *
+ * On success, the returned key slot has been registered for reading.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * the unregister with mutex lock and unlock operations.
+ */
+static psa_status_t psa_get_and_lock_key_slot_with_policy(
+    mbedtls_svc_key_id_t key,
+    psa_key_slot_t **p_slot,
+    psa_key_usage_t usage,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+
+    status = psa_get_and_lock_key_slot(key, p_slot);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    slot = *p_slot;
+
+    /* Enforce that usage policy for the key slot contains all the flags
+     * required by the usage parameter. There is one exception: public
+     * keys can always be exported, so we treat public key objects as
+     * if they had the export flag. */
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {
+        usage &= ~PSA_KEY_USAGE_EXPORT;
+    }
+
+    if ((slot->attr.policy.usage & usage) != usage) {
+        status = PSA_ERROR_NOT_PERMITTED;
+        goto error;
+    }
+
+    /* Enforce that the usage policy permits the requested algorithm. */
+    if (alg != 0) {
+        status = psa_key_policy_permits(&slot->attr.policy,
+                                        slot->attr.type,
+                                        alg);
+        if (status != PSA_SUCCESS) {
+            goto error;
+        }
+    }
+
+    return PSA_SUCCESS;
+
+error:
+    *p_slot = NULL;
+    psa_unregister_read_under_mutex(slot);
+
+    return status;
+}
+
+/** Get a key slot containing a transparent key and lock it.
+ *
+ * A transparent key is a key for which the key material is directly
+ * available, as opposed to a key in a secure element and/or to be used
+ * by a secure element.
+ *
+ * This is a temporary function that may be used instead of
+ * psa_get_and_lock_key_slot_with_policy() when there is no opaque key support
+ * for a cryptographic operation.
+ *
+ * On success, the returned key slot has been registered for reading.
+ * It is the responsibility of the caller to then unregister
+ * once they have finished reading the contents of the slot.
+ * The caller unregisters by calling psa_unregister_read() or
+ * psa_unregister_read_under_mutex(). psa_unregister_read() must be called
+ * if and only if the caller already holds the global key slot mutex
+ * (when mutexes are enabled). psa_unregister_read_under_mutex() encapsulates
+ * psa_unregister_read() with mutex lock and unlock operations.
+ */
+static psa_status_t psa_get_and_lock_transparent_key_slot_with_policy(
+    mbedtls_svc_key_id_t key,
+    psa_key_slot_t **p_slot,
+    psa_key_usage_t usage,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = psa_get_and_lock_key_slot_with_policy(key, p_slot,
+                                                                usage, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    if (psa_key_lifetime_is_external((*p_slot)->attr.lifetime)) {
+        psa_unregister_read_under_mutex(*p_slot);
+        *p_slot = NULL;
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot)
+{
+    if (slot->key.data != NULL) {
+        mbedtls_zeroize_and_free(slot->key.data, slot->key.bytes);
+    }
+
+    slot->key.data = NULL;
+    slot->key.bytes = 0;
+
+    return PSA_SUCCESS;
+}
+
+/** Completely wipe a slot in memory, including its policy.
+ * Persistent storage is not affected. */
+psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot)
+{
+    psa_status_t status = psa_remove_key_data_from_memory(slot);
+
+    /*
+     * As the return error code may not be handled in case of multiple errors,
+     * do our best to report an unexpected amount of registered readers or
+     * an unexpected state.
+     * Assert with MBEDTLS_TEST_HOOK_TEST_ASSERT that the slot is valid for
+     * wiping.
+     * if the MBEDTLS_TEST_HOOKS configuration option is enabled and the
+     * function is called as part of the execution of a test suite, the
+     * execution of the test suite is stopped in error if the assertion fails.
+     */
+    switch (slot->state) {
+        case PSA_SLOT_FULL:
+        /* In this state psa_wipe_key_slot() must only be called if the
+         * caller is the last reader. */
+        case PSA_SLOT_PENDING_DELETION:
+            /* In this state psa_wipe_key_slot() must only be called if the
+             * caller is the last reader. */
+            if (slot->var.occupied.registered_readers != 1) {
+                MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 1);
+                status = PSA_ERROR_CORRUPTION_DETECTED;
+            }
+            break;
+        case PSA_SLOT_FILLING:
+            /* In this state registered_readers must be 0. */
+            if (slot->var.occupied.registered_readers != 0) {
+                MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->var.occupied.registered_readers == 0);
+                status = PSA_ERROR_CORRUPTION_DETECTED;
+            }
+            break;
+        case PSA_SLOT_EMPTY:
+            /* The slot is already empty, it cannot be wiped. */
+            MBEDTLS_TEST_HOOK_TEST_ASSERT(slot->state != PSA_SLOT_EMPTY);
+            status = PSA_ERROR_CORRUPTION_DETECTED;
+            break;
+        default:
+            /* The slot's state is invalid. */
+            status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    size_t slice_index = slot->slice_index;
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+
+    /* Multipart operations may still be using the key. This is safe
+     * because all multipart operation objects are independent from
+     * the key slot: if they need to access the key after the setup
+     * phase, they have a copy of the key. Note that this means that
+     * key material can linger until all operations are completed. */
+    /* At this point, key material and other type-specific content has
+     * been wiped. Clear remaining metadata. We can call memset and not
+     * zeroize because the metadata is not particularly sensitive.
+     * This memset also sets the slot's state to PSA_SLOT_EMPTY. */
+    memset(slot, 0, sizeof(*slot));
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    /* If the slot is already corrupted, something went deeply wrong,
+     * like a thread still using the slot or a stray pointer leading
+     * to the slot's memory being used for another object. Let the slot
+     * leak rather than make the corruption worse. */
+    if (status == PSA_SUCCESS) {
+        status = psa_free_key_slot(slice_index, slot);
+    }
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+    return status;
+}
+
+psa_status_t psa_destroy_key(mbedtls_svc_key_id_t key)
+{
+    psa_key_slot_t *slot;
+    psa_status_t status; /* status of the last operation */
+    psa_status_t overall_status = PSA_SUCCESS;
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    psa_se_drv_table_entry_t *driver;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    if (mbedtls_svc_key_id_is_null(key)) {
+        return PSA_SUCCESS;
+    }
+
+    /*
+     * Get the description of the key in a key slot, and register to read it.
+     * In the case of a persistent key, this will load the key description
+     * from persistent memory if not done yet.
+     * We cannot avoid this loading as without it we don't know if
+     * the key is operated by an SE or not and this information is needed by
+     * the current implementation. */
+    status = psa_get_and_lock_key_slot(key, &slot);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    /* We cannot unlock between setting the state to PENDING_DELETION
+     * and destroying the key in storage, as otherwise another thread
+     * could load the key into a new slot and the key will not be
+     * fully destroyed. */
+    PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(
+                                    &mbedtls_threading_key_slot_mutex));
+
+    if (slot->state == PSA_SLOT_PENDING_DELETION) {
+        /* Another thread has destroyed the key between us locking the slot
+         * and us gaining the mutex. Unregister from the slot,
+         * and report that the key does not exist. */
+        status = psa_unregister_read(slot);
+
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+        return (status == PSA_SUCCESS) ? PSA_ERROR_INVALID_HANDLE : status;
+    }
+#endif
+    /* Set the key slot containing the key description's state to
+     * PENDING_DELETION. This stops new operations from registering
+     * to read the slot. Current readers can safely continue to access
+     * the key within the slot; the last registered reader will
+     * automatically wipe the slot when they call psa_unregister_read().
+     * If the key is persistent, we can now delete the copy of the key
+     * from memory. If the key is opaque, we require the driver to
+     * deal with the deletion. */
+    overall_status = psa_key_slot_state_transition(slot, PSA_SLOT_FULL,
+                                                   PSA_SLOT_PENDING_DELETION);
+
+    if (overall_status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (PSA_KEY_LIFETIME_IS_READ_ONLY(slot->attr.lifetime)) {
+        /* Refuse the destruction of a read-only key (which may or may not work
+         * if we attempt it, depending on whether the key is merely read-only
+         * by policy or actually physically read-only).
+         * Just do the best we can, which is to wipe the copy in memory
+         * (done in this function's cleanup code). */
+        overall_status = PSA_ERROR_NOT_PERMITTED;
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    driver = psa_get_se_driver_entry(slot->attr.lifetime);
+    if (driver != NULL) {
+        /* For a key in a secure element, we need to do three things:
+         * remove the key file in internal storage, destroy the
+         * key inside the secure element, and update the driver's
+         * persistent data. Start a transaction that will encompass these
+         * three actions. */
+        psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_DESTROY_KEY);
+        psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
+        psa_crypto_transaction.key.slot = psa_key_slot_get_slot_number(slot);
+        psa_crypto_transaction.key.id = slot->attr.id;
+        status = psa_crypto_save_transaction();
+        if (status != PSA_SUCCESS) {
+            (void) psa_crypto_stop_transaction();
+            /* We should still try to destroy the key in the secure
+             * element and the key metadata in storage. This is especially
+             * important if the error is that the storage is full.
+             * But how to do it exactly without risking an inconsistent
+             * state after a reset?
+             * https://github.com/ARMmbed/mbed-crypto/issues/215
+             */
+            overall_status = status;
+            goto exit;
+        }
+
+        status = psa_destroy_se_key(driver,
+                                    psa_key_slot_get_slot_number(slot));
+        if (overall_status == PSA_SUCCESS) {
+            overall_status = status;
+        }
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
+        /* Destroy the copy of the persistent key from storage.
+         * The slot will still hold a copy of the key until the last reader
+         * unregisters. */
+        status = psa_destroy_persistent_key(slot->attr.id);
+        if (overall_status == PSA_SUCCESS) {
+            overall_status = status;
+        }
+    }
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    if (driver != NULL) {
+        status = psa_save_se_persistent_data(driver);
+        if (overall_status == PSA_SUCCESS) {
+            overall_status = status;
+        }
+        status = psa_crypto_stop_transaction();
+        if (overall_status == PSA_SUCCESS) {
+            overall_status = status;
+        }
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+exit:
+    /* Unregister from reading the slot. If we are the last active reader
+     * then this will wipe the slot. */
+    status = psa_unregister_read(slot);
+    /* Prioritize CORRUPTION_DETECTED from unregistering over
+     * a storage error. */
+    if (status != PSA_SUCCESS) {
+        overall_status = status;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    /* Don't overwrite existing errors if the unlock fails. */
+    status = overall_status;
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+
+    return overall_status;
+}
+
+/** Retrieve all the publicly-accessible attributes of a key.
+ */
+psa_status_t psa_get_key_attributes(mbedtls_svc_key_id_t key,
+                                    psa_key_attributes_t *attributes)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    psa_reset_key_attributes(attributes);
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    *attributes = slot->attr;
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    if (psa_get_se_driver_entry(slot->attr.lifetime) != NULL) {
+        psa_set_key_slot_number(attributes,
+                                psa_key_slot_get_slot_number(slot));
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    return psa_unregister_read_under_mutex(slot);
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+psa_status_t psa_get_key_slot_number(
+    const psa_key_attributes_t *attributes,
+    psa_key_slot_number_t *slot_number)
+{
+    if (attributes->has_slot_number) {
+        *slot_number = attributes->slot_number;
+        return PSA_SUCCESS;
+    } else {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+static psa_status_t psa_export_key_buffer_internal(const uint8_t *key_buffer,
+                                                   size_t key_buffer_size,
+                                                   uint8_t *data,
+                                                   size_t data_size,
+                                                   size_t *data_length)
+{
+    if (key_buffer_size > data_size) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+    memcpy(data, key_buffer, key_buffer_size);
+    memset(data + key_buffer_size, 0,
+           data_size - key_buffer_size);
+    *data_length = key_buffer_size;
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_export_key_internal(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length)
+{
+    psa_key_type_t type = attributes->type;
+
+    if (key_type_is_raw_bytes(type) ||
+        PSA_KEY_TYPE_IS_RSA(type)   ||
+        PSA_KEY_TYPE_IS_ECC(type)   ||
+        PSA_KEY_TYPE_IS_DH(type)) {
+        return psa_export_key_buffer_internal(
+            key_buffer, key_buffer_size,
+            data, data_size, data_length);
+    } else {
+        /* This shouldn't happen in the reference implementation, but
+           it is valid for a special-purpose implementation to omit
+           support for exporting certain key types. */
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+}
+
+psa_status_t psa_export_key(mbedtls_svc_key_id_t key,
+                            uint8_t *data_external,
+                            size_t data_size,
+                            size_t *data_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+    LOCAL_OUTPUT_DECLARE(data_external, data);
+
+    /* Reject a zero-length output buffer now, since this can never be a
+     * valid key representation. This way we know that data must be a valid
+     * pointer and we can do things like memset(data, ..., data_size). */
+    if (data_size == 0) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    /* Set the key to empty now, so that even when there are errors, we always
+     * set data_length to a value between 0 and data_size. On error, setting
+     * the key to empty is a good choice because an empty key representation is
+     * unlikely to be accepted anywhere. */
+    *data_length = 0;
+
+    /* Export requires the EXPORT flag. There is an exception for public keys,
+     * which don't require any flag, but
+     * psa_get_and_lock_key_slot_with_policy() takes care of this.
+     */
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_EXPORT, 0);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
+
+    status = psa_driver_wrapper_export_key(&slot->attr,
+                                           slot->key.data, slot->key.bytes,
+                                           data, data_size, data_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    LOCAL_OUTPUT_FREE(data_external, data);
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_export_public_key_internal(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    uint8_t *data,
+    size_t data_size,
+    size_t *data_length)
+{
+    psa_key_type_t type = attributes->type;
+
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
+        (PSA_KEY_TYPE_IS_RSA(type) || PSA_KEY_TYPE_IS_ECC(type) ||
+         PSA_KEY_TYPE_IS_DH(type))) {
+        /* Exporting public -> public */
+        return psa_export_key_buffer_internal(
+            key_buffer, key_buffer_size,
+            data, data_size, data_length);
+    } else if (PSA_KEY_TYPE_IS_RSA(type)) {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+        return mbedtls_psa_rsa_export_public_key(attributes,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 data,
+                                                 data_size,
+                                                 data_length);
+#else
+        /* We don't know how to convert a private RSA key to public. */
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+    } else if (PSA_KEY_TYPE_IS_ECC(type)) {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
+        return mbedtls_psa_ecp_export_public_key(attributes,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 data,
+                                                 data_size,
+                                                 data_length);
+#else
+        /* We don't know how to convert a private ECC key to public */
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+    } else if (PSA_KEY_TYPE_IS_DH(type)) {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
+        defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
+        return mbedtls_psa_ffdh_export_public_key(attributes,
+                                                  key_buffer,
+                                                  key_buffer_size,
+                                                  data, data_size,
+                                                  data_length);
+#else
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) */
+    } else {
+        (void) key_buffer;
+        (void) key_buffer_size;
+        (void) data;
+        (void) data_size;
+        (void) data_length;
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+}
+
+psa_status_t psa_export_public_key(mbedtls_svc_key_id_t key,
+                                   uint8_t *data_external,
+                                   size_t data_size,
+                                   size_t *data_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_OUTPUT_DECLARE(data_external, data);
+
+    /* Reject a zero-length output buffer now, since this can never be a
+     * valid key representation. This way we know that data must be a valid
+     * pointer and we can do things like memset(data, ..., data_size). */
+    if (data_size == 0) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    /* Set the key to empty now, so that even when there are errors, we always
+     * set data_length to a value between 0 and data_size. On error, setting
+     * the key to empty is a good choice because an empty key representation is
+     * unlikely to be accepted anywhere. */
+    *data_length = 0;
+
+    /* Exporting a public key doesn't require a usage flag. */
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot, 0, 0);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    LOCAL_OUTPUT_ALLOC(data_external, data_size, data);
+
+    if (!PSA_KEY_TYPE_IS_ASYMMETRIC(slot->attr.type)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_export_public_key(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        data, data_size, data_length);
+
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    LOCAL_OUTPUT_FREE(data_external, data);
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+/** Validate that a key policy is internally well-formed.
+ *
+ * This function only rejects invalid policies. It does not validate the
+ * consistency of the policy with respect to other attributes of the key
+ * such as the key type.
+ */
+static psa_status_t psa_validate_key_policy(const psa_key_policy_t *policy)
+{
+    if ((policy->usage & ~(PSA_KEY_USAGE_EXPORT |
+                           PSA_KEY_USAGE_COPY |
+                           PSA_KEY_USAGE_ENCRYPT |
+                           PSA_KEY_USAGE_DECRYPT |
+                           PSA_KEY_USAGE_SIGN_MESSAGE |
+                           PSA_KEY_USAGE_VERIFY_MESSAGE |
+                           PSA_KEY_USAGE_SIGN_HASH |
+                           PSA_KEY_USAGE_VERIFY_HASH |
+                           PSA_KEY_USAGE_VERIFY_DERIVATION |
+                           PSA_KEY_USAGE_DERIVE)) != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return PSA_SUCCESS;
+}
+
+/** Validate the internal consistency of key attributes.
+ *
+ * This function only rejects invalid attribute values. If does not
+ * validate the consistency of the attributes with any key data that may
+ * be involved in the creation of the key.
+ *
+ * Call this function early in the key creation process.
+ *
+ * \param[in] attributes    Key attributes for the new key.
+ * \param[out] p_drv        On any return, the driver for the key, if any.
+ *                          NULL for a transparent key.
+ *
+ */
+static psa_status_t psa_validate_key_attributes(
+    const psa_key_attributes_t *attributes,
+    psa_se_drv_table_entry_t **p_drv)
+{
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_lifetime_t lifetime = psa_get_key_lifetime(attributes);
+    mbedtls_svc_key_id_t key = psa_get_key_id(attributes);
+
+    status = psa_validate_key_location(lifetime, p_drv);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_validate_key_persistence(lifetime);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
+        if (MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key) != 0) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        if (!psa_is_valid_key_id(psa_get_key_id(attributes), 0)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    status = psa_validate_key_policy(&attributes->policy);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Refuse to create overly large keys.
+     * Note that this doesn't trigger on import if the attributes don't
+     * explicitly specify a size (so psa_get_key_bits returns 0), so
+     * psa_import_key() needs its own checks. */
+    if (psa_get_key_bits(attributes) > PSA_MAX_KEY_BITS) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+
+/** Prepare a key slot to receive key material.
+ *
+ * This function allocates a key slot and sets its metadata.
+ *
+ * If this function fails, call psa_fail_key_creation().
+ *
+ * This function is intended to be used as follows:
+ * -# Call psa_start_key_creation() to allocate a key slot, prepare
+ *    it with the specified attributes, and in case of a volatile key assign it
+ *    a volatile key identifier.
+ * -# Populate the slot with the key material.
+ * -# Call psa_finish_key_creation() to finalize the creation of the slot.
+ * In case of failure at any step, stop the sequence and call
+ * psa_fail_key_creation().
+ *
+ * On success, the key slot's state is PSA_SLOT_FILLING.
+ * It is the responsibility of the caller to change the slot's state to
+ * PSA_SLOT_EMPTY/FULL once key creation has finished.
+ *
+ * \param method            An identification of the calling function.
+ * \param[in] attributes    Key attributes for the new key.
+ * \param[out] p_slot       On success, a pointer to the prepared slot.
+ * \param[out] p_drv        On any return, the driver for the key, if any.
+ *                          NULL for a transparent key.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key slot is ready to receive key material.
+ * \return If this function fails, the key slot is an invalid state.
+ *         You must call psa_fail_key_creation() to wipe and free the slot.
+ */
+static psa_status_t psa_start_key_creation(
+    psa_key_creation_method_t method,
+    const psa_key_attributes_t *attributes,
+    psa_key_slot_t **p_slot,
+    psa_se_drv_table_entry_t **p_drv)
+{
+    psa_status_t status;
+
+    (void) method;
+    *p_drv = NULL;
+
+    status = psa_validate_key_attributes(attributes, p_drv);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    int key_is_volatile = PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime);
+    psa_key_id_t volatile_key_id;
+
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    status = psa_reserve_free_key_slot(
+        key_is_volatile ? &volatile_key_id : NULL,
+        p_slot);
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    psa_key_slot_t *slot = *p_slot;
+
+    /* We're storing the declared bit-size of the key. It's up to each
+     * creation mechanism to verify that this information is correct.
+     * It's automatically correct for mechanisms that use the bit-size as
+     * an input (generate, device) but not for those where the bit-size
+     * is optional (import, copy). In case of a volatile key, assign it the
+     * volatile key identifier associated to the slot returned to contain its
+     * definition. */
+
+    slot->attr = *attributes;
+    if (key_is_volatile) {
+#if !defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+        slot->attr.id = volatile_key_id;
+#else
+        slot->attr.id.key_id = volatile_key_id;
+#endif
+    }
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* For a key in a secure element, we need to do three things
+     * when creating or registering a persistent key:
+     * create the key file in internal storage, create the
+     * key inside the secure element, and update the driver's
+     * persistent data. This is done by starting a transaction that will
+     * encompass these three actions.
+     * For registering a volatile key, we just need to find an appropriate
+     * slot number inside the SE. Since the key is designated volatile, creating
+     * a transaction is not required. */
+    /* The first thing to do is to find a slot number for the new key.
+     * We save the slot number in persistent storage as part of the
+     * transaction data. It will be needed to recover if the power
+     * fails during the key creation process, to clean up on the secure
+     * element side after restarting. Obtaining a slot number from the
+     * secure element driver updates its persistent state, but we do not yet
+     * save the driver's persistent state, so that if the power fails,
+     * we can roll back to a state where the key doesn't exist. */
+    if (*p_drv != NULL) {
+        psa_key_slot_number_t slot_number;
+        status = psa_find_se_slot_for_key(attributes, method, *p_drv,
+                                          &slot_number);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        if (!PSA_KEY_LIFETIME_IS_VOLATILE(attributes->lifetime)) {
+            psa_crypto_prepare_transaction(PSA_CRYPTO_TRANSACTION_CREATE_KEY);
+            psa_crypto_transaction.key.lifetime = slot->attr.lifetime;
+            psa_crypto_transaction.key.slot = slot_number;
+            psa_crypto_transaction.key.id = slot->attr.id;
+            status = psa_crypto_save_transaction();
+            if (status != PSA_SUCCESS) {
+                (void) psa_crypto_stop_transaction();
+                return status;
+            }
+        }
+
+        status = psa_copy_key_material_into_slot(
+            slot, (uint8_t *) (&slot_number), sizeof(slot_number));
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    }
+
+    if (*p_drv == NULL && method == PSA_KEY_CREATION_REGISTER) {
+        /* Key registration only makes sense with a secure element. */
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    return PSA_SUCCESS;
+}
+
+/** Finalize the creation of a key once its key material has been set.
+ *
+ * This entails writing the key to persistent storage.
+ *
+ * If this function fails, call psa_fail_key_creation().
+ * See the documentation of psa_start_key_creation() for the intended use
+ * of this function.
+ *
+ * If the finalization succeeds, the function sets the key slot's state to
+ * PSA_SLOT_FULL, and the key slot can no longer be accessed as part of the
+ * key creation process.
+ *
+ * \param[in,out] slot  Pointer to the slot with key material.
+ * \param[in] driver    The secure element driver for the key,
+ *                      or NULL for a transparent key.
+ * \param[out] key      On success, identifier of the key. Note that the
+ *                      key identifier is also stored in the key slot.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was successfully created.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ *
+ * \return If this function fails, the key slot is an invalid state.
+ *         You must call psa_fail_key_creation() to wipe and free the slot.
+ */
+static psa_status_t psa_finish_key_creation(
+    psa_key_slot_t *slot,
+    psa_se_drv_table_entry_t *driver,
+    mbedtls_svc_key_id_t *key)
+{
+    psa_status_t status = PSA_SUCCESS;
+    (void) slot;
+    (void) driver;
+
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+        if (driver != NULL) {
+            psa_se_key_data_storage_t data;
+            psa_key_slot_number_t slot_number =
+                psa_key_slot_get_slot_number(slot);
+
+            MBEDTLS_STATIC_ASSERT(sizeof(slot_number) ==
+                                  sizeof(data.slot_number),
+                                  "Slot number size does not match psa_se_key_data_storage_t");
+
+            memcpy(&data.slot_number, &slot_number, sizeof(slot_number));
+            status = psa_save_persistent_key(&slot->attr,
+                                             (uint8_t *) &data,
+                                             sizeof(data));
+        } else
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+        {
+            /* Key material is saved in export representation in the slot, so
+             * just pass the slot buffer for storage. */
+            status = psa_save_persistent_key(&slot->attr,
+                                             slot->key.data,
+                                             slot->key.bytes);
+        }
+    }
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* Finish the transaction for a key creation. This does not
+     * happen when registering an existing key. Detect this case
+     * by checking whether a transaction is in progress (actual
+     * creation of a persistent key in a secure element requires a transaction,
+     * but registration or volatile key creation doesn't use one). */
+    if (driver != NULL &&
+        psa_crypto_transaction.unknown.type == PSA_CRYPTO_TRANSACTION_CREATE_KEY) {
+        status = psa_save_se_persistent_data(driver);
+        if (status != PSA_SUCCESS) {
+            psa_destroy_persistent_key(slot->attr.id);
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                      &mbedtls_threading_key_slot_mutex));
+#endif
+            return status;
+        }
+        status = psa_crypto_stop_transaction();
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    if (status == PSA_SUCCESS) {
+        *key = slot->attr.id;
+        status = psa_key_slot_state_transition(slot, PSA_SLOT_FILLING,
+                                               PSA_SLOT_FULL);
+        if (status != PSA_SUCCESS) {
+            *key = MBEDTLS_SVC_KEY_ID_INIT;
+        }
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    return status;
+}
+
+/** Abort the creation of a key.
+ *
+ * You may call this function after calling psa_start_key_creation(),
+ * or after psa_finish_key_creation() fails. In other circumstances, this
+ * function may not clean up persistent storage.
+ * See the documentation of psa_start_key_creation() for the intended use
+ * of this function. Sets the slot's state to PSA_SLOT_EMPTY.
+ *
+ * \param[in,out] slot  Pointer to the slot with key material.
+ * \param[in] driver    The secure element driver for the key,
+ *                      or NULL for a transparent key.
+ */
+static void psa_fail_key_creation(psa_key_slot_t *slot,
+                                  psa_se_drv_table_entry_t *driver)
+{
+    (void) driver;
+
+    if (slot == NULL) {
+        return;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    /* If the lock operation fails we still wipe the slot.
+     * Operations will no longer work after a failed lock,
+     * but we still need to wipe the slot of confidential data. */
+    mbedtls_mutex_lock(&mbedtls_threading_key_slot_mutex);
+#endif
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* TODO: If the key has already been created in the secure
+     * element, and the failure happened later (when saving metadata
+     * to internal storage), we need to destroy the key in the secure
+     * element.
+     * https://github.com/ARMmbed/mbed-crypto/issues/217
+     */
+
+    /* Abort the ongoing transaction if any (there may not be one if
+     * the creation process failed before starting one, or if the
+     * key creation is a registration of a key in a secure element).
+     * Earlier functions must already have done what it takes to undo any
+     * partial creation. All that's left is to update the transaction data
+     * itself. */
+    (void) psa_crypto_stop_transaction();
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    psa_wipe_key_slot(slot);
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_key_slot_mutex);
+#endif
+}
+
+/** Validate optional attributes during key creation.
+ *
+ * Some key attributes are optional during key creation. If they are
+ * specified in the attributes structure, check that they are consistent
+ * with the data in the slot.
+ *
+ * This function should be called near the end of key creation, after
+ * the slot in memory is fully populated but before saving persistent data.
+ */
+static psa_status_t psa_validate_optional_attributes(
+    const psa_key_slot_t *slot,
+    const psa_key_attributes_t *attributes)
+{
+    if (attributes->type != 0) {
+        if (attributes->type != slot->attr.type) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    if (attributes->bits != 0) {
+        if (attributes->bits != slot->attr.bits) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_import_key(const psa_key_attributes_t *attributes,
+                            const uint8_t *data_external,
+                            size_t data_length,
+                            mbedtls_svc_key_id_t *key)
+{
+    psa_status_t status;
+    LOCAL_INPUT_DECLARE(data_external, data);
+    psa_key_slot_t *slot = NULL;
+    psa_se_drv_table_entry_t *driver = NULL;
+    size_t bits;
+    size_t storage_size = data_length;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Reject zero-length symmetric keys (including raw data key objects).
+     * This also rejects any key which might be encoded as an empty string,
+     * which is never valid. */
+    if (data_length == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Ensure that the bytes-to-bits conversion cannot overflow. */
+    if (data_length > SIZE_MAX / 8) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    LOCAL_INPUT_ALLOC(data_external, data_length, data);
+
+    status = psa_start_key_creation(PSA_KEY_CREATION_IMPORT, attributes,
+                                    &slot, &driver);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* In the case of a transparent key or an opaque key stored in local
+     * storage ( thus not in the case of importing a key in a secure element
+     * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
+     * buffer to hold the imported key material. */
+    if (slot->key.data == NULL) {
+        if (psa_key_lifetime_is_external(attributes->lifetime)) {
+            status = psa_driver_wrapper_get_key_buffer_size_from_key_data(
+                attributes, data, data_length, &storage_size);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+        }
+        status = psa_allocate_buffer_to_slot(slot, storage_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    bits = slot->attr.bits;
+    status = psa_driver_wrapper_import_key(attributes,
+                                           data, data_length,
+                                           slot->key.data,
+                                           slot->key.bytes,
+                                           &slot->key.bytes, &bits);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (slot->attr.bits == 0) {
+        slot->attr.bits = (psa_key_bits_t) bits;
+    } else if (bits != slot->attr.bits) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    /* Enforce a size limit, and in particular ensure that the bit
+     * size fits in its representation type.*/
+    if (bits > PSA_MAX_KEY_BITS) {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+    status = psa_validate_optional_attributes(slot, attributes);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_finish_key_creation(slot, driver, key);
+exit:
+    LOCAL_INPUT_FREE(data_external, data);
+    if (status != PSA_SUCCESS) {
+        psa_fail_key_creation(slot, driver);
+    }
+
+    return status;
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+psa_status_t mbedtls_psa_register_se_key(
+    const psa_key_attributes_t *attributes)
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    psa_se_drv_table_entry_t *driver = NULL;
+    mbedtls_svc_key_id_t key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Leaving attributes unspecified is not currently supported.
+     * It could make sense to query the key type and size from the
+     * secure element, but not all secure elements support this
+     * and the driver HAL doesn't currently support it. */
+    if (psa_get_key_type(attributes) == PSA_KEY_TYPE_NONE) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    if (psa_get_key_bits(attributes) == 0) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Not usable with volatile keys, even with an appropriate location,
+     * due to the API design.
+     * https://github.com/Mbed-TLS/mbedtls/issues/9253
+     */
+    if (PSA_KEY_LIFETIME_IS_VOLATILE(psa_get_key_lifetime(attributes))) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_start_key_creation(PSA_KEY_CREATION_REGISTER, attributes,
+                                    &slot, &driver);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_finish_key_creation(slot, driver, &key);
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_fail_key_creation(slot, driver);
+    }
+
+    /* Registration doesn't keep the key in RAM. */
+    psa_close_key(key);
+    return status;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+psa_status_t psa_copy_key(mbedtls_svc_key_id_t source_key,
+                          const psa_key_attributes_t *specified_attributes,
+                          mbedtls_svc_key_id_t *target_key)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *source_slot = NULL;
+    psa_key_slot_t *target_slot = NULL;
+    psa_key_attributes_t actual_attributes = *specified_attributes;
+    psa_se_drv_table_entry_t *driver = NULL;
+    size_t storage_size = 0;
+
+    *target_key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        source_key, &source_slot, PSA_KEY_USAGE_COPY, 0);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_validate_optional_attributes(source_slot,
+                                              specified_attributes);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* The target key type and number of bits have been validated by
+     * psa_validate_optional_attributes() to be either equal to zero or
+     * equal to the ones of the source key. So it is safe to inherit
+     * them from the source key now."
+     * */
+    actual_attributes.bits = source_slot->attr.bits;
+    actual_attributes.type = source_slot->attr.type;
+
+
+    status = psa_restrict_key_policy(source_slot->attr.type,
+                                     &actual_attributes.policy,
+                                     &source_slot->attr.policy);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_start_key_creation(PSA_KEY_CREATION_COPY, &actual_attributes,
+                                    &target_slot, &driver);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    if (PSA_KEY_LIFETIME_GET_LOCATION(target_slot->attr.lifetime) !=
+        PSA_KEY_LIFETIME_GET_LOCATION(source_slot->attr.lifetime)) {
+        /*
+         * If the source and target keys are stored in different locations,
+         * the source key would need to be exported as plaintext and re-imported
+         * in the other location. This has security implications which have not
+         * been fully mapped. For now, this can be achieved through
+         * appropriate API invocations from the application, if needed.
+         * */
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+    /*
+     * When the source and target keys are within the same location,
+     * - For transparent keys it is a blind copy without any driver invocation,
+     * - For opaque keys this translates to an invocation of the drivers'
+     *   copy_key entry point through the dispatch layer.
+     * */
+    if (psa_key_lifetime_is_external(actual_attributes.lifetime)) {
+        status = psa_driver_wrapper_get_key_buffer_size(&actual_attributes,
+                                                        &storage_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_allocate_buffer_to_slot(target_slot, storage_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status = psa_driver_wrapper_copy_key(&actual_attributes,
+                                             source_slot->key.data,
+                                             source_slot->key.bytes,
+                                             target_slot->key.data,
+                                             target_slot->key.bytes,
+                                             &target_slot->key.bytes);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    } else {
+        status = psa_copy_key_material_into_slot(target_slot,
+                                                 source_slot->key.data,
+                                                 source_slot->key.bytes);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+    status = psa_finish_key_creation(target_slot, driver, target_key);
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_fail_key_creation(target_slot, driver);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(source_slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+
+
+/****************************************************************/
+/* Message digests */
+/****************************************************************/
+
+psa_status_t psa_hash_abort(psa_hash_operation_t *operation)
+{
+    /* Aborting a non-active operation is allowed */
+    if (operation->id == 0) {
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = psa_driver_wrapper_hash_abort(operation);
+    operation->id = 0;
+
+    return status;
+}
+
+psa_status_t psa_hash_setup(psa_hash_operation_t *operation,
+                            psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* A context must be freshly initialized before it can be set up. */
+    if (operation->id != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (!PSA_ALG_IS_HASH(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    /* Ensure all of the context is zeroized, since PSA_HASH_OPERATION_INIT only
+     * directly zeroes the int-sized dummy member of the context union. */
+    memset(&operation->ctx, 0, sizeof(operation->ctx));
+
+    status = psa_driver_wrapper_hash_setup(operation, alg);
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_hash_abort(operation);
+    }
+
+    return status;
+}
+
+psa_status_t psa_hash_update(psa_hash_operation_t *operation,
+                             const uint8_t *input_external,
+                             size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* Don't require hash implementations to behave correctly on a
+     * zero-length input, which may have an invalid pointer. */
+    if (input_length == 0) {
+        return PSA_SUCCESS;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_hash_update(operation, input, input_length);
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_hash_abort(operation);
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+    return status;
+}
+
+static psa_status_t psa_hash_finish_internal(psa_hash_operation_t *operation,
+                                             uint8_t *hash,
+                                             size_t hash_size,
+                                             size_t *hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *hash_length = 0;
+    if (operation->id == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_driver_wrapper_hash_finish(
+        operation, hash, hash_size, hash_length);
+    psa_hash_abort(operation);
+
+    return status;
+}
+
+psa_status_t psa_hash_finish(psa_hash_operation_t *operation,
+                             uint8_t *hash_external,
+                             size_t hash_size,
+                             size_t *hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_OUTPUT_DECLARE(hash_external, hash);
+
+    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
+    status = psa_hash_finish_internal(operation, hash, hash_size, hash_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_OUTPUT_FREE(hash_external, hash);
+    return status;
+}
+
+psa_status_t psa_hash_verify(psa_hash_operation_t *operation,
+                             const uint8_t *hash_external,
+                             size_t hash_length)
+{
+    uint8_t actual_hash[PSA_HASH_MAX_SIZE];
+    size_t actual_hash_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+
+    status = psa_hash_finish_internal(
+        operation,
+        actual_hash, sizeof(actual_hash),
+        &actual_hash_length);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (actual_hash_length != hash_length) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+exit:
+    mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));
+    if (status != PSA_SUCCESS) {
+        psa_hash_abort(operation);
+    }
+    LOCAL_INPUT_FREE(hash_external, hash);
+    return status;
+}
+
+psa_status_t psa_hash_compute(psa_algorithm_t alg,
+                              const uint8_t *input_external, size_t input_length,
+                              uint8_t *hash_external, size_t hash_size,
+                              size_t *hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(hash_external, hash);
+
+    *hash_length = 0;
+    if (!PSA_ALG_IS_HASH(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(hash_external, hash_size, hash);
+    status = psa_driver_wrapper_hash_compute(alg, input, input_length,
+                                             hash, hash_size, hash_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(hash_external, hash);
+    return status;
+}
+
+psa_status_t psa_hash_compare(psa_algorithm_t alg,
+                              const uint8_t *input_external, size_t input_length,
+                              const uint8_t *hash_external, size_t hash_length)
+{
+    uint8_t actual_hash[PSA_HASH_MAX_SIZE];
+    size_t actual_hash_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+
+    if (!PSA_ALG_IS_HASH(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_hash_compute(
+        alg, input, input_length,
+        actual_hash, sizeof(actual_hash),
+        &actual_hash_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    if (actual_hash_length != hash_length) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    if (mbedtls_ct_memcmp(hash, actual_hash, actual_hash_length) != 0) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+exit:
+    mbedtls_platform_zeroize(actual_hash, sizeof(actual_hash));
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(hash_external, hash);
+
+    return status;
+}
+
+psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation,
+                            psa_hash_operation_t *target_operation)
+{
+    if (source_operation->id == 0 ||
+        target_operation->id != 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    psa_status_t status = psa_driver_wrapper_hash_clone(source_operation,
+                                                        target_operation);
+    if (status != PSA_SUCCESS) {
+        psa_hash_abort(target_operation);
+    }
+
+    return status;
+}
+
+
+/****************************************************************/
+/* MAC */
+/****************************************************************/
+
+psa_status_t psa_mac_abort(psa_mac_operation_t *operation)
+{
+    /* Aborting a non-active operation is allowed */
+    if (operation->id == 0) {
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = psa_driver_wrapper_mac_abort(operation);
+    operation->mac_size = 0;
+    operation->is_sign = 0;
+    operation->id = 0;
+
+    return status;
+}
+
+static psa_status_t psa_mac_finalize_alg_and_key_validation(
+    psa_algorithm_t alg,
+    const psa_key_attributes_t *attributes,
+    uint8_t *mac_size)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t key_type = psa_get_key_type(attributes);
+    size_t key_bits = psa_get_key_bits(attributes);
+
+    if (!PSA_ALG_IS_MAC(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Validate the combination of key type and algorithm */
+    status = psa_mac_key_can_do(alg, key_type);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Get the output length for the algorithm and key combination */
+    *mac_size = PSA_MAC_LENGTH(key_type, key_bits, alg);
+
+    if (*mac_size < 4) {
+        /* A very short MAC is too short for security since it can be
+         * brute-forced. Ancient protocols with 32-bit MACs do exist,
+         * so we make this our minimum, even though 32 bits is still
+         * too small for security. */
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (*mac_size > PSA_MAC_LENGTH(key_type, key_bits,
+                                   PSA_ALG_FULL_LENGTH_MAC(alg))) {
+        /* It's impossible to "truncate" to a larger length than the full length
+         * of the algorithm. */
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (*mac_size > PSA_MAC_MAX_SIZE) {
+        /* PSA_MAC_LENGTH returns the correct length even for a MAC algorithm
+         * that is disabled in the compile-time configuration. The result can
+         * therefore be larger than PSA_MAC_MAX_SIZE, which does take the
+         * configuration into account. In this case, force a return of
+         * PSA_ERROR_NOT_SUPPORTED here. Otherwise psa_mac_verify(), or
+         * psa_mac_compute(mac_size=PSA_MAC_MAX_SIZE), would return
+         * PSA_ERROR_BUFFER_TOO_SMALL for an unsupported algorithm whose MAC size
+         * is larger than PSA_MAC_MAX_SIZE, which is misleading and which breaks
+         * systematically generated tests. */
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_mac_setup(psa_mac_operation_t *operation,
+                                  mbedtls_svc_key_id_t key,
+                                  psa_algorithm_t alg,
+                                  int is_sign)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+
+    /* A context must be freshly initialized before it can be set up. */
+    if (operation->id != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key,
+        &slot,
+        is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,
+        alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
+                                                     &operation->mac_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    operation->is_sign = is_sign;
+    /* Dispatch the MAC setup call with validated input */
+    if (is_sign) {
+        status = psa_driver_wrapper_mac_sign_setup(operation,
+                                                   &slot->attr,
+                                                   slot->key.data,
+                                                   slot->key.bytes,
+                                                   alg);
+    } else {
+        status = psa_driver_wrapper_mac_verify_setup(operation,
+                                                     &slot->attr,
+                                                     slot->key.data,
+                                                     slot->key.bytes,
+                                                     alg);
+    }
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_mac_abort(operation);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation,
+                                mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg)
+{
+    return psa_mac_setup(operation, key, alg, 1);
+}
+
+psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation,
+                                  mbedtls_svc_key_id_t key,
+                                  psa_algorithm_t alg)
+{
+    return psa_mac_setup(operation, key, alg, 0);
+}
+
+psa_status_t psa_mac_update(psa_mac_operation_t *operation,
+                            const uint8_t *input_external,
+                            size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        return status;
+    }
+
+    /* Don't require hash implementations to behave correctly on a
+     * zero-length input, which may have an invalid pointer. */
+    if (input_length == 0) {
+        status = PSA_SUCCESS;
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_mac_update(operation, input, input_length);
+
+    if (status != PSA_SUCCESS) {
+        psa_mac_abort(operation);
+    }
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+
+    return status;
+}
+
+psa_status_t psa_mac_sign_finish(psa_mac_operation_t *operation,
+                                 uint8_t *mac_external,
+                                 size_t mac_size,
+                                 size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_OUTPUT_DECLARE(mac_external, mac);
+    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (!operation->is_sign) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* Sanity check. This will guarantee that mac_size != 0 (and so mac != NULL)
+     * once all the error checks are done. */
+    if (operation->mac_size == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (mac_size < operation->mac_size) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+
+    status = psa_driver_wrapper_mac_sign_finish(operation,
+                                                mac, operation->mac_size,
+                                                mac_length);
+
+exit:
+    /* In case of success, set the potential excess room in the output buffer
+     * to an invalid value, to avoid potentially leaking a longer MAC.
+     * In case of error, set the output length and content to a safe default,
+     * such that in case the caller misses an error check, the output would be
+     * an unachievable MAC.
+     */
+    if (status != PSA_SUCCESS) {
+        *mac_length = mac_size;
+        operation->mac_size = 0;
+    }
+
+    if (mac != NULL) {
+        psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
+    }
+
+    abort_status = psa_mac_abort(operation);
+    LOCAL_OUTPUT_FREE(mac_external, mac);
+
+    return status == PSA_SUCCESS ? abort_status : status;
+}
+
+psa_status_t psa_mac_verify_finish(psa_mac_operation_t *operation,
+                                   const uint8_t *mac_external,
+                                   size_t mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(mac_external, mac);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->is_sign) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->mac_size != mac_length) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
+    status = psa_driver_wrapper_mac_verify_finish(operation,
+                                                  mac, mac_length);
+
+exit:
+    abort_status = psa_mac_abort(operation);
+    LOCAL_INPUT_FREE(mac_external, mac);
+
+    return status == PSA_SUCCESS ? abort_status : status;
+}
+
+static psa_status_t psa_mac_compute_internal(mbedtls_svc_key_id_t key,
+                                             psa_algorithm_t alg,
+                                             const uint8_t *input,
+                                             size_t input_length,
+                                             uint8_t *mac,
+                                             size_t mac_size,
+                                             size_t *mac_length,
+                                             int is_sign)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+    uint8_t operation_mac_size = 0;
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key,
+        &slot,
+        is_sign ? PSA_KEY_USAGE_SIGN_MESSAGE : PSA_KEY_USAGE_VERIFY_MESSAGE,
+        alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_mac_finalize_alg_and_key_validation(alg, &slot->attr,
+                                                     &operation_mac_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (mac_size < operation_mac_size) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_mac_compute(
+        &slot->attr,
+        slot->key.data, slot->key.bytes,
+        alg,
+        input, input_length,
+        mac, operation_mac_size, mac_length);
+
+exit:
+    /* In case of success, set the potential excess room in the output buffer
+     * to an invalid value, to avoid potentially leaking a longer MAC.
+     * In case of error, set the output length and content to a safe default,
+     * such that in case the caller misses an error check, the output would be
+     * an unachievable MAC.
+     */
+    if (status != PSA_SUCCESS) {
+        *mac_length = mac_size;
+        operation_mac_size = 0;
+    }
+
+    psa_wipe_tag_output_buffer(mac, status, mac_size, *mac_length);
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_mac_compute(mbedtls_svc_key_id_t key,
+                             psa_algorithm_t alg,
+                             const uint8_t *input_external,
+                             size_t input_length,
+                             uint8_t *mac_external,
+                             size_t mac_size,
+                             size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(mac_external, mac);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(mac_external, mac_size, mac);
+    status = psa_mac_compute_internal(key, alg,
+                                      input, input_length,
+                                      mac, mac_size, mac_length, 1);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(mac_external, mac);
+
+    return status;
+}
+
+psa_status_t psa_mac_verify(mbedtls_svc_key_id_t key,
+                            psa_algorithm_t alg,
+                            const uint8_t *input_external,
+                            size_t input_length,
+                            const uint8_t *mac_external,
+                            size_t mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t actual_mac[PSA_MAC_MAX_SIZE];
+    size_t actual_mac_length;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(mac_external, mac);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_mac_compute_internal(key, alg,
+                                      input, input_length,
+                                      actual_mac, sizeof(actual_mac),
+                                      &actual_mac_length, 0);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (mac_length != actual_mac_length) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(mac_external, mac_length, mac);
+    if (mbedtls_ct_memcmp(mac, actual_mac, actual_mac_length) != 0) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+exit:
+    mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(mac_external, mac);
+
+    return status;
+}
+
+/****************************************************************/
+/* Asymmetric cryptography */
+/****************************************************************/
+
+static psa_status_t psa_sign_verify_check_alg(int input_is_message,
+                                              psa_algorithm_t alg)
+{
+    if (input_is_message) {
+        if (!PSA_ALG_IS_SIGN_MESSAGE(alg)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+
+        if (PSA_ALG_IS_SIGN_HASH(alg)) {
+            if (!PSA_ALG_IS_HASH(PSA_ALG_SIGN_GET_HASH(alg))) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+        }
+    } else {
+        if (!PSA_ALG_IS_SIGN_HASH(alg)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_sign_internal(mbedtls_svc_key_id_t key,
+                                      int input_is_message,
+                                      psa_algorithm_t alg,
+                                      const uint8_t *input,
+                                      size_t input_length,
+                                      uint8_t *signature,
+                                      size_t signature_size,
+                                      size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    *signature_length = 0;
+
+    status = psa_sign_verify_check_alg(input_is_message, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Immediately reject a zero-length signature buffer. This guarantees
+     * that signature must be a valid pointer. (On the other hand, the input
+     * buffer can in principle be empty since it doesn't actually have
+     * to be a hash.) */
+    if (signature_size == 0) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot,
+        input_is_message ? PSA_KEY_USAGE_SIGN_MESSAGE :
+        PSA_KEY_USAGE_SIGN_HASH,
+        alg);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    if (input_is_message) {
+        status = psa_driver_wrapper_sign_message(
+            &slot->attr, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_size, signature_length);
+    } else {
+
+        status = psa_driver_wrapper_sign_hash(
+            &slot->attr, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_size, signature_length);
+    }
+
+
+exit:
+    psa_wipe_tag_output_buffer(signature, status, signature_size,
+                               *signature_length);
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+static psa_status_t psa_verify_internal(mbedtls_svc_key_id_t key,
+                                        int input_is_message,
+                                        psa_algorithm_t alg,
+                                        const uint8_t *input,
+                                        size_t input_length,
+                                        const uint8_t *signature,
+                                        size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    status = psa_sign_verify_check_alg(input_is_message, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot,
+        input_is_message ? PSA_KEY_USAGE_VERIFY_MESSAGE :
+        PSA_KEY_USAGE_VERIFY_HASH,
+        alg);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    if (input_is_message) {
+        status = psa_driver_wrapper_verify_message(
+            &slot->attr, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_length);
+    } else {
+        status = psa_driver_wrapper_verify_hash(
+            &slot->attr, slot->key.data, slot->key.bytes,
+            alg, input, input_length,
+            signature, signature_length);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+
+}
+
+psa_status_t psa_sign_message_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *signature,
+    size_t signature_size,
+    size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_ALG_IS_SIGN_HASH(alg)) {
+        size_t hash_length;
+        uint8_t hash[PSA_HASH_MAX_SIZE];
+
+        status = psa_driver_wrapper_hash_compute(
+            PSA_ALG_SIGN_GET_HASH(alg),
+            input, input_length,
+            hash, sizeof(hash), &hash_length);
+
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        return psa_driver_wrapper_sign_hash(
+            attributes, key_buffer, key_buffer_size,
+            alg, hash, hash_length,
+            signature, signature_size, signature_length);
+    }
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t psa_sign_message(mbedtls_svc_key_id_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *input_external,
+                              size_t input_length,
+                              uint8_t *signature_external,
+                              size_t signature_size,
+                              size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+    status = psa_sign_internal(key, 1, alg, input, input_length, signature,
+                               signature_size, signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+    return status;
+}
+
+psa_status_t psa_verify_message_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    const uint8_t *signature,
+    size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_ALG_IS_SIGN_HASH(alg)) {
+        size_t hash_length;
+        uint8_t hash[PSA_HASH_MAX_SIZE];
+
+        status = psa_driver_wrapper_hash_compute(
+            PSA_ALG_SIGN_GET_HASH(alg),
+            input, input_length,
+            hash, sizeof(hash), &hash_length);
+
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        return psa_driver_wrapper_verify_hash(
+            attributes, key_buffer, key_buffer_size,
+            alg, hash, hash_length,
+            signature, signature_length);
+    }
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t psa_verify_message(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input_external,
+                                size_t input_length,
+                                const uint8_t *signature_external,
+                                size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+    status = psa_verify_internal(key, 1, alg, input, input_length, signature,
+                                 signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
+    return status;
+}
+
+psa_status_t psa_sign_hash_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length)
+{
+    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
+            PSA_ALG_IS_RSA_PSS(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+            return mbedtls_psa_rsa_sign_hash(
+                attributes,
+                key_buffer, key_buffer_size,
+                alg, hash, hash_length,
+                signature, signature_size, signature_length);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
+        } else {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
+        if (PSA_ALG_IS_ECDSA(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+            return mbedtls_psa_ecdsa_sign_hash(
+                attributes,
+                key_buffer, key_buffer_size,
+                alg, hash, hash_length,
+                signature, signature_size, signature_length);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+        } else {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t psa_sign_hash(mbedtls_svc_key_id_t key,
+                           psa_algorithm_t alg,
+                           const uint8_t *hash_external,
+                           size_t hash_length,
+                           uint8_t *signature_external,
+                           size_t signature_size,
+                           size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+    status = psa_sign_internal(key, 0, alg, hash, hash_length, signature,
+                               signature_size, signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+
+    return status;
+}
+
+psa_status_t psa_verify_hash_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length)
+{
+    if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
+        if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) ||
+            PSA_ALG_IS_RSA_PSS(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+            return mbedtls_psa_rsa_verify_hash(
+                attributes,
+                key_buffer, key_buffer_size,
+                alg, hash, hash_length,
+                signature, signature_length);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
+        } else {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else if (PSA_KEY_TYPE_IS_ECC(attributes->type)) {
+        if (PSA_ALG_IS_ECDSA(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+            return mbedtls_psa_ecdsa_verify_hash(
+                attributes,
+                key_buffer, key_buffer_size,
+                alg, hash, hash_length,
+                signature, signature_length);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+        } else {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t psa_verify_hash(mbedtls_svc_key_id_t key,
+                             psa_algorithm_t alg,
+                             const uint8_t *hash_external,
+                             size_t hash_length,
+                             const uint8_t *signature_external,
+                             size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+    status = psa_verify_internal(key, 0, alg, hash, hash_length, signature,
+                                 signature_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
+    return status;
+}
+
+psa_status_t psa_asymmetric_encrypt(mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input_external,
+                                    size_t input_length,
+                                    const uint8_t *salt_external,
+                                    size_t salt_length,
+                                    uint8_t *output_external,
+                                    size_t output_size,
+                                    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(salt_external, salt);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    (void) input;
+    (void) input_length;
+    (void) salt;
+    (void) output;
+    (void) output_size;
+
+    *output_length = 0;
+
+    if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    if (!(PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type) ||
+          PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type))) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_asymmetric_encrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg, input, input_length, salt, salt_length,
+        output, output_size, output_length);
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(salt_external, salt);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_asymmetric_decrypt(mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg,
+                                    const uint8_t *input_external,
+                                    size_t input_length,
+                                    const uint8_t *salt_external,
+                                    size_t salt_length,
+                                    uint8_t *output_external,
+                                    size_t output_size,
+                                    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_DECLARE(salt_external, salt);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    (void) input;
+    (void) input_length;
+    (void) salt;
+    (void) output;
+    (void) output_size;
+
+    *output_length = 0;
+
+    if (!PSA_ALG_IS_RSA_OAEP(alg) && salt_length != 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot, PSA_KEY_USAGE_DECRYPT, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_INPUT_ALLOC(salt_external, salt_length, salt);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_asymmetric_decrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg, input, input_length, salt, salt_length,
+        output, output_size, output_length);
+
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_INPUT_FREE(salt_external, salt);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+/****************************************************************/
+/* Asymmetric interruptible cryptography                        */
+/****************************************************************/
+
+static uint32_t psa_interruptible_max_ops = PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED;
+
+void psa_interruptible_set_max_ops(uint32_t max_ops)
+{
+    psa_interruptible_max_ops = max_ops;
+}
+
+uint32_t psa_interruptible_get_max_ops(void)
+{
+    return psa_interruptible_max_ops;
+}
+
+uint32_t psa_sign_hash_get_num_ops(
+    const psa_sign_hash_interruptible_operation_t *operation)
+{
+    return operation->num_ops;
+}
+
+uint32_t psa_verify_hash_get_num_ops(
+    const psa_verify_hash_interruptible_operation_t *operation)
+{
+    return operation->num_ops;
+}
+
+static psa_status_t psa_sign_hash_abort_internal(
+    psa_sign_hash_interruptible_operation_t *operation)
+{
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_driver_wrapper_sign_hash_abort(operation);
+
+    operation->id = 0;
+
+    /* Do not clear either the error_occurred or num_ops elements here as they
+     * only want to be cleared by the application calling abort, not by abort
+     * being called at completion of an operation. */
+
+    return status;
+}
+
+psa_status_t psa_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+    const uint8_t *hash_external, size_t hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+
+    /* Check that start has not been previously called, or operation has not
+     * previously errored. */
+    if (operation->id != 0 || operation->error_occurred) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_sign_verify_check_alg(0, alg);
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_SIGN_HASH,
+                                                   alg);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (!PSA_KEY_TYPE_IS_KEY_PAIR(slot->attr.type)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+
+    /* Ensure ops count gets reset, in case of operation re-use. */
+    operation->num_ops = 0;
+
+    status = psa_driver_wrapper_sign_hash_start(operation, &slot->attr,
+                                                slot->key.data,
+                                                slot->key.bytes, alg,
+                                                hash, hash_length);
+exit:
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        psa_sign_hash_abort_internal(operation);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    if (unlock_status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+    }
+
+    LOCAL_INPUT_FREE(hash_external, hash);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+
+psa_status_t psa_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature_external, size_t signature_size,
+    size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_OUTPUT_DECLARE(signature_external, signature);
+
+    *signature_length = 0;
+
+    /* Check that start has been called first, and that operation has not
+     * previously errored. */
+    if (operation->id == 0 || operation->error_occurred) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* Immediately reject a zero-length signature buffer. This guarantees that
+     * signature must be a valid pointer. */
+    if (signature_size == 0) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    LOCAL_OUTPUT_ALLOC(signature_external, signature_size, signature);
+
+    status = psa_driver_wrapper_sign_hash_complete(operation, signature,
+                                                   signature_size,
+                                                   signature_length);
+
+    /* Update ops count with work done. */
+    operation->num_ops = psa_driver_wrapper_sign_hash_get_num_ops(operation);
+
+exit:
+
+    if (signature != NULL) {
+        psa_wipe_tag_output_buffer(signature, status, signature_size,
+                                   *signature_length);
+    }
+
+    if (status != PSA_OPERATION_INCOMPLETE) {
+        if (status != PSA_SUCCESS) {
+            operation->error_occurred = 1;
+        }
+
+        psa_sign_hash_abort_internal(operation);
+    }
+
+    LOCAL_OUTPUT_FREE(signature_external, signature);
+
+    return status;
+}
+
+psa_status_t psa_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_sign_hash_abort_internal(operation);
+
+    /* We clear the number of ops done here, so that it is not cleared when
+     * the operation fails or succeeds, only on manual abort. */
+    operation->num_ops = 0;
+
+    /* Likewise, failure state. */
+    operation->error_occurred = 0;
+
+    return status;
+}
+
+static psa_status_t psa_verify_hash_abort_internal(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_driver_wrapper_verify_hash_abort(operation);
+
+    operation->id = 0;
+
+    /* Do not clear either the error_occurred or num_ops elements here as they
+     * only want to be cleared by the application calling abort, not by abort
+     * being called at completion of an operation. */
+
+    return status;
+}
+
+psa_status_t psa_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    mbedtls_svc_key_id_t key, psa_algorithm_t alg,
+    const uint8_t *hash_external, size_t hash_length,
+    const uint8_t *signature_external, size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(hash_external, hash);
+    LOCAL_INPUT_DECLARE(signature_external, signature);
+
+    /* Check that start has not been previously called, or operation has not
+     * previously errored. */
+    if (operation->id != 0 || operation->error_occurred) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_sign_verify_check_alg(0, alg);
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_VERIFY_HASH,
+                                                   alg);
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(hash_external, hash_length, hash);
+    LOCAL_INPUT_ALLOC(signature_external, signature_length, signature);
+
+    /* Ensure ops count gets reset, in case of operation re-use. */
+    operation->num_ops = 0;
+
+    status = psa_driver_wrapper_verify_hash_start(operation, &slot->attr,
+                                                  slot->key.data,
+                                                  slot->key.bytes,
+                                                  alg, hash, hash_length,
+                                                  signature, signature_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+
+    if (status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+        psa_verify_hash_abort_internal(operation);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    if (unlock_status != PSA_SUCCESS) {
+        operation->error_occurred = 1;
+    }
+
+    LOCAL_INPUT_FREE(hash_external, hash);
+    LOCAL_INPUT_FREE(signature_external, signature);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* Check that start has been called first, and that operation has not
+     * previously errored. */
+    if (operation->id == 0 || operation->error_occurred) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_verify_hash_complete(operation);
+
+    /* Update ops count with work done. */
+    operation->num_ops = psa_driver_wrapper_verify_hash_get_num_ops(
+        operation);
+
+exit:
+
+    if (status != PSA_OPERATION_INCOMPLETE) {
+        if (status != PSA_SUCCESS) {
+            operation->error_occurred = 1;
+        }
+
+        psa_verify_hash_abort_internal(operation);
+    }
+
+    return status;
+}
+
+psa_status_t psa_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_verify_hash_abort_internal(operation);
+
+    /* We clear the number of ops done here, so that it is not cleared when
+     * the operation fails or succeeds, only on manual abort. */
+    operation->num_ops = 0;
+
+    /* Likewise, failure state. */
+    operation->error_occurred = 0;
+
+    return status;
+}
+
+/****************************************************************/
+/* Asymmetric interruptible cryptography internal               */
+/* implementations                                              */
+/****************************************************************/
+
+void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    /* Internal implementation uses zero to indicate infinite number max ops,
+     * therefore avoid this value, and set to minimum possible. */
+    if (max_ops == 0) {
+        max_ops = 1;
+    }
+
+    mbedtls_ecp_set_max_ops(max_ops);
+#else
+    (void) max_ops;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+uint32_t mbedtls_psa_sign_hash_get_num_ops(
+    const mbedtls_psa_sign_hash_interruptible_operation_t *operation)
+{
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    return operation->num_ops;
+#else
+    (void) operation;
+    return 0;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+uint32_t mbedtls_psa_verify_hash_get_num_ops(
+    const mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+    #if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    return operation->num_ops;
+#else
+    (void) operation;
+    return 0;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_sign_hash_start(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t required_hash_length;
+
+    if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (!PSA_ALG_IS_ECDSA(alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+
+    /* Ensure num_ops is zero'ed in case of context re-use. */
+    operation->num_ops = 0;
+
+    status = mbedtls_psa_ecp_load_representation(attributes->type,
+                                                 attributes->bits,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &operation->ctx);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    operation->coordinate_bytes = PSA_BITS_TO_BYTES(
+        operation->ctx->grp.nbits);
+
+    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
+    operation->md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
+    operation->alg = alg;
+
+    /* We only need to store the same length of hash as the private key size
+     * here, it would be truncated by the internal implementation anyway. */
+    required_hash_length = (hash_length < operation->coordinate_bytes ?
+                            hash_length : operation->coordinate_bytes);
+
+    if (required_hash_length > sizeof(operation->hash)) {
+        /* Shouldn't happen, but better safe than sorry. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    memcpy(operation->hash, hash, required_hash_length);
+    operation->hash_length = required_hash_length;
+
+    return PSA_SUCCESS;
+
+#else
+    (void) operation;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) status;
+    (void) required_hash_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_sign_hash_complete(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length)
+{
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi r;
+    mbedtls_mpi s;
+
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
+
+    /* Ensure max_ops is set to the current value (or default). */
+    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
+
+    if (signature_size < 2 * operation->coordinate_bytes) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(operation->alg)) {
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+        status = mbedtls_to_psa_error(
+            mbedtls_ecdsa_sign_det_restartable(&operation->ctx->grp,
+                                               &r,
+                                               &s,
+                                               &operation->ctx->d,
+                                               operation->hash,
+                                               operation->hash_length,
+                                               operation->md_alg,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE,
+                                               &operation->restart_ctx));
+#else /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+    } else {
+        status = mbedtls_to_psa_error(
+            mbedtls_ecdsa_sign_restartable(&operation->ctx->grp,
+                                           &r,
+                                           &s,
+                                           &operation->ctx->d,
+                                           operation->hash,
+                                           operation->hash_length,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE,
+                                           &operation->restart_ctx));
+    }
+
+    /* Hide the fact that the restart context only holds a delta of number of
+     * ops done during the last operation, not an absolute value. */
+    operation->num_ops += operation->restart_ctx.ecp.ops_done;
+
+    if (status == PSA_SUCCESS) {
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&r,
+                                     signature,
+                                     operation->coordinate_bytes)
+            );
+
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        status =  mbedtls_to_psa_error(
+            mbedtls_mpi_write_binary(&s,
+                                     signature +
+                                     operation->coordinate_bytes,
+                                     operation->coordinate_bytes)
+            );
+
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        *signature_length = operation->coordinate_bytes * 2;
+
+        status = PSA_SUCCESS;
+    }
+
+exit:
+
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
+    return status;
+
+ #else
+
+    (void) operation;
+    (void) signature;
+    (void) signature_size;
+    (void) signature_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_sign_hash_abort(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    if (operation->ctx) {
+        mbedtls_ecdsa_free(operation->ctx);
+        mbedtls_free(operation->ctx);
+        operation->ctx = NULL;
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    operation->num_ops = 0;
+
+    return PSA_SUCCESS;
+
+#else
+
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_verify_hash_start(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t coordinate_bytes = 0;
+    size_t required_hash_length = 0;
+
+    if (!PSA_KEY_TYPE_IS_ECC(attributes->type)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (!PSA_ALG_IS_ECDSA(alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    mbedtls_ecdsa_restart_init(&operation->restart_ctx);
+    mbedtls_mpi_init(&operation->r);
+    mbedtls_mpi_init(&operation->s);
+
+    /* Ensure num_ops is zero'ed in case of context re-use. */
+    operation->num_ops = 0;
+
+    status = mbedtls_psa_ecp_load_representation(attributes->type,
+                                                 attributes->bits,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &operation->ctx);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    coordinate_bytes = PSA_BITS_TO_BYTES(operation->ctx->grp.nbits);
+
+    if (signature_length != 2 * coordinate_bytes) {
+        return PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_mpi_read_binary(&operation->r,
+                                signature,
+                                coordinate_bytes));
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_mpi_read_binary(&operation->s,
+                                signature +
+                                coordinate_bytes,
+                                coordinate_bytes));
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = mbedtls_psa_ecp_load_public_part(operation->ctx);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* We only need to store the same length of hash as the private key size
+     * here, it would be truncated by the internal implementation anyway. */
+    required_hash_length = (hash_length < coordinate_bytes ? hash_length :
+                            coordinate_bytes);
+
+    if (required_hash_length > sizeof(operation->hash)) {
+        /* Shouldn't happen, but better safe than sorry. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    memcpy(operation->hash, hash, required_hash_length);
+    operation->hash_length = required_hash_length;
+
+    return PSA_SUCCESS;
+#else
+    (void) operation;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) alg;
+    (void) hash;
+    (void) hash_length;
+    (void) signature;
+    (void) signature_length;
+    (void) status;
+    (void) coordinate_bytes;
+    (void) required_hash_length;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_verify_hash_complete(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* Ensure max_ops is set to the current value (or default). */
+    mbedtls_psa_interruptible_set_max_ops(psa_interruptible_get_max_ops());
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdsa_verify_restartable(&operation->ctx->grp,
+                                         operation->hash,
+                                         operation->hash_length,
+                                         &operation->ctx->Q,
+                                         &operation->r,
+                                         &operation->s,
+                                         &operation->restart_ctx));
+
+    /* Hide the fact that the restart context only holds a delta of number of
+     * ops done during the last operation, not an absolute value. */
+    operation->num_ops += operation->restart_ctx.ecp.ops_done;
+
+    return status;
+#else
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+psa_status_t mbedtls_psa_verify_hash_abort(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation)
+{
+
+#if (defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)) && \
+    defined(MBEDTLS_ECP_RESTARTABLE)
+
+    if (operation->ctx) {
+        mbedtls_ecdsa_free(operation->ctx);
+        mbedtls_free(operation->ctx);
+        operation->ctx = NULL;
+    }
+
+    mbedtls_ecdsa_restart_free(&operation->restart_ctx);
+
+    operation->num_ops = 0;
+
+    mbedtls_mpi_free(&operation->r);
+    mbedtls_mpi_free(&operation->s);
+
+    return PSA_SUCCESS;
+
+#else
+    (void) operation;
+
+    return PSA_ERROR_NOT_SUPPORTED;
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) &&
+        * defined( MBEDTLS_ECP_RESTARTABLE ) */
+}
+
+static psa_status_t psa_generate_random_internal(uint8_t *output,
+                                                 size_t output_size)
+{
+    GUARD_MODULE_INITIALIZED;
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+    psa_status_t status;
+    size_t output_length = 0;
+    status = mbedtls_psa_external_get_random(&global_data.rng,
+                                             output, output_size,
+                                             &output_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    /* Breaking up a request into smaller chunks is currently not supported
+     * for the external RNG interface. */
+    if (output_length != output_size) {
+        return PSA_ERROR_INSUFFICIENT_ENTROPY;
+    }
+    return PSA_SUCCESS;
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+    while (output_size > 0) {
+        int ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+        size_t request_size =
+            (output_size > MBEDTLS_PSA_RANDOM_MAX_REQUEST ?
+             MBEDTLS_PSA_RANDOM_MAX_REQUEST :
+             output_size);
+#if defined(MBEDTLS_CTR_DRBG_C)
+        ret = mbedtls_ctr_drbg_random(&global_data.rng.drbg, output, request_size);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+        ret = mbedtls_hmac_drbg_random(&global_data.rng.drbg, output, request_size);
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+        if (ret != 0) {
+            return mbedtls_to_psa_error(ret);
+        }
+        output_size -= request_size;
+        output += request_size;
+    }
+    return PSA_SUCCESS;
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+
+/****************************************************************/
+/* Symmetric cryptography */
+/****************************************************************/
+
+static psa_status_t psa_cipher_setup(psa_cipher_operation_t *operation,
+                                     mbedtls_svc_key_id_t key,
+                                     psa_algorithm_t alg,
+                                     mbedtls_operation_t cipher_operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    psa_key_usage_t usage = (cipher_operation == MBEDTLS_ENCRYPT ?
+                             PSA_KEY_USAGE_ENCRYPT :
+                             PSA_KEY_USAGE_DECRYPT);
+
+    /* A context must be freshly initialized before it can be set up. */
+    if (operation->id != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (!PSA_ALG_IS_CIPHER(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot, usage, alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* Initialize the operation struct members, except for id. The id member
+     * is used to indicate to psa_cipher_abort that there are resources to free,
+     * so we only set it (in the driver wrapper) after resources have been
+     * allocated/initialized. */
+    operation->iv_set = 0;
+    if (alg == PSA_ALG_ECB_NO_PADDING) {
+        operation->iv_required = 0;
+    } else {
+        operation->iv_required = 1;
+    }
+    operation->default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
+
+    /* Try doing the operation through a driver before using software fallback. */
+    if (cipher_operation == MBEDTLS_ENCRYPT) {
+        status = psa_driver_wrapper_cipher_encrypt_setup(operation,
+                                                         &slot->attr,
+                                                         slot->key.data,
+                                                         slot->key.bytes,
+                                                         alg);
+    } else {
+        status = psa_driver_wrapper_cipher_decrypt_setup(operation,
+                                                         &slot->attr,
+                                                         slot->key.data,
+                                                         slot->key.bytes,
+                                                         alg);
+    }
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_cipher_abort(operation);
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation,
+                                      mbedtls_svc_key_id_t key,
+                                      psa_algorithm_t alg)
+{
+    return psa_cipher_setup(operation, key, alg, MBEDTLS_ENCRYPT);
+}
+
+psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation,
+                                      mbedtls_svc_key_id_t key,
+                                      psa_algorithm_t alg)
+{
+    return psa_cipher_setup(operation, key, alg, MBEDTLS_DECRYPT);
+}
+
+psa_status_t psa_cipher_generate_iv(psa_cipher_operation_t *operation,
+                                    uint8_t *iv_external,
+                                    size_t iv_size,
+                                    size_t *iv_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t default_iv_length = 0;
+
+    LOCAL_OUTPUT_DECLARE(iv_external, iv);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->iv_set || !operation->iv_required) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    default_iv_length = operation->default_iv_length;
+    if (iv_size < default_iv_length) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {
+        status = PSA_ERROR_GENERIC_ERROR;
+        goto exit;
+    }
+
+    LOCAL_OUTPUT_ALLOC(iv_external, default_iv_length, iv);
+
+    status = psa_generate_random_internal(iv, default_iv_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_cipher_set_iv(operation,
+                                              iv, default_iv_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        *iv_length = default_iv_length;
+        operation->iv_set = 1;
+    } else {
+        *iv_length = 0;
+        psa_cipher_abort(operation);
+        if (iv != NULL) {
+            mbedtls_platform_zeroize(iv, default_iv_length);
+        }
+    }
+
+    LOCAL_OUTPUT_FREE(iv_external, iv);
+    return status;
+}
+
+psa_status_t psa_cipher_set_iv(psa_cipher_operation_t *operation,
+                               const uint8_t *iv_external,
+                               size_t iv_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_INPUT_DECLARE(iv_external, iv);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->iv_set || !operation->iv_required) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (iv_length > PSA_CIPHER_IV_MAX_SIZE) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(iv_external, iv_length, iv);
+
+    status = psa_driver_wrapper_cipher_set_iv(operation,
+                                              iv,
+                                              iv_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->iv_set = 1;
+    } else {
+        psa_cipher_abort(operation);
+    }
+
+    LOCAL_INPUT_FREE(iv_external, iv);
+
+    return status;
+}
+
+psa_status_t psa_cipher_update(psa_cipher_operation_t *operation,
+                               const uint8_t *input_external,
+                               size_t input_length,
+                               uint8_t *output_external,
+                               size_t output_size,
+                               size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->iv_required && !operation->iv_set) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_cipher_update(operation,
+                                              input,
+                                              input_length,
+                                              output,
+                                              output_size,
+                                              output_length);
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_cipher_abort(operation);
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
+}
+
+psa_status_t psa_cipher_finish(psa_cipher_operation_t *operation,
+                               uint8_t *output_external,
+                               size_t output_size,
+                               size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->iv_required && !operation->iv_set) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_cipher_finish(operation,
+                                              output,
+                                              output_size,
+                                              output_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        status = psa_cipher_abort(operation);
+    } else {
+        *output_length = 0;
+        (void) psa_cipher_abort(operation);
+    }
+
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
+}
+
+psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation)
+{
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    psa_driver_wrapper_cipher_abort(operation);
+
+    operation->id = 0;
+    operation->iv_set = 0;
+    operation->iv_required = 0;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_cipher_encrypt(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input_external,
+                                size_t input_length,
+                                uint8_t *output_external,
+                                size_t output_size,
+                                size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    uint8_t local_iv[PSA_CIPHER_IV_MAX_SIZE];
+    size_t default_iv_length = 0;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    if (!PSA_ALG_IS_CIPHER(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_ENCRYPT,
+                                                   alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    default_iv_length = PSA_CIPHER_IV_LENGTH(slot->attr.type, alg);
+    if (default_iv_length > PSA_CIPHER_IV_MAX_SIZE) {
+        status = PSA_ERROR_GENERIC_ERROR;
+        goto exit;
+    }
+
+    if (default_iv_length > 0) {
+        if (output_size < default_iv_length) {
+            status = PSA_ERROR_BUFFER_TOO_SMALL;
+            goto exit;
+        }
+
+        status = psa_generate_random_internal(local_iv, default_iv_length);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_cipher_encrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg, local_iv, default_iv_length, input, input_length,
+        psa_crypto_buffer_offset(output, default_iv_length),
+        output_size - default_iv_length, output_length);
+
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+    if (status == PSA_SUCCESS) {
+        status = unlock_status;
+    }
+
+    if (status == PSA_SUCCESS) {
+        if (default_iv_length > 0) {
+            memcpy(output, local_iv, default_iv_length);
+        }
+        *output_length += default_iv_length;
+    } else {
+        *output_length = 0;
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
+}
+
+psa_status_t psa_cipher_decrypt(mbedtls_svc_key_id_t key,
+                                psa_algorithm_t alg,
+                                const uint8_t *input_external,
+                                size_t input_length,
+                                uint8_t *output_external,
+                                size_t output_size,
+                                size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    if (!PSA_ALG_IS_CIPHER(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot,
+                                                   PSA_KEY_USAGE_DECRYPT,
+                                                   alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (input_length < PSA_CIPHER_IV_LENGTH(slot->attr.type, alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_cipher_decrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg, input, input_length,
+        output, output_size, output_length);
+
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+    if (status == PSA_SUCCESS) {
+        status = unlock_status;
+    }
+
+    if (status != PSA_SUCCESS) {
+        *output_length = 0;
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
+}
+
+
+/****************************************************************/
+/* AEAD */
+/****************************************************************/
+
+/* Helper function to get the base algorithm from its variants. */
+static psa_algorithm_t psa_aead_get_base_algorithm(psa_algorithm_t alg)
+{
+    return PSA_ALG_AEAD_WITH_DEFAULT_LENGTH_TAG(alg);
+}
+
+/* Helper function to perform common nonce length checks. */
+static psa_status_t psa_aead_check_nonce_length(psa_algorithm_t alg,
+                                                size_t nonce_length)
+{
+    psa_algorithm_t base_alg = psa_aead_get_base_algorithm(alg);
+
+    switch (base_alg) {
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Not checking max nonce size here as GCM spec allows almost
+             * arbitrarily large nonces. Please note that we do not generally
+             * recommend the usage of nonces of greater length than
+             * PSA_AEAD_NONCE_MAX_SIZE, as large nonces are hashed to a shorter
+             * size, which can then lead to collisions if you encrypt a very
+             * large number of messages.*/
+            if (nonce_length != 0) {
+                return PSA_SUCCESS;
+            }
+            break;
+#endif /* PSA_WANT_ALG_GCM */
+#if defined(PSA_WANT_ALG_CCM)
+        case PSA_ALG_CCM:
+            if (nonce_length >= 7 && nonce_length <= 13) {
+                return PSA_SUCCESS;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CCM */
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            if (nonce_length == 12) {
+                return PSA_SUCCESS;
+            } else if (nonce_length == 8) {
+                return PSA_ERROR_NOT_SUPPORTED;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            (void) nonce_length;
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_ERROR_INVALID_ARGUMENT;
+}
+
+static psa_status_t psa_aead_check_algorithm(psa_algorithm_t alg)
+{
+    if (!PSA_ALG_IS_AEAD(alg) || PSA_ALG_IS_WILDCARD(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_aead_encrypt(mbedtls_svc_key_id_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *nonce_external,
+                              size_t nonce_length,
+                              const uint8_t *additional_data_external,
+                              size_t additional_data_length,
+                              const uint8_t *plaintext_external,
+                              size_t plaintext_length,
+                              uint8_t *ciphertext_external,
+                              size_t ciphertext_size,
+                              size_t *ciphertext_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
+    LOCAL_INPUT_DECLARE(plaintext_external, plaintext);
+    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
+
+    *ciphertext_length = 0;
+
+    status = psa_aead_check_algorithm(alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot, PSA_KEY_USAGE_ENCRYPT, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
+    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length, additional_data);
+    LOCAL_INPUT_ALLOC(plaintext_external, plaintext_length, plaintext);
+    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
+
+    status = psa_aead_check_nonce_length(alg, nonce_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_encrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg,
+        nonce, nonce_length,
+        additional_data, additional_data_length,
+        plaintext, plaintext_length,
+        ciphertext, ciphertext_size, ciphertext_length);
+
+    if (status != PSA_SUCCESS && ciphertext_size != 0) {
+        memset(ciphertext, 0, ciphertext_size);
+    }
+
+exit:
+    LOCAL_INPUT_FREE(nonce_external, nonce);
+    LOCAL_INPUT_FREE(additional_data_external, additional_data);
+    LOCAL_INPUT_FREE(plaintext_external, plaintext);
+    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
+
+    psa_unregister_read_under_mutex(slot);
+
+    return status;
+}
+
+psa_status_t psa_aead_decrypt(mbedtls_svc_key_id_t key,
+                              psa_algorithm_t alg,
+                              const uint8_t *nonce_external,
+                              size_t nonce_length,
+                              const uint8_t *additional_data_external,
+                              size_t additional_data_length,
+                              const uint8_t *ciphertext_external,
+                              size_t ciphertext_length,
+                              uint8_t *plaintext_external,
+                              size_t plaintext_size,
+                              size_t *plaintext_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_DECLARE(additional_data_external, additional_data);
+    LOCAL_INPUT_DECLARE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
+
+    *plaintext_length = 0;
+
+    status = psa_aead_check_algorithm(alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(
+        key, &slot, PSA_KEY_USAGE_DECRYPT, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
+    LOCAL_INPUT_ALLOC(additional_data_external, additional_data_length,
+                      additional_data);
+    LOCAL_INPUT_ALLOC(ciphertext_external, ciphertext_length, ciphertext);
+    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
+
+    status = psa_aead_check_nonce_length(alg, nonce_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_decrypt(
+        &slot->attr, slot->key.data, slot->key.bytes,
+        alg,
+        nonce, nonce_length,
+        additional_data, additional_data_length,
+        ciphertext, ciphertext_length,
+        plaintext, plaintext_size, plaintext_length);
+
+    if (status != PSA_SUCCESS && plaintext_size != 0) {
+        memset(plaintext, 0, plaintext_size);
+    }
+
+exit:
+    LOCAL_INPUT_FREE(nonce_external, nonce);
+    LOCAL_INPUT_FREE(additional_data_external, additional_data);
+    LOCAL_INPUT_FREE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
+
+    psa_unregister_read_under_mutex(slot);
+
+    return status;
+}
+
+static psa_status_t psa_validate_tag_length(psa_algorithm_t alg)
+{
+    const uint8_t tag_len = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
+
+    switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
+#if defined(PSA_WANT_ALG_CCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
+            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.*/
+            if (tag_len < 4 || tag_len > 16 || tag_len % 2) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CCM */
+
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
+            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16. */
+            if (tag_len != 4 && tag_len != 8 && (tag_len < 12 || tag_len > 16)) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif /* PSA_WANT_ALG_GCM */
+
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
+            /* We only support the default tag length. */
+            if (tag_len != 16) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+
+        default:
+            (void) tag_len;
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+    return PSA_SUCCESS;
+}
+
+/* Set the key for a multipart authenticated operation. */
+static psa_status_t psa_aead_setup(psa_aead_operation_t *operation,
+                                   int is_encrypt,
+                                   mbedtls_svc_key_id_t key,
+                                   psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    psa_key_usage_t key_usage = 0;
+
+    status = psa_aead_check_algorithm(alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (operation->id != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->nonce_set || operation->lengths_set ||
+        operation->ad_started || operation->body_started) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (is_encrypt) {
+        key_usage = PSA_KEY_USAGE_ENCRYPT;
+    } else {
+        key_usage = PSA_KEY_USAGE_DECRYPT;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(key, &slot, key_usage,
+                                                   alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if ((status = psa_validate_tag_length(alg)) != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (is_encrypt) {
+        status = psa_driver_wrapper_aead_encrypt_setup(operation,
+                                                       &slot->attr,
+                                                       slot->key.data,
+                                                       slot->key.bytes,
+                                                       alg);
+    } else {
+        status = psa_driver_wrapper_aead_decrypt_setup(operation,
+                                                       &slot->attr,
+                                                       slot->key.data,
+                                                       slot->key.bytes,
+                                                       alg);
+    }
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    operation->key_type = psa_get_key_type(&slot->attr);
+
+exit:
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    if (status == PSA_SUCCESS) {
+        status = unlock_status;
+        operation->alg = psa_aead_get_base_algorithm(alg);
+        operation->is_encrypt = is_encrypt;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    return status;
+}
+
+/* Set the key for a multipart authenticated encryption operation. */
+psa_status_t psa_aead_encrypt_setup(psa_aead_operation_t *operation,
+                                    mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg)
+{
+    return psa_aead_setup(operation, 1, key, alg);
+}
+
+/* Set the key for a multipart authenticated decryption operation. */
+psa_status_t psa_aead_decrypt_setup(psa_aead_operation_t *operation,
+                                    mbedtls_svc_key_id_t key,
+                                    psa_algorithm_t alg)
+{
+    return psa_aead_setup(operation, 0, key, alg);
+}
+
+static psa_status_t psa_aead_set_nonce_internal(psa_aead_operation_t *operation,
+                                                const uint8_t *nonce,
+                                                size_t nonce_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->nonce_set) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_aead_check_nonce_length(operation->alg, nonce_length);
+    if (status != PSA_SUCCESS) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_set_nonce(operation, nonce,
+                                               nonce_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->nonce_set = 1;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    return status;
+}
+
+/* Generate a random nonce / IV for multipart AEAD operation */
+psa_status_t psa_aead_generate_nonce(psa_aead_operation_t *operation,
+                                     uint8_t *nonce_external,
+                                     size_t nonce_size,
+                                     size_t *nonce_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t local_nonce[PSA_AEAD_NONCE_MAX_SIZE];
+    size_t required_nonce_size = 0;
+
+    LOCAL_OUTPUT_DECLARE(nonce_external, nonce);
+    LOCAL_OUTPUT_ALLOC(nonce_external, nonce_size, nonce);
+
+    *nonce_length = 0;
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->nonce_set || !operation->is_encrypt) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* For CCM, this size may not be correct according to the PSA
+     * specification. The PSA Crypto 1.0.1 specification states:
+     *
+     * CCM encodes the plaintext length pLen in L octets, with L the smallest
+     * integer >= 2 where pLen < 2^(8L). The nonce length is then 15 - L bytes.
+     *
+     * However this restriction that L has to be the smallest integer is not
+     * applied in practice, and it is not implementable here since the
+     * plaintext length may or may not be known at this time. */
+    required_nonce_size = PSA_AEAD_NONCE_LENGTH(operation->key_type,
+                                                operation->alg);
+    if (nonce_size < required_nonce_size) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    status = psa_generate_random_internal(local_nonce, required_nonce_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_aead_set_nonce_internal(operation, local_nonce,
+                                         required_nonce_size);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        memcpy(nonce, local_nonce, required_nonce_size);
+        *nonce_length = required_nonce_size;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    LOCAL_OUTPUT_FREE(nonce_external, nonce);
+
+    return status;
+}
+
+/* Set the nonce for a multipart authenticated encryption or decryption
+   operation.*/
+psa_status_t psa_aead_set_nonce(psa_aead_operation_t *operation,
+                                const uint8_t *nonce_external,
+                                size_t nonce_length)
+{
+    psa_status_t status;
+
+    LOCAL_INPUT_DECLARE(nonce_external, nonce);
+    LOCAL_INPUT_ALLOC(nonce_external, nonce_length, nonce);
+
+    status = psa_aead_set_nonce_internal(operation, nonce, nonce_length);
+
+/* Exit label is only needed for buffer copying, prevent unused warnings. */
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+
+    LOCAL_INPUT_FREE(nonce_external, nonce);
+
+    return status;
+}
+
+/* Declare the lengths of the message and additional data for multipart AEAD. */
+psa_status_t psa_aead_set_lengths(psa_aead_operation_t *operation,
+                                  size_t ad_length,
+                                  size_t plaintext_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->lengths_set || operation->ad_started ||
+        operation->body_started) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_GCM)
+        case PSA_ALG_GCM:
+            /* Lengths can only be too large for GCM if size_t is bigger than 32
+             * bits. Without the guard this code will generate warnings on 32bit
+             * builds. */
+#if SIZE_MAX > UINT32_MAX
+            if (((uint64_t) ad_length) >> 61 != 0 ||
+                ((uint64_t) plaintext_length) > 0xFFFFFFFE0ull) {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
+#endif
+            break;
+#endif /* PSA_WANT_ALG_GCM */
+#if defined(PSA_WANT_ALG_CCM)
+        case PSA_ALG_CCM:
+            if (ad_length > 0xFF00) {
+                status = PSA_ERROR_INVALID_ARGUMENT;
+                goto exit;
+            }
+            break;
+#endif /* PSA_WANT_ALG_CCM */
+#if defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            /* No length restrictions for ChaChaPoly. */
+            break;
+#endif /* PSA_WANT_ALG_CHACHA20_POLY1305 */
+        default:
+            break;
+    }
+
+    status = psa_driver_wrapper_aead_set_lengths(operation, ad_length,
+                                                 plaintext_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->ad_remaining = ad_length;
+        operation->body_remaining = plaintext_length;
+        operation->lengths_set = 1;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    return status;
+}
+
+/* Pass additional data to an active multipart AEAD operation. */
+psa_status_t psa_aead_update_ad(psa_aead_operation_t *operation,
+                                const uint8_t *input_external,
+                                size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (!operation->nonce_set || operation->body_started) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    /* No input to add (zero length), nothing to do. */
+    if (input_length == 0) {
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+
+    if (operation->lengths_set) {
+        if (operation->ad_remaining < input_length) {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        operation->ad_remaining -= input_length;
+    }
+#if defined(PSA_WANT_ALG_CCM)
+    else if (operation->alg == PSA_ALG_CCM) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+#endif /* PSA_WANT_ALG_CCM */
+
+    status = psa_driver_wrapper_aead_update_ad(operation, input,
+                                               input_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->ad_started = 1;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+
+    return status;
+}
+
+/* Encrypt or decrypt a message fragment in an active multipart AEAD
+   operation.*/
+psa_status_t psa_aead_update(psa_aead_operation_t *operation,
+                             const uint8_t *input_external,
+                             size_t input_length,
+                             uint8_t *output_external,
+                             size_t output_size,
+                             size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+
+    LOCAL_INPUT_DECLARE(input_external, input);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    *output_length = 0;
+
+    if (operation->id == 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (!operation->nonce_set) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (operation->lengths_set) {
+        /* Additional data length was supplied, but not all the additional
+           data was supplied.*/
+        if (operation->ad_remaining != 0) {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        /* Too much data provided. */
+        if (operation->body_remaining < input_length) {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+
+        operation->body_remaining -= input_length;
+    }
+#if defined(PSA_WANT_ALG_CCM)
+    else if (operation->alg == PSA_ALG_CCM) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+#endif /* PSA_WANT_ALG_CCM */
+
+    status = psa_driver_wrapper_aead_update(operation, input, input_length,
+                                            output, output_size,
+                                            output_length);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        operation->body_started = 1;
+    } else {
+        psa_aead_abort(operation);
+    }
+
+    LOCAL_INPUT_FREE(input_external, input);
+    LOCAL_OUTPUT_FREE(output_external, output);
+
+    return status;
+}
+
+static psa_status_t psa_aead_final_checks(const psa_aead_operation_t *operation)
+{
+    if (operation->id == 0 || !operation->nonce_set) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (operation->lengths_set && (operation->ad_remaining != 0 ||
+                                   operation->body_remaining != 0)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return PSA_SUCCESS;
+}
+
+/* Finish encrypting a message in a multipart AEAD operation. */
+psa_status_t psa_aead_finish(psa_aead_operation_t *operation,
+                             uint8_t *ciphertext_external,
+                             size_t ciphertext_size,
+                             size_t *ciphertext_length,
+                             uint8_t *tag_external,
+                             size_t tag_size,
+                             size_t *tag_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_OUTPUT_DECLARE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_DECLARE(tag_external, tag);
+
+    LOCAL_OUTPUT_ALLOC(ciphertext_external, ciphertext_size, ciphertext);
+    LOCAL_OUTPUT_ALLOC(tag_external, tag_size, tag);
+
+    *ciphertext_length = 0;
+    *tag_length = tag_size;
+
+    status = psa_aead_final_checks(operation);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (!operation->is_encrypt) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_finish(operation, ciphertext,
+                                            ciphertext_size,
+                                            ciphertext_length,
+                                            tag, tag_size, tag_length);
+
+exit:
+
+
+    /* In case the operation fails and the user fails to check for failure or
+     * the zero tag size, make sure the tag is set to something implausible.
+     * Even if the operation succeeds, make sure we clear the rest of the
+     * buffer to prevent potential leakage of anything previously placed in
+     * the same buffer.*/
+    psa_wipe_tag_output_buffer(tag, status, tag_size, *tag_length);
+
+    psa_aead_abort(operation);
+
+    LOCAL_OUTPUT_FREE(ciphertext_external, ciphertext);
+    LOCAL_OUTPUT_FREE(tag_external, tag);
+
+    return status;
+}
+
+/* Finish authenticating and decrypting a message in a multipart AEAD
+   operation.*/
+psa_status_t psa_aead_verify(psa_aead_operation_t *operation,
+                             uint8_t *plaintext_external,
+                             size_t plaintext_size,
+                             size_t *plaintext_length,
+                             const uint8_t *tag_external,
+                             size_t tag_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    LOCAL_OUTPUT_DECLARE(plaintext_external, plaintext);
+    LOCAL_INPUT_DECLARE(tag_external, tag);
+
+    LOCAL_OUTPUT_ALLOC(plaintext_external, plaintext_size, plaintext);
+    LOCAL_INPUT_ALLOC(tag_external, tag_length, tag);
+
+    *plaintext_length = 0;
+
+    status = psa_aead_final_checks(operation);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (operation->is_encrypt) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_aead_verify(operation, plaintext,
+                                            plaintext_size,
+                                            plaintext_length,
+                                            tag, tag_length);
+
+exit:
+    psa_aead_abort(operation);
+
+    LOCAL_OUTPUT_FREE(plaintext_external, plaintext);
+    LOCAL_INPUT_FREE(tag_external, tag);
+
+    return status;
+}
+
+/* Abort an AEAD operation. */
+psa_status_t psa_aead_abort(psa_aead_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->id == 0) {
+        /* The object has (apparently) been initialized but it is not (yet)
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    }
+
+    status = psa_driver_wrapper_aead_abort(operation);
+
+    memset(operation, 0, sizeof(*operation));
+
+    return status;
+}
+
+/****************************************************************/
+/* Generators */
+/****************************************************************/
+
+#if defined(BUILTIN_ALG_ANY_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) || \
+    defined(PSA_HAVE_SOFT_PBKDF2)
+#define AT_LEAST_ONE_BUILTIN_KDF
+#endif /* At least one builtin KDF */
+
+#if defined(BUILTIN_ALG_ANY_HKDF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_key_derivation_start_hmac(
+    psa_mac_operation_t *operation,
+    psa_algorithm_t hash_alg,
+    const uint8_t *hmac_key,
+    size_t hmac_key_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(hmac_key_length));
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_HASH);
+
+    operation->is_sign = 1;
+    operation->mac_size = PSA_HASH_LENGTH(hash_alg);
+
+    status = psa_driver_wrapper_mac_sign_setup(operation,
+                                               &attributes,
+                                               hmac_key, hmac_key_length,
+                                               PSA_ALG_HMAC(hash_alg));
+
+    psa_reset_key_attributes(&attributes);
+    return status;
+}
+#endif /* KDF algorithms reliant on HMAC */
+
+#define HKDF_STATE_INIT 0 /* no input yet */
+#define HKDF_STATE_STARTED 1 /* got salt */
+#define HKDF_STATE_KEYED 2 /* got key */
+#define HKDF_STATE_OUTPUT 3 /* output started */
+
+static psa_algorithm_t psa_key_derivation_get_kdf_alg(
+    const psa_key_derivation_operation_t *operation)
+{
+    if (PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {
+        return PSA_ALG_KEY_AGREEMENT_GET_KDF(operation->alg);
+    } else {
+        return operation->alg;
+    }
+}
+
+psa_status_t psa_key_derivation_abort(psa_key_derivation_operation_t *operation)
+{
+    psa_status_t status = PSA_SUCCESS;
+    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
+    if (kdf_alg == 0) {
+        /* The object has (apparently) been initialized but it is not
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+    } else
+#if defined(BUILTIN_ALG_ANY_HKDF)
+    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
+        mbedtls_free(operation->ctx.hkdf.info);
+        status = psa_mac_abort(&operation->ctx.hkdf.hmac);
+    } else
+#endif /* BUILTIN_ALG_ANY_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
+        /* TLS-1.2 PSK-to-MS KDF uses the same core as TLS-1.2 PRF */
+        PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
+        if (operation->ctx.tls12_prf.secret != NULL) {
+            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.secret,
+                                     operation->ctx.tls12_prf.secret_length);
+        }
+
+        if (operation->ctx.tls12_prf.seed != NULL) {
+            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.seed,
+                                     operation->ctx.tls12_prf.seed_length);
+        }
+
+        if (operation->ctx.tls12_prf.label != NULL) {
+            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.label,
+                                     operation->ctx.tls12_prf.label_length);
+        }
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+        if (operation->ctx.tls12_prf.other_secret != NULL) {
+            mbedtls_zeroize_and_free(operation->ctx.tls12_prf.other_secret,
+                                     operation->ctx.tls12_prf.other_secret_length);
+        }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+        status = PSA_SUCCESS;
+
+        /* We leave the fields Ai and output_block to be erased safely by the
+         * mbedtls_platform_zeroize() in the end of this function. */
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS) */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        mbedtls_platform_zeroize(operation->ctx.tls12_ecjpake_to_pms.data,
+                                 sizeof(operation->ctx.tls12_ecjpake_to_pms.data));
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS) */
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
+        if (operation->ctx.pbkdf2.salt != NULL) {
+            mbedtls_zeroize_and_free(operation->ctx.pbkdf2.salt,
+                                     operation->ctx.pbkdf2.salt_length);
+        }
+
+        status = PSA_SUCCESS;
+    } else
+#endif /* defined(PSA_HAVE_SOFT_PBKDF2) */
+    {
+        status = PSA_ERROR_BAD_STATE;
+    }
+    mbedtls_platform_zeroize(operation, sizeof(*operation));
+    return status;
+}
+
+psa_status_t psa_key_derivation_get_capacity(const psa_key_derivation_operation_t *operation,
+                                             size_t *capacity)
+{
+    if (operation->alg == 0) {
+        /* This is a blank key derivation operation. */
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    *capacity = operation->capacity;
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_key_derivation_set_capacity(psa_key_derivation_operation_t *operation,
+                                             size_t capacity)
+{
+    if (operation->alg == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+    if (capacity > operation->capacity) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    operation->capacity = capacity;
+    return PSA_SUCCESS;
+}
+
+#if defined(BUILTIN_ALG_ANY_HKDF)
+/* Read some bytes from an HKDF-based operation. */
+static psa_status_t psa_key_derivation_hkdf_read(psa_hkdf_key_derivation_t *hkdf,
+                                                 psa_algorithm_t kdf_alg,
+                                                 uint8_t *output,
+                                                 size_t output_length)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
+    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
+    size_t hmac_output_length;
+    psa_status_t status;
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+    const uint8_t last_block = PSA_ALG_IS_HKDF_EXTRACT(kdf_alg) ? 0 : 0xff;
+#else
+    const uint8_t last_block = 0xff;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+
+    if (hkdf->state < HKDF_STATE_KEYED ||
+        (!hkdf->info_set
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+         && !PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+        )) {
+        return PSA_ERROR_BAD_STATE;
+    }
+    hkdf->state = HKDF_STATE_OUTPUT;
+
+    while (output_length != 0) {
+        /* Copy what remains of the current block */
+        uint8_t n = hash_length - hkdf->offset_in_block;
+        if (n > output_length) {
+            n = (uint8_t) output_length;
+        }
+        memcpy(output, hkdf->output_block + hkdf->offset_in_block, n);
+        output += n;
+        output_length -= n;
+        hkdf->offset_in_block += n;
+        if (output_length == 0) {
+            break;
+        }
+        /* We can't be wanting more output after the last block, otherwise
+         * the capacity check in psa_key_derivation_output_bytes() would have
+         * prevented this call. It could happen only if the operation
+         * object was corrupted or if this function is called directly
+         * inside the library. */
+        if (hkdf->block_number == last_block) {
+            return PSA_ERROR_BAD_STATE;
+        }
+
+        /* We need a new block */
+        ++hkdf->block_number;
+        hkdf->offset_in_block = 0;
+
+        status = psa_key_derivation_start_hmac(&hkdf->hmac,
+                                               hash_alg,
+                                               hkdf->prk,
+                                               hash_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+        if (hkdf->block_number != 1) {
+            status = psa_mac_update(&hkdf->hmac,
+                                    hkdf->output_block,
+                                    hash_length);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+        status = psa_mac_update(&hkdf->hmac,
+                                hkdf->info,
+                                hkdf->info_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        status = psa_mac_update(&hkdf->hmac,
+                                &hkdf->block_number, 1);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        status = psa_mac_sign_finish(&hkdf->hmac,
+                                     hkdf->output_block,
+                                     sizeof(hkdf->output_block),
+                                     &hmac_output_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    }
+
+    return PSA_SUCCESS;
+}
+#endif /* BUILTIN_ALG_ANY_HKDF */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_key_derivation_tls12_prf_generate_next_block(
+    psa_tls12_prf_key_derivation_t *tls12_prf,
+    psa_algorithm_t alg)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(alg);
+    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
+    psa_mac_operation_t hmac = PSA_MAC_OPERATION_INIT;
+    size_t hmac_output_length;
+    psa_status_t status, cleanup_status;
+
+    /* We can't be wanting more output after block 0xff, otherwise
+     * the capacity check in psa_key_derivation_output_bytes() would have
+     * prevented this call. It could happen only if the operation
+     * object was corrupted or if this function is called directly
+     * inside the library. */
+    if (tls12_prf->block_number == 0xff) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    /* We need a new block */
+    ++tls12_prf->block_number;
+    tls12_prf->left_in_block = hash_length;
+
+    /* Recall the definition of the TLS-1.2-PRF from RFC 5246:
+     *
+     * PRF(secret, label, seed) = P_<hash>(secret, label + seed)
+     *
+     * P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) +
+     *                        HMAC_hash(secret, A(2) + seed) +
+     *                        HMAC_hash(secret, A(3) + seed) + ...
+     *
+     * A(0) = seed
+     * A(i) = HMAC_hash(secret, A(i-1))
+     *
+     * The `psa_tls12_prf_key_derivation` structure saves the block
+     * `HMAC_hash(secret, A(i) + seed)` from which the output
+     * is currently extracted as `output_block` and where i is
+     * `block_number`.
+     */
+
+    status = psa_key_derivation_start_hmac(&hmac,
+                                           hash_alg,
+                                           tls12_prf->secret,
+                                           tls12_prf->secret_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    /* Calculate A(i) where i = tls12_prf->block_number. */
+    if (tls12_prf->block_number == 1) {
+        /* A(1) = HMAC_hash(secret, A(0)), where A(0) = seed. (The RFC overloads
+         * the variable seed and in this instance means it in the context of the
+         * P_hash function, where seed = label + seed.) */
+        status = psa_mac_update(&hmac,
+                                tls12_prf->label,
+                                tls12_prf->label_length);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+        status = psa_mac_update(&hmac,
+                                tls12_prf->seed,
+                                tls12_prf->seed_length);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+    } else {
+        /* A(i) = HMAC_hash(secret, A(i-1)) */
+        status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+    }
+
+    status = psa_mac_sign_finish(&hmac,
+                                 tls12_prf->Ai, hash_length,
+                                 &hmac_output_length);
+    if (hmac_output_length != hash_length) {
+        status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    /* Calculate HMAC_hash(secret, A(i) + label + seed). */
+    status = psa_key_derivation_start_hmac(&hmac,
+                                           hash_alg,
+                                           tls12_prf->secret,
+                                           tls12_prf->secret_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_update(&hmac, tls12_prf->Ai, hash_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_update(&hmac, tls12_prf->label, tls12_prf->label_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_update(&hmac, tls12_prf->seed, tls12_prf->seed_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_sign_finish(&hmac,
+                                 tls12_prf->output_block, hash_length,
+                                 &hmac_output_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+
+cleanup:
+    cleanup_status = psa_mac_abort(&hmac);
+    if (status == PSA_SUCCESS && cleanup_status != PSA_SUCCESS) {
+        status = cleanup_status;
+    }
+
+    return status;
+}
+
+static psa_status_t psa_key_derivation_tls12_prf_read(
+    psa_tls12_prf_key_derivation_t *tls12_prf,
+    psa_algorithm_t alg,
+    uint8_t *output,
+    size_t output_length)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH(alg);
+    uint8_t hash_length = PSA_HASH_LENGTH(hash_alg);
+    psa_status_t status;
+    uint8_t offset, length;
+
+    switch (tls12_prf->state) {
+        case PSA_TLS12_PRF_STATE_LABEL_SET:
+            tls12_prf->state = PSA_TLS12_PRF_STATE_OUTPUT;
+            break;
+        case PSA_TLS12_PRF_STATE_OUTPUT:
+            break;
+        default:
+            return PSA_ERROR_BAD_STATE;
+    }
+
+    while (output_length != 0) {
+        /* Check if we have fully processed the current block. */
+        if (tls12_prf->left_in_block == 0) {
+            status = psa_key_derivation_tls12_prf_generate_next_block(tls12_prf,
+                                                                      alg);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+
+            continue;
+        }
+
+        if (tls12_prf->left_in_block > output_length) {
+            length = (uint8_t) output_length;
+        } else {
+            length = tls12_prf->left_in_block;
+        }
+
+        offset = hash_length - tls12_prf->left_in_block;
+        memcpy(output, tls12_prf->output_block + offset, length);
+        output += length;
+        output_length -= length;
+        tls12_prf->left_in_block -= length;
+    }
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+static psa_status_t psa_key_derivation_tls12_ecjpake_to_pms_read(
+    psa_tls12_ecjpake_to_pms_t *ecjpake,
+    uint8_t *output,
+    size_t output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t output_size = 0;
+
+    if (output_length != 32) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_hash_compute(PSA_ALG_SHA_256, ecjpake->data,
+                              PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE, output, output_length,
+                              &output_size);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    if (output_size != output_length) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+
+    return PSA_SUCCESS;
+}
+#endif
+
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+static psa_status_t psa_key_derivation_pbkdf2_generate_block(
+    psa_pbkdf2_key_derivation_t *pbkdf2,
+    psa_algorithm_t prf_alg,
+    uint8_t prf_output_length,
+    psa_key_attributes_t *attributes)
+{
+    psa_status_t status;
+    psa_mac_operation_t mac_operation = PSA_MAC_OPERATION_INIT;
+    size_t mac_output_length;
+    uint8_t U_i[PSA_MAC_MAX_SIZE];
+    uint8_t *U_accumulator = pbkdf2->output_block;
+    uint64_t i;
+    uint8_t block_counter[4];
+
+    mac_operation.is_sign = 1;
+    mac_operation.mac_size = prf_output_length;
+    MBEDTLS_PUT_UINT32_BE(pbkdf2->block_number, block_counter, 0);
+
+    status = psa_driver_wrapper_mac_sign_setup(&mac_operation,
+                                               attributes,
+                                               pbkdf2->password,
+                                               pbkdf2->password_length,
+                                               prf_alg);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_update(&mac_operation, pbkdf2->salt, pbkdf2->salt_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_update(&mac_operation, block_counter, sizeof(block_counter));
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+    status = psa_mac_sign_finish(&mac_operation, U_i, sizeof(U_i),
+                                 &mac_output_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    if (mac_output_length != prf_output_length) {
+        status = PSA_ERROR_CORRUPTION_DETECTED;
+        goto cleanup;
+    }
+
+    memcpy(U_accumulator, U_i, prf_output_length);
+
+    for (i = 1; i < pbkdf2->input_cost; i++) {
+        /* We are passing prf_output_length as mac_size because the driver
+         * function directly sets mac_output_length as mac_size upon success.
+         * See https://github.com/Mbed-TLS/mbedtls/issues/7801 */
+        status = psa_driver_wrapper_mac_compute(attributes,
+                                                pbkdf2->password,
+                                                pbkdf2->password_length,
+                                                prf_alg, U_i, prf_output_length,
+                                                U_i, prf_output_length,
+                                                &mac_output_length);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+
+        mbedtls_xor(U_accumulator, U_accumulator, U_i, prf_output_length);
+    }
+
+cleanup:
+    /* Zeroise buffers to clear sensitive data from memory. */
+    mbedtls_platform_zeroize(U_i, PSA_MAC_MAX_SIZE);
+    return status;
+}
+
+static psa_status_t psa_key_derivation_pbkdf2_read(
+    psa_pbkdf2_key_derivation_t *pbkdf2,
+    psa_algorithm_t kdf_alg,
+    uint8_t *output,
+    size_t output_length)
+{
+    psa_status_t status;
+    psa_algorithm_t prf_alg;
+    uint8_t prf_output_length;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(pbkdf2->password_length));
+    psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        prf_alg = PSA_ALG_HMAC(PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg));
+        prf_output_length = PSA_HASH_LENGTH(prf_alg);
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+    } else if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
+        prf_alg = PSA_ALG_CMAC;
+        prf_output_length = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
+    } else {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    switch (pbkdf2->state) {
+        case PSA_PBKDF2_STATE_PASSWORD_SET:
+            /* Initially we need a new block so bytes_used is equal to block size*/
+            pbkdf2->bytes_used = prf_output_length;
+            pbkdf2->state = PSA_PBKDF2_STATE_OUTPUT;
+            break;
+        case PSA_PBKDF2_STATE_OUTPUT:
+            break;
+        default:
+            return PSA_ERROR_BAD_STATE;
+    }
+
+    while (output_length != 0) {
+        uint8_t n = prf_output_length - pbkdf2->bytes_used;
+        if (n > output_length) {
+            n = (uint8_t) output_length;
+        }
+        memcpy(output, pbkdf2->output_block + pbkdf2->bytes_used, n);
+        output += n;
+        output_length -= n;
+        pbkdf2->bytes_used += n;
+
+        if (output_length == 0) {
+            break;
+        }
+
+        /* We need a new block */
+        pbkdf2->bytes_used = 0;
+        pbkdf2->block_number++;
+
+        status = psa_key_derivation_pbkdf2_generate_block(pbkdf2, prf_alg,
+                                                          prf_output_length,
+                                                          &attributes);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    }
+
+    return PSA_SUCCESS;
+}
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+
+psa_status_t psa_key_derivation_output_bytes(
+    psa_key_derivation_operation_t *operation,
+    uint8_t *output_external,
+    size_t output_length)
+{
+    psa_status_t status;
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+
+    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
+
+    if (operation->alg == 0) {
+        /* This is a blank operation. */
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (output_length == 0 && operation->capacity == 0) {
+        /* Edge case: this is a finished operation, and 0 bytes
+         * were requested. The right error in this case could
+         * be either INSUFFICIENT_CAPACITY or BAD_STATE. Return
+         * INSUFFICIENT_CAPACITY, which is right for a finished
+         * operation, for consistency with the case when
+         * output_length > 0. */
+        return PSA_ERROR_INSUFFICIENT_DATA;
+    }
+
+    LOCAL_OUTPUT_ALLOC(output_external, output_length, output);
+    if (output_length > operation->capacity) {
+        operation->capacity = 0;
+        /* Go through the error path to wipe all confidential data now
+         * that the operation object is useless. */
+        status = PSA_ERROR_INSUFFICIENT_DATA;
+        goto exit;
+    }
+
+    operation->capacity -= output_length;
+
+#if defined(BUILTIN_ALG_ANY_HKDF)
+    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
+        status = psa_key_derivation_hkdf_read(&operation->ctx.hkdf, kdf_alg,
+                                              output, output_length);
+    } else
+#endif /* BUILTIN_ALG_ANY_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) ||
+        PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
+        status = psa_key_derivation_tls12_prf_read(&operation->ctx.tls12_prf,
+                                                   kdf_alg, output,
+                                                   output_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        status = psa_key_derivation_tls12_ecjpake_to_pms_read(
+            &operation->ctx.tls12_ecjpake_to_pms, output, output_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
+        status = psa_key_derivation_pbkdf2_read(&operation->ctx.pbkdf2, kdf_alg,
+                                                output, output_length);
+    } else
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+
+    {
+        (void) kdf_alg;
+        status = PSA_ERROR_BAD_STATE;
+        LOCAL_OUTPUT_FREE(output_external, output);
+
+        return status;
+    }
+
+exit:
+    if (status != PSA_SUCCESS) {
+        /* Preserve the algorithm upon errors, but clear all sensitive state.
+         * This allows us to differentiate between exhausted operations and
+         * blank operations, so we can return PSA_ERROR_BAD_STATE on blank
+         * operations. */
+        psa_algorithm_t alg = operation->alg;
+        psa_key_derivation_abort(operation);
+        operation->alg = alg;
+        if (output != NULL) {
+            memset(output, '!', output_length);
+        }
+    }
+
+    LOCAL_OUTPUT_FREE(output_external, output);
+    return status;
+}
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+static void psa_des_set_key_parity(uint8_t *data, size_t data_size)
+{
+    if (data_size >= 8) {
+        mbedtls_des_key_set_parity(data);
+    }
+    if (data_size >= 16) {
+        mbedtls_des_key_set_parity(data + 8);
+    }
+    if (data_size >= 24) {
+        mbedtls_des_key_set_parity(data + 16);
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
+
+/*
+ * ECC keys on a Weierstrass elliptic curve require the generation
+ * of a private key which is an integer
+ * in the range [1, N - 1], where N is the boundary of the private key domain:
+ * N is the prime p for Diffie-Hellman, or the order of the
+ * curve’s base point for ECC.
+ *
+ * Let m be the bit size of N, such that 2^m > N >= 2^(m-1).
+ * This function generates the private key using the following process:
+ *
+ * 1. Draw a byte string of length ceiling(m/8) bytes.
+ * 2. If m is not a multiple of 8, set the most significant
+ *    (8 * ceiling(m/8) - m) bits of the first byte in the string to zero.
+ * 3. Convert the string to integer k by decoding it as a big-endian byte string.
+ * 4. If k > N - 2, discard the result and return to step 1.
+ * 5. Output k + 1 as the private key.
+ *
+ * This method allows compliance to NIST standards, specifically the methods titled
+ * Key-Pair Generation by Testing Candidates in the following publications:
+ * - NIST Special Publication 800-56A: Recommendation for Pair-Wise Key-Establishment
+ *   Schemes Using Discrete Logarithm Cryptography [SP800-56A] §5.6.1.1.4 for
+ *   Diffie-Hellman keys.
+ *
+ * - [SP800-56A] §5.6.1.2.2 or FIPS Publication 186-4: Digital Signature
+ *   Standard (DSS) [FIPS186-4] §B.4.2 for elliptic curve keys.
+ *
+ * Note: Function allocates memory for *data buffer, so given *data should be
+ *       always NULL.
+ */
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(
+    psa_key_slot_t *slot,
+    size_t bits,
+    psa_key_derivation_operation_t *operation,
+    uint8_t **data
+    )
+{
+    unsigned key_out_of_range = 1;
+    mbedtls_mpi k;
+    mbedtls_mpi diff_N_2;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t m;
+    size_t m_bytes;
+
+    mbedtls_mpi_init(&k);
+    mbedtls_mpi_init(&diff_N_2);
+
+    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
+        slot->attr.type);
+    mbedtls_ecp_group_id grp_id =
+        mbedtls_ecc_group_from_psa(curve, bits);
+
+    if (grp_id == MBEDTLS_ECP_DP_NONE) {
+        ret = MBEDTLS_ERR_ASN1_INVALID_DATA;
+        goto cleanup;
+    }
+
+    mbedtls_ecp_group ecp_group;
+    mbedtls_ecp_group_init(&ecp_group);
+
+    MBEDTLS_MPI_CHK(mbedtls_ecp_group_load(&ecp_group, grp_id));
+
+    /* N is the boundary of the private key domain (ecp_group.N). */
+    /* Let m be the bit size of N. */
+    m = ecp_group.nbits;
+
+    m_bytes = PSA_BITS_TO_BYTES(m);
+
+    /* Calculate N - 2 - it will be needed later. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&diff_N_2, &ecp_group.N, 2));
+
+    /* Note: This function is always called with *data == NULL and it
+     * allocates memory for the data buffer. */
+    *data = mbedtls_calloc(1, m_bytes);
+    if (*data == NULL) {
+        ret = MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+        goto cleanup;
+    }
+
+    while (key_out_of_range) {
+        /* 1. Draw a byte string of length ceiling(m/8) bytes. */
+        if ((status = psa_key_derivation_output_bytes(operation, *data, m_bytes)) != 0) {
+            goto cleanup;
+        }
+
+        /* 2. If m is not a multiple of 8 */
+        if (m % 8 != 0) {
+            /* Set the most significant
+             * (8 * ceiling(m/8) - m) bits of the first byte in
+             * the string to zero.
+             */
+            uint8_t clear_bit_mask = (1 << (m % 8)) - 1;
+            (*data)[0] &= clear_bit_mask;
+        }
+
+        /* 3. Convert the string to integer k by decoding it as a
+         *    big-endian byte string.
+         */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&k, *data, m_bytes));
+
+        /* 4. If k > N - 2, discard the result and return to step 1.
+         *    Result of comparison is returned. When it indicates error
+         *    then this function is called again.
+         */
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lt_mpi_ct(&diff_N_2, &k, &key_out_of_range));
+    }
+
+    /* 5. Output k + 1 as the private key. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&k, &k, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&k, *data, m_bytes));
+cleanup:
+    if (ret != 0) {
+        status = mbedtls_to_psa_error(ret);
+    }
+    if (status != PSA_SUCCESS) {
+        mbedtls_free(*data);
+        *data = NULL;
+    }
+    mbedtls_mpi_free(&k);
+    mbedtls_mpi_free(&diff_N_2);
+    return status;
+}
+
+/* ECC keys on a Montgomery elliptic curve draws a byte string whose length
+ * is determined by the curve, and sets the mandatory bits accordingly. That is:
+ *
+ * - Curve25519 (PSA_ECC_FAMILY_MONTGOMERY, 255 bits):
+ *   draw a 32-byte string and process it as specified in
+ *   Elliptic Curves for Security [RFC7748] §5.
+ *
+ * - Curve448 (PSA_ECC_FAMILY_MONTGOMERY, 448 bits):
+ *   draw a 56-byte string and process it as specified in [RFC7748] §5.
+ *
+ * Note: Function allocates memory for *data buffer, so given *data should be
+ *       always NULL.
+ */
+
+static psa_status_t psa_generate_derived_ecc_key_montgomery_helper(
+    size_t bits,
+    psa_key_derivation_operation_t *operation,
+    uint8_t **data
+    )
+{
+    size_t output_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    switch (bits) {
+        case 255:
+            output_length = 32;
+            break;
+        case 448:
+            output_length = 56;
+            break;
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+            break;
+    }
+
+    *data = mbedtls_calloc(1, output_length);
+
+    if (*data == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    status = psa_key_derivation_output_bytes(operation, *data, output_length);
+
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    switch (bits) {
+        case 255:
+            (*data)[0] &= 248;
+            (*data)[31] &= 127;
+            (*data)[31] |= 64;
+            break;
+        case 448:
+            (*data)[0] &= 252;
+            (*data)[55] |= 128;
+            break;
+        default:
+            return PSA_ERROR_CORRUPTION_DETECTED;
+            break;
+    }
+
+    return status;
+}
+#else /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
+static psa_status_t psa_generate_derived_ecc_key_weierstrass_helper(
+    psa_key_slot_t *slot, size_t bits,
+    psa_key_derivation_operation_t *operation, uint8_t **data)
+{
+    (void) slot;
+    (void) bits;
+    (void) operation;
+    (void) data;
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+static psa_status_t psa_generate_derived_ecc_key_montgomery_helper(
+    size_t bits, psa_key_derivation_operation_t *operation, uint8_t **data)
+{
+    (void) bits;
+    (void) operation;
+    (void) data;
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
+#endif /* PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE */
+
+static psa_status_t psa_generate_derived_key_internal(
+    psa_key_slot_t *slot,
+    size_t bits,
+    psa_key_derivation_operation_t *operation)
+{
+    uint8_t *data = NULL;
+    size_t bytes = PSA_BITS_TO_BYTES(bits);
+    size_t storage_size = bytes;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(slot->attr.type)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE)
+    if (PSA_KEY_TYPE_IS_ECC(slot->attr.type)) {
+        psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(slot->attr.type);
+        if (PSA_ECC_FAMILY_IS_WEIERSTRASS(curve)) {
+            /* Weierstrass elliptic curve */
+            status = psa_generate_derived_ecc_key_weierstrass_helper(slot, bits, operation, &data);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+        } else {
+            /* Montgomery elliptic curve */
+            status = psa_generate_derived_ecc_key_montgomery_helper(bits, operation, &data);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+        }
+    } else
+#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) ||
+          defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_DERIVE) */
+    if (key_type_is_raw_bytes(slot->attr.type)) {
+        if (bits % 8 != 0) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+        data = mbedtls_calloc(1, bytes);
+        if (data == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        status = psa_key_derivation_output_bytes(operation, data, bytes);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+        if (slot->attr.type == PSA_KEY_TYPE_DES) {
+            psa_des_set_key_parity(data, bytes);
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES) */
+    } else {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    slot->attr.bits = (psa_key_bits_t) bits;
+
+    if (psa_key_lifetime_is_external(slot->attr.lifetime)) {
+        status = psa_driver_wrapper_get_key_buffer_size(&slot->attr,
+                                                        &storage_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+    status = psa_allocate_buffer_to_slot(slot, storage_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_import_key(&slot->attr,
+                                           data, bytes,
+                                           slot->key.data,
+                                           slot->key.bytes,
+                                           &slot->key.bytes, &bits);
+    if (bits != slot->attr.bits) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+exit:
+    mbedtls_free(data);
+    return status;
+}
+
+static const psa_custom_key_parameters_t default_custom_production =
+    PSA_CUSTOM_KEY_PARAMETERS_INIT;
+
+int psa_custom_key_parameters_are_default(
+    const psa_custom_key_parameters_t *custom,
+    size_t custom_data_length)
+{
+    if (custom->flags != 0) {
+        return 0;
+    }
+    if (custom_data_length != 0) {
+        return 0;
+    }
+    return 1;
+}
+
+psa_status_t psa_key_derivation_output_key_custom(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_custom_key_parameters_t *custom,
+    const uint8_t *custom_data,
+    size_t custom_data_length,
+    mbedtls_svc_key_id_t *key)
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    psa_se_drv_table_entry_t *driver = NULL;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Reject any attempt to create a zero-length key so that we don't
+     * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
+    if (psa_get_key_bits(attributes) == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    (void) custom_data;         /* We only accept 0-length data */
+    if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (operation->alg == PSA_ALG_NONE) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (!operation->can_output_key) {
+        return PSA_ERROR_NOT_PERMITTED;
+    }
+
+    status = psa_start_key_creation(PSA_KEY_CREATION_DERIVE, attributes,
+                                    &slot, &driver);
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    if (driver != NULL) {
+        /* Deriving a key in a secure element is not implemented yet. */
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+    if (status == PSA_SUCCESS) {
+        status = psa_generate_derived_key_internal(slot,
+                                                   attributes->bits,
+                                                   operation);
+    }
+    if (status == PSA_SUCCESS) {
+        status = psa_finish_key_creation(slot, driver, key);
+    }
+    if (status != PSA_SUCCESS) {
+        psa_fail_key_creation(slot, driver);
+    }
+
+    return status;
+}
+
+psa_status_t psa_key_derivation_output_key_ext(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    const psa_key_production_parameters_t *params,
+    size_t params_data_length,
+    mbedtls_svc_key_id_t *key)
+{
+    return psa_key_derivation_output_key_custom(
+        attributes, operation,
+        (const psa_custom_key_parameters_t *) params,
+        params->data, params_data_length,
+        key);
+}
+
+psa_status_t psa_key_derivation_output_key(
+    const psa_key_attributes_t *attributes,
+    psa_key_derivation_operation_t *operation,
+    mbedtls_svc_key_id_t *key)
+{
+    return psa_key_derivation_output_key_custom(attributes, operation,
+                                                &default_custom_production,
+                                                NULL, 0,
+                                                key);
+}
+
+
+/****************************************************************/
+/* Key derivation */
+/****************************************************************/
+
+#if defined(AT_LEAST_ONE_BUILTIN_KDF)
+static int is_kdf_alg_supported(psa_algorithm_t kdf_alg)
+{
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF)
+    if (PSA_ALG_IS_HKDF(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+    if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
+    if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        return 1;
+    }
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
+    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
+        return 1;
+    }
+#endif
+    return 0;
+}
+
+static psa_status_t psa_hash_try_support(psa_algorithm_t alg)
+{
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    psa_status_t status = psa_hash_setup(&operation, alg);
+    psa_hash_abort(&operation);
+    return status;
+}
+
+static psa_status_t psa_key_derivation_set_maximum_capacity(
+    psa_key_derivation_operation_t *operation,
+    psa_algorithm_t kdf_alg)
+{
+#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        operation->capacity = PSA_HASH_LENGTH(PSA_ALG_SHA_256);
+        return PSA_SUCCESS;
+    }
+#endif
+#if defined(PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128)
+    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
+#if (SIZE_MAX > UINT32_MAX)
+        operation->capacity = UINT32_MAX * (size_t) PSA_MAC_LENGTH(
+            PSA_KEY_TYPE_AES,
+            128U,
+            PSA_ALG_CMAC);
+#else
+        operation->capacity = SIZE_MAX;
+#endif
+        return PSA_SUCCESS;
+    }
+#endif /* PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 */
+
+    /* After this point, if kdf_alg is not valid then value of hash_alg may be
+     * invalid or meaningless but it does not affect this function */
+    psa_algorithm_t hash_alg = PSA_ALG_GET_HASH(kdf_alg);
+    size_t hash_size = PSA_HASH_LENGTH(hash_alg);
+    if (hash_size == 0) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* Make sure that hash_alg is a supported hash algorithm. Otherwise
+     * we might fail later, which is somewhat unfriendly and potentially
+     * risk-prone. */
+    psa_status_t status = psa_hash_try_support(hash_alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+#if defined(PSA_WANT_ALG_HKDF)
+    if (PSA_ALG_IS_HKDF(kdf_alg)) {
+        operation->capacity = 255 * hash_size;
+    } else
+#endif
+#if defined(PSA_WANT_ALG_HKDF_EXTRACT)
+    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+        operation->capacity = hash_size;
+    } else
+#endif
+#if defined(PSA_WANT_ALG_HKDF_EXPAND)
+    if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
+        operation->capacity = 255 * hash_size;
+    } else
+#endif
+#if defined(PSA_WANT_ALG_TLS12_PRF)
+    if (PSA_ALG_IS_TLS12_PRF(kdf_alg) &&
+        (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
+        operation->capacity = SIZE_MAX;
+    } else
+#endif
+#if defined(PSA_WANT_ALG_TLS12_PSK_TO_MS)
+    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg) &&
+        (hash_alg == PSA_ALG_SHA_256 || hash_alg == PSA_ALG_SHA_384)) {
+        /* Master Secret is always 48 bytes
+         * https://datatracker.ietf.org/doc/html/rfc5246.html#section-8.1 */
+        operation->capacity = 48U;
+    } else
+#endif
+#if defined(PSA_WANT_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+#if (SIZE_MAX > UINT32_MAX)
+        operation->capacity = UINT32_MAX * hash_size;
+#else
+        operation->capacity = SIZE_MAX;
+#endif
+    } else
+#endif /* PSA_WANT_ALG_PBKDF2_HMAC */
+    {
+        (void) hash_size;
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+    return status;
+}
+
+static psa_status_t psa_key_derivation_setup_kdf(
+    psa_key_derivation_operation_t *operation,
+    psa_algorithm_t kdf_alg)
+{
+    /* Make sure that operation->ctx is properly zero-initialised. (Macro
+     * initialisers for this union leave some bytes unspecified.) */
+    memset(&operation->ctx, 0, sizeof(operation->ctx));
+
+    /* Make sure that kdf_alg is a supported key derivation algorithm. */
+    if (!is_kdf_alg_supported(kdf_alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    psa_status_t status = psa_key_derivation_set_maximum_capacity(operation,
+                                                                  kdf_alg);
+    return status;
+}
+
+static psa_status_t psa_key_agreement_try_support(psa_algorithm_t alg)
+{
+#if defined(PSA_WANT_ALG_ECDH)
+    if (alg == PSA_ALG_ECDH) {
+        return PSA_SUCCESS;
+    }
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+    if (alg == PSA_ALG_FFDH) {
+        return PSA_SUCCESS;
+    }
+#endif
+    (void) alg;
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+static int psa_key_derivation_allows_free_form_secret_input(
+    psa_algorithm_t kdf_alg)
+{
+#if defined(PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        return 0;
+    }
+#endif
+    (void) kdf_alg;
+    return 1;
+}
+#endif /* AT_LEAST_ONE_BUILTIN_KDF */
+
+psa_status_t psa_key_derivation_setup(psa_key_derivation_operation_t *operation,
+                                      psa_algorithm_t alg)
+{
+    psa_status_t status;
+
+    if (operation->alg != 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    } else if (PSA_ALG_IS_KEY_AGREEMENT(alg)) {
+#if defined(AT_LEAST_ONE_BUILTIN_KDF)
+        psa_algorithm_t kdf_alg = PSA_ALG_KEY_AGREEMENT_GET_KDF(alg);
+        psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(alg);
+        status = psa_key_agreement_try_support(ka_alg);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+        if (!psa_key_derivation_allows_free_form_secret_input(kdf_alg)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+        status = psa_key_derivation_setup_kdf(operation, kdf_alg);
+#else
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* AT_LEAST_ONE_BUILTIN_KDF */
+    } else if (PSA_ALG_IS_KEY_DERIVATION(alg)) {
+#if defined(AT_LEAST_ONE_BUILTIN_KDF)
+        status = psa_key_derivation_setup_kdf(operation, alg);
+#else
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* AT_LEAST_ONE_BUILTIN_KDF */
+    } else {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (status == PSA_SUCCESS) {
+        operation->alg = alg;
+    }
+    return status;
+}
+
+#if defined(BUILTIN_ALG_ANY_HKDF)
+static psa_status_t psa_hkdf_input(psa_hkdf_key_derivation_t *hkdf,
+                                   psa_algorithm_t kdf_alg,
+                                   psa_key_derivation_step_t step,
+                                   const uint8_t *data,
+                                   size_t data_length)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_HKDF_GET_HASH(kdf_alg);
+    psa_status_t status;
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SALT:
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
+            if (hkdf->state != HKDF_STATE_INIT) {
+                return PSA_ERROR_BAD_STATE;
+            } else {
+                status = psa_key_derivation_start_hmac(&hkdf->hmac,
+                                                       hash_alg,
+                                                       data, data_length);
+                if (status != PSA_SUCCESS) {
+                    return status;
+                }
+                hkdf->state = HKDF_STATE_STARTED;
+                return PSA_SUCCESS;
+            }
+        case PSA_KEY_DERIVATION_INPUT_SECRET:
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg)) {
+                /* We shouldn't be in different state as HKDF_EXPAND only allows
+                 * two inputs: SECRET (this case) and INFO which does not modify
+                 * the state. It could happen only if the hkdf
+                 * object was corrupted. */
+                if (hkdf->state != HKDF_STATE_INIT) {
+                    return PSA_ERROR_BAD_STATE;
+                }
+
+                /* Allow only input that fits expected prk size */
+                if (data_length != PSA_HASH_LENGTH(hash_alg)) {
+                    return PSA_ERROR_INVALID_ARGUMENT;
+                }
+
+                memcpy(hkdf->prk, data, data_length);
+            } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND */
+            {
+                /* HKDF: If no salt was provided, use an empty salt.
+                 * HKDF-EXTRACT: salt is mandatory. */
+                if (hkdf->state == HKDF_STATE_INIT) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+                    if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+                        return PSA_ERROR_BAD_STATE;
+                    }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+                    status = psa_key_derivation_start_hmac(&hkdf->hmac,
+                                                           hash_alg,
+                                                           NULL, 0);
+                    if (status != PSA_SUCCESS) {
+                        return status;
+                    }
+                    hkdf->state = HKDF_STATE_STARTED;
+                }
+                if (hkdf->state != HKDF_STATE_STARTED) {
+                    return PSA_ERROR_BAD_STATE;
+                }
+                status = psa_mac_update(&hkdf->hmac,
+                                        data, data_length);
+                if (status != PSA_SUCCESS) {
+                    return status;
+                }
+                status = psa_mac_sign_finish(&hkdf->hmac,
+                                             hkdf->prk,
+                                             sizeof(hkdf->prk),
+                                             &data_length);
+                if (status != PSA_SUCCESS) {
+                    return status;
+                }
+            }
+
+            hkdf->state = HKDF_STATE_KEYED;
+            hkdf->block_number = 0;
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+            if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+                /* The only block of output is the PRK. */
+                memcpy(hkdf->output_block, hkdf->prk, PSA_HASH_LENGTH(hash_alg));
+                hkdf->offset_in_block = 0;
+            } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+            {
+                /* Block 0 is empty, and the next block will be
+                 * generated by psa_key_derivation_hkdf_read(). */
+                hkdf->offset_in_block = PSA_HASH_LENGTH(hash_alg);
+            }
+
+            return PSA_SUCCESS;
+        case PSA_KEY_DERIVATION_INPUT_INFO:
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT)
+            if (PSA_ALG_IS_HKDF_EXTRACT(kdf_alg)) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXPAND)
+            if (PSA_ALG_IS_HKDF_EXPAND(kdf_alg) &&
+                hkdf->state == HKDF_STATE_INIT) {
+                return PSA_ERROR_BAD_STATE;
+            }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HKDF_EXTRACT */
+            if (hkdf->state == HKDF_STATE_OUTPUT) {
+                return PSA_ERROR_BAD_STATE;
+            }
+            if (hkdf->info_set) {
+                return PSA_ERROR_BAD_STATE;
+            }
+            hkdf->info_length = data_length;
+            if (data_length != 0) {
+                hkdf->info = mbedtls_calloc(1, data_length);
+                if (hkdf->info == NULL) {
+                    return PSA_ERROR_INSUFFICIENT_MEMORY;
+                }
+                memcpy(hkdf->info, data, data_length);
+            }
+            hkdf->info_set = 1;
+            return PSA_SUCCESS;
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+#endif /* BUILTIN_ALG_ANY_HKDF */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_tls12_prf_set_seed(psa_tls12_prf_key_derivation_t *prf,
+                                           const uint8_t *data,
+                                           size_t data_length)
+{
+    if (prf->state != PSA_TLS12_PRF_STATE_INIT) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length != 0) {
+        prf->seed = mbedtls_calloc(1, data_length);
+        if (prf->seed == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(prf->seed, data, data_length);
+        prf->seed_length = data_length;
+    }
+
+    prf->state = PSA_TLS12_PRF_STATE_SEED_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_tls12_prf_set_key(psa_tls12_prf_key_derivation_t *prf,
+                                          const uint8_t *data,
+                                          size_t data_length)
+{
+    if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET &&
+        prf->state != PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length != 0) {
+        prf->secret = mbedtls_calloc(1, data_length);
+        if (prf->secret == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(prf->secret, data, data_length);
+        prf->secret_length = data_length;
+    }
+
+    prf->state = PSA_TLS12_PRF_STATE_KEY_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_tls12_prf_set_label(psa_tls12_prf_key_derivation_t *prf,
+                                            const uint8_t *data,
+                                            size_t data_length)
+{
+    if (prf->state != PSA_TLS12_PRF_STATE_KEY_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length != 0) {
+        prf->label = mbedtls_calloc(1, data_length);
+        if (prf->label == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(prf->label, data, data_length);
+        prf->label_length = data_length;
+    }
+
+    prf->state = PSA_TLS12_PRF_STATE_LABEL_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_tls12_prf_input(psa_tls12_prf_key_derivation_t *prf,
+                                        psa_key_derivation_step_t step,
+                                        const uint8_t *data,
+                                        size_t data_length)
+{
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SEED:
+            return psa_tls12_prf_set_seed(prf, data, data_length);
+        case PSA_KEY_DERIVATION_INPUT_SECRET:
+            return psa_tls12_prf_set_key(prf, data, data_length);
+        case PSA_KEY_DERIVATION_INPUT_LABEL:
+            return psa_tls12_prf_set_label(prf, data, data_length);
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF) ||
+        * MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+static psa_status_t psa_tls12_prf_psk_to_ms_set_key(
+    psa_tls12_prf_key_derivation_t *prf,
+    const uint8_t *data,
+    size_t data_length)
+{
+    psa_status_t status;
+    const size_t pms_len = (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET ?
+                            4 + data_length + prf->other_secret_length :
+                            4 + 2 * data_length);
+
+    if (data_length > PSA_TLS12_PSK_TO_MS_PSK_MAX_SIZE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    uint8_t *pms = mbedtls_calloc(1, pms_len);
+    if (pms == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    uint8_t *cur = pms;
+
+    /* pure-PSK:
+     * Quoting RFC 4279, Section 2:
+     *
+     * The premaster secret is formed as follows: if the PSK is N octets
+     * long, concatenate a uint16 with the value N, N zero octets, a second
+     * uint16 with the value N, and the PSK itself.
+     *
+     * mixed-PSK:
+     * In a DHE-PSK, RSA-PSK, ECDHE-PSK the premaster secret is formed as
+     * follows: concatenate a uint16 with the length of the other secret,
+     * the other secret itself, uint16 with the length of PSK, and the
+     * PSK itself.
+     * For details please check:
+     * - RFC 4279, Section 4 for the definition of RSA-PSK,
+     * - RFC 4279, Section 3 for the definition of DHE-PSK,
+     * - RFC 5489 for the definition of ECDHE-PSK.
+     */
+
+    if (prf->state == PSA_TLS12_PRF_STATE_OTHER_KEY_SET) {
+        *cur++ = MBEDTLS_BYTE_1(prf->other_secret_length);
+        *cur++ = MBEDTLS_BYTE_0(prf->other_secret_length);
+        if (prf->other_secret_length != 0) {
+            memcpy(cur, prf->other_secret, prf->other_secret_length);
+            mbedtls_platform_zeroize(prf->other_secret, prf->other_secret_length);
+            cur += prf->other_secret_length;
+        }
+    } else {
+        *cur++ = MBEDTLS_BYTE_1(data_length);
+        *cur++ = MBEDTLS_BYTE_0(data_length);
+        memset(cur, 0, data_length);
+        cur += data_length;
+    }
+
+    *cur++ = MBEDTLS_BYTE_1(data_length);
+    *cur++ = MBEDTLS_BYTE_0(data_length);
+    memcpy(cur, data, data_length);
+    cur += data_length;
+
+    status = psa_tls12_prf_set_key(prf, pms, (size_t) (cur - pms));
+
+    mbedtls_zeroize_and_free(pms, pms_len);
+    return status;
+}
+
+static psa_status_t psa_tls12_prf_psk_to_ms_set_other_key(
+    psa_tls12_prf_key_derivation_t *prf,
+    const uint8_t *data,
+    size_t data_length)
+{
+    if (prf->state != PSA_TLS12_PRF_STATE_SEED_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length != 0) {
+        prf->other_secret = mbedtls_calloc(1, data_length);
+        if (prf->other_secret == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        memcpy(prf->other_secret, data, data_length);
+        prf->other_secret_length = data_length;
+    } else {
+        prf->other_secret_length = 0;
+    }
+
+    prf->state = PSA_TLS12_PRF_STATE_OTHER_KEY_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_tls12_prf_psk_to_ms_input(
+    psa_tls12_prf_key_derivation_t *prf,
+    psa_key_derivation_step_t step,
+    const uint8_t *data,
+    size_t data_length)
+{
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SECRET:
+            return psa_tls12_prf_psk_to_ms_set_key(prf,
+                                                   data, data_length);
+            break;
+        case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:
+            return psa_tls12_prf_psk_to_ms_set_other_key(prf,
+                                                         data,
+                                                         data_length);
+            break;
+        default:
+            return psa_tls12_prf_input(prf, step, data, data_length);
+            break;
+
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+static psa_status_t psa_tls12_ecjpake_to_pms_input(
+    psa_tls12_ecjpake_to_pms_t *ecjpake,
+    psa_key_derivation_step_t step,
+    const uint8_t *data,
+    size_t data_length)
+{
+    if (data_length != PSA_TLS12_ECJPAKE_TO_PMS_INPUT_SIZE ||
+        step != PSA_KEY_DERIVATION_INPUT_SECRET) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Check if the passed point is in an uncompressed form */
+    if (data[0] != 0x04) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Only K.X has to be extracted - bytes 1 to 32 inclusive. */
+    memcpy(ecjpake->data, data + 1, PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+static psa_status_t psa_pbkdf2_set_input_cost(
+    psa_pbkdf2_key_derivation_t *pbkdf2,
+    psa_key_derivation_step_t step,
+    uint64_t data)
+{
+    if (step != PSA_KEY_DERIVATION_INPUT_COST) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (pbkdf2->state != PSA_PBKDF2_STATE_INIT) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data > PSA_VENDOR_PBKDF2_MAX_ITERATIONS) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (data == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    pbkdf2->input_cost = data;
+    pbkdf2->state = PSA_PBKDF2_STATE_INPUT_COST_SET;
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_pbkdf2_set_salt(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                        const uint8_t *data,
+                                        size_t data_length)
+{
+    if (pbkdf2->state == PSA_PBKDF2_STATE_INPUT_COST_SET) {
+        pbkdf2->state = PSA_PBKDF2_STATE_SALT_SET;
+    } else if (pbkdf2->state == PSA_PBKDF2_STATE_SALT_SET) {
+        /* Appending to existing salt. No state change. */
+    } else {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (data_length == 0) {
+        /* Appending an empty string, nothing to do. */
+    } else {
+        uint8_t *next_salt;
+
+        next_salt = mbedtls_calloc(1, data_length + pbkdf2->salt_length);
+        if (next_salt == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+
+        if (pbkdf2->salt_length != 0) {
+            memcpy(next_salt, pbkdf2->salt, pbkdf2->salt_length);
+        }
+        memcpy(next_salt + pbkdf2->salt_length, data, data_length);
+        pbkdf2->salt_length += data_length;
+        mbedtls_free(pbkdf2->salt);
+        pbkdf2->salt = next_salt;
+    }
+    return PSA_SUCCESS;
+}
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+static psa_status_t psa_pbkdf2_hmac_set_password(psa_algorithm_t hash_alg,
+                                                 const uint8_t *input,
+                                                 size_t input_len,
+                                                 uint8_t *output,
+                                                 size_t *output_len)
+{
+    psa_status_t status = PSA_SUCCESS;
+    if (input_len > PSA_HASH_BLOCK_LENGTH(hash_alg)) {
+        return psa_hash_compute(hash_alg, input, input_len, output,
+                                PSA_HMAC_MAX_HASH_BLOCK_SIZE, output_len);
+    } else if (input_len > 0) {
+        memcpy(output, input, input_len);
+    }
+    *output_len = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
+static psa_status_t psa_pbkdf2_cmac_set_password(const uint8_t *input,
+                                                 size_t input_len,
+                                                 uint8_t *output,
+                                                 size_t *output_len)
+{
+    psa_status_t status = PSA_SUCCESS;
+    if (input_len != PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC)) {
+        psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+        uint8_t zeros[16] = { 0 };
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
+        psa_set_key_bits(&attributes, PSA_BYTES_TO_BITS(sizeof(zeros)));
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+        /* Passing PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC) as
+         * mac_size as the driver function sets mac_output_length = mac_size
+         * on success. See https://github.com/Mbed-TLS/mbedtls/issues/7801 */
+        status = psa_driver_wrapper_mac_compute(&attributes,
+                                                zeros, sizeof(zeros),
+                                                PSA_ALG_CMAC, input, input_len,
+                                                output,
+                                                PSA_MAC_LENGTH(PSA_KEY_TYPE_AES,
+                                                               128U,
+                                                               PSA_ALG_CMAC),
+                                                output_len);
+    } else {
+        memcpy(output, input, input_len);
+        *output_len = PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128U, PSA_ALG_CMAC);
+    }
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */
+
+static psa_status_t psa_pbkdf2_set_password(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                            psa_algorithm_t kdf_alg,
+                                            const uint8_t *data,
+                                            size_t data_length)
+{
+    psa_status_t status = PSA_SUCCESS;
+    if (pbkdf2->state != PSA_PBKDF2_STATE_SALT_SET) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC)
+    if (PSA_ALG_IS_PBKDF2_HMAC(kdf_alg)) {
+        psa_algorithm_t hash_alg = PSA_ALG_PBKDF2_HMAC_GET_HASH(kdf_alg);
+        status = psa_pbkdf2_hmac_set_password(hash_alg, data, data_length,
+                                              pbkdf2->password,
+                                              &pbkdf2->password_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_HMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128)
+    if (kdf_alg == PSA_ALG_PBKDF2_AES_CMAC_PRF_128) {
+        status = psa_pbkdf2_cmac_set_password(data, data_length,
+                                              pbkdf2->password,
+                                              &pbkdf2->password_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_PBKDF2_AES_CMAC_PRF_128 */
+    {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    pbkdf2->state = PSA_PBKDF2_STATE_PASSWORD_SET;
+
+    return status;
+}
+
+static psa_status_t psa_pbkdf2_input(psa_pbkdf2_key_derivation_t *pbkdf2,
+                                     psa_algorithm_t kdf_alg,
+                                     psa_key_derivation_step_t step,
+                                     const uint8_t *data,
+                                     size_t data_length)
+{
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SALT:
+            return psa_pbkdf2_set_salt(pbkdf2, data, data_length);
+        case PSA_KEY_DERIVATION_INPUT_PASSWORD:
+            return psa_pbkdf2_set_password(pbkdf2, kdf_alg, data, data_length);
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+    }
+}
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+
+/** Check whether the given key type is acceptable for the given
+ * input step of a key derivation.
+ *
+ * Secret inputs must have the type #PSA_KEY_TYPE_DERIVE.
+ * Non-secret inputs must have the type #PSA_KEY_TYPE_RAW_DATA.
+ * Both secret and non-secret inputs can alternatively have the type
+ * #PSA_KEY_TYPE_NONE, which is never the type of a key object, meaning
+ * that the input was passed as a buffer rather than via a key object.
+ */
+static int psa_key_derivation_check_input_type(
+    psa_key_derivation_step_t step,
+    psa_key_type_t key_type)
+{
+    switch (step) {
+        case PSA_KEY_DERIVATION_INPUT_SECRET:
+            if (key_type == PSA_KEY_TYPE_DERIVE) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_NONE) {
+                return PSA_SUCCESS;
+            }
+            break;
+        case PSA_KEY_DERIVATION_INPUT_OTHER_SECRET:
+            if (key_type == PSA_KEY_TYPE_DERIVE) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_NONE) {
+                return PSA_SUCCESS;
+            }
+            break;
+        case PSA_KEY_DERIVATION_INPUT_LABEL:
+        case PSA_KEY_DERIVATION_INPUT_SALT:
+        case PSA_KEY_DERIVATION_INPUT_INFO:
+        case PSA_KEY_DERIVATION_INPUT_SEED:
+            if (key_type == PSA_KEY_TYPE_RAW_DATA) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_NONE) {
+                return PSA_SUCCESS;
+            }
+            break;
+        case PSA_KEY_DERIVATION_INPUT_PASSWORD:
+            if (key_type == PSA_KEY_TYPE_PASSWORD) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_DERIVE) {
+                return PSA_SUCCESS;
+            }
+            if (key_type == PSA_KEY_TYPE_NONE) {
+                return PSA_SUCCESS;
+            }
+            break;
+    }
+    return PSA_ERROR_INVALID_ARGUMENT;
+}
+
+static psa_status_t psa_key_derivation_input_internal(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    psa_key_type_t key_type,
+    const uint8_t *data,
+    size_t data_length)
+{
+    psa_status_t status;
+    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
+
+    status = psa_key_derivation_check_input_type(step, key_type);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+#if defined(BUILTIN_ALG_ANY_HKDF)
+    if (PSA_ALG_IS_ANY_HKDF(kdf_alg)) {
+        status = psa_hkdf_input(&operation->ctx.hkdf, kdf_alg,
+                                step, data, data_length);
+    } else
+#endif /* BUILTIN_ALG_ANY_HKDF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF)
+    if (PSA_ALG_IS_TLS12_PRF(kdf_alg)) {
+        status = psa_tls12_prf_input(&operation->ctx.tls12_prf,
+                                     step, data, data_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PRF */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS)
+    if (PSA_ALG_IS_TLS12_PSK_TO_MS(kdf_alg)) {
+        status = psa_tls12_prf_psk_to_ms_input(&operation->ctx.tls12_prf,
+                                               step, data, data_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_PSK_TO_MS */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS)
+    if (kdf_alg == PSA_ALG_TLS12_ECJPAKE_TO_PMS) {
+        status = psa_tls12_ecjpake_to_pms_input(
+            &operation->ctx.tls12_ecjpake_to_pms, step, data, data_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_TLS12_ECJPAKE_TO_PMS */
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
+        status = psa_pbkdf2_input(&operation->ctx.pbkdf2, kdf_alg,
+                                  step, data, data_length);
+    } else
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+    {
+        /* This can't happen unless the operation object was not initialized */
+        (void) data;
+        (void) data_length;
+        (void) kdf_alg;
+        return PSA_ERROR_BAD_STATE;
+    }
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(operation);
+    }
+    return status;
+}
+
+static psa_status_t psa_key_derivation_input_integer_internal(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    uint64_t value)
+{
+    psa_status_t status;
+    psa_algorithm_t kdf_alg = psa_key_derivation_get_kdf_alg(operation);
+
+#if defined(PSA_HAVE_SOFT_PBKDF2)
+    if (PSA_ALG_IS_PBKDF2(kdf_alg)) {
+        status = psa_pbkdf2_set_input_cost(
+            &operation->ctx.pbkdf2, step, value);
+    } else
+#endif /* PSA_HAVE_SOFT_PBKDF2 */
+    {
+        (void) step;
+        (void) value;
+        (void) kdf_alg;
+        status = PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(operation);
+    }
+    return status;
+}
+
+psa_status_t psa_key_derivation_input_bytes(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    const uint8_t *data_external,
+    size_t data_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(data_external, data);
+
+    LOCAL_INPUT_ALLOC(data_external, data_length, data);
+
+    status = psa_key_derivation_input_internal(operation, step,
+                                               PSA_KEY_TYPE_NONE,
+                                               data, data_length);
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_INPUT_FREE(data_external, data);
+    return status;
+}
+
+psa_status_t psa_key_derivation_input_integer(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    uint64_t value)
+{
+    return psa_key_derivation_input_integer_internal(operation, step, value);
+}
+
+psa_status_t psa_key_derivation_input_key(
+    psa_key_derivation_operation_t *operation,
+    psa_key_derivation_step_t step,
+    mbedtls_svc_key_id_t key)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+        key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(operation);
+        return status;
+    }
+
+    /* Passing a key object as a SECRET or PASSWORD input unlocks the
+     * permission to output to a key object. */
+    if (step == PSA_KEY_DERIVATION_INPUT_SECRET ||
+        step == PSA_KEY_DERIVATION_INPUT_PASSWORD) {
+        operation->can_output_key = 1;
+    }
+
+    status = psa_key_derivation_input_internal(operation,
+                                               step, slot->attr.type,
+                                               slot->key.data,
+                                               slot->key.bytes);
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+
+
+/****************************************************************/
+/* Key agreement */
+/****************************************************************/
+
+psa_status_t psa_key_agreement_raw_builtin(const psa_key_attributes_t *attributes,
+                                           const uint8_t *key_buffer,
+                                           size_t key_buffer_size,
+                                           psa_algorithm_t alg,
+                                           const uint8_t *peer_key,
+                                           size_t peer_key_length,
+                                           uint8_t *shared_secret,
+                                           size_t shared_secret_size,
+                                           size_t *shared_secret_length)
+{
+    switch (alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+        case PSA_ALG_ECDH:
+            return mbedtls_psa_key_agreement_ecdh(attributes, key_buffer,
+                                                  key_buffer_size, alg,
+                                                  peer_key, peer_key_length,
+                                                  shared_secret,
+                                                  shared_secret_size,
+                                                  shared_secret_length);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
+        case PSA_ALG_FFDH:
+            return mbedtls_psa_ffdh_key_agreement(attributes,
+                                                  peer_key,
+                                                  peer_key_length,
+                                                  key_buffer,
+                                                  key_buffer_size,
+                                                  shared_secret,
+                                                  shared_secret_size,
+                                                  shared_secret_length);
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
+
+        default:
+            (void) attributes;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) peer_key;
+            (void) peer_key_length;
+            (void) shared_secret;
+            (void) shared_secret_size;
+            (void) shared_secret_length;
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+}
+
+/** Internal function for raw key agreement
+ *  Calls the driver wrapper which will hand off key agreement task
+ *  to the driver's implementation if a driver is present.
+ *  Fallback specified in the driver wrapper is built-in raw key agreement
+ *  (psa_key_agreement_raw_builtin).
+ */
+static psa_status_t psa_key_agreement_raw_internal(psa_algorithm_t alg,
+                                                   psa_key_slot_t *private_key,
+                                                   const uint8_t *peer_key,
+                                                   size_t peer_key_length,
+                                                   uint8_t *shared_secret,
+                                                   size_t shared_secret_size,
+                                                   size_t *shared_secret_length)
+{
+    if (!PSA_ALG_IS_RAW_KEY_AGREEMENT(alg)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return psa_driver_wrapper_key_agreement(&private_key->attr,
+                                            private_key->key.data,
+                                            private_key->key.bytes, alg,
+                                            peer_key, peer_key_length,
+                                            shared_secret,
+                                            shared_secret_size,
+                                            shared_secret_length);
+}
+
+/* Note that if this function fails, you must call psa_key_derivation_abort()
+ * to potentially free embedded data structures and wipe confidential data.
+ */
+static psa_status_t psa_key_agreement_internal(psa_key_derivation_operation_t *operation,
+                                               psa_key_derivation_step_t step,
+                                               psa_key_slot_t *private_key,
+                                               const uint8_t *peer_key,
+                                               size_t peer_key_length)
+{
+    psa_status_t status;
+    uint8_t shared_secret[PSA_RAW_KEY_AGREEMENT_OUTPUT_MAX_SIZE] = { 0 };
+    size_t shared_secret_length = 0;
+    psa_algorithm_t ka_alg = PSA_ALG_KEY_AGREEMENT_GET_BASE(operation->alg);
+
+    /* Step 1: run the secret agreement algorithm to generate the shared
+     * secret. */
+    status = psa_key_agreement_raw_internal(ka_alg,
+                                            private_key,
+                                            peer_key, peer_key_length,
+                                            shared_secret,
+                                            sizeof(shared_secret),
+                                            &shared_secret_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* Step 2: set up the key derivation to generate key material from
+     * the shared secret. A shared secret is permitted wherever a key
+     * of type DERIVE is permitted. */
+    status = psa_key_derivation_input_internal(operation, step,
+                                               PSA_KEY_TYPE_DERIVE,
+                                               shared_secret,
+                                               shared_secret_length);
+exit:
+    mbedtls_platform_zeroize(shared_secret, shared_secret_length);
+    return status;
+}
+
+psa_status_t psa_key_derivation_key_agreement(psa_key_derivation_operation_t *operation,
+                                              psa_key_derivation_step_t step,
+                                              mbedtls_svc_key_id_t private_key,
+                                              const uint8_t *peer_key_external,
+                                              size_t peer_key_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
+
+    if (!PSA_ALG_IS_KEY_AGREEMENT(operation->alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+        private_key, &slot, PSA_KEY_USAGE_DERIVE, operation->alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
+    status = psa_key_agreement_internal(operation, step,
+                                        slot,
+                                        peer_key, peer_key_length);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(operation);
+    } else {
+        /* If a private key has been added as SECRET, we allow the derived
+         * key material to be used as a key in PSA Crypto. */
+        if (step == PSA_KEY_DERIVATION_INPUT_SECRET) {
+            operation->can_output_key = 1;
+        }
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+    LOCAL_INPUT_FREE(peer_key_external, peer_key);
+
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_raw_key_agreement(psa_algorithm_t alg,
+                                   mbedtls_svc_key_id_t private_key,
+                                   const uint8_t *peer_key_external,
+                                   size_t peer_key_length,
+                                   uint8_t *output_external,
+                                   size_t output_size,
+                                   size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    size_t expected_length;
+    LOCAL_INPUT_DECLARE(peer_key_external, peer_key);
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    if (!PSA_ALG_IS_KEY_AGREEMENT(alg)) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+    status = psa_get_and_lock_transparent_key_slot_with_policy(
+        private_key, &slot, PSA_KEY_USAGE_DERIVE, alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is in general an upper bound
+     * for the output size. The PSA specification only guarantees that this
+     * function works if output_size >= PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(...),
+     * but it might be nice to allow smaller buffers if the output fits.
+     * At the time of writing this comment, with only ECDH implemented,
+     * PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() is exact so the point is moot.
+     * If FFDH is implemented, PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE() can easily
+     * be exact for it as well. */
+    expected_length =
+        PSA_RAW_KEY_AGREEMENT_OUTPUT_SIZE(slot->attr.type, slot->attr.bits);
+    if (output_size < expected_length) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(peer_key_external, peer_key_length, peer_key);
+    status = psa_key_agreement_raw_internal(alg, slot,
+                                            peer_key, peer_key_length,
+                                            output, output_size,
+                                            output_length);
+
+exit:
+    /* Check for successful allocation of output,
+     * with an unsuccessful status. */
+    if (output != NULL && status != PSA_SUCCESS) {
+        /* If an error happens and is not handled properly, the output
+         * may be used as a key to protect sensitive data. Arrange for such
+         * a key to be random, which is likely to result in decryption or
+         * verification errors. This is better than filling the buffer with
+         * some constant data such as zeros, which would result in the data
+         * being protected with a reproducible, easily knowable key.
+         */
+        psa_generate_random_internal(output, output_size);
+        *output_length = output_size;
+    }
+
+    if (output == NULL) {
+        /* output allocation failed. */
+        *output_length = 0;
+    }
+
+    unlock_status = psa_unregister_read_under_mutex(slot);
+
+    LOCAL_INPUT_FREE(peer_key_external, peer_key);
+    LOCAL_OUTPUT_FREE(output_external, output);
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+
+/****************************************************************/
+/* Random generation */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+#include "entropy_poll.h"
+#endif
+
+/** Initialize the PSA random generator.
+ *
+ *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
+ *  this function if mutexes are enabled.
+ */
+static void mbedtls_psa_random_init(mbedtls_psa_random_context_t *rng)
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    memset(rng, 0, sizeof(*rng));
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+    /* Set default configuration if
+     * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */
+    if (rng->entropy_init == NULL) {
+        rng->entropy_init = mbedtls_entropy_init;
+    }
+    if (rng->entropy_free == NULL) {
+        rng->entropy_free = mbedtls_entropy_free;
+    }
+
+    rng->entropy_init(&rng->entropy);
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \
+    defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
+    /* The PSA entropy injection feature depends on using NV seed as an entropy
+     * source. Add NV seed as an entropy source for PSA entropy injection. */
+    mbedtls_entropy_add_source(&rng->entropy,
+                               mbedtls_nv_seed_poll, NULL,
+                               MBEDTLS_ENTROPY_BLOCK_SIZE,
+                               MBEDTLS_ENTROPY_SOURCE_STRONG);
+#endif
+
+    mbedtls_psa_drbg_init(&rng->drbg);
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+/** Deinitialize the PSA random generator.
+ *
+ *  Note: the mbedtls_threading_psa_rngdata_mutex should be held when calling
+ *  this function if mutexes are enabled.
+ */
+static void mbedtls_psa_random_free(mbedtls_psa_random_context_t *rng)
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    memset(rng, 0, sizeof(*rng));
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+    mbedtls_psa_drbg_free(&rng->drbg);
+    rng->entropy_free(&rng->entropy);
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+/** Seed the PSA random generator.
+ */
+static psa_status_t mbedtls_psa_random_seed(mbedtls_psa_random_context_t *rng)
+{
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+    /* Do nothing: the external RNG seeds itself. */
+    (void) rng;
+    return PSA_SUCCESS;
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+    const unsigned char drbg_seed[] = "PSA";
+    int ret = mbedtls_psa_drbg_seed(&rng->drbg, &rng->entropy,
+                                    drbg_seed, sizeof(drbg_seed) - 1);
+    return mbedtls_to_psa_error(ret);
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+}
+
+psa_status_t psa_generate_random(uint8_t *output_external,
+                                 size_t output_size)
+{
+    psa_status_t status;
+
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_generate_random_internal(output, output_size);
+
+#if !defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+exit:
+#endif
+    LOCAL_OUTPUT_FREE(output_external, output);
+    return status;
+}
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+psa_status_t mbedtls_psa_inject_entropy(const uint8_t *seed,
+                                        size_t seed_size)
+{
+    if (psa_get_initialized()) {
+        return PSA_ERROR_NOT_PERMITTED;
+    }
+
+    if (((seed_size < MBEDTLS_ENTROPY_MIN_PLATFORM) ||
+         (seed_size < MBEDTLS_ENTROPY_BLOCK_SIZE)) ||
+        (seed_size > MBEDTLS_ENTROPY_MAX_SEED_SIZE)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return mbedtls_psa_storage_inject_entropy(seed, seed_size);
+}
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+
+/** Validate the key type and size for key generation
+ *
+ * \param  type  The key type
+ * \param  bits  The number of bits of the key
+ *
+ * \retval #PSA_SUCCESS
+ *         The key type and size are valid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size in bits of the key is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The type and/or the size in bits of the key or the combination of
+ *         the two is not supported.
+ */
+static psa_status_t psa_validate_key_type_and_size_for_key_generation(
+    psa_key_type_t type, size_t bits)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (key_type_is_raw_bytes(type)) {
+        status = psa_validate_unstructured_key_bit_size(type, bits);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    } else
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    if (PSA_KEY_TYPE_IS_RSA(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+        if (bits < PSA_VENDOR_RSA_GENERATE_MIN_KEY_BITS) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+
+        /* Accept only byte-aligned keys, for the same reasons as
+         * in psa_import_rsa_key(). */
+        if (bits % 8 != 0) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+    } else
+#endif /* defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+    if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        /* To avoid empty block, return successfully here. */
+        return PSA_SUCCESS;
+    } else
+#endif /* defined(PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */
+
+#if defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+    if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        if (psa_is_dh_key_size_valid(bits) == 0) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+    } else
+#endif /* defined(PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) */
+    {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_generate_key_internal(
+    const psa_key_attributes_t *attributes,
+    const psa_custom_key_parameters_t *custom,
+    const uint8_t *custom_data,
+    size_t custom_data_length,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_type_t type = attributes->type;
+
+    /* Only used for RSA */
+    (void) custom;
+    (void) custom_data;
+    (void) custom_data_length;
+
+    if (key_type_is_raw_bytes(type)) {
+        status = psa_generate_random_internal(key_buffer, key_buffer_size);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+        if (type == PSA_KEY_TYPE_DES) {
+            psa_des_set_key_parity(key_buffer, key_buffer_size);
+        }
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES */
+    } else
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    if (type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        return mbedtls_psa_rsa_generate_key(attributes,
+                                            custom_data, custom_data_length,
+                                            key_buffer,
+                                            key_buffer_size,
+                                            key_buffer_length);
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+    if (PSA_KEY_TYPE_IS_ECC(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        return mbedtls_psa_ecp_generate_key(attributes,
+                                            key_buffer,
+                                            key_buffer_size,
+                                            key_buffer_length);
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+    if (PSA_KEY_TYPE_IS_DH(type) && PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        return mbedtls_psa_ffdh_generate_key(attributes,
+                                             key_buffer,
+                                             key_buffer_size,
+                                             key_buffer_length);
+    } else
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) */
+    {
+        (void) key_buffer_length;
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_generate_key_custom(const psa_key_attributes_t *attributes,
+                                     const psa_custom_key_parameters_t *custom,
+                                     const uint8_t *custom_data,
+                                     size_t custom_data_length,
+                                     mbedtls_svc_key_id_t *key)
+{
+    psa_status_t status;
+    psa_key_slot_t *slot = NULL;
+    psa_se_drv_table_entry_t *driver = NULL;
+    size_t key_buffer_size;
+
+    *key = MBEDTLS_SVC_KEY_ID_INIT;
+
+    /* Reject any attempt to create a zero-length key so that we don't
+     * risk tripping up later, e.g. on a malloc(0) that returns NULL. */
+    if (psa_get_key_bits(attributes) == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    /* Reject any attempt to create a public key. */
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(attributes->type)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+        if (custom->flags != 0) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else
+#endif
+    if (!psa_custom_key_parameters_are_default(custom, custom_data_length)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_start_key_creation(PSA_KEY_CREATION_GENERATE, attributes,
+                                    &slot, &driver);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* In the case of a transparent key or an opaque key stored in local
+     * storage ( thus not in the case of generating a key in a secure element
+     * with storage ( MBEDTLS_PSA_CRYPTO_SE_C ) ),we have to allocate a
+     * buffer to hold the generated key material. */
+    if (slot->key.data == NULL) {
+        if (PSA_KEY_LIFETIME_GET_LOCATION(attributes->lifetime) ==
+            PSA_KEY_LOCATION_LOCAL_STORAGE) {
+            status = psa_validate_key_type_and_size_for_key_generation(
+                attributes->type, attributes->bits);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            key_buffer_size = PSA_EXPORT_KEY_OUTPUT_SIZE(
+                attributes->type,
+                attributes->bits);
+        } else {
+            status = psa_driver_wrapper_get_key_buffer_size(
+                attributes, &key_buffer_size);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+        }
+
+        status = psa_allocate_buffer_to_slot(slot, key_buffer_size);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    status = psa_driver_wrapper_generate_key(attributes,
+                                             custom,
+                                             custom_data, custom_data_length,
+                                             slot->key.data, slot->key.bytes,
+                                             &slot->key.bytes);
+    if (status != PSA_SUCCESS) {
+        psa_remove_key_data_from_memory(slot);
+    }
+
+exit:
+    if (status == PSA_SUCCESS) {
+        status = psa_finish_key_creation(slot, driver, key);
+    }
+    if (status != PSA_SUCCESS) {
+        psa_fail_key_creation(slot, driver);
+    }
+
+    return status;
+}
+
+psa_status_t psa_generate_key_ext(const psa_key_attributes_t *attributes,
+                                  const psa_key_production_parameters_t *params,
+                                  size_t params_data_length,
+                                  mbedtls_svc_key_id_t *key)
+{
+    return psa_generate_key_custom(
+        attributes,
+        (const psa_custom_key_parameters_t *) params,
+        params->data, params_data_length,
+        key);
+}
+
+psa_status_t psa_generate_key(const psa_key_attributes_t *attributes,
+                              mbedtls_svc_key_id_t *key)
+{
+    return psa_generate_key_custom(attributes,
+                                   &default_custom_production,
+                                   NULL, 0,
+                                   key);
+}
+
+/****************************************************************/
+/* Module setup */
+/****************************************************************/
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
+    void (* entropy_init)(mbedtls_entropy_context *ctx),
+    void (* entropy_free)(mbedtls_entropy_context *ctx))
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    if (global_data.rng_state != RNG_NOT_INITIALIZED) {
+        status = PSA_ERROR_BAD_STATE;
+    } else {
+        global_data.rng.entropy_init = entropy_init;
+        global_data.rng.entropy_free = entropy_free;
+        status = PSA_SUCCESS;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return status;
+}
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+void mbedtls_psa_crypto_free(void)
+{
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    /* Nothing to do to free transaction. */
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED) {
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+    }
+
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED) {
+        psa_wipe_all_key_slots();
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    if (global_data.rng_state != RNG_NOT_INITIALIZED) {
+        mbedtls_psa_random_free(&global_data.rng);
+    }
+    global_data.rng_state = RNG_NOT_INITIALIZED;
+    mbedtls_platform_zeroize(&global_data.rng, sizeof(global_data.rng));
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_rngdata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    /* Terminate drivers */
+    if (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED) {
+        psa_driver_wrapper_free();
+        global_data.initialized &= ~PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+}
+
+#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
+/** Recover a transaction that was interrupted by a power failure.
+ *
+ * This function is called during initialization, before psa_crypto_init()
+ * returns. If this function returns a failure status, the initialization
+ * fails.
+ */
+static psa_status_t psa_crypto_recover_transaction(
+    const psa_crypto_transaction_t *transaction)
+{
+    switch (transaction->unknown.type) {
+        case PSA_CRYPTO_TRANSACTION_CREATE_KEY:
+        case PSA_CRYPTO_TRANSACTION_DESTROY_KEY:
+        /* TODO - fall through to the failure case until this
+         * is implemented.
+         * https://github.com/ARMmbed/mbed-crypto/issues/218
+         */
+        default:
+            /* We found an unsupported transaction in the storage.
+             * We don't know what state the storage is in. Give up. */
+            return PSA_ERROR_DATA_INVALID;
+    }
+}
+#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
+
+static psa_status_t mbedtls_psa_crypto_init_subsystem(mbedtls_psa_crypto_subsystem subsystem)
+{
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t driver_wrappers_initialized = 0;
+
+    switch (subsystem) {
+        case PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED)) {
+                /* Init drivers */
+                status = psa_driver_wrapper_init();
+
+                /* Drivers need shutdown regardless of startup errors. */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED;
+
+
+            }
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED)) {
+                status = psa_initialize_key_slots();
+
+                /* Need to wipe keys even if initialization fails. */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS_INITIALIZED;
+
+            }
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_RNG:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            driver_wrappers_initialized =
+                (global_data.initialized & PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS_INITIALIZED);
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            /* Need to use separate mutex here, as initialisation can require
+             * testing of init flags, which requires locking the global data
+             * mutex. */
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_rngdata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            /* Initialize and seed the random generator. */
+            if (global_data.rng_state == RNG_NOT_INITIALIZED && driver_wrappers_initialized) {
+                mbedtls_psa_random_init(&global_data.rng);
+                global_data.rng_state = RNG_INITIALIZED;
+
+                status = mbedtls_psa_random_seed(&global_data.rng);
+                if (status == PSA_SUCCESS) {
+                    global_data.rng_state = RNG_SEEDED;
+                }
+            }
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_rngdata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        case PSA_CRYPTO_SUBSYSTEM_TRANSACTION:
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            if (!(global_data.initialized & PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED)) {
+#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
+                status = psa_crypto_load_transaction();
+                if (status == PSA_SUCCESS) {
+                    status = psa_crypto_recover_transaction(&psa_crypto_transaction);
+                    if (status == PSA_SUCCESS) {
+                        global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                    }
+                    status = psa_crypto_stop_transaction();
+                } else if (status == PSA_ERROR_DOES_NOT_EXIST) {
+                    /* There's no transaction to complete. It's all good. */
+                    global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                    status = PSA_SUCCESS;
+                }
+#else /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
+                global_data.initialized |= PSA_CRYPTO_SUBSYSTEM_TRANSACTION_INITIALIZED;
+                status = PSA_SUCCESS;
+#endif /* defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS) */
+            }
+
+#if defined(MBEDTLS_THREADING_C)
+            PSA_THREADING_CHK_GOTO_EXIT(mbedtls_mutex_unlock(
+                                            &mbedtls_threading_psa_globaldata_mutex));
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+            break;
+
+        default:
+            status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    /* Exit label only required when using threading macros. */
+#if defined(MBEDTLS_THREADING_C)
+exit:
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return status;
+}
+
+psa_status_t psa_crypto_init(void)
+{
+    psa_status_t status;
+
+    /* Double initialization is explicitly allowed. Early out if everything is
+     * done. */
+    if (psa_get_initialized()) {
+        return PSA_SUCCESS;
+    }
+
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_DRIVER_WRAPPERS);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_KEY_SLOTS);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_RNG);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_psa_crypto_init_subsystem(PSA_CRYPTO_SUBSYSTEM_TRANSACTION);
+
+exit:
+
+    if (status != PSA_SUCCESS) {
+        mbedtls_psa_crypto_free();
+    }
+
+    return status;
+}
+
+#if defined(PSA_WANT_ALG_SOME_PAKE)
+psa_status_t psa_crypto_driver_pake_get_password_len(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    size_t *password_len)
+{
+    if (inputs->password_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    *password_len = inputs->password_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_password(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    uint8_t *buffer, size_t buffer_size, size_t *buffer_length)
+{
+    if (inputs->password_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (buffer_size < inputs->password_len) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    memcpy(buffer, inputs->password, inputs->password_len);
+    *buffer_length = inputs->password_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_user_len(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    size_t *user_len)
+{
+    if (inputs->user_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    *user_len = inputs->user_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_user(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    uint8_t *user_id, size_t user_id_size, size_t *user_id_len)
+{
+    if (inputs->user_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (user_id_size < inputs->user_len) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    memcpy(user_id, inputs->user, inputs->user_len);
+    *user_id_len = inputs->user_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_peer_len(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    size_t *peer_len)
+{
+    if (inputs->peer_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    *peer_len = inputs->peer_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_peer(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    uint8_t *peer_id, size_t peer_id_size, size_t *peer_id_length)
+{
+    if (inputs->peer_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (peer_id_size < inputs->peer_len) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    memcpy(peer_id, inputs->peer, inputs->peer_len);
+    *peer_id_length = inputs->peer_len;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_driver_pake_get_cipher_suite(
+    const psa_crypto_driver_pake_inputs_t *inputs,
+    psa_pake_cipher_suite_t *cipher_suite)
+{
+    if (inputs->cipher_suite.algorithm == PSA_ALG_NONE) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    *cipher_suite = inputs->cipher_suite;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_pake_setup(
+    psa_pake_operation_t *operation,
+    const psa_pake_cipher_suite_t *cipher_suite)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_SETUP) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (PSA_ALG_IS_PAKE(cipher_suite->algorithm) == 0 ||
+        PSA_ALG_IS_HASH(cipher_suite->hash) == 0) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    memset(&operation->data.inputs, 0, sizeof(operation->data.inputs));
+
+    operation->alg = cipher_suite->algorithm;
+    operation->primitive = PSA_PAKE_PRIMITIVE(cipher_suite->type,
+                                              cipher_suite->family, cipher_suite->bits);
+    operation->data.inputs.cipher_suite = *cipher_suite;
+
+#if defined(PSA_WANT_ALG_JPAKE)
+    if (operation->alg == PSA_ALG_JPAKE) {
+        psa_jpake_computation_stage_t *computation_stage =
+            &operation->computation_stage.jpake;
+
+        memset(computation_stage, 0, sizeof(*computation_stage));
+        computation_stage->step = PSA_PAKE_STEP_KEY_SHARE;
+    } else
+#endif /* PSA_WANT_ALG_JPAKE */
+    {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+
+    operation->stage = PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS;
+
+    return PSA_SUCCESS;
+exit:
+    psa_pake_abort(operation);
+    return status;
+}
+
+psa_status_t psa_pake_set_password_key(
+    psa_pake_operation_t *operation,
+    mbedtls_svc_key_id_t password)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t unlock_status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot = NULL;
+    psa_key_type_t type;
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    status = psa_get_and_lock_key_slot_with_policy(password, &slot,
+                                                   PSA_KEY_USAGE_DERIVE,
+                                                   operation->alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    type = psa_get_key_type(&slot->attr);
+
+    if (type != PSA_KEY_TYPE_PASSWORD &&
+        type != PSA_KEY_TYPE_PASSWORD_HASH) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    operation->data.inputs.password = mbedtls_calloc(1, slot->key.bytes);
+    if (operation->data.inputs.password == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto exit;
+    }
+
+    memcpy(operation->data.inputs.password, slot->key.data, slot->key.bytes);
+    operation->data.inputs.password_len = slot->key.bytes;
+    operation->data.inputs.attributes = slot->attr;
+
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
+    unlock_status = psa_unregister_read_under_mutex(slot);
+    return (status == PSA_SUCCESS) ? unlock_status : status;
+}
+
+psa_status_t psa_pake_set_user(
+    psa_pake_operation_t *operation,
+    const uint8_t *user_id_external,
+    size_t user_id_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(user_id_external, user_id);
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (user_id_len == 0) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    if (operation->data.inputs.user_len != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    operation->data.inputs.user = mbedtls_calloc(1, user_id_len);
+    if (operation->data.inputs.user == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(user_id_external, user_id_len, user_id);
+
+    memcpy(operation->data.inputs.user, user_id, user_id_len);
+    operation->data.inputs.user_len = user_id_len;
+
+    status = PSA_SUCCESS;
+
+exit:
+    LOCAL_INPUT_FREE(user_id_external, user_id);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
+    return status;
+}
+
+psa_status_t psa_pake_set_peer(
+    psa_pake_operation_t *operation,
+    const uint8_t *peer_id_external,
+    size_t peer_id_len)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    LOCAL_INPUT_DECLARE(peer_id_external, peer_id);
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (peer_id_len == 0) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    if (operation->data.inputs.peer_len != 0) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    operation->data.inputs.peer = mbedtls_calloc(1, peer_id_len);
+    if (operation->data.inputs.peer == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(peer_id_external, peer_id_len, peer_id);
+
+    memcpy(operation->data.inputs.peer, peer_id, peer_id_len);
+    operation->data.inputs.peer_len = peer_id_len;
+
+    status = PSA_SUCCESS;
+
+exit:
+    LOCAL_INPUT_FREE(peer_id_external, peer_id);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
+    return status;
+}
+
+psa_status_t psa_pake_set_role(
+    psa_pake_operation_t *operation,
+    psa_pake_role_t role)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        case PSA_ALG_JPAKE:
+            if (role == PSA_PAKE_ROLE_NONE) {
+                return PSA_SUCCESS;
+            }
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            break;
+#endif
+        default:
+            (void) role;
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+    }
+exit:
+    psa_pake_abort(operation);
+    return status;
+}
+
+/* Auxiliary function to convert core computation stage to single driver step. */
+#if defined(PSA_WANT_ALG_JPAKE)
+static psa_crypto_driver_pake_step_t convert_jpake_computation_stage_to_driver_step(
+    psa_jpake_computation_stage_t *stage)
+{
+    psa_crypto_driver_pake_step_t key_share_step;
+    if (stage->round == PSA_JPAKE_FIRST) {
+        int is_x1;
+
+        if (stage->io_mode == PSA_JPAKE_OUTPUT) {
+            is_x1 = (stage->outputs < 1);
+        } else {
+            is_x1 = (stage->inputs < 1);
+        }
+
+        key_share_step = is_x1 ?
+                         PSA_JPAKE_X1_STEP_KEY_SHARE :
+                         PSA_JPAKE_X2_STEP_KEY_SHARE;
+    } else if (stage->round == PSA_JPAKE_SECOND) {
+        key_share_step = (stage->io_mode == PSA_JPAKE_OUTPUT) ?
+                         PSA_JPAKE_X2S_STEP_KEY_SHARE :
+                         PSA_JPAKE_X4S_STEP_KEY_SHARE;
+    } else {
+        return PSA_JPAKE_STEP_INVALID;
+    }
+    return (psa_crypto_driver_pake_step_t) (key_share_step + stage->step - PSA_PAKE_STEP_KEY_SHARE);
+}
+#endif /* PSA_WANT_ALG_JPAKE */
+
+static psa_status_t psa_pake_complete_inputs(
+    psa_pake_operation_t *operation)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    /* Create copy of the inputs on stack as inputs share memory
+       with the driver context which will be setup by the driver. */
+    psa_crypto_driver_pake_inputs_t inputs = operation->data.inputs;
+
+    if (inputs.password_len == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (operation->alg == PSA_ALG_JPAKE) {
+        if (inputs.user_len == 0 || inputs.peer_len == 0) {
+            return PSA_ERROR_BAD_STATE;
+        }
+    }
+
+    /* Clear driver context */
+    mbedtls_platform_zeroize(&operation->data, sizeof(operation->data));
+
+    status = psa_driver_wrapper_pake_setup(operation, &inputs);
+
+    /* Driver is responsible for creating its own copy of the password. */
+    mbedtls_zeroize_and_free(inputs.password, inputs.password_len);
+
+    /* User and peer are translated to role. */
+    mbedtls_free(inputs.user);
+    mbedtls_free(inputs.peer);
+
+    if (status == PSA_SUCCESS) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        if (operation->alg == PSA_ALG_JPAKE) {
+            operation->stage = PSA_PAKE_OPERATION_STAGE_COMPUTATION;
+        } else
+#endif /* PSA_WANT_ALG_JPAKE */
+        {
+            status = PSA_ERROR_NOT_SUPPORTED;
+        }
+    }
+    return status;
+}
+
+#if defined(PSA_WANT_ALG_JPAKE)
+static psa_status_t psa_jpake_prologue(
+    psa_pake_operation_t *operation,
+    psa_pake_step_t step,
+    psa_jpake_io_mode_t io_mode)
+{
+    if (step != PSA_PAKE_STEP_KEY_SHARE &&
+        step != PSA_PAKE_STEP_ZK_PUBLIC &&
+        step != PSA_PAKE_STEP_ZK_PROOF) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    psa_jpake_computation_stage_t *computation_stage =
+        &operation->computation_stage.jpake;
+
+    if (computation_stage->round != PSA_JPAKE_FIRST &&
+        computation_stage->round != PSA_JPAKE_SECOND) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    /* Check that the step we are given is the one we were expecting */
+    if (step != computation_stage->step) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    if (step == PSA_PAKE_STEP_KEY_SHARE &&
+        computation_stage->inputs == 0 &&
+        computation_stage->outputs == 0) {
+        /* Start of the round, so function decides whether we are inputting
+         * or outputting */
+        computation_stage->io_mode = io_mode;
+    } else if (computation_stage->io_mode != io_mode) {
+        /* Middle of the round so the mode we are in must match the function
+         * called by the user */
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t psa_jpake_epilogue(
+    psa_pake_operation_t *operation,
+    psa_jpake_io_mode_t io_mode)
+{
+    psa_jpake_computation_stage_t *stage =
+        &operation->computation_stage.jpake;
+
+    if (stage->step == PSA_PAKE_STEP_ZK_PROOF) {
+        /* End of an input/output */
+        if (io_mode == PSA_JPAKE_INPUT) {
+            stage->inputs++;
+            if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round)) {
+                stage->io_mode = PSA_JPAKE_OUTPUT;
+            }
+        }
+        if (io_mode == PSA_JPAKE_OUTPUT) {
+            stage->outputs++;
+            if (stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
+                stage->io_mode = PSA_JPAKE_INPUT;
+            }
+        }
+        if (stage->inputs == PSA_JPAKE_EXPECTED_INPUTS(stage->round) &&
+            stage->outputs == PSA_JPAKE_EXPECTED_OUTPUTS(stage->round)) {
+            /* End of a round, move to the next round */
+            stage->inputs = 0;
+            stage->outputs = 0;
+            stage->round++;
+        }
+        stage->step = PSA_PAKE_STEP_KEY_SHARE;
+    } else {
+        stage->step++;
+    }
+    return PSA_SUCCESS;
+}
+
+#endif /* PSA_WANT_ALG_JPAKE */
+
+psa_status_t psa_pake_output(
+    psa_pake_operation_t *operation,
+    psa_pake_step_t step,
+    uint8_t *output_external,
+    size_t output_size,
+    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
+    LOCAL_OUTPUT_DECLARE(output_external, output);
+    *output_length = 0;
+
+    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = psa_pake_complete_inputs(operation);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (output_size == 0) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        case PSA_ALG_JPAKE:
+            status = psa_jpake_prologue(operation, step, PSA_JPAKE_OUTPUT);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+            driver_step = convert_jpake_computation_stage_to_driver_step(
+                &operation->computation_stage.jpake);
+            break;
+#endif /* PSA_WANT_ALG_JPAKE */
+        default:
+            (void) step;
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+    }
+
+    LOCAL_OUTPUT_ALLOC(output_external, output_size, output);
+
+    status = psa_driver_wrapper_pake_output(operation, driver_step,
+                                            output, output_size, output_length);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        case PSA_ALG_JPAKE:
+            status = psa_jpake_epilogue(operation, PSA_JPAKE_OUTPUT);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+            break;
+#endif /* PSA_WANT_ALG_JPAKE */
+        default:
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+    }
+
+exit:
+    LOCAL_OUTPUT_FREE(output_external, output);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
+    return status;
+}
+
+psa_status_t psa_pake_input(
+    psa_pake_operation_t *operation,
+    psa_pake_step_t step,
+    const uint8_t *input_external,
+    size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_crypto_driver_pake_step_t driver_step = PSA_JPAKE_STEP_INVALID;
+    const size_t max_input_length = (size_t) PSA_PAKE_INPUT_SIZE(operation->alg,
+                                                                 operation->primitive,
+                                                                 step);
+    LOCAL_INPUT_DECLARE(input_external, input);
+
+    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        status = psa_pake_complete_inputs(operation);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
+        status =  PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+    if (input_length == 0 || input_length > max_input_length) {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        case PSA_ALG_JPAKE:
+            status = psa_jpake_prologue(operation, step, PSA_JPAKE_INPUT);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+            driver_step = convert_jpake_computation_stage_to_driver_step(
+                &operation->computation_stage.jpake);
+            break;
+#endif /* PSA_WANT_ALG_JPAKE */
+        default:
+            (void) step;
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+    }
+
+    LOCAL_INPUT_ALLOC(input_external, input_length, input);
+    status = psa_driver_wrapper_pake_input(operation, driver_step,
+                                           input, input_length);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(PSA_WANT_ALG_JPAKE)
+        case PSA_ALG_JPAKE:
+            status = psa_jpake_epilogue(operation, PSA_JPAKE_INPUT);
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+            break;
+#endif /* PSA_WANT_ALG_JPAKE */
+        default:
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+    }
+
+exit:
+    LOCAL_INPUT_FREE(input_external, input);
+    if (status != PSA_SUCCESS) {
+        psa_pake_abort(operation);
+    }
+    return status;
+}
+
+psa_status_t psa_pake_get_implicit_key(
+    psa_pake_operation_t *operation,
+    psa_key_derivation_operation_t *output)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+    uint8_t shared_key[MBEDTLS_PSA_JPAKE_BUFFER_SIZE];
+    size_t shared_key_len = 0;
+
+    if (operation->stage != PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
+        status = PSA_ERROR_BAD_STATE;
+        goto exit;
+    }
+
+#if defined(PSA_WANT_ALG_JPAKE)
+    if (operation->alg == PSA_ALG_JPAKE) {
+        psa_jpake_computation_stage_t *computation_stage =
+            &operation->computation_stage.jpake;
+        if (computation_stage->round != PSA_JPAKE_FINISHED) {
+            status = PSA_ERROR_BAD_STATE;
+            goto exit;
+        }
+    } else
+#endif /* PSA_WANT_ALG_JPAKE */
+    {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+
+    status = psa_driver_wrapper_pake_get_implicit_key(operation,
+                                                      shared_key,
+                                                      sizeof(shared_key),
+                                                      &shared_key_len);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_key_derivation_input_bytes(output,
+                                            PSA_KEY_DERIVATION_INPUT_SECRET,
+                                            shared_key,
+                                            shared_key_len);
+
+    mbedtls_platform_zeroize(shared_key, sizeof(shared_key));
+exit:
+    abort_status = psa_pake_abort(operation);
+    return status == PSA_SUCCESS ? abort_status : status;
+}
+
+psa_status_t psa_pake_abort(
+    psa_pake_operation_t *operation)
+{
+    psa_status_t status = PSA_SUCCESS;
+
+    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COMPUTATION) {
+        status = psa_driver_wrapper_pake_abort(operation);
+    }
+
+    if (operation->stage == PSA_PAKE_OPERATION_STAGE_COLLECT_INPUTS) {
+        if (operation->data.inputs.password != NULL) {
+            mbedtls_zeroize_and_free(operation->data.inputs.password,
+                                     operation->data.inputs.password_len);
+        }
+        if (operation->data.inputs.user != NULL) {
+            mbedtls_free(operation->data.inputs.user);
+        }
+        if (operation->data.inputs.peer != NULL) {
+            mbedtls_free(operation->data.inputs.peer);
+        }
+    }
+    memset(operation, 0, sizeof(psa_pake_operation_t));
+
+    return status;
+}
+#endif /* PSA_WANT_ALG_SOME_PAKE */
+
+/* Memory copying test hooks. These are called before input copy, after input
+ * copy, before output copy and after output copy, respectively.
+ * They are used by memory-poisoning tests to temporarily unpoison buffers
+ * while they are copied. */
+#if defined(MBEDTLS_TEST_HOOKS)
+void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
+void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len) = NULL;
+void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
+void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len) = NULL;
+#endif
+
+/** Copy from an input buffer to a local copy.
+ *
+ * \param[in] input             Pointer to input buffer.
+ * \param[in] input_len         Length of the input buffer.
+ * \param[out] input_copy       Pointer to a local copy in which to store the input data.
+ * \param[out] input_copy_len   Length of the local copy buffer.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_CORRUPTION_DETECTED, if the local
+ *                              copy is too small to hold contents of the
+ *                              input buffer.
+ */
+MBEDTLS_STATIC_TESTABLE
+psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,
+                                   uint8_t *input_copy, size_t input_copy_len)
+{
+    if (input_len > input_copy_len) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_input_pre_copy_hook != NULL) {
+        psa_input_pre_copy_hook(input, input_len);
+    }
+#endif
+
+    if (input_len > 0) {
+        memcpy(input_copy, input, input_len);
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_input_post_copy_hook != NULL) {
+        psa_input_post_copy_hook(input, input_len);
+    }
+#endif
+
+    return PSA_SUCCESS;
+}
+
+/** Copy from a local output buffer into a user-supplied one.
+ *
+ * \param[in] output_copy       Pointer to a local buffer containing the output.
+ * \param[in] output_copy_len   Length of the local buffer.
+ * \param[out] output           Pointer to user-supplied output buffer.
+ * \param[out] output_len       Length of the user-supplied output buffer.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_BUFFER_TOO_SMALL, if the
+ *                              user-supplied output buffer is too small to
+ *                              hold the contents of the local buffer.
+ */
+MBEDTLS_STATIC_TESTABLE
+psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,
+                                    uint8_t *output, size_t output_len)
+{
+    if (output_len < output_copy_len) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_output_pre_copy_hook != NULL) {
+        psa_output_pre_copy_hook(output, output_len);
+    }
+#endif
+
+    if (output_copy_len > 0) {
+        memcpy(output, output_copy, output_copy_len);
+    }
+
+#if defined(MBEDTLS_TEST_HOOKS)
+    if (psa_output_post_copy_hook != NULL) {
+        psa_output_post_copy_hook(output, output_len);
+    }
+#endif
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
+                                          psa_crypto_local_input_t *local_input)
+{
+    psa_status_t status;
+
+    *local_input = PSA_CRYPTO_LOCAL_INPUT_INIT;
+
+    if (input_len == 0) {
+        return PSA_SUCCESS;
+    }
+
+    local_input->buffer = mbedtls_calloc(input_len, 1);
+    if (local_input->buffer == NULL) {
+        /* Since we dealt with the zero-length case above, we know that
+         * a NULL return value means a failure of allocation. */
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    /* From now on, we must free local_input->buffer on error. */
+
+    local_input->length = input_len;
+
+    status = psa_crypto_copy_input(input, input_len,
+                                   local_input->buffer, local_input->length);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    return PSA_SUCCESS;
+
+error:
+    mbedtls_free(local_input->buffer);
+    local_input->buffer = NULL;
+    local_input->length = 0;
+    return status;
+}
+
+void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input)
+{
+    mbedtls_free(local_input->buffer);
+    local_input->buffer = NULL;
+    local_input->length = 0;
+}
+
+psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
+                                           psa_crypto_local_output_t *local_output)
+{
+    *local_output = PSA_CRYPTO_LOCAL_OUTPUT_INIT;
+
+    if (output_len == 0) {
+        return PSA_SUCCESS;
+    }
+    local_output->buffer = mbedtls_calloc(output_len, 1);
+    if (local_output->buffer == NULL) {
+        /* Since we dealt with the zero-length case above, we know that
+         * a NULL return value means a failure of allocation. */
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    local_output->length = output_len;
+    local_output->original = output;
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output)
+{
+    psa_status_t status;
+
+    if (local_output->buffer == NULL) {
+        local_output->length = 0;
+        return PSA_SUCCESS;
+    }
+    if (local_output->original == NULL) {
+        /* We have an internal copy but nothing to copy back to. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    status = psa_crypto_copy_output(local_output->buffer, local_output->length,
+                                    local_output->original, local_output->length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    mbedtls_free(local_output->buffer);
+    local_output->buffer = NULL;
+    local_output->length = 0;
+
+    return PSA_SUCCESS;
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_aead.c b/lib/libmbedtls/mbedtls/library/psa_crypto_aead.c
new file mode 100644
index 0000000000000000000000000000000000000000..a201985b4f0678ba881f4689222106421fa9789c
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_aead.c
@@ -0,0 +1,649 @@
+/*
+ *  PSA AEAD entry points
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa_crypto_aead.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_cipher.h"
+
+#include <string.h>
+#include "mbedtls/platform.h"
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/chachapoly.h"
+#include "mbedtls/cipher.h"
+#include "mbedtls/gcm.h"
+#include "mbedtls/error.h"
+
+static psa_status_t psa_aead_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_cipher_id_t cipher_id;
+    mbedtls_cipher_mode_t mode;
+    size_t key_bits = attributes->bits;
+    (void) key_buffer_size;
+
+    status = mbedtls_cipher_values_from_psa(alg, attributes->type,
+                                            &key_bits, &mode, &cipher_id);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    switch (PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
+            operation->alg = PSA_ALG_CCM;
+            /* CCM allows the following tag lengths: 4, 6, 8, 10, 12, 14, 16.
+             * The call to mbedtls_ccm_encrypt_and_tag or
+             * mbedtls_ccm_auth_decrypt will validate the tag length. */
+            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+
+            mbedtls_ccm_init(&operation->ctx.ccm);
+            status = mbedtls_to_psa_error(
+                mbedtls_ccm_setkey(&operation->ctx.ccm, cipher_id,
+                                   key_buffer, (unsigned int) key_bits));
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
+            operation->alg = PSA_ALG_GCM;
+            /* GCM allows the following tag lengths: 4, 8, 12, 13, 14, 15, 16.
+             * The call to mbedtls_gcm_crypt_and_tag or
+             * mbedtls_gcm_auth_decrypt will validate the tag length. */
+            if (PSA_BLOCK_CIPHER_BLOCK_LENGTH(attributes->type) != 16) {
+                return PSA_ERROR_INVALID_ARGUMENT;
+            }
+
+            mbedtls_gcm_init(&operation->ctx.gcm);
+            status = mbedtls_to_psa_error(
+                mbedtls_gcm_setkey(&operation->ctx.gcm, cipher_id,
+                                   key_buffer, (unsigned int) key_bits));
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
+            operation->alg = PSA_ALG_CHACHA20_POLY1305;
+            /* We only support the default tag length. */
+            if (alg != PSA_ALG_CHACHA20_POLY1305) {
+                return PSA_ERROR_NOT_SUPPORTED;
+            }
+
+            mbedtls_chachapoly_init(&operation->ctx.chachapoly);
+            status = mbedtls_to_psa_error(
+                mbedtls_chachapoly_setkey(&operation->ctx.chachapoly,
+                                          key_buffer));
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+
+        default:
+            (void) status;
+            (void) key_buffer;
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    operation->key_type = psa_get_key_type(attributes);
+
+    operation->tag_length = PSA_ALG_AEAD_GET_TAG_LENGTH(alg);
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
+    uint8_t *tag;
+
+    status = psa_aead_setup(&operation, attributes, key_buffer,
+                            key_buffer_size, alg);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* For all currently supported modes, the tag is at the end of the
+     * ciphertext. */
+    if (ciphertext_size < (plaintext_length + operation.tag_length)) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+    tag = ciphertext + plaintext_length;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation.alg == PSA_ALG_CCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_encrypt_and_tag(&operation.ctx.ccm,
+                                        plaintext_length,
+                                        nonce, nonce_length,
+                                        additional_data,
+                                        additional_data_length,
+                                        plaintext, ciphertext,
+                                        tag, operation.tag_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation.alg == PSA_ALG_GCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_crypt_and_tag(&operation.ctx.gcm,
+                                      MBEDTLS_GCM_ENCRYPT,
+                                      plaintext_length,
+                                      nonce, nonce_length,
+                                      additional_data, additional_data_length,
+                                      plaintext, ciphertext,
+                                      operation.tag_length, tag));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
+        if (operation.tag_length != 16) {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+        }
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_encrypt_and_tag(&operation.ctx.chachapoly,
+                                               plaintext_length,
+                                               nonce,
+                                               additional_data,
+                                               additional_data_length,
+                                               plaintext,
+                                               ciphertext,
+                                               tag));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) tag;
+        (void) nonce;
+        (void) nonce_length;
+        (void) additional_data;
+        (void) additional_data_length;
+        (void) plaintext;
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status == PSA_SUCCESS) {
+        *ciphertext_length = plaintext_length + operation.tag_length;
+    }
+
+exit:
+    mbedtls_psa_aead_abort(&operation);
+
+    return status;
+}
+
+/* Locate the tag in a ciphertext buffer containing the encrypted data
+ * followed by the tag. Return the length of the part preceding the tag in
+ * *plaintext_length. This is the size of the plaintext in modes where
+ * the encrypted data has the same size as the plaintext, such as
+ * CCM and GCM. */
+static psa_status_t psa_aead_unpadded_locate_tag(size_t tag_length,
+                                                 const uint8_t *ciphertext,
+                                                 size_t ciphertext_length,
+                                                 size_t plaintext_size,
+                                                 const uint8_t **p_tag)
+{
+    size_t payload_length;
+    if (tag_length > ciphertext_length) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    payload_length = ciphertext_length - tag_length;
+    if (payload_length > plaintext_size) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+    *p_tag = ciphertext + payload_length;
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_psa_aead_operation_t operation = MBEDTLS_PSA_AEAD_OPERATION_INIT;
+    const uint8_t *tag = NULL;
+
+    status = psa_aead_setup(&operation, attributes, key_buffer,
+                            key_buffer_size, alg);
+
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_aead_unpadded_locate_tag(operation.tag_length,
+                                          ciphertext, ciphertext_length,
+                                          plaintext_size, &tag);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation.alg == PSA_ALG_CCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_auth_decrypt(&operation.ctx.ccm,
+                                     ciphertext_length - operation.tag_length,
+                                     nonce, nonce_length,
+                                     additional_data,
+                                     additional_data_length,
+                                     ciphertext, plaintext,
+                                     tag, operation.tag_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation.alg == PSA_ALG_GCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_auth_decrypt(&operation.ctx.gcm,
+                                     ciphertext_length - operation.tag_length,
+                                     nonce, nonce_length,
+                                     additional_data,
+                                     additional_data_length,
+                                     tag, operation.tag_length,
+                                     ciphertext, plaintext));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation.alg == PSA_ALG_CHACHA20_POLY1305) {
+        if (operation.tag_length != 16) {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto exit;
+        }
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_auth_decrypt(&operation.ctx.chachapoly,
+                                            ciphertext_length - operation.tag_length,
+                                            nonce,
+                                            additional_data,
+                                            additional_data_length,
+                                            tag,
+                                            ciphertext,
+                                            plaintext));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) nonce;
+        (void) nonce_length;
+        (void) additional_data;
+        (void) additional_data_length;
+        (void) plaintext;
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status == PSA_SUCCESS) {
+        *plaintext_length = ciphertext_length - operation.tag_length;
+    }
+
+exit:
+    mbedtls_psa_aead_abort(&operation);
+
+    if (status == PSA_SUCCESS) {
+        *plaintext_length = ciphertext_length - operation.tag_length;
+    }
+    return status;
+}
+
+/* Set the key and algorithm for a multipart authenticated encryption
+ * operation. */
+psa_status_t mbedtls_psa_aead_encrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_aead_setup(operation, attributes, key_buffer,
+                            key_buffer_size, alg);
+
+    if (status == PSA_SUCCESS) {
+        operation->is_encrypt = 1;
+    }
+
+    return status;
+}
+
+/* Set the key and algorithm for a multipart authenticated decryption
+ * operation. */
+psa_status_t mbedtls_psa_aead_decrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    status = psa_aead_setup(operation, attributes, key_buffer,
+                            key_buffer_size, alg);
+
+    if (status == PSA_SUCCESS) {
+        operation->is_encrypt = 0;
+    }
+
+    return status;
+}
+
+/* Set a nonce for the multipart AEAD operation*/
+psa_status_t mbedtls_psa_aead_set_nonce(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation->alg == PSA_ALG_GCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_starts(&operation->ctx.gcm,
+                               operation->is_encrypt ?
+                               MBEDTLS_GCM_ENCRYPT : MBEDTLS_GCM_DECRYPT,
+                               nonce,
+                               nonce_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation->alg == PSA_ALG_CCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_starts(&operation->ctx.ccm,
+                               operation->is_encrypt ?
+                               MBEDTLS_CCM_ENCRYPT : MBEDTLS_CCM_DECRYPT,
+                               nonce,
+                               nonce_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
+        /* Note - ChaChaPoly allows an 8 byte nonce, but we would have to
+         * allocate a buffer in the operation, copy the nonce to it and pad
+         * it, so for now check the nonce is 12 bytes, as
+         * mbedtls_chachapoly_starts() assumes it can read 12 bytes from the
+         * passed in buffer. */
+        if (nonce_length != 12) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_starts(&operation->ctx.chachapoly,
+                                      nonce,
+                                      operation->is_encrypt ?
+                                      MBEDTLS_CHACHAPOLY_ENCRYPT :
+                                      MBEDTLS_CHACHAPOLY_DECRYPT));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) operation;
+        (void) nonce;
+        (void) nonce_length;
+
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+/* Declare the lengths of the message and additional data for AEAD. */
+psa_status_t mbedtls_psa_aead_set_lengths(
+    mbedtls_psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length)
+{
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation->alg == PSA_ALG_CCM) {
+        return mbedtls_to_psa_error(
+            mbedtls_ccm_set_lengths(&operation->ctx.ccm,
+                                    ad_length,
+                                    plaintext_length,
+                                    operation->tag_length));
+
+    }
+#else /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+    (void) operation;
+    (void) ad_length;
+    (void) plaintext_length;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+
+    return PSA_SUCCESS;
+}
+
+/* Pass additional data to an active multipart AEAD operation. */
+psa_status_t mbedtls_psa_aead_update_ad(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation->alg == PSA_ALG_GCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_gcm_update_ad(&operation->ctx.gcm, input, input_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation->alg == PSA_ALG_CCM) {
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_update_ad(&operation->ctx.ccm, input, input_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_update_aad(&operation->ctx.chachapoly,
+                                          input,
+                                          input_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) operation;
+        (void) input;
+        (void) input_length;
+
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+/* Encrypt or decrypt a message fragment in an active multipart AEAD
+ * operation.*/
+psa_status_t mbedtls_psa_aead_update(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    size_t update_output_length;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    update_output_length = input_length;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation->alg == PSA_ALG_GCM) {
+        status =  mbedtls_to_psa_error(
+            mbedtls_gcm_update(&operation->ctx.gcm,
+                               input, input_length,
+                               output, output_size,
+                               &update_output_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation->alg == PSA_ALG_CCM) {
+        if (output_size < input_length) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_update(&operation->ctx.ccm,
+                               input, input_length,
+                               output, output_size,
+                               &update_output_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
+        if (output_size < input_length) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_update(&operation->ctx.chachapoly,
+                                      input_length,
+                                      input,
+                                      output));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) operation;
+        (void) input;
+        (void) output;
+        (void) output_size;
+
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status == PSA_SUCCESS) {
+        *output_length = update_output_length;
+    }
+
+    return status;
+}
+
+/* Finish encrypting a message in a multipart AEAD operation. */
+psa_status_t mbedtls_psa_aead_finish(
+    mbedtls_psa_aead_operation_t *operation,
+    uint8_t *ciphertext,
+    size_t ciphertext_size,
+    size_t *ciphertext_length,
+    uint8_t *tag,
+    size_t tag_size,
+    size_t *tag_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t finish_output_size = 0;
+
+    if (tag_size < operation->tag_length) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+    if (operation->alg == PSA_ALG_GCM) {
+        status =  mbedtls_to_psa_error(
+            mbedtls_gcm_finish(&operation->ctx.gcm,
+                               ciphertext, ciphertext_size, ciphertext_length,
+                               tag, operation->tag_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+    if (operation->alg == PSA_ALG_CCM) {
+        /* tag must be big enough to store a tag of size passed into set
+         * lengths. */
+        if (tag_size < operation->tag_length) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_ccm_finish(&operation->ctx.ccm,
+                               tag, operation->tag_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+    if (operation->alg == PSA_ALG_CHACHA20_POLY1305) {
+        /* Belt and braces. Although the above tag_size check should have
+         * already done this, if we later start supporting smaller tag sizes
+         * for chachapoly, then passing a tag buffer smaller than 16 into here
+         * could cause a buffer overflow, so better safe than sorry. */
+        if (tag_size < 16) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_chachapoly_finish(&operation->ctx.chachapoly,
+                                      tag));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    {
+        (void) ciphertext;
+        (void) ciphertext_size;
+        (void) ciphertext_length;
+        (void) tag;
+        (void) tag_size;
+        (void) tag_length;
+
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status == PSA_SUCCESS) {
+        /* This will be zero for all supported algorithms currently, but left
+         * here for future support. */
+        *ciphertext_length = finish_output_size;
+        *tag_length = operation->tag_length;
+    }
+
+    return status;
+}
+
+/* Abort an AEAD operation */
+psa_status_t mbedtls_psa_aead_abort(
+    mbedtls_psa_aead_operation_t *operation)
+{
+    switch (operation->alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+        case PSA_ALG_CCM:
+            mbedtls_ccm_free(&operation->ctx.ccm);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+        case PSA_ALG_GCM:
+            mbedtls_gcm_free(&operation->ctx.gcm);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_GCM */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+        case PSA_ALG_CHACHA20_POLY1305:
+            mbedtls_chachapoly_free(&operation->ctx.chachapoly);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305 */
+    }
+
+    operation->is_encrypt = 0;
+
+    return PSA_SUCCESS;
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_aead.h b/lib/libmbedtls/mbedtls/library/psa_crypto_aead.h
new file mode 100644
index 0000000000000000000000000000000000000000..a3392199f61a8b9ef62fcfab063d936ee5a2ab0b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_aead.h
@@ -0,0 +1,499 @@
+/*
+ *  PSA AEAD driver entry points
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_AEAD_H
+#define PSA_CRYPTO_AEAD_H
+
+#include <psa/crypto.h>
+
+/**
+ * \brief Process an authenticated encryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_encrypt entry point. This function behaves as an aead_encrypt
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes         The attributes of the key to use for the
+ *                                operation.
+ * \param[in]  key_buffer         The buffer containing the key context.
+ * \param      key_buffer_size    Size of the \p key_buffer buffer in bytes.
+ * \param      alg                The AEAD algorithm to compute.
+ * \param[in]  nonce              Nonce or IV to use.
+ * \param      nonce_length       Size of the nonce buffer in bytes. This must
+ *                                be appropriate for the selected algorithm.
+ *                                The default nonce size is
+ *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where
+ *                                key_type is the type of key.
+ * \param[in]  additional_data    Additional data that will be authenticated
+ *                                but not encrypted.
+ * \param      additional_data_length  Size of additional_data in bytes.
+ * \param[in]  plaintext          Data that will be authenticated and encrypted.
+ * \param      plaintext_length   Size of plaintext in bytes.
+ * \param[out] ciphertext         Output buffer for the authenticated and
+ *                                encrypted data. The additional data is not
+ *                                part of this output. For algorithms where the
+ *                                encrypted data and the authentication tag are
+ *                                defined as separate outputs, the
+ *                                authentication tag is appended to the
+ *                                encrypted data.
+ * \param      ciphertext_size    Size of the ciphertext buffer in bytes. This
+ *                                must be appropriate for the selected algorithm
+ *                                and key:
+ *                                - A sufficient output size is
+ *                                  PSA_AEAD_ENCRYPT_OUTPUT_SIZE(key_type, alg,
+ *                                  plaintext_length) where key_type is the type
+ *                                  of key.
+ *                                - PSA_AEAD_ENCRYPT_OUTPUT_MAX_SIZE(
+ *                                  plaintext_length) evaluates to the maximum
+ *                                  ciphertext size of any supported AEAD
+ *                                  encryption.
+ * \param[out] ciphertext_length  On success, the size of the output in the
+ *                                ciphertext buffer.
+ *
+ * \retval #PSA_SUCCESS Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         ciphertext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length);
+
+/**
+ * \brief Process an authenticated decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_decrypt entry point. This function behaves as an aead_decrypt
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes         The attributes of the key to use for the
+ *                                operation.
+ * \param[in]  key_buffer         The buffer containing the key context.
+ * \param      key_buffer_size    Size of the \p key_buffer buffer in bytes.
+ * \param      alg                The AEAD algorithm to compute.
+ * \param[in]  nonce              Nonce or IV to use.
+ * \param      nonce_length       Size of the nonce buffer in bytes. This must
+ *                                be appropriate for the selected algorithm.
+ *                                The default nonce size is
+ *                                PSA_AEAD_NONCE_LENGTH(key_type, alg) where
+ *                                key_type is the type of key.
+ * \param[in]  additional_data    Additional data that has been authenticated
+ *                                but not encrypted.
+ * \param      additional_data_length  Size of additional_data in bytes.
+ * \param[in]  ciphertext         Data that has been authenticated and
+ *                                encrypted. For algorithms where the encrypted
+ *                                data and the authentication tag are defined
+ *                                as separate inputs, the buffer contains
+ *                                encrypted data followed by the authentication
+ *                                tag.
+ * \param      ciphertext_length  Size of ciphertext in bytes.
+ * \param[out] plaintext          Output buffer for the decrypted data.
+ * \param      plaintext_size     Size of the plaintext buffer in bytes. This
+ *                                must be appropriate for the selected algorithm
+ *                                and key:
+ *                                - A sufficient output size is
+ *                                  PSA_AEAD_DECRYPT_OUTPUT_SIZE(key_type, alg,
+ *                                  ciphertext_length) where key_type is the
+ *                                  type of key.
+ *                                - PSA_AEAD_DECRYPT_OUTPUT_MAX_SIZE(
+ *                                  ciphertext_length) evaluates to the maximum
+ *                                  plaintext size of any supported AEAD
+ *                                  decryption.
+ * \param[out] plaintext_length   On success, the size of the output in the
+ *                                plaintext buffer.
+ *
+ * \retval #PSA_SUCCESS Success.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The cipher is not authentic.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         plaintext_size is too small.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length);
+
+/** Set the key for a multipart authenticated encryption operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_encrypt_setup entry point. This function behaves as an
+ *       aead_encrypt_setup entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * If an error occurs at any step after a call to
+ * mbedtls_psa_aead_encrypt_setup(), the operation is reset by the PSA core by a
+ * call to mbedtls_psa_aead_abort(). The PSA core may call
+ * mbedtls_psa_aead_abort() at any time after the operation has been
+ * initialized, and is required to when the operation is no longer needed.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #mbedtls_psa_aead_operation_t and not yet in
+ *                              use.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param      key_buffer_size  Size of the \p key_buffer buffer in bytes.
+                                It must be consistent with the size in bits
+                                recorded in \p attributes.
+ * \param alg                   The AEAD algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An invalid block length was supplied.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Failed to allocate memory for key material
+ */
+psa_status_t mbedtls_psa_aead_encrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Set the key for a multipart authenticated decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       aead_decrypt_setup entry point. This function behaves as an
+ *       aead_decrypt_setup entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * If an error occurs at any step after a call to
+ * mbedtls_psa_aead_decrypt_setup(), the PSA core resets the operation by a
+ * call to mbedtls_psa_aead_abort(). The PSA core may call
+ * mbedtls_psa_aead_abort() at any time after the operation has been
+ * initialized, and is required to when the operation is no longer needed.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized as per the documentation for
+ *                              #mbedtls_psa_aead_operation_t and not yet in
+ *                              use.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param      key_buffer_size  Size of the \p key_buffer buffer in bytes.
+                                It must be consistent with the size in bits
+                                recorded in \p attributes.
+ * \param alg                   The AEAD algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_AEAD(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An invalid block length was supplied.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Failed to allocate memory for key material
+ */
+psa_status_t mbedtls_psa_aead_decrypt_setup(
+    mbedtls_psa_aead_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Set the nonce for an authenticated encryption or decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver aead_set_nonce
+ *       entry point. This function behaves as an aead_set_nonce entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * This function sets the nonce for the authenticated
+ * encryption or decryption operation.
+ *
+ * The PSA core calls mbedtls_psa_aead_encrypt_setup() or
+ * mbedtls_psa_aead_decrypt_setup() before calling this function.
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] nonce             Buffer containing the nonce to use.
+ * \param nonce_length          Size of the nonce in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p nonce is not acceptable for the chosen algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_set_nonce(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *nonce,
+    size_t nonce_length);
+
+/** Declare the lengths of the message and additional data for AEAD.
+ *
+ * \note The signature of this function is that of a PSA driver aead_set_lengths
+ *       entry point. This function behaves as an aead_set_lengths entry point
+ *       as defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls this function before calling mbedtls_psa_aead_update_ad()
+ * or mbedtls_psa_aead_update() if the algorithm for the operation requires it.
+ * If the algorithm does not require it, calling this function is optional, but
+ * if this function is called then the implementation must enforce the lengths.
+ *
+ * The PSA core may call this function before or after setting the nonce with
+ * mbedtls_psa_aead_set_nonce().
+ *
+ * - For #PSA_ALG_CCM, calling this function is required.
+ * - For the other AEAD algorithms defined in this specification, calling
+ *   this function is not required.
+ *
+ * If this function returns an error status, the PSA core calls
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param ad_length             Size of the non-encrypted additional
+ *                              authenticated data in bytes.
+ * \param plaintext_length      Size of the plaintext to encrypt in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         At least one of the lengths is not acceptable for the chosen
+ *         algorithm.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_set_lengths(
+    mbedtls_psa_aead_operation_t *operation,
+    size_t ad_length,
+    size_t plaintext_length);
+
+/** Pass additional data to an active AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_update_ad entry point. This function behaves as an aead_update_ad
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Additional data is authenticated, but not encrypted.
+ *
+ * The PSA core can call this function multiple times to pass successive
+ * fragments of the additional data. It will not call this function after
+ * passing data to encrypt or decrypt with mbedtls_psa_aead_update().
+ *
+ * Before calling this function, the PSA core will:
+ *    1. Call either mbedtls_psa_aead_encrypt_setup() or
+ *       mbedtls_psa_aead_decrypt_setup().
+ *    2. Set the nonce with mbedtls_psa_aead_set_nonce().
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] input             Buffer containing the fragment of
+ *                              additional data.
+ * \param input_length          Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Algorithm previously set is not supported in this configuration of
+ *         the library.
+ */
+psa_status_t mbedtls_psa_aead_update_ad(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length);
+
+/** Encrypt or decrypt a message fragment in an active AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_update entry point. This function behaves as an aead_update entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Before calling this function, the PSA core will:
+ *    1. Call either mbedtls_psa_aead_encrypt_setup() or
+ *       mbedtls_psa_aead_decrypt_setup(). The choice of setup function
+ *       determines whether this function encrypts or decrypts its input.
+ *    2. Set the nonce with mbedtls_psa_aead_set_nonce().
+ *    3. Call mbedtls_psa_aead_update_ad() to pass all the additional data.
+ *
+ * If this function returns an error status, the PSA core will call
+ * mbedtls_psa_aead_abort().
+ *
+ * This function does not require the input to be aligned to any
+ * particular block boundary. If the implementation can only process
+ * a whole block at a time, it must consume all the input provided, but
+ * it may delay the end of the corresponding output until a subsequent
+ * call to mbedtls_psa_aead_update(), mbedtls_psa_aead_finish() provides
+ * sufficient input. The amount of data that can be delayed in this way is
+ * bounded by #PSA_AEAD_UPDATE_OUTPUT_SIZE.
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[in] input             Buffer containing the message fragment to
+ *                              encrypt or decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                                algorithm and key:
+ *                                - A sufficient output size is
+ *                                  #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type,
+ *                                  \c alg, \p input_length) where
+ *                                  \c key_type is the type of key and \c alg is
+ *                                  the algorithm that were used to set up the
+ *                                  operation.
+ *                                - #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p
+ *                                  input_length) evaluates to the maximum
+ *                                  output size of any supported AEAD
+ *                                  algorithm.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ *         #PSA_AEAD_UPDATE_OUTPUT_SIZE(\c key_type, \c alg, \p input_length) or
+ *         #PSA_AEAD_UPDATE_OUTPUT_MAX_SIZE(\p input_length) can be used to
+ *         determine the required buffer size.
+ */
+psa_status_t mbedtls_psa_aead_update(
+    mbedtls_psa_aead_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length);
+
+/** Finish encrypting a message in an AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_finish entry point. This function behaves as an aead_finish entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * The operation must have been set up by the PSA core with
+ * mbedtls_psa_aead_encrypt_setup().
+ *
+ * This function finishes the authentication of the additional data
+ * formed by concatenating the inputs passed to preceding calls to
+ * mbedtls_psa_aead_update_ad() with the plaintext formed by concatenating the
+ * inputs passed to preceding calls to mbedtls_psa_aead_update().
+ *
+ * This function has two output buffers:
+ * - \p ciphertext contains trailing ciphertext that was buffered from
+ *   preceding calls to mbedtls_psa_aead_update().
+ * - \p tag contains the authentication tag.
+ *
+ * Whether or not this function returns successfully, the PSA core subsequently
+ * calls mbedtls_psa_aead_abort() to deactivate the operation.
+ *
+ * \param[in,out] operation     Active AEAD operation.
+ * \param[out] ciphertext       Buffer where the last part of the ciphertext
+ *                              is to be written.
+ * \param ciphertext_size       Size of the \p ciphertext buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - A sufficient output size is
+ *                                #PSA_AEAD_FINISH_OUTPUT_SIZE(\c key_type,
+ *                                \c alg) where \c key_type is the type of key
+ *                                and \c alg is the algorithm that were used to
+ *                                set up the operation.
+ *                              - #PSA_AEAD_FINISH_OUTPUT_MAX_SIZE evaluates to
+ *                                the maximum output size of any supported AEAD
+ *                                algorithm.
+ * \param[out] ciphertext_length On success, the number of bytes of
+ *                              returned ciphertext.
+ * \param[out] tag              Buffer where the authentication tag is
+ *                              to be written.
+ * \param tag_size              Size of the \p tag buffer in bytes.
+ *                              This must be appropriate for the selected
+ *                              algorithm and key:
+ *                              - The exact tag size is #PSA_AEAD_TAG_LENGTH(\c
+ *                                key_type, \c key_bits, \c alg) where
+ *                                \c key_type and \c key_bits are the type and
+ *                                bit-size of the key, and \c alg are the
+ *                                algorithm that were used in the call to
+ *                                mbedtls_psa_aead_encrypt_setup().
+ *                              - #PSA_AEAD_TAG_MAX_SIZE evaluates to the
+ *                                maximum tag size of any supported AEAD
+ *                                algorithm.
+ * \param[out] tag_length       On success, the number of bytes
+ *                              that make up the returned tag.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p tag buffer is too small.
+ *         #PSA_AEAD_TAG_LENGTH(\c key_type, key_bits, \c alg) or
+ *         #PSA_AEAD_TAG_MAX_SIZE can be used to determine the required \p tag
+ *         buffer size.
+ */
+psa_status_t mbedtls_psa_aead_finish(
+    mbedtls_psa_aead_operation_t *operation,
+    uint8_t *ciphertext,
+    size_t ciphertext_size,
+    size_t *ciphertext_length,
+    uint8_t *tag,
+    size_t tag_size,
+    size_t *tag_length);
+
+/** Abort an AEAD operation.
+ *
+ *  \note The signature of this function is that of a PSA driver
+ *       aead_abort entry point. This function behaves as an aead_abort entry
+ *       point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by the PSA core by it calling
+ * mbedtls_psa_aead_encrypt_setup() or mbedtls_psa_aead_decrypt_setup() again.
+ *
+ * The PSA core may call this function any time after the operation object has
+ * been initialized as described in #mbedtls_psa_aead_operation_t.
+ *
+ * In particular, calling mbedtls_psa_aead_abort() after the operation has been
+ * terminated by a call to mbedtls_psa_aead_abort() or
+ * mbedtls_psa_aead_finish() is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized AEAD operation.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ */
+psa_status_t mbedtls_psa_aead_abort(
+    mbedtls_psa_aead_operation_t *operation);
+
+#endif /* PSA_CRYPTO_AEAD_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.c b/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.c
new file mode 100644
index 0000000000000000000000000000000000000000..3216c94898631dad6d8dd968fffd7f8c0b602e6d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.c
@@ -0,0 +1,724 @@
+/*
+ *  PSA cipher driver entry points
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_random_impl.h"
+
+#include "mbedtls/cipher.h"
+#include "mbedtls/error.h"
+
+#include <string.h>
+
+/* mbedtls_cipher_values_from_psa() below only checks if the proper build symbols
+ * are enabled, but it does not provide any compatibility check between them
+ * (i.e. if the specified key works with the specified algorithm). This helper
+ * function is meant to provide this support.
+ * mbedtls_cipher_info_from_psa() might be used for the same purpose, but it
+ * requires CIPHER_C to be enabled.
+ */
+static psa_status_t mbedtls_cipher_validate_values(
+    psa_algorithm_t alg,
+    psa_key_type_t key_type)
+{
+    /* Reduce code size - hinting to the compiler about what it can assume allows the compiler to
+       eliminate bits of the logic below. */
+#if !defined(PSA_WANT_KEY_TYPE_AES)
+    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_AES);
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_ARIA)
+    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_ARIA);
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_CAMELLIA)
+    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CAMELLIA);
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_CHACHA20)
+    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_CHACHA20);
+#endif
+#if !defined(PSA_WANT_KEY_TYPE_DES)
+    MBEDTLS_ASSUME(key_type != PSA_KEY_TYPE_DES);
+#endif
+#if !defined(PSA_WANT_ALG_CCM)
+    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0));
+#endif
+#if !defined(PSA_WANT_ALG_GCM)
+    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0));
+#endif
+#if !defined(PSA_WANT_ALG_STREAM_CIPHER)
+    MBEDTLS_ASSUME(alg != PSA_ALG_STREAM_CIPHER);
+#endif
+#if !defined(PSA_WANT_ALG_CHACHA20_POLY1305)
+    MBEDTLS_ASSUME(alg != PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0));
+#endif
+#if !defined(PSA_WANT_ALG_CCM_STAR_NO_TAG)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CCM_STAR_NO_TAG);
+#endif
+#if !defined(PSA_WANT_ALG_CTR)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CTR);
+#endif
+#if !defined(PSA_WANT_ALG_CFB)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CFB);
+#endif
+#if !defined(PSA_WANT_ALG_OFB)
+    MBEDTLS_ASSUME(alg != PSA_ALG_OFB);
+#endif
+#if !defined(PSA_WANT_ALG_XTS)
+    MBEDTLS_ASSUME(alg != PSA_ALG_XTS);
+#endif
+#if !defined(PSA_WANT_ALG_ECB_NO_PADDING)
+    MBEDTLS_ASSUME(alg != PSA_ALG_ECB_NO_PADDING);
+#endif
+#if !defined(PSA_WANT_ALG_CBC_NO_PADDING)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_NO_PADDING);
+#endif
+#if !defined(PSA_WANT_ALG_CBC_PKCS7)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CBC_PKCS7);
+#endif
+#if !defined(PSA_WANT_ALG_CMAC)
+    MBEDTLS_ASSUME(alg != PSA_ALG_CMAC);
+#endif
+
+    if (alg == PSA_ALG_STREAM_CIPHER ||
+        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0)) {
+        if (key_type == PSA_KEY_TYPE_CHACHA20) {
+            return PSA_SUCCESS;
+        }
+    }
+
+    if (alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0) ||
+        alg == PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0) ||
+        alg == PSA_ALG_CCM_STAR_NO_TAG) {
+        if (key_type == PSA_KEY_TYPE_AES ||
+            key_type == PSA_KEY_TYPE_ARIA ||
+            key_type == PSA_KEY_TYPE_CAMELLIA) {
+            return PSA_SUCCESS;
+        }
+    }
+
+    if (alg == PSA_ALG_CTR ||
+        alg == PSA_ALG_CFB ||
+        alg == PSA_ALG_OFB ||
+        alg == PSA_ALG_XTS ||
+        alg == PSA_ALG_ECB_NO_PADDING ||
+        alg == PSA_ALG_CBC_NO_PADDING ||
+        alg == PSA_ALG_CBC_PKCS7 ||
+        alg == PSA_ALG_CMAC) {
+        if (key_type == PSA_KEY_TYPE_AES ||
+            key_type == PSA_KEY_TYPE_ARIA ||
+            key_type == PSA_KEY_TYPE_DES ||
+            key_type == PSA_KEY_TYPE_CAMELLIA) {
+            return PSA_SUCCESS;
+        }
+    }
+
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+psa_status_t mbedtls_cipher_values_from_psa(
+    psa_algorithm_t alg,
+    psa_key_type_t key_type,
+    size_t *key_bits,
+    mbedtls_cipher_mode_t *mode,
+    mbedtls_cipher_id_t *cipher_id)
+{
+    mbedtls_cipher_id_t cipher_id_tmp;
+    /* Only DES modifies key_bits */
+#if !defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+    (void) key_bits;
+#endif
+
+    if (PSA_ALG_IS_AEAD(alg)) {
+        alg = PSA_ALG_AEAD_WITH_SHORTENED_TAG(alg, 0);
+    }
+
+    if (PSA_ALG_IS_CIPHER(alg) || PSA_ALG_IS_AEAD(alg)) {
+        switch (alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_STREAM_CIPHER)
+            case PSA_ALG_STREAM_CIPHER:
+                *mode = MBEDTLS_MODE_STREAM;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CTR)
+            case PSA_ALG_CTR:
+                *mode = MBEDTLS_MODE_CTR;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CFB)
+            case PSA_ALG_CFB:
+                *mode = MBEDTLS_MODE_CFB;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_OFB)
+            case PSA_ALG_OFB:
+                *mode = MBEDTLS_MODE_OFB;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
+            case PSA_ALG_ECB_NO_PADDING:
+                *mode = MBEDTLS_MODE_ECB;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING)
+            case PSA_ALG_CBC_NO_PADDING:
+                *mode = MBEDTLS_MODE_CBC;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
+            case PSA_ALG_CBC_PKCS7:
+                *mode = MBEDTLS_MODE_CBC;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM_STAR_NO_TAG)
+            case PSA_ALG_CCM_STAR_NO_TAG:
+                *mode = MBEDTLS_MODE_CCM_STAR_NO_TAG;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CCM)
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, 0):
+                *mode = MBEDTLS_MODE_CCM;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_GCM)
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_GCM, 0):
+                *mode = MBEDTLS_MODE_GCM;
+                break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CHACHA20_POLY1305)
+            case PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CHACHA20_POLY1305, 0):
+                *mode = MBEDTLS_MODE_CHACHAPOLY;
+                break;
+#endif
+            default:
+                return PSA_ERROR_NOT_SUPPORTED;
+        }
+    } else if (alg == PSA_ALG_CMAC) {
+        *mode = MBEDTLS_MODE_ECB;
+    } else {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    switch (key_type) {
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_AES)
+        case PSA_KEY_TYPE_AES:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_AES;
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ARIA)
+        case PSA_KEY_TYPE_ARIA:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_ARIA;
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+        case PSA_KEY_TYPE_DES:
+            /* key_bits is 64 for Single-DES, 128 for two-key Triple-DES,
+             * and 192 for three-key Triple-DES. */
+            if (*key_bits == 64) {
+                cipher_id_tmp = MBEDTLS_CIPHER_ID_DES;
+            } else {
+                cipher_id_tmp = MBEDTLS_CIPHER_ID_3DES;
+            }
+            /* mbedtls doesn't recognize two-key Triple-DES as an algorithm,
+             * but two-key Triple-DES is functionally three-key Triple-DES
+             * with K1=K3, so that's how we present it to mbedtls. */
+            if (*key_bits == 128) {
+                *key_bits = 192;
+            }
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CAMELLIA)
+        case PSA_KEY_TYPE_CAMELLIA:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_CAMELLIA;
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_CHACHA20)
+        case PSA_KEY_TYPE_CHACHA20:
+            cipher_id_tmp = MBEDTLS_CIPHER_ID_CHACHA20;
+            break;
+#endif
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+    if (cipher_id != NULL) {
+        *cipher_id = cipher_id_tmp;
+    }
+
+    return mbedtls_cipher_validate_values(alg, key_type);
+}
+
+#if defined(MBEDTLS_CIPHER_C)
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
+    psa_algorithm_t alg,
+    psa_key_type_t key_type,
+    size_t key_bits,
+    mbedtls_cipher_id_t *cipher_id)
+{
+    mbedtls_cipher_mode_t mode;
+    psa_status_t status;
+    mbedtls_cipher_id_t cipher_id_tmp = MBEDTLS_CIPHER_ID_NONE;
+
+    status = mbedtls_cipher_values_from_psa(alg, key_type, &key_bits, &mode, &cipher_id_tmp);
+    if (status != PSA_SUCCESS) {
+        return NULL;
+    }
+    if (cipher_id != NULL) {
+        *cipher_id = cipher_id_tmp;
+    }
+
+    return mbedtls_cipher_info_from_values(cipher_id_tmp, (int) key_bits, mode);
+}
+#endif /* MBEDTLS_CIPHER_C */
+
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+
+static psa_status_t psa_cipher_setup(
+    mbedtls_psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    mbedtls_operation_t cipher_operation)
+{
+    int ret = 0;
+    size_t key_bits;
+    const mbedtls_cipher_info_t *cipher_info = NULL;
+    psa_key_type_t key_type = attributes->type;
+
+    (void) key_buffer_size;
+
+    mbedtls_cipher_init(&operation->ctx.cipher);
+
+    operation->alg = alg;
+    key_bits = attributes->bits;
+    cipher_info = mbedtls_cipher_info_from_psa(alg, key_type,
+                                               key_bits, NULL);
+    if (cipher_info == NULL) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    ret = mbedtls_cipher_setup(&operation->ctx.cipher, cipher_info);
+    if (ret != 0) {
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DES)
+    if (key_type == PSA_KEY_TYPE_DES && key_bits == 128) {
+        /* Two-key Triple-DES is 3-key Triple-DES with K1=K3 */
+        uint8_t keys[24];
+        memcpy(keys, key_buffer, 16);
+        memcpy(keys + 16, key_buffer, 8);
+        ret = mbedtls_cipher_setkey(&operation->ctx.cipher,
+                                    keys,
+                                    192, cipher_operation);
+    } else
+#endif
+    {
+        ret = mbedtls_cipher_setkey(&operation->ctx.cipher, key_buffer,
+                                    (int) key_bits, cipher_operation);
+    }
+    if (ret != 0) {
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7)
+    switch (alg) {
+        case PSA_ALG_CBC_NO_PADDING:
+            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
+                                                  MBEDTLS_PADDING_NONE);
+            break;
+        case PSA_ALG_CBC_PKCS7:
+            ret = mbedtls_cipher_set_padding_mode(&operation->ctx.cipher,
+                                                  MBEDTLS_PADDING_PKCS7);
+            break;
+        default:
+            /* The algorithm doesn't involve padding. */
+            ret = 0;
+            break;
+    }
+    if (ret != 0) {
+        goto exit;
+    }
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CBC_NO_PADDING ||
+          MBEDTLS_PSA_BUILTIN_ALG_CBC_PKCS7 */
+
+    operation->block_length = (PSA_ALG_IS_STREAM_CIPHER(alg) ? 1 :
+                               PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type));
+    operation->iv_length = PSA_CIPHER_IV_LENGTH(key_type, alg);
+
+exit:
+    return mbedtls_to_psa_error(ret);
+}
+
+psa_status_t mbedtls_psa_cipher_encrypt_setup(
+    mbedtls_psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    return psa_cipher_setup(operation, attributes,
+                            key_buffer, key_buffer_size,
+                            alg, MBEDTLS_ENCRYPT);
+}
+
+psa_status_t mbedtls_psa_cipher_decrypt_setup(
+    mbedtls_psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    return psa_cipher_setup(operation, attributes,
+                            key_buffer, key_buffer_size,
+                            alg, MBEDTLS_DECRYPT);
+}
+
+psa_status_t mbedtls_psa_cipher_set_iv(
+    mbedtls_psa_cipher_operation_t *operation,
+    const uint8_t *iv, size_t iv_length)
+{
+    if (iv_length != operation->iv_length) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    return mbedtls_to_psa_error(
+        mbedtls_cipher_set_iv(&operation->ctx.cipher,
+                              iv, iv_length));
+}
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
+/** Process input for which the algorithm is set to ECB mode.
+ *
+ * This requires manual processing, since the PSA API is defined as being
+ * able to process arbitrary-length calls to psa_cipher_update() with ECB mode,
+ * but the underlying mbedtls_cipher_update only takes full blocks.
+ *
+ * \param ctx           The mbedtls cipher context to use. It must have been
+ *                      set up for ECB.
+ * \param[in] input     The input plaintext or ciphertext to process.
+ * \param input_length  The number of bytes to process from \p input.
+ *                      This does not need to be aligned to a block boundary.
+ *                      If there is a partial block at the end of the input,
+ *                      it is stored in \p ctx for future processing.
+ * \param output        The buffer where the output is written. It must be
+ *                      at least `BS * floor((p + input_length) / BS)` bytes
+ *                      long, where `p` is the number of bytes in the
+ *                      unprocessed partial block in \p ctx (with
+ *                      `0 <= p <= BS - 1`) and `BS` is the block size.
+ * \param output_length On success, the number of bytes written to \p output.
+ *                      \c 0 on error.
+ *
+ * \return #PSA_SUCCESS or an error from a hardware accelerator
+ */
+static psa_status_t psa_cipher_update_ecb(
+    mbedtls_cipher_context_t *ctx,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t block_size = mbedtls_cipher_info_get_block_size(ctx->cipher_info);
+    size_t internal_output_length = 0;
+    *output_length = 0;
+
+    if (input_length == 0) {
+        status = PSA_SUCCESS;
+        goto exit;
+    }
+
+    if (ctx->unprocessed_len > 0) {
+        /* Fill up to block size, and run the block if there's a full one. */
+        size_t bytes_to_copy = block_size - ctx->unprocessed_len;
+
+        if (input_length < bytes_to_copy) {
+            bytes_to_copy = input_length;
+        }
+
+        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
+               input, bytes_to_copy);
+        input_length -= bytes_to_copy;
+        input += bytes_to_copy;
+        ctx->unprocessed_len += bytes_to_copy;
+
+        if (ctx->unprocessed_len == block_size) {
+            status = mbedtls_to_psa_error(
+                mbedtls_cipher_update(ctx,
+                                      ctx->unprocessed_data,
+                                      block_size,
+                                      output, &internal_output_length));
+
+            if (status != PSA_SUCCESS) {
+                goto exit;
+            }
+
+            output += internal_output_length;
+            *output_length += internal_output_length;
+            ctx->unprocessed_len = 0;
+        }
+    }
+
+    while (input_length >= block_size) {
+        /* Run all full blocks we have, one by one */
+        status = mbedtls_to_psa_error(
+            mbedtls_cipher_update(ctx, input,
+                                  block_size,
+                                  output, &internal_output_length));
+
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        input_length -= block_size;
+        input += block_size;
+
+        output += internal_output_length;
+        *output_length += internal_output_length;
+    }
+
+    if (input_length > 0) {
+        /* Save unprocessed bytes for later processing */
+        memcpy(&(ctx->unprocessed_data[ctx->unprocessed_len]),
+               input, input_length);
+        ctx->unprocessed_len += input_length;
+    }
+
+    status = PSA_SUCCESS;
+
+exit:
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
+
+psa_status_t mbedtls_psa_cipher_update(
+    mbedtls_psa_cipher_operation_t *operation,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t expected_output_size;
+
+    if (!PSA_ALG_IS_STREAM_CIPHER(operation->alg)) {
+        /* Take the unprocessed partial block left over from previous
+         * update calls, if any, plus the input to this call. Remove
+         * the last partial block, if any. You get the data that will be
+         * output in this call. */
+        expected_output_size =
+            (operation->ctx.cipher.unprocessed_len + input_length)
+            / operation->block_length * operation->block_length;
+    } else {
+        expected_output_size = input_length;
+    }
+
+    if (output_size < expected_output_size) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING)
+    if (operation->alg == PSA_ALG_ECB_NO_PADDING) {
+        /* mbedtls_cipher_update has an API inconsistency: it will only
+         * process a single block at a time in ECB mode. Abstract away that
+         * inconsistency here to match the PSA API behaviour. */
+        status = psa_cipher_update_ecb(&operation->ctx.cipher,
+                                       input,
+                                       input_length,
+                                       output,
+                                       output_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECB_NO_PADDING */
+    if (input_length == 0) {
+        /* There is no input, nothing to be done */
+        *output_length = 0;
+        status = PSA_SUCCESS;
+    } else {
+        status = mbedtls_to_psa_error(
+            mbedtls_cipher_update(&operation->ctx.cipher, input,
+                                  input_length, output, output_length));
+
+        if (*output_length > output_size) {
+            return PSA_ERROR_CORRUPTION_DETECTED;
+        }
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_cipher_finish(
+    mbedtls_psa_cipher_operation_t *operation,
+    uint8_t *output, size_t output_size, size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_GENERIC_ERROR;
+    uint8_t temp_output_buffer[MBEDTLS_MAX_BLOCK_LENGTH];
+
+    if (operation->ctx.cipher.unprocessed_len != 0) {
+        if (operation->alg == PSA_ALG_ECB_NO_PADDING ||
+            operation->alg == PSA_ALG_CBC_NO_PADDING) {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto exit;
+        }
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_cipher_finish(&operation->ctx.cipher,
+                              temp_output_buffer,
+                              output_length));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (*output_length == 0) {
+        ; /* Nothing to copy. Note that output may be NULL in this case. */
+    } else if (output_size >= *output_length) {
+        memcpy(output, temp_output_buffer, *output_length);
+    } else {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+
+exit:
+    mbedtls_platform_zeroize(temp_output_buffer,
+                             sizeof(temp_output_buffer));
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_cipher_abort(
+    mbedtls_psa_cipher_operation_t *operation)
+{
+    /* Sanity check (shouldn't happen: operation->alg should
+     * always have been initialized to a valid value). */
+    if (!PSA_ALG_IS_CIPHER(operation->alg)) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    mbedtls_cipher_free(&operation->ctx.cipher);
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *iv,
+    size_t iv_length,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
+    size_t update_output_length, finish_output_length;
+
+    status = mbedtls_psa_cipher_encrypt_setup(&operation, attributes,
+                                              key_buffer, key_buffer_size,
+                                              alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (iv_length > 0) {
+        status = mbedtls_psa_cipher_set_iv(&operation, iv, iv_length);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    status = mbedtls_psa_cipher_update(&operation, input, input_length,
+                                       output, output_size,
+                                       &update_output_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_psa_cipher_finish(
+        &operation,
+        mbedtls_buffer_offset(output, update_output_length),
+        output_size - update_output_length, &finish_output_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    *output_length = update_output_length + finish_output_length;
+
+exit:
+    if (status == PSA_SUCCESS) {
+        status = mbedtls_psa_cipher_abort(&operation);
+    } else {
+        mbedtls_psa_cipher_abort(&operation);
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_psa_cipher_operation_t operation = MBEDTLS_PSA_CIPHER_OPERATION_INIT;
+    size_t olength, accumulated_length;
+
+    status = mbedtls_psa_cipher_decrypt_setup(&operation, attributes,
+                                              key_buffer, key_buffer_size,
+                                              alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (operation.iv_length > 0) {
+        status = mbedtls_psa_cipher_set_iv(&operation,
+                                           input, operation.iv_length);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    status = mbedtls_psa_cipher_update(
+        &operation,
+        mbedtls_buffer_offset_const(input, operation.iv_length),
+        input_length - operation.iv_length,
+        output, output_size, &olength);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    accumulated_length = olength;
+
+    status = mbedtls_psa_cipher_finish(
+        &operation,
+        mbedtls_buffer_offset(output, accumulated_length),
+        output_size - accumulated_length, &olength);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    *output_length = accumulated_length + olength;
+
+exit:
+    if (status == PSA_SUCCESS) {
+        status = mbedtls_psa_cipher_abort(&operation);
+    } else {
+        mbedtls_psa_cipher_abort(&operation);
+    }
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.h b/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc565851cc8bf74066f40e8dda525904e6884bdb
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_cipher.h
@@ -0,0 +1,316 @@
+/*
+ *  PSA cipher driver entry points and associated auxiliary functions
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_CIPHER_H
+#define PSA_CRYPTO_CIPHER_H
+
+#include <mbedtls/cipher.h>
+#include <psa/crypto.h>
+
+/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
+ *  as well as the PSA type and size of the key to be used with the cipher
+ *  algorithm.
+ *
+ * \param[in]      alg          PSA cipher algorithm identifier
+ * \param[in]      key_type     PSA key type
+ * \param[in,out]  key_bits     Size of the key in bits. The value provided in input
+ *                              might be updated if necessary.
+ * \param[out]     mode         Mbed TLS cipher mode
+ * \param[out]     cipher_id    Mbed TLS cipher algorithm identifier
+ *
+ * \return  On success \c PSA_SUCCESS is returned and key_bits, mode and cipher_id
+ *          are properly updated.
+ *          \c PSA_ERROR_NOT_SUPPORTED is returned if the cipher algorithm is not
+ *          supported.
+ */
+
+psa_status_t mbedtls_cipher_values_from_psa(psa_algorithm_t alg, psa_key_type_t key_type,
+                                            size_t *key_bits, mbedtls_cipher_mode_t *mode,
+                                            mbedtls_cipher_id_t *cipher_id);
+
+#if defined(MBEDTLS_CIPHER_C)
+/** Get Mbed TLS cipher information given the cipher algorithm PSA identifier
+ *  as well as the PSA type and size of the key to be used with the cipher
+ *  algorithm.
+ *
+ * \param       alg        PSA cipher algorithm identifier
+ * \param       key_type   PSA key type
+ * \param       key_bits   Size of the key in bits
+ * \param[out]  cipher_id  Mbed TLS cipher algorithm identifier
+ *
+ * \return  The Mbed TLS cipher information of the cipher algorithm.
+ *          \c NULL if the PSA cipher algorithm is not supported.
+ */
+const mbedtls_cipher_info_t *mbedtls_cipher_info_from_psa(
+    psa_algorithm_t alg, psa_key_type_t key_type, size_t key_bits,
+    mbedtls_cipher_id_t *cipher_id);
+#endif /* MBEDTLS_CIPHER_C */
+
+/**
+ * \brief Set the key for a multipart symmetric encryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_encrypt_setup entry point. This function behaves as a
+ *       cipher_encrypt_setup entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It has been
+ *                              initialized as per the documentation for
+ *                              #psa_cipher_operation_t and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key context.
+ * \param[in] key_buffer_size   Size of the \p key_buffer buffer in bytes.
+ * \param[in] alg               The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_encrypt_setup(
+    mbedtls_psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/**
+ * \brief Set the key for a multipart symmetric decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_decrypt_setup entry point. This function behaves as a
+ *       cipher_decrypt_setup entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It has been
+ *                              initialized as per the documentation for
+ *                              #psa_cipher_operation_t and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key context.
+ * \param[in] key_buffer_size   Size of the \p key_buffer buffer in bytes.
+ * \param[in] alg               The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_decrypt_setup(
+    mbedtls_psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Set the IV for a symmetric encryption or decryption operation.
+ *
+ * This function sets the IV (initialization vector), nonce
+ * or initial counter value for the encryption or decryption operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_set_iv entry point. This function behaves as a
+ *       cipher_set_iv entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] iv                Buffer containing the IV to use.
+ * \param[in] iv_length         Size of the IV in bytes. It is guaranteed by
+ *                              the core to be less or equal to
+ *                              PSA_CIPHER_IV_MAX_SIZE.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p iv is not acceptable for the chosen algorithm,
+ *         or the chosen algorithm does not use an IV.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_set_iv(
+    mbedtls_psa_cipher_operation_t *operation,
+    const uint8_t *iv, size_t iv_length);
+
+/** Encrypt or decrypt a message fragment in an active cipher operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_update entry point. This function behaves as a
+ *       cipher_update entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[in] input             Buffer containing the message fragment to
+ *                              encrypt or decrypt.
+ * \param[in] input_length      Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param[in]  output_size      Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_update(
+    mbedtls_psa_cipher_operation_t *operation,
+    const uint8_t *input, size_t input_length,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+/** Finish encrypting or decrypting a message in a cipher operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_finish entry point. This function behaves as a
+ *       cipher_finish entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     Active cipher operation.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param[in]  output_size      Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The total input size passed to this operation is not valid for
+ *         this particular algorithm. For example, the algorithm is a based
+ *         on block cipher and requires a whole number of blocks, but the
+ *         total input size is not a multiple of the block size.
+ * \retval #PSA_ERROR_INVALID_PADDING
+ *         This is a decryption operation for an algorithm that includes
+ *         padding, and the ciphertext does not contain valid padding.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_finish(
+    mbedtls_psa_cipher_operation_t *operation,
+    uint8_t *output, size_t output_size, size_t *output_length);
+
+/** Abort a cipher operation.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_abort entry point. This function behaves as a
+ *       cipher_abort entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation     Initialized cipher operation.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ */
+psa_status_t mbedtls_psa_cipher_abort(mbedtls_psa_cipher_operation_t *operation);
+
+/** Encrypt a message using a symmetric cipher.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_encrypt entry point. This function behaves as a
+ *       cipher_encrypt entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key context.
+ * \param[in] key_buffer_size   Size of the \p key_buffer buffer in bytes.
+ * \param[in] alg               The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param[in] iv                Buffer containing the IV for encryption. The
+ *                              IV has been generated by the core.
+ * \param[in] iv_length         Size of the \p iv in bytes.
+ * \param[in] input             Buffer containing the message to encrypt.
+ * \param[in] input_length      Size of the \p input buffer in bytes.
+ * \param[in,out] output        Buffer where the output is to be written.
+ * \param[in]  output_size      Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes that make up
+ *                              the returned output. Initialized to zero
+ *                              by the core.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size \p iv_length is not acceptable for the chosen algorithm,
+ *         or the chosen algorithm does not use an IV.
+ *         The total input size passed to this operation is not valid for
+ *         this particular algorithm. For example, the algorithm is a based
+ *         on block cipher and requires a whole number of blocks, but the
+ *         total input size is not a multiple of the block size.
+ * \retval #PSA_ERROR_INVALID_PADDING
+ *         This is a decryption operation for an algorithm that includes
+ *         padding, and the ciphertext does not contain valid padding.
+ */
+psa_status_t mbedtls_psa_cipher_encrypt(const psa_key_attributes_t *attributes,
+                                        const uint8_t *key_buffer,
+                                        size_t key_buffer_size,
+                                        psa_algorithm_t alg,
+                                        const uint8_t *iv,
+                                        size_t iv_length,
+                                        const uint8_t *input,
+                                        size_t input_length,
+                                        uint8_t *output,
+                                        size_t output_size,
+                                        size_t *output_length);
+
+/** Decrypt a message using a symmetric cipher.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       cipher_decrypt entry point. This function behaves as a
+ *       cipher_decrypt entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              The cipher algorithm to compute
+ *                              (\c PSA_ALG_XXX value such that
+ *                              #PSA_ALG_IS_CIPHER(\p alg) is true).
+ * \param[in]  input            Buffer containing the iv and the ciphertext.
+ * \param[in]  input_length     Size of the \p input buffer in bytes.
+ * \param[out] output           Buffer where the output is to be written.
+ * \param[in]  output_size      Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes that make up
+ *                              the returned output. Initialized to zero
+ *                              by the core.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size of \p iv is not acceptable for the chosen algorithm,
+ *         or the chosen algorithm does not use an IV.
+ *         The total input size passed to this operation is not valid for
+ *         this particular algorithm. For example, the algorithm is a based
+ *         on block cipher and requires a whole number of blocks, but the
+ *         total input size is not a multiple of the block size.
+ * \retval #PSA_ERROR_INVALID_PADDING
+ *         This is a decryption operation for an algorithm that includes
+ *         padding, and the ciphertext does not contain valid padding.
+ */
+psa_status_t mbedtls_psa_cipher_decrypt(const psa_key_attributes_t *attributes,
+                                        const uint8_t *key_buffer,
+                                        size_t key_buffer_size,
+                                        psa_algorithm_t alg,
+                                        const uint8_t *input,
+                                        size_t input_length,
+                                        uint8_t *output,
+                                        size_t output_size,
+                                        size_t *output_length);
+
+#endif /* PSA_CRYPTO_CIPHER_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_client.c b/lib/libmbedtls/mbedtls/library/psa_crypto_client.c
new file mode 100644
index 0000000000000000000000000000000000000000..72f671d63d5a8da8d89a86f72b587f474709482c
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_client.c
@@ -0,0 +1,22 @@
+/*
+ *  PSA crypto client code
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+#include <string.h>
+#include "mbedtls/platform.h"
+
+void psa_reset_key_attributes(psa_key_attributes_t *attributes)
+{
+    memset(attributes, 0, sizeof(*attributes));
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_core.h b/lib/libmbedtls/mbedtls/library/psa_crypto_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..21e7559f01c37287f42aa8c420c7c9117adab86a
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_core.h
@@ -0,0 +1,1003 @@
+/*
+ *  PSA crypto core internal interfaces
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_CORE_H
+#define PSA_CRYPTO_CORE_H
+
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
+
+#include "psa/crypto.h"
+#include "psa/crypto_se_driver.h"
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+/**
+ * Tell if PSA is ready for this hash.
+ *
+ * \note            For now, only checks the state of the driver subsystem,
+ *                  not the algorithm. Might do more in the future.
+ *
+ * \param hash_alg  The hash algorithm (ignored for now).
+ *
+ * \return 1 if the driver subsytem is ready, 0 otherwise.
+ */
+int psa_can_do_hash(psa_algorithm_t hash_alg);
+
+/**
+ * Tell if PSA is ready for this cipher.
+ *
+ * \note            For now, only checks the state of the driver subsystem,
+ *                  not the algorithm. Might do more in the future.
+ *
+ * \param cipher_alg  The cipher algorithm (ignored for now).
+ *
+ * \return 1 if the driver subsytem is ready, 0 otherwise.
+ */
+int psa_can_do_cipher(psa_key_type_t key_type, psa_algorithm_t cipher_alg);
+
+typedef enum {
+    PSA_SLOT_EMPTY = 0,
+    PSA_SLOT_FILLING,
+    PSA_SLOT_FULL,
+    PSA_SLOT_PENDING_DELETION,
+} psa_key_slot_state_t;
+
+/** The data structure representing a key slot, containing key material
+ * and metadata for one key.
+ */
+typedef struct {
+    /* This field is accessed in a lot of places. Putting it first
+     * reduces the code size. */
+    psa_key_attributes_t attr;
+
+    /*
+     * The current state of the key slot, as described in
+     * docs/architecture/psa-thread-safety/psa-thread-safety.md.
+     *
+     * Library functions can modify the state of a key slot by calling
+     * psa_key_slot_state_transition.
+     *
+     * The state variable is used to help determine whether library functions
+     * which operate on the slot succeed. For example, psa_finish_key_creation,
+     * which transfers the state of a slot from PSA_SLOT_FILLING to
+     * PSA_SLOT_FULL, must fail with error code PSA_ERROR_CORRUPTION_DETECTED
+     * if the state of the slot is not PSA_SLOT_FILLING.
+     *
+     * Library functions which traverse the array of key slots only consider
+     * slots that are in a suitable state for the function.
+     * For example, psa_get_and_lock_key_slot_in_memory, which finds a slot
+     * containing a given key ID, will only check slots whose state variable is
+     * PSA_SLOT_FULL.
+     */
+    psa_key_slot_state_t state;
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    /* The index of the slice containing this slot.
+     * This field must be filled if the slot contains a key
+     * (including keys being created or destroyed), and can be either
+     * filled or 0 when the slot is free.
+     *
+     * In most cases, the slice index can be deduced from the key identifer.
+     * We keep it in a separate field for robustness (it reduces the chance
+     * that a coding mistake in the key store will result in accessing the
+     * wrong slice), and also so that it's available even on code paths
+     * during creation or destruction where the key identifier might not be
+     * filled in.
+     * */
+    uint8_t slice_index;
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+    union {
+        struct {
+            /* The index of the next slot in the free list for this
+             * slice, relative * to the next array element.
+             *
+             * That is, 0 means the next slot, 1 means the next slot
+             * but one, etc. -1 would mean the slot itself. -2 means
+             * the previous slot, etc.
+             *
+             * If this is beyond the array length, the free list ends with the
+             * current element.
+             *
+             * The reason for this strange encoding is that 0 means the next
+             * element. This way, when we allocate a slice and initialize it
+             * to all-zero, the slice is ready for use, with a free list that
+             * consists of all the slots in order.
+             */
+            int32_t next_free_relative_to_next;
+        } free;
+
+        struct {
+            /*
+             * Number of functions registered as reading the material in the key slot.
+             *
+             * Library functions must not write directly to registered_readers
+             *
+             * A function must call psa_register_read(slot) before reading
+             * the current contents of the slot for an operation.
+             * They then must call psa_unregister_read(slot) once they have
+             * finished reading the current contents of the slot. If the key
+             * slot mutex is not held (when mutexes are enabled), this call
+             * must be done via a call to
+             * psa_unregister_read_under_mutex(slot).
+             * A function must call psa_key_slot_has_readers(slot) to check if
+             * the slot is in use for reading.
+             *
+             * This counter is used to prevent resetting the key slot while
+             * the library may access it. For example, such control is needed
+             * in the following scenarios:
+             * . In case of key slot starvation, all key slots contain the
+             *   description of a key, and the library asks for the
+             *   description of a persistent key not present in the
+             *   key slots, the key slots currently accessed by the
+             *   library cannot be reclaimed to free a key slot to load
+             *   the persistent key.
+             * . In case of a multi-threaded application where one thread
+             *   asks to close or purge or destroy a key while it is in use
+             *   by the library through another thread. */
+            size_t registered_readers;
+        } occupied;
+    } var;
+
+    /* Dynamically allocated key data buffer.
+     * Format as specified in psa_export_key(). */
+    struct key_data {
+        uint8_t *data;
+        size_t bytes;
+    } key;
+} psa_key_slot_t;
+
+#if defined(MBEDTLS_THREADING_C)
+
+/** Perform a mutex operation and return immediately upon failure.
+ *
+ * Returns PSA_ERROR_SERVICE_FAILURE if the operation fails
+ * and status was PSA_SUCCESS.
+ *
+ * Assumptions:
+ *  psa_status_t status exists.
+ *  f is a mutex operation which returns 0 upon success.
+ */
+#define PSA_THREADING_CHK_RET(f)                       \
+    do                                                 \
+    {                                                  \
+        if ((f) != 0) {                                \
+            if (status == PSA_SUCCESS) {               \
+                return PSA_ERROR_SERVICE_FAILURE;      \
+            }                                          \
+            return status;                             \
+        }                                              \
+    } while (0);
+
+/** Perform a mutex operation and goto exit on failure.
+ *
+ * Sets status to PSA_ERROR_SERVICE_FAILURE if status was PSA_SUCCESS.
+ *
+ * Assumptions:
+ *  psa_status_t status exists.
+ *  Label exit: exists.
+ *  f is a mutex operation which returns 0 upon success.
+ */
+#define PSA_THREADING_CHK_GOTO_EXIT(f)                 \
+    do                                                 \
+    {                                                  \
+        if ((f) != 0) {                                \
+            if (status == PSA_SUCCESS) {               \
+                status = PSA_ERROR_SERVICE_FAILURE;    \
+            }                                          \
+            goto exit;                                 \
+        }                                              \
+    } while (0);
+#endif
+
+/** Test whether a key slot has any registered readers.
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param[in] slot      The key slot to test.
+ *
+ * \return 1 if the slot has any registered readers, 0 otherwise.
+ */
+static inline int psa_key_slot_has_readers(const psa_key_slot_t *slot)
+{
+    return slot->var.occupied.registered_readers > 0;
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/** Get the SE slot number of a key from the key slot storing its description.
+ *
+ * \param[in]  slot  The key slot to query. This must be a key slot storing
+ *                   the description of a key of a dynamically registered
+ *                   secure element, otherwise the behaviour is undefined.
+ */
+static inline psa_key_slot_number_t psa_key_slot_get_slot_number(
+    const psa_key_slot_t *slot)
+{
+    return *((psa_key_slot_number_t *) (slot->key.data));
+}
+#endif
+
+/** Completely wipe a slot in memory, including its policy.
+ *
+ * Persistent storage is not affected.
+ * Sets the slot's state to PSA_SLOT_EMPTY.
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param[in,out] slot  The key slot to wipe.
+ *
+ * \retval #PSA_SUCCESS
+ *         The slot has been successfully wiped.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *         The slot's state was PSA_SLOT_FULL or PSA_SLOT_PENDING_DELETION, and
+ *         the amount of registered readers was not equal to 1. Or,
+ *         the slot's state was PSA_SLOT_EMPTY. Or,
+ *         the slot's state was PSA_SLOT_FILLING, and the amount
+ *         of registered readers was not equal to 0.
+ */
+psa_status_t psa_wipe_key_slot(psa_key_slot_t *slot);
+
+/** Try to allocate a buffer to an empty key slot.
+ *
+ * \param[in,out] slot          Key slot to attach buffer to.
+ * \param[in] buffer_length     Requested size of the buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The buffer has been successfully allocated.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Not enough memory was available for allocation.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         Trying to allocate a buffer to a non-empty key slot.
+ */
+psa_status_t psa_allocate_buffer_to_slot(psa_key_slot_t *slot,
+                                         size_t buffer_length);
+
+/** Wipe key data from a slot. Preserves metadata such as the policy. */
+psa_status_t psa_remove_key_data_from_memory(psa_key_slot_t *slot);
+
+/** Copy key data (in export format) into an empty key slot.
+ *
+ * This function assumes that the slot does not contain
+ * any key material yet. On failure, the slot content is unchanged.
+ *
+ * \param[in,out] slot          Key slot to copy the key into.
+ * \param[in] data              Buffer containing the key material.
+ * \param data_length           Size of the key buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key has been copied successfully.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         Not enough memory was available for allocation of the
+ *         copy buffer.
+ * \retval #PSA_ERROR_ALREADY_EXISTS
+ *         There was other key material already present in the slot.
+ */
+psa_status_t psa_copy_key_material_into_slot(psa_key_slot_t *slot,
+                                             const uint8_t *data,
+                                             size_t data_length);
+
+/** Convert an Mbed TLS error code to a PSA error code
+ *
+ * \note This function is provided solely for the convenience of
+ *       Mbed TLS and may be removed at any time without notice.
+ *
+ * \param ret           An Mbed TLS-thrown error code
+ *
+ * \return              The corresponding PSA error code
+ */
+psa_status_t mbedtls_to_psa_error(int ret);
+
+/** Import a key in binary format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       import_key entry point. This function behaves as an import_key
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes for the key to import.
+ * \param[in]  data             The buffer containing the key data in import
+ *                              format.
+ * \param[in]  data_length      Size of the \p data buffer in bytes.
+ * \param[out] key_buffer       The buffer to contain the key data in output
+ *                              format upon successful return.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes. This
+ *                              size is greater or equal to \p data_length.
+ * \param[out] key_buffer_length  The length of the data written in \p
+ *                                key_buffer in bytes.
+ * \param[out] bits             The key size in number of bits.
+ *
+ * \retval #PSA_SUCCESS  The key was imported successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key data is not correctly formatted.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t psa_import_key_into_slot(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits);
+
+/** Export a key in binary format
+ *
+ * \note The signature of this function is that of a PSA driver export_key
+ *       entry point. This function behaves as an export_key entry point as
+ *       defined in the PSA driver interface specification.
+ *
+ * \param[in]  attributes       The attributes for the key to export.
+ * \param[in]  key_buffer       Material or context of the key to export.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[out] data             Buffer where the key data is to be written.
+ * \param[in]  data_size        Size of the \p data buffer in bytes.
+ * \param[out] data_length      On success, the number of bytes written in
+ *                              \p data
+ *
+ * \retval #PSA_SUCCESS  The key was exported successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t psa_export_key_internal(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+/** Export a public key or the public part of a key pair in binary format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       export_public_key entry point. This function behaves as an
+ *       export_public_key entry point as defined in the PSA driver interface
+ *       specification.
+ *
+ * \param[in]  attributes       The attributes for the key to export.
+ * \param[in]  key_buffer       Material or context of the key to export.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[out] data             Buffer where the key data is to be written.
+ * \param[in]  data_size        Size of the \p data buffer in bytes.
+ * \param[out] data_length      On success, the number of bytes written in
+ *                              \p data
+ *
+ * \retval #PSA_SUCCESS  The public key was exported successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t psa_export_public_key_internal(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+/** Whether a key custom production parameters structure is the default.
+ *
+ * Calls to a key generation driver with non-default custom production parameters
+ * require a driver supporting custom production parameters.
+ *
+ * \param[in] custom            The key custom production parameters to check.
+ * \param custom_data_length    Size of the associated variable-length data
+ *                              in bytes.
+ */
+int psa_custom_key_parameters_are_default(
+    const psa_custom_key_parameters_t *custom,
+    size_t custom_data_length);
+
+/**
+ * \brief Generate a key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ *       entry point.
+ *
+ * \param[in]  attributes         The attributes for the key to generate.
+ * \param[in] custom              Custom parameters for the key generation.
+ * \param[in] custom_data         Variable-length data associated with \c custom.
+ * \param custom_data_length      Length of `custom_data` in bytes.
+ * \param[out] key_buffer         Buffer where the key data is to be written.
+ * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length  On success, the number of bytes written in
+ *                                \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was generated successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Key size in bits or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ */
+psa_status_t psa_generate_key_internal(const psa_key_attributes_t *attributes,
+                                       const psa_custom_key_parameters_t *custom,
+                                       const uint8_t *custom_data,
+                                       size_t custom_data_length,
+                                       uint8_t *key_buffer,
+                                       size_t key_buffer_size,
+                                       size_t *key_buffer_length);
+
+/** Sign a message with a private key. For hash-and-sign algorithms,
+ *  this includes the hashing step.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_message entry point. This function behaves as a sign_message
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \note This function will call the driver for psa_sign_hash
+ *       and go through driver dispatch again.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in]  input            The input message to sign.
+ * \param[in]  input_length     Size of the \p input buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param[in]  signature_size   Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of the key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ */
+psa_status_t psa_sign_message_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *input, size_t input_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+/** Verify the signature of a message with a public key, using
+ *  a hash-and-sign verification algorithm.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_message entry point. This function behaves as a verify_message
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \note This function will call the driver for psa_verify_hash
+ *       and go through driver dispatch again.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in]  input            The message whose signature is to be verified.
+ * \param[in]  input_length     Size of the \p input buffer in bytes.
+ * \param[in]  signature        Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t psa_verify_message_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *input, size_t input_length,
+    const uint8_t *signature, size_t signature_length);
+
+/** Sign an already-calculated hash with a private key.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash entry point. This function behaves as a sign_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in]  hash             The hash or message to sign.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param[in]  signature_size   Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of the key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ */
+psa_status_t psa_sign_hash_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+/**
+ * \brief Verify the signature a hash or short message using a public key.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash entry point. This function behaves as a verify_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in]  hash             The hash or message whose signature is to be
+ *                              verified.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[in]  signature        Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t psa_verify_hash_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief Validate the key bit size for unstructured keys.
+ *
+ * \note  Check that the bit size is acceptable for a given key type for
+ *        unstructured keys.
+ *
+ * \param[in]  type  The key type
+ * \param[in]  bits  The number of bits of the key
+ *
+ * \retval #PSA_SUCCESS
+ *         The key type and size are valid.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The size in bits of the key is not valid.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The type and/or the size in bits of the key or the combination of
+ *         the two is not supported.
+ */
+psa_status_t psa_validate_unstructured_key_bit_size(psa_key_type_t type,
+                                                    size_t bits);
+
+/** Perform a key agreement and return the raw shared secret, using
+    built-in raw key agreement functions.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       key_agreement entry point. This function behaves as a key_agreement
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  context.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in
+ *                                  bytes.
+ * \param[in]  alg                  A key agreement algorithm that is
+ *                                  compatible with the type of the key.
+ * \param[in]  peer_key             The buffer containing the key context
+ *                                  of the peer's public key.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that make
+ *                                  up the returned shared secret.
+ * \retval #PSA_SUCCESS
+ *         Success. Shared secret successfully calculated.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p alg is not a key agreement algorithm, or
+ *         \p private_key is not compatible with \p alg,
+ *         or \p peer_key is not valid for \p alg or not compatible with
+ *         \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p shared_secret_size is too small
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not a supported key agreement algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE \emptydescription
+ */
+psa_status_t psa_key_agreement_raw_builtin(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length);
+
+/**
+ * \brief Set the maximum number of ops allowed to be executed by an
+ *        interruptible function in a single call.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       interruptible_set_max_ops entry point. This function behaves as an
+ *       interruptible_set_max_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in]  max_ops          The maximum number of ops to be executed in a
+ *                              single call, this can be a number from 0 to
+ *                              #PSA_INTERRUPTIBLE_MAX_OPS_UNLIMITED, where 0
+ *                              is obviously the least amount of work done per
+ *                              call.
+ */
+void mbedtls_psa_interruptible_set_max_ops(uint32_t max_ops);
+
+/**
+ * \brief Get the maximum number of ops allowed to be executed by an
+ *        interruptible function in a single call.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       interruptible_get_max_ops entry point. This function behaves as an
+ *       interruptible_get_max_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \return                      Maximum number of ops allowed to be executed
+ *                              by an interruptible function in a single call.
+ */
+uint32_t mbedtls_psa_interruptible_get_max_ops(void);
+
+/**
+ * \brief Get the number of ops that a hash signing operation has taken for the
+ *        previous call. If no call or work has taken place, this will return
+ *        zero.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_get_num_ops entry point. This function behaves as an
+ *       sign_hash_get_num_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param   operation           The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that were completed
+ *                              in the last call to \c
+ *                              mbedtls_psa_sign_hash_complete().
+ */
+uint32_t mbedtls_psa_sign_hash_get_num_ops(
+    const mbedtls_psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Get the number of ops that a hash verification operation has taken for
+ *        the previous call. If no call or work has taken place, this will
+ *        return zero.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_get_num_ops entry point. This function behaves as an
+ *       verify_hash_get_num_ops entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param   operation           The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \return                      Number of ops that were completed
+ *                              in the last call to \c
+ *                              mbedtls_psa_verify_hash_complete().
+ */
+uint32_t mbedtls_psa_verify_hash_get_num_ops(
+    const mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief  Start signing a hash or short message with a private key, in an
+ *         interruptible manner.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_start entry point. This function behaves as a
+ *       sign_hash_start entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in] hash              The hash or message to sign.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - call \c psa_sign_hash_complete()
+ *         with the same context to complete the operation
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An unsupported, incorrectly formatted or incorrect type of key was
+ *         used.
+ * \retval #PSA_ERROR_NOT_SUPPORTED Either no internal interruptible operations
+ *         are currently supported, or the key type is currently unsupported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         There was insufficient memory to load the key representation.
+ */
+psa_status_t mbedtls_psa_sign_hash_start(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length);
+
+/**
+ * \brief Continue and eventually complete the action of signing a hash or
+ *        short message with a private key, in an interruptible manner.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_complete entry point. This function behaves as a
+ *       sign_hash_complete entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param signature_size        Size of the \p signature buffer in bytes. This
+ *                              must be appropriate for the selected
+ *                              algorithm and key.
+ * \param[out] signature_length On success, the number of bytes that make up
+ *                              the returned signature value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(), there is still work to be done,
+ *         please call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ */
+psa_status_t mbedtls_psa_sign_hash_complete(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length);
+
+/**
+ * \brief Abort a sign hash operation.
+ *
+ * \note The signature of this function is that of a PSA driver sign_hash_abort
+ *       entry point. This function behaves as a sign_hash_abort entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to abort.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ */
+psa_status_t mbedtls_psa_sign_hash_abort(
+    mbedtls_psa_sign_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief  Start reading and verifying a hash or short message, in an
+ *         interruptible manner.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_start entry point. This function behaves as a
+ *       verify_hash_start entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ * \param[in]  attributes       The attributes of the key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the key context.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              the type of the key.
+ * \param[in] hash              The hash whose signature is to be verified.
+ * \param hash_length           Size of the \p hash buffer in bytes.
+ * \param[in] signature         Buffer containing the signature to verify.
+ * \param signature_length      Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation started successfully - call \c psa_sign_hash_complete()
+ *         with the same context to complete the operation
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         An unsupported or incorrect type of key was used.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *        Either no internal interruptible operations are currently supported,
+ *         or the key type is currently unsupported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *        There was insufficient memory either to load the key representation,
+ *        or to prepare the operation.
+ */
+psa_status_t mbedtls_psa_verify_hash_start(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief Continue and eventually complete the action of signing a hash or
+ *        short message with a private key, in an interruptible manner.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash_complete entry point. This function behaves as a
+ *       sign_hash_complete entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_sign_hash_interruptible_operation_t
+ *                              to use. This must be initialized first.
+ *
+ * \retval #PSA_SUCCESS
+ *         Operation completed successfully, and the passed signature is valid.
+ *
+ * \retval #PSA_OPERATION_INCOMPLETE
+ *         Operation was interrupted due to the setting of \c
+ *         psa_interruptible_set_max_ops(), there is still work to be done,
+ *         please call this function again with the same operation object.
+ *
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ *
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_verify_hash_complete(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
+/**
+ * \brief Abort a verify signed hash operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash_abort entry point. This function behaves as a
+ *       verify_hash_abort entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * \param[in]  operation        The \c
+ *                              mbedtls_psa_verify_hash_interruptible_operation_t
+ *                              to abort.
+ *
+ * \retval #PSA_SUCCESS
+ *         The operation was aborted successfully.
+ */
+psa_status_t mbedtls_psa_verify_hash_abort(
+    mbedtls_psa_verify_hash_interruptible_operation_t *operation);
+
+typedef struct psa_crypto_local_input_s {
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_input_t;
+
+#define PSA_CRYPTO_LOCAL_INPUT_INIT ((psa_crypto_local_input_t) { NULL, 0 })
+
+/** Allocate a local copy of an input buffer and copy the contents into it.
+ *
+ * \param[in] input             Pointer to input buffer.
+ * \param[in] input_len         Length of the input buffer.
+ * \param[out] local_input      Pointer to a psa_crypto_local_input_t struct
+ *                              containing a local input copy.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
+ *                              the buffer cannot be allocated.
+ */
+psa_status_t psa_crypto_local_input_alloc(const uint8_t *input, size_t input_len,
+                                          psa_crypto_local_input_t *local_input);
+
+/** Free a local copy of an input buffer.
+ *
+ * \param[in] local_input       Pointer to a psa_crypto_local_input_t struct
+ *                              populated by a previous call to
+ *                              psa_crypto_local_input_alloc().
+ */
+void psa_crypto_local_input_free(psa_crypto_local_input_t *local_input);
+
+typedef struct psa_crypto_local_output_s {
+    uint8_t *original;
+    uint8_t *buffer;
+    size_t length;
+} psa_crypto_local_output_t;
+
+#define PSA_CRYPTO_LOCAL_OUTPUT_INIT ((psa_crypto_local_output_t) { NULL, NULL, 0 })
+
+/** Allocate a local copy of an output buffer.
+ *
+ * \note                        This does not copy any data from the original
+ *                              output buffer but only allocates a buffer
+ *                              whose contents will be copied back to the
+ *                              original in a future call to
+ *                              psa_crypto_local_output_free().
+ *
+ * \param[in] output            Pointer to output buffer.
+ * \param[in] output_len        Length of the output buffer.
+ * \param[out] local_output     Pointer to a psa_crypto_local_output_t struct to
+ *                              populate with the local output copy.
+ * \return                      #PSA_SUCCESS, if the buffer was successfully
+ *                              copied.
+ * \return                      #PSA_ERROR_INSUFFICIENT_MEMORY, if a copy of
+ *                              the buffer cannot be allocated.
+ */
+psa_status_t psa_crypto_local_output_alloc(uint8_t *output, size_t output_len,
+                                           psa_crypto_local_output_t *local_output);
+
+/** Copy from a local copy of an output buffer back to the original, then
+ *  free the local copy.
+ *
+ * \param[in] local_output      Pointer to a psa_crypto_local_output_t struct
+ *                              populated by a previous call to
+ *                              psa_crypto_local_output_alloc().
+ * \return                      #PSA_SUCCESS, if the local output was
+ *                              successfully copied back to the original.
+ * \return                      #PSA_ERROR_CORRUPTION_DETECTED, if the output
+ *                              could not be copied back to the original.
+ */
+psa_status_t psa_crypto_local_output_free(psa_crypto_local_output_t *local_output);
+
+#endif /* PSA_CRYPTO_CORE_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_core_common.h b/lib/libmbedtls/mbedtls/library/psa_crypto_core_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..98fce2cca4e44051921b6dcdb6786cb859ff8fc3
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_core_common.h
@@ -0,0 +1,52 @@
+/**
+ * \file psa_crypto_core_common.h
+ *
+ * \brief Utility macros for internal use in the PSA cryptography core.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_CORE_COMMON_H
+#define PSA_CRYPTO_CORE_COMMON_H
+
+/** Return an offset into a buffer.
+ *
+ * This is just the addition of an offset to a pointer, except that this
+ * function also accepts an offset of 0 into a buffer whose pointer is null.
+ * (`p + n` has undefined behavior when `p` is null, even when `n == 0`.
+ * A null pointer is a valid buffer pointer when the size is 0, for example
+ * as the result of `malloc(0)` on some platforms.)
+ *
+ * \param p     Pointer to a buffer of at least n bytes.
+ *              This may be \p NULL if \p n is zero.
+ * \param n     An offset in bytes.
+ * \return      Pointer to offset \p n in the buffer \p p.
+ *              Note that this is only a valid pointer if the size of the
+ *              buffer is at least \p n + 1.
+ */
+static inline unsigned char *psa_crypto_buffer_offset(
+    unsigned char *p, size_t n)
+{
+    return p == NULL ? NULL : p + n;
+}
+
+/** Return an offset into a read-only buffer.
+ *
+ * Similar to mbedtls_buffer_offset(), but for const pointers.
+ *
+ * \param p     Pointer to a buffer of at least n bytes.
+ *              This may be \p NULL if \p n is zero.
+ * \param n     An offset in bytes.
+ * \return      Pointer to offset \p n in the buffer \p p.
+ *              Note that this is only a valid pointer if the size of the
+ *              buffer is at least \p n + 1.
+ */
+static inline const unsigned char *psa_crypto_buffer_offset_const(
+    const unsigned char *p, size_t n)
+{
+    return p == NULL ? NULL : p + n;
+}
+
+#endif /* PSA_CRYPTO_CORE_COMMON_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers.h b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9015572084c39ea09dd25fe74fec4df3a802d59
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers.h
@@ -0,0 +1,2898 @@
+/*
+ *  Functions to delegate cryptographic operations to an available
+ *  and appropriate accelerator.
+ *  Warning: This file is now auto-generated.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+
+/* BEGIN-common headers */
+#include "common.h"
+#include "psa_crypto_aead.h"
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
+#include "psa_crypto_pake.h"
+#include "psa_crypto_rsa.h"
+
+#include "mbedtls/platform.h"
+#include "mbedtls/constant_time.h"
+/* END-common headers */
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* BEGIN-driver headers */
+/* Headers for mbedtls_test opaque driver */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include "test/drivers/test_driver.h"
+
+#endif
+/* Headers for mbedtls_test transparent driver */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include "test/drivers/test_driver.h"
+
+#endif
+/* Headers for p256 transparent driver */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h"
+
+#endif
+
+/* END-driver headers */
+
+/* Auto-generated values depending on which drivers are registered.
+ * ID 0 is reserved for unallocated operations.
+ * ID 1 is reserved for the Mbed TLS software driver. */
+/* BEGIN-driver id definition */
+#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
+#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)
+#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)
+#define P256_TRANSPARENT_DRIVER_ID (4)
+
+/* END-driver id */
+
+/* BEGIN-Common Macro definitions */
+
+/* END-Common Macro definitions */
+
+/* Support the 'old' SE interface when asked to */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
+ * SE driver is present, to avoid unused argument errors at compile time. */
+#ifndef PSA_CRYPTO_DRIVER_PRESENT
+#define PSA_CRYPTO_DRIVER_PRESENT
+#endif
+#include "psa_crypto_se.h"
+#endif
+
+static inline psa_status_t psa_driver_wrapper_init( void )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    status = psa_init_all_se_drivers( );
+    if( status != PSA_SUCCESS )
+        return( status );
+#endif
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    status = mbedtls_test_transparent_init( );
+    if( status != PSA_SUCCESS )
+        return( status );
+
+    status = mbedtls_test_opaque_init( );
+    if( status != PSA_SUCCESS )
+        return( status );
+#endif
+
+    (void) status;
+    return( PSA_SUCCESS );
+}
+
+static inline void psa_driver_wrapper_free( void )
+{
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* Unregister all secure element drivers, so that we restart from
+     * a pristine state. */
+    psa_unregister_all_se_drivers( );
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    mbedtls_test_transparent_free( );
+    mbedtls_test_opaque_free( );
+#endif
+}
+
+/* Start delegation functions */
+static inline psa_status_t psa_driver_wrapper_sign_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *signature,
+    size_t signature_size,
+    size_t *signature_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_signature_sign_message(
+                        attributes,
+                        key_buffer,
+                        key_buffer_size,
+                        alg,
+                        input,
+                        input_length,
+                        signature,
+                        signature_size,
+                        signature_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            break;
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_signature_sign_message(
+                        attributes,
+                        key_buffer,
+                        key_buffer_size,
+                        alg,
+                        input,
+                        input_length,
+                        signature,
+                        signature_size,
+                        signature_length );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+            break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            break;
+    }
+
+    return( psa_sign_message_builtin( attributes,
+                                      key_buffer,
+                                      key_buffer_size,
+                                      alg,
+                                      input,
+                                      input_length,
+                                      signature,
+                                      signature_size,
+                                      signature_length ) );
+}
+
+static inline psa_status_t psa_driver_wrapper_verify_message(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    const uint8_t *signature,
+    size_t signature_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_signature_verify_message(
+                        attributes,
+                        key_buffer,
+                        key_buffer_size,
+                        alg,
+                        input,
+                        input_length,
+                        signature,
+                        signature_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            break;
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_signature_verify_message(
+                        attributes,
+                        key_buffer,
+                        key_buffer_size,
+                        alg,
+                        input,
+                        input_length,
+                        signature,
+                        signature_length ) );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+            break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            break;
+    }
+
+    return( psa_verify_message_builtin( attributes,
+                                        key_buffer,
+                                        key_buffer_size,
+                                        alg,
+                                        input,
+                                        input_length,
+                                        signature,
+                                        signature_length ) );
+}
+
+static inline psa_status_t psa_driver_wrapper_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length )
+{
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        if( drv->asymmetric == NULL ||
+            drv->asymmetric->p_sign == NULL )
+        {
+            /* Key is defined in SE, but we have no way to exercise it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->asymmetric->p_sign(
+                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),
+                    alg, hash, hash_length,
+                    signature, signature_size, signature_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_signature_sign_hash( attributes,
+                                                           key_buffer,
+                                                           key_buffer_size,
+                                                           alg,
+                                                           hash,
+                                                           hash_length,
+                                                           signature,
+                                                           signature_size,
+                                                           signature_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&
+                PSA_ALG_IS_ECDSA(alg) &&
+                !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) &&
+                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&
+                psa_get_key_bits(attributes) == 256 )
+            {
+                status = p256_transparent_sign_hash( attributes,
+                                                     key_buffer,
+                                                     key_buffer_size,
+                                                     alg,
+                                                     hash,
+                                                     hash_length,
+                                                     signature,
+                                                     signature_size,
+                                                     signature_length );
+                if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+            }
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            /* Fell through, meaning no accelerator supports this operation */
+            return( psa_sign_hash_builtin( attributes,
+                                           key_buffer,
+                                           key_buffer_size,
+                                           alg,
+                                           hash,
+                                           hash_length,
+                                           signature,
+                                           signature_size,
+                                           signature_length ) );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_signature_sign_hash( attributes,
+                                                             key_buffer,
+                                                             key_buffer_size,
+                                                             alg,
+                                                             hash,
+                                                             hash_length,
+                                                             signature,
+                                                             signature_size,
+                                                             signature_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length )
+{
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        if( drv->asymmetric == NULL ||
+            drv->asymmetric->p_verify == NULL )
+        {
+            /* Key is defined in SE, but we have no way to exercise it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->asymmetric->p_verify(
+                    drv_context, *( (psa_key_slot_number_t *)key_buffer ),
+                    alg, hash, hash_length,
+                    signature, signature_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_signature_verify_hash(
+                         attributes,
+                         key_buffer,
+                         key_buffer_size,
+                         alg,
+                         hash,
+                         hash_length,
+                         signature,
+                         signature_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined (MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&
+                PSA_ALG_IS_ECDSA(alg) &&
+                !PSA_ALG_ECDSA_IS_DETERMINISTIC( alg ) &&
+                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&
+                psa_get_key_bits(attributes) == 256 )
+            {
+                status = p256_transparent_verify_hash( attributes,
+                                                       key_buffer,
+                                                       key_buffer_size,
+                                                       alg,
+                                                       hash,
+                                                       hash_length,
+                                                       signature,
+                                                       signature_length );
+                if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+            }
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            return( psa_verify_hash_builtin( attributes,
+                                             key_buffer,
+                                             key_buffer_size,
+                                             alg,
+                                             hash,
+                                             hash_length,
+                                             signature,
+                                             signature_length ) );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_signature_verify_hash( attributes,
+                                                               key_buffer,
+                                                               key_buffer_size,
+                                                               alg,
+                                                               hash,
+                                                               hash_length,
+                                                               signature,
+                                                               signature_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline uint32_t psa_driver_wrapper_sign_hash_get_num_ops(
+    psa_sign_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        /* If uninitialised, return 0, as no work can have been done. */
+        case 0:
+            return 0;
+
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return(mbedtls_psa_sign_hash_get_num_ops(&operation->ctx.mbedtls_ctx));
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    /* Can't happen (see discussion in #8271) */
+    return 0;
+}
+
+static inline uint32_t psa_driver_wrapper_verify_hash_get_num_ops(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        /* If uninitialised, return 0, as no work can have been done. */
+        case 0:
+            return 0;
+
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return (mbedtls_psa_verify_hash_get_num_ops(&operation->ctx.mbedtls_ctx));
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+    }
+
+    /* Can't happen (see discussion in #8271) */
+    return 0;
+}
+
+static inline psa_status_t psa_driver_wrapper_sign_hash_start(
+    psa_sign_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                                    psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+            /* Add test driver tests here */
+
+            /* Declared with fallback == true */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_sign_hash_start( &operation->ctx.mbedtls_ctx,
+                                                  attributes,
+                                                  key_buffer, key_buffer_size,
+                                                  alg, hash, hash_length );
+            break;
+
+            /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            break;
+    }
+
+    return( status );
+}
+
+static inline psa_status_t psa_driver_wrapper_sign_hash_complete(
+    psa_sign_hash_interruptible_operation_t *operation,
+    uint8_t *signature, size_t signature_size,
+    size_t *signature_length )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_sign_hash_complete( &operation->ctx.mbedtls_ctx,
+                                                    signature, signature_size,
+                                                    signature_length ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    ( void ) signature;
+    ( void ) signature_size;
+    ( void ) signature_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_sign_hash_abort(
+    psa_sign_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_sign_hash_abort( &operation->ctx.mbedtls_ctx ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_verify_hash_start(
+    psa_verify_hash_interruptible_operation_t *operation,
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg,
+    const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                                    psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+
+            /* Add test driver tests here */
+
+            /* Declared with fallback == true */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_verify_hash_start( &operation->ctx.mbedtls_ctx,
+                                                    attributes,
+                                                    key_buffer, key_buffer_size,
+                                                    alg, hash, hash_length,
+                                                    signature, signature_length );
+            break;
+
+            /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            break;
+    }
+
+    return( status );
+}
+
+static inline psa_status_t psa_driver_wrapper_verify_hash_complete(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_verify_hash_complete(
+                                                     &operation->ctx.mbedtls_ctx
+                                                     ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_verify_hash_abort(
+    psa_verify_hash_interruptible_operation_t *operation )
+{
+    switch( operation->id )
+    {
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_verify_hash_abort( &operation->ctx.mbedtls_ctx
+                                                 ) );
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            /* Add test driver tests here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+/** Calculate the key buffer size required to store the key material of a key
+ *  associated with an opaque driver from input key data.
+ *
+ * \param[in] attributes        The key attributes
+ * \param[in] data              The input key data.
+ * \param[in] data_length       The input data length.
+ * \param[out] key_buffer_size  Minimum buffer size to contain the key material.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ */
+static inline psa_status_t psa_driver_wrapper_get_key_buffer_size_from_key_data(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data,
+    size_t data_length,
+    size_t *key_buffer_size )
+{
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+    psa_key_type_t key_type = psa_get_key_type(attributes);
+
+    *key_buffer_size = 0;
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,
+                                     PSA_BYTES_TO_BITS( data_length ) );
+            return( ( *key_buffer_size != 0 ) ?
+                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+        default:
+            (void)key_type;
+            (void)data;
+            (void)data_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_generate_key(
+    const psa_key_attributes_t *attributes,
+    const psa_custom_key_parameters_t *custom,
+    const uint8_t *custom_data, size_t custom_data_length,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+    int is_default_production =
+        psa_custom_key_parameters_are_default(custom, custom_data_length);
+    if( location != PSA_KEY_LOCATION_LOCAL_STORAGE && !is_default_production )
+    {
+        /* We don't support passing custom production parameters
+         * to drivers yet. */
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+#else
+    int is_default_production = 1;
+    (void) is_default_production;
+#endif
+
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        size_t pubkey_length = 0; /* We don't support this feature yet */
+        if( drv->key_management == NULL ||
+            drv->key_management->p_generate == NULL )
+        {
+            /* Key is defined as being in SE, but we have no way to generate it */
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+        return( drv->key_management->p_generate(
+            drv_context,
+            *( (psa_key_slot_number_t *)key_buffer ),
+            attributes, NULL, 0, &pubkey_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+            /* Transparent drivers are limited to generating asymmetric keys. */
+            /* We don't support passing custom production parameters
+             * to drivers yet. */
+            if( PSA_KEY_TYPE_IS_ASYMMETRIC( psa_get_key_type(attributes) ) &&
+                is_default_production )
+            {
+            /* Cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+                status = mbedtls_test_transparent_generate_key(
+                    attributes, key_buffer, key_buffer_size,
+                    key_buffer_length );
+                /* Declared with fallback == true */
+                if( status != PSA_ERROR_NOT_SUPPORTED )
+                    break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+                if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&
+                    psa_get_key_type(attributes) == PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1) &&
+                    psa_get_key_bits(attributes) == 256 )
+                {
+                    status = p256_transparent_generate_key( attributes,
+                                                            key_buffer,
+                                                            key_buffer_size,
+                                                            key_buffer_length );
+                    if( status != PSA_ERROR_NOT_SUPPORTED )
+                        break;
+                }
+
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
+            }
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Software fallback */
+            status = psa_generate_key_internal(
+                attributes, custom, custom_data, custom_data_length,
+                key_buffer, key_buffer_size, key_buffer_length );
+            break;
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_generate_key(
+                attributes, key_buffer, key_buffer_size, key_buffer_length );
+            break;
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            break;
+    }
+
+    return( status );
+}
+
+static inline psa_status_t psa_driver_wrapper_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data,
+    size_t data_length,
+    uint8_t *key_buffer,
+    size_t key_buffer_size,
+    size_t *key_buffer_length,
+    size_t *bits )
+{
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                      psa_get_key_lifetime( attributes ) );
+
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        if( drv->key_management == NULL ||
+            drv->key_management->p_import == NULL )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* The driver should set the number of key bits, however in
+         * case it doesn't, we initialize bits to an invalid value. */
+        *bits = PSA_MAX_KEY_BITS + 1;
+        status = drv->key_management->p_import(
+            drv_context,
+            *( (psa_key_slot_number_t *)key_buffer ),
+            attributes, data, data_length, bits );
+
+        if( status != PSA_SUCCESS )
+            return( status );
+
+        if( (*bits) > PSA_MAX_KEY_BITS )
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        return( PSA_SUCCESS );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+            status = mbedtls_test_transparent_import_key
+                (attributes,
+                                data,
+                                data_length,
+                                key_buffer,
+                                key_buffer_size,
+                                key_buffer_length,
+                                bits
+            );
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif
+
+#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )
+            status = p256_transparent_import_key
+                (attributes,
+                                data,
+                                data_length,
+                                key_buffer,
+                                key_buffer_size,
+                                key_buffer_length,
+                                bits
+            );
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            return( psa_import_key_into_slot( attributes,
+                                              data, data_length,
+                                              key_buffer, key_buffer_size,
+                                              key_buffer_length, bits ) );
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+        case 0x7fffff:
+            return( mbedtls_test_opaque_import_key
+            (attributes,
+                            data,
+                            data_length,
+                            key_buffer,
+                            key_buffer_size,
+                            key_buffer_length,
+                            bits
+        ));
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+
+}
+
+static inline psa_status_t psa_driver_wrapper_export_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length )
+
+{
+
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                      psa_get_key_lifetime( attributes ) );
+
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        if( ( drv->key_management == NULL   ) ||
+            ( drv->key_management->p_export == NULL ) )
+        {
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+
+        return( drv->key_management->p_export(
+                     drv_context,
+                     *( (psa_key_slot_number_t *)key_buffer ),
+                     data, data_size, data_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            return( psa_export_key_internal( attributes,
+                                             key_buffer,
+                                             key_buffer_size,
+                                             data,
+                                             data_size,
+                                             data_length ) );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+        case 0x7fffff:
+            return( mbedtls_test_opaque_export_key
+            (attributes,
+                            key_buffer,
+                            key_buffer_size,
+                            data,
+                            data_size,
+                            data_length
+        ));
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+
+}
+
+static inline psa_status_t psa_driver_wrapper_copy_key(
+    psa_key_attributes_t *attributes,
+    const uint8_t *source_key, size_t source_key_length,
+    uint8_t *target_key_buffer, size_t target_key_buffer_size,
+    size_t *target_key_buffer_length )
+{
+
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        /* Copying to a secure element is not implemented yet. */
+        return( PSA_ERROR_NOT_SUPPORTED );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+        case 0x7fffff:
+            return( mbedtls_test_opaque_copy_key
+            (attributes,
+                            source_key,
+                            source_key_length,
+                            target_key_buffer,
+                            target_key_buffer_size,
+                            target_key_buffer_length
+        ));
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void)source_key;
+            (void)source_key_length;
+            (void)target_key_buffer;
+            (void)target_key_buffer_size;
+            (void)target_key_buffer_length;
+            status = PSA_ERROR_INVALID_ARGUMENT;
+    }
+    return( status );
+
+}
+
+/*
+ * Cipher functions
+ */
+static inline psa_status_t psa_driver_wrapper_cipher_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *iv,
+    size_t iv_length,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_cipher_encrypt( attributes,
+                                                              key_buffer,
+                                                              key_buffer_size,
+                                                              alg,
+                                                              iv,
+                                                              iv_length,
+                                                              input,
+                                                              input_length,
+                                                              output,
+                                                              output_size,
+                                                              output_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+            return( mbedtls_psa_cipher_encrypt( attributes,
+                                                key_buffer,
+                                                key_buffer_size,
+                                                alg,
+                                                iv,
+                                                iv_length,
+                                                input,
+                                                input_length,
+                                                output,
+                                                output_size,
+                                                output_length ) );
+#else
+            return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_cipher_encrypt( attributes,
+                                                        key_buffer,
+                                                        key_buffer_size,
+                                                        alg,
+                                                        iv,
+                                                        iv_length,
+                                                        input,
+                                                        input_length,
+                                                        output,
+                                                        output_size,
+                                                        output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            (void)iv;
+            (void)iv_length;
+            (void)input;
+            (void)input_length;
+            (void)output;
+            (void)output_size;
+            (void)output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_cipher_decrypt( attributes,
+                                                              key_buffer,
+                                                              key_buffer_size,
+                                                              alg,
+                                                              input,
+                                                              input_length,
+                                                              output,
+                                                              output_size,
+                                                              output_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+            return( mbedtls_psa_cipher_decrypt( attributes,
+                                                key_buffer,
+                                                key_buffer_size,
+                                                alg,
+                                                input,
+                                                input_length,
+                                                output,
+                                                output_size,
+                                                output_length ) );
+#else
+            return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_cipher_decrypt( attributes,
+                                                        key_buffer,
+                                                        key_buffer_size,
+                                                        alg,
+                                                        input,
+                                                        input_length,
+                                                        output,
+                                                        output_size,
+                                                        output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            (void)input;
+            (void)input_length;
+            (void)output;
+            (void)output_size;
+            (void)output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_encrypt_setup(
+    psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_cipher_encrypt_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer,
+                key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_cipher_encrypt_setup( &operation->ctx.mbedtls_ctx,
+                                                       attributes,
+                                                       key_buffer,
+                                                       key_buffer_size,
+                                                       alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_cipher_encrypt_setup(
+                &operation->ctx.opaque_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)operation;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_decrypt_setup(
+    psa_cipher_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_cipher_decrypt_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer,
+                key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_cipher_decrypt_setup( &operation->ctx.mbedtls_ctx,
+                                                       attributes,
+                                                       key_buffer,
+                                                       key_buffer_size,
+                                                       alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            return( status );
+#else /* MBEDTLS_PSA_BUILTIN_CIPHER */
+            return( PSA_ERROR_NOT_SUPPORTED );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_cipher_decrypt_setup(
+                         &operation->ctx.opaque_test_driver_ctx,
+                         attributes,
+                         key_buffer, key_buffer_size,
+                         alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)operation;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_set_iv(
+    psa_cipher_operation_t *operation,
+    const uint8_t *iv,
+    size_t iv_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_cipher_set_iv( &operation->ctx.mbedtls_ctx,
+                                               iv,
+                                               iv_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_set_iv(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        iv, iv_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_cipher_set_iv(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        iv, iv_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)iv;
+    (void)iv_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_update(
+    psa_cipher_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_cipher_update( &operation->ctx.mbedtls_ctx,
+                                               input,
+                                               input_length,
+                                               output,
+                                               output_size,
+                                               output_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length,
+                        output, output_size, output_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_cipher_update(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        input, input_length,
+                        output, output_size, output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)input;
+    (void)input_length;
+    (void)output;
+    (void)output_size;
+    (void)output_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_finish(
+    psa_cipher_operation_t *operation,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_cipher_finish( &operation->ctx.mbedtls_ctx,
+                                               output,
+                                               output_size,
+                                               output_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_cipher_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        output, output_size, output_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_cipher_finish(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        output, output_size, output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)output;
+    (void)output_size;
+    (void)output_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_cipher_abort(
+    psa_cipher_operation_t *operation )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_CIPHER)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_cipher_abort( &operation->ctx.mbedtls_ctx ) );
+#endif /* MBEDTLS_PSA_BUILTIN_CIPHER */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            status = mbedtls_test_transparent_cipher_abort(
+                         &operation->ctx.transparent_test_driver_ctx );
+            mbedtls_platform_zeroize(
+                &operation->ctx.transparent_test_driver_ctx,
+                sizeof( operation->ctx.transparent_test_driver_ctx ) );
+            return( status );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            status = mbedtls_test_opaque_cipher_abort(
+                         &operation->ctx.opaque_test_driver_ctx );
+            mbedtls_platform_zeroize(
+                &operation->ctx.opaque_test_driver_ctx,
+                sizeof( operation->ctx.opaque_test_driver_ctx ) );
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)status;
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+/*
+ * Hashing functions
+ */
+static inline psa_status_t psa_driver_wrapper_hash_compute(
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* Try accelerators first */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    status = mbedtls_test_transparent_hash_compute(
+                alg, input, input_length, hash, hash_size, hash_length );
+    if( status != PSA_ERROR_NOT_SUPPORTED )
+        return( status );
+#endif
+
+    /* If software fallback is compiled in, try fallback */
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+    status = mbedtls_psa_hash_compute( alg, input, input_length,
+                                       hash, hash_size, hash_length );
+    if( status != PSA_ERROR_NOT_SUPPORTED )
+        return( status );
+#endif
+    (void) status;
+    (void) alg;
+    (void) input;
+    (void) input_length;
+    (void) hash;
+    (void) hash_size;
+    (void) hash_length;
+
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+static inline psa_status_t psa_driver_wrapper_hash_setup(
+    psa_hash_operation_t *operation,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* Try setup on accelerators first */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+    status = mbedtls_test_transparent_hash_setup(
+                &operation->ctx.test_driver_ctx, alg );
+    if( status == PSA_SUCCESS )
+        operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+
+    if( status != PSA_ERROR_NOT_SUPPORTED )
+        return( status );
+#endif
+
+    /* If software fallback is compiled in, try fallback */
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+    status = mbedtls_psa_hash_setup( &operation->ctx.mbedtls_ctx, alg );
+    if( status == PSA_SUCCESS )
+        operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+    if( status != PSA_ERROR_NOT_SUPPORTED )
+        return( status );
+#endif
+    /* Nothing left to try if we fall through here */
+    (void) status;
+    (void) operation;
+    (void) alg;
+    return( PSA_ERROR_NOT_SUPPORTED );
+}
+
+static inline psa_status_t psa_driver_wrapper_hash_clone(
+    const psa_hash_operation_t *source_operation,
+    psa_hash_operation_t *target_operation )
+{
+    switch( source_operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            target_operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            return( mbedtls_psa_hash_clone( &source_operation->ctx.mbedtls_ctx,
+                                            &target_operation->ctx.mbedtls_ctx ) );
+#endif
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            target_operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+            return( mbedtls_test_transparent_hash_clone(
+                        &source_operation->ctx.test_driver_ctx,
+                        &target_operation->ctx.test_driver_ctx ) );
+#endif
+        default:
+            (void) target_operation;
+            return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_hash_update(
+    psa_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_hash_update( &operation->ctx.mbedtls_ctx,
+                                             input, input_length ) );
+#endif
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_hash_update(
+                        &operation->ctx.test_driver_ctx,
+                        input, input_length ) );
+#endif
+        default:
+            (void) input;
+            (void) input_length;
+            return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_hash_finish(
+    psa_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_hash_finish( &operation->ctx.mbedtls_ctx,
+                                             hash, hash_size, hash_length ) );
+#endif
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_hash_finish(
+                        &operation->ctx.test_driver_ctx,
+                        hash, hash_size, hash_length ) );
+#endif
+        default:
+            (void) hash;
+            (void) hash_size;
+            (void) hash_length;
+            return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_hash_abort(
+    psa_hash_operation_t *operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_hash_abort( &operation->ctx.mbedtls_ctx ) );
+#endif
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_hash_abort(
+                        &operation->ctx.test_driver_ctx ) );
+#endif
+        default:
+            return( PSA_ERROR_BAD_STATE );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_encrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *plaintext, size_t plaintext_length,
+    uint8_t *ciphertext, size_t ciphertext_size, size_t *ciphertext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_aead_encrypt(
+                         attributes, key_buffer, key_buffer_size,
+                         alg,
+                         nonce, nonce_length,
+                         additional_data, additional_data_length,
+                         plaintext, plaintext_length,
+                         ciphertext, ciphertext_size, ciphertext_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            return( mbedtls_psa_aead_encrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        plaintext, plaintext_length,
+                        ciphertext, ciphertext_size, ciphertext_length ) );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_decrypt(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *nonce, size_t nonce_length,
+    const uint8_t *additional_data, size_t additional_data_length,
+    const uint8_t *ciphertext, size_t ciphertext_length,
+    uint8_t *plaintext, size_t plaintext_size, size_t *plaintext_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_aead_decrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        ciphertext, ciphertext_length,
+                        plaintext, plaintext_size, plaintext_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            return( mbedtls_psa_aead_decrypt(
+                        attributes, key_buffer, key_buffer_size,
+                        alg,
+                        nonce, nonce_length,
+                        additional_data, additional_data_length,
+                        ciphertext, ciphertext_length,
+                        plaintext, plaintext_size, plaintext_length ) );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_encrypt_setup(
+   psa_aead_operation_t *operation,
+   const psa_key_attributes_t *attributes,
+   const uint8_t *key_buffer, size_t key_buffer_size,
+   psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+            status = mbedtls_test_transparent_aead_encrypt_setup(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        attributes, key_buffer, key_buffer_size,
+                        alg );
+
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_aead_encrypt_setup(
+                        &operation->ctx.mbedtls_ctx, attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            return( status );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_decrypt_setup(
+   psa_aead_operation_t *operation,
+   const psa_key_attributes_t *attributes,
+   const uint8_t *key_buffer, size_t key_buffer_size,
+   psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+            status = mbedtls_test_transparent_aead_decrypt_setup(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Fell through, meaning no accelerator supports this operation */
+            operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+            status = mbedtls_psa_aead_decrypt_setup(
+                        &operation->ctx.mbedtls_ctx,
+                        attributes,
+                        key_buffer, key_buffer_size,
+                        alg );
+
+            return( status );
+
+        /* Add cases for opaque driver here */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_set_nonce(
+   psa_aead_operation_t *operation,
+   const uint8_t *nonce,
+   size_t nonce_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_set_nonce( &operation->ctx.mbedtls_ctx,
+                                                nonce,
+                                                nonce_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_set_nonce(
+                         &operation->ctx.transparent_test_driver_ctx,
+                         nonce, nonce_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)nonce;
+    (void)nonce_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_set_lengths(
+   psa_aead_operation_t *operation,
+   size_t ad_length,
+   size_t plaintext_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_set_lengths( &operation->ctx.mbedtls_ctx,
+                                                  ad_length,
+                                                  plaintext_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_set_lengths(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        ad_length, plaintext_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)ad_length;
+    (void)plaintext_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_update_ad(
+   psa_aead_operation_t *operation,
+   const uint8_t *input,
+   size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_update_ad( &operation->ctx.mbedtls_ctx,
+                                                input,
+                                                input_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_update_ad(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)input;
+    (void)input_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_update(
+   psa_aead_operation_t *operation,
+   const uint8_t *input,
+   size_t input_length,
+   uint8_t *output,
+   size_t output_size,
+   size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_update( &operation->ctx.mbedtls_ctx,
+                                             input, input_length,
+                                             output, output_size,
+                                             output_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length, output, output_size,
+                        output_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)input;
+    (void)input_length;
+    (void)output;
+    (void)output_size;
+    (void)output_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_finish(
+   psa_aead_operation_t *operation,
+   uint8_t *ciphertext,
+   size_t ciphertext_size,
+   size_t *ciphertext_length,
+   uint8_t *tag,
+   size_t tag_size,
+   size_t *tag_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
+                                             ciphertext,
+                                             ciphertext_size,
+                                             ciphertext_length, tag,
+                                             tag_size, tag_length ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        ciphertext, ciphertext_size,
+                        ciphertext_length, tag, tag_size, tag_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)ciphertext;
+    (void)ciphertext_size;
+    (void)ciphertext_length;
+    (void)tag;
+    (void)tag_size;
+    (void)tag_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_verify(
+   psa_aead_operation_t *operation,
+   uint8_t *plaintext,
+   size_t plaintext_size,
+   size_t *plaintext_length,
+   const uint8_t *tag,
+   size_t tag_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            {
+                psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+                uint8_t check_tag[PSA_AEAD_TAG_MAX_SIZE];
+                size_t check_tag_length;
+
+                status = mbedtls_psa_aead_finish( &operation->ctx.mbedtls_ctx,
+                                                  plaintext,
+                                                  plaintext_size,
+                                                  plaintext_length,
+                                                  check_tag,
+                                                  sizeof( check_tag ),
+                                                  &check_tag_length );
+
+                if( status == PSA_SUCCESS )
+                {
+                    if( tag_length != check_tag_length ||
+                        mbedtls_ct_memcmp( tag, check_tag, tag_length )
+                        != 0 )
+                        status = PSA_ERROR_INVALID_SIGNATURE;
+                }
+
+                mbedtls_platform_zeroize( check_tag, sizeof( check_tag ) );
+
+                return( status );
+            }
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_verify(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        plaintext, plaintext_size,
+                        plaintext_length, tag, tag_length ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    (void)plaintext;
+    (void)plaintext_size;
+    (void)plaintext_length;
+    (void)tag;
+    (void)tag_length;
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+static inline psa_status_t psa_driver_wrapper_aead_abort(
+   psa_aead_operation_t *operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_AEAD)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_aead_abort( &operation->ctx.mbedtls_ctx ) );
+
+#endif /* MBEDTLS_PSA_BUILTIN_AEAD */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_aead_abort(
+               &operation->ctx.transparent_test_driver_ctx ) );
+
+        /* Add cases for opaque driver here */
+
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+    }
+
+    return( PSA_ERROR_INVALID_ARGUMENT );
+}
+
+/*
+ * MAC functions
+ */
+static inline psa_status_t psa_driver_wrapper_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_compute(
+                attributes, key_buffer, key_buffer_size, alg,
+                input, input_length,
+                mac, mac_size, mac_length );
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            (void) input;
+            (void) input_length;
+            (void) mac;
+            (void) mac_size;
+            (void) mac_length;
+            (void) status;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_sign_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_sign_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_sign_setup( &operation->ctx.mbedtls_ctx,
+                                                 attributes,
+                                                 key_buffer, key_buffer_size,
+                                                 alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_sign_setup(
+                &operation->ctx.opaque_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) status;
+            (void) operation;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_verify_setup(
+    psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_mac_verify_setup(
+                &operation->ctx.transparent_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+            /* Declared with fallback == true */
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+            /* Fell through, meaning no accelerator supports this operation */
+            status = mbedtls_psa_mac_verify_setup( &operation->ctx.mbedtls_ctx,
+                                                   attributes,
+                                                   key_buffer, key_buffer_size,
+                                                   alg );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            status = mbedtls_test_opaque_mac_verify_setup(
+                &operation->ctx.opaque_test_driver_ctx,
+                attributes,
+                key_buffer, key_buffer_size,
+                alg );
+
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_OPAQUE_DRIVER_ID;
+
+            return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void) status;
+            (void) operation;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) alg;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_update(
+    psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_update( &operation->ctx.mbedtls_ctx,
+                                            input, input_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_update(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        input, input_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_update(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        input, input_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) input;
+            (void) input_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_sign_finish(
+    psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_sign_finish( &operation->ctx.mbedtls_ctx,
+                                                 mac, mac_size, mac_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_sign_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_size, mac_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_sign_finish(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        mac, mac_size, mac_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) mac;
+            (void) mac_size;
+            (void) mac_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_verify_finish(
+    psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_verify_finish( &operation->ctx.mbedtls_ctx,
+                                                   mac, mac_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_verify_finish(
+                        &operation->ctx.transparent_test_driver_ctx,
+                        mac, mac_length ) );
+
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_verify_finish(
+                        &operation->ctx.opaque_test_driver_ctx,
+                        mac, mac_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) mac;
+            (void) mac_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_mac_abort(
+    psa_mac_operation_t *operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_MAC)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_mac_abort( &operation->ctx.mbedtls_ctx ) );
+#endif /* MBEDTLS_PSA_BUILTIN_MAC */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_mac_abort(
+                        &operation->ctx.transparent_test_driver_ctx ) );
+        case MBEDTLS_TEST_OPAQUE_DRIVER_ID:
+            return( mbedtls_test_opaque_mac_abort(
+                        &operation->ctx.opaque_test_driver_ctx ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+/*
+ * Asymmetric cryptography
+ */
+static inline psa_status_t psa_driver_wrapper_asymmetric_encrypt(
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
+    size_t input_length, const uint8_t *salt, size_t salt_length,
+    uint8_t *output, size_t output_size, size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_asymmetric_encrypt( attributes,
+                        key_buffer, key_buffer_size, alg, input, input_length,
+                        salt, salt_length, output, output_size,
+                        output_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            return( mbedtls_psa_asymmetric_encrypt( attributes,
+                        key_buffer, key_buffer_size, alg, input, input_length,
+                        salt, salt_length, output, output_size, output_length )
+                  );
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_asymmetric_encrypt( attributes,
+                        key_buffer, key_buffer_size, alg, input, input_length,
+                        salt, salt_length, output, output_size, output_length )
+                  );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            (void)input;
+            (void)input_length;
+            (void)salt;
+            (void)salt_length;
+            (void)output;
+            (void)output_size;
+            (void)output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_asymmetric_decrypt(
+    const psa_key_attributes_t *attributes, const uint8_t *key_buffer,
+    size_t key_buffer_size, psa_algorithm_t alg, const uint8_t *input,
+    size_t input_length, const uint8_t *salt, size_t salt_length,
+    uint8_t *output, size_t output_size, size_t *output_length )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_asymmetric_decrypt( attributes,
+                        key_buffer, key_buffer_size, alg, input, input_length,
+                        salt, salt_length, output, output_size,
+                        output_length );
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            return( mbedtls_psa_asymmetric_decrypt( attributes,
+                        key_buffer, key_buffer_size, alg,input, input_length,
+                        salt, salt_length, output, output_size,
+                        output_length ) );
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_asymmetric_decrypt( attributes,
+                        key_buffer, key_buffer_size, alg, input, input_length,
+                        salt, salt_length, output, output_size,
+                        output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)status;
+            (void)key_buffer;
+            (void)key_buffer_size;
+            (void)alg;
+            (void)input;
+            (void)input_length;
+            (void)salt;
+            (void)salt_length;
+            (void)output;
+            (void)output_size;
+            (void)output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length
+ )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_location_t location =
+        PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status =
+                mbedtls_test_transparent_key_agreement( attributes,
+                        key_buffer, key_buffer_size, alg, peer_key,
+                        peer_key_length, shared_secret, shared_secret_size,
+                        shared_secret_length );
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+            if( PSA_KEY_TYPE_IS_ECC( psa_get_key_type(attributes) ) &&
+                PSA_ALG_IS_ECDH(alg) &&
+                PSA_KEY_TYPE_ECC_GET_FAMILY(psa_get_key_type(attributes)) == PSA_ECC_FAMILY_SECP_R1 &&
+                psa_get_key_bits(attributes) == 256 )
+            {
+                status = p256_transparent_key_agreement( attributes,
+                                                         key_buffer,
+                                                         key_buffer_size,
+                                                         alg,
+                                                         peer_key,
+                                                         peer_key_length,
+                                                         shared_secret,
+                                                         shared_secret_size,
+                                                         shared_secret_length );
+                if( status != PSA_ERROR_NOT_SUPPORTED)
+                    return( status );
+            }
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+            /* Software Fallback */
+            status = psa_key_agreement_raw_builtin( attributes,
+                                                    key_buffer,
+                                                    key_buffer_size,
+                                                    alg,
+                                                    peer_key,
+                                                    peer_key_length,
+                                                    shared_secret,
+                                                    shared_secret_size,
+                                                    shared_secret_length );
+            return( status );
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+            return( mbedtls_test_opaque_key_agreement( attributes,
+                        key_buffer, key_buffer_size, alg, peer_key,
+                        peer_key_length, shared_secret, shared_secret_size,
+                        shared_secret_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+
+        default:
+            (void) attributes;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) peer_key;
+            (void) peer_key_length;
+            (void) shared_secret;
+            (void) shared_secret_size;
+            (void) shared_secret_length;
+            return( PSA_ERROR_NOT_SUPPORTED );
+
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_pake_setup(
+    psa_pake_operation_t *operation,
+    const psa_crypto_driver_pake_inputs_t *inputs )
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    psa_key_location_t location =
+            PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime( &inputs->attributes ) );
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+            status = PSA_ERROR_NOT_SUPPORTED;
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+            status = mbedtls_test_transparent_pake_setup(
+                        &operation->data.ctx.transparent_test_driver_ctx,
+                        inputs );
+            if( status == PSA_SUCCESS )
+                operation->id = MBEDTLS_TEST_TRANSPARENT_DRIVER_ID;
+            /* Declared with fallback == true */
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+            status = mbedtls_psa_pake_setup( &operation->data.ctx.mbedtls_ctx,
+                        inputs );
+            if( status == PSA_SUCCESS )
+                operation->id = PSA_CRYPTO_MBED_TLS_DRIVER_ID;
+#endif
+            return status;
+        /* Add cases for opaque driver here */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            (void)operation;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_pake_output(
+    psa_pake_operation_t *operation,
+    psa_crypto_driver_pake_step_t step,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_pake_output( &operation->data.ctx.mbedtls_ctx, step,
+                                             output, output_size, output_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_pake_output(
+                        &operation->data.ctx.transparent_test_driver_ctx,
+                        step, output, output_size, output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) step;
+            (void) output;
+            (void) output_size;
+            (void) output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_pake_input(
+    psa_pake_operation_t *operation,
+    psa_crypto_driver_pake_step_t step,
+    const uint8_t *input,
+    size_t input_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_pake_input( &operation->data.ctx.mbedtls_ctx,
+                                            step, input,
+                                            input_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_pake_input(
+                        &operation->data.ctx.transparent_test_driver_ctx,
+                        step,
+                        input, input_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) step;
+            (void) input;
+            (void) input_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_pake_get_implicit_key(
+    psa_pake_operation_t *operation,
+    uint8_t *output, size_t output_size,
+    size_t *output_length )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_pake_get_implicit_key( &operation->data.ctx.mbedtls_ctx,
+                                                       output, output_size, output_length ) );
+#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_pake_get_implicit_key(
+                        &operation->data.ctx.transparent_test_driver_ctx,
+                        output, output_size, output_length ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) output;
+            (void) output_size;
+            (void) output_length;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+static inline psa_status_t psa_driver_wrapper_pake_abort(
+    psa_pake_operation_t * operation )
+{
+    switch( operation->id )
+    {
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+        case PSA_CRYPTO_MBED_TLS_DRIVER_ID:
+            return( mbedtls_psa_pake_abort( &operation->data.ctx.mbedtls_ctx ) );
+#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
+
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case MBEDTLS_TEST_TRANSPARENT_DRIVER_ID:
+            return( mbedtls_test_transparent_pake_abort(
+                        &operation->data.ctx.transparent_test_driver_ctx ) );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.c b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.c
new file mode 100644
index 0000000000000000000000000000000000000000..de8a5269b341d9efe547a163cc6f5d3116f9432a
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.c
@@ -0,0 +1,256 @@
+/*
+ *  Functions to delegate cryptographic operations to an available
+ *  and appropriate accelerator.
+ *  Warning: This file is now auto-generated.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+
+/* BEGIN-common headers */
+#include "common.h"
+#include "psa_crypto_aead.h"
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
+#include "psa_crypto_hash.h"
+#include "psa_crypto_mac.h"
+#include "psa_crypto_pake.h"
+#include "psa_crypto_rsa.h"
+
+#include "mbedtls/platform.h"
+/* END-common headers */
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* BEGIN-driver headers */
+/* Headers for mbedtls_test opaque driver */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include "test/drivers/test_driver.h"
+
+#endif
+/* Headers for mbedtls_test transparent driver */
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+#include "test/drivers/test_driver.h"
+
+#endif
+/* Headers for p256 transparent driver */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+#include "../3rdparty/p256-m/p256-m_driver_entrypoints.h"
+
+#endif
+
+/* END-driver headers */
+
+/* Auto-generated values depending on which drivers are registered.
+ * ID 0 is reserved for unallocated operations.
+ * ID 1 is reserved for the Mbed TLS software driver. */
+/* BEGIN-driver id definition */
+#define PSA_CRYPTO_MBED_TLS_DRIVER_ID (1)
+#define MBEDTLS_TEST_OPAQUE_DRIVER_ID (2)
+#define MBEDTLS_TEST_TRANSPARENT_DRIVER_ID (3)
+#define P256_TRANSPARENT_DRIVER_ID (4)
+
+/* END-driver id */
+
+/* BEGIN-Common Macro definitions */
+
+/* END-Common Macro definitions */
+
+/* Support the 'old' SE interface when asked to */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/* PSA_CRYPTO_DRIVER_PRESENT is defined when either a new-style or old-style
+ * SE driver is present, to avoid unused argument errors at compile time. */
+#ifndef PSA_CRYPTO_DRIVER_PRESENT
+#define PSA_CRYPTO_DRIVER_PRESENT
+#endif
+#include "psa_crypto_se.h"
+#endif
+
+/** Get the key buffer size required to store the key material of a key
+ *  associated with an opaque driver.
+ *
+ * \param[in] attributes  The key attributes.
+ * \param[out] key_buffer_size  Minimum buffer size to contain the key material
+ *
+ * \retval #PSA_SUCCESS
+ *         The minimum size for a buffer to contain the key material has been
+ *         returned successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The type and/or the size in bits of the key or the combination of
+ *         the two is not supported.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key is declared with a lifetime not known to us.
+ */
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+    const psa_key_attributes_t *attributes,
+    size_t *key_buffer_size )
+{
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+    psa_key_type_t key_type = psa_get_key_type(attributes);
+    size_t key_bits = psa_get_key_bits(attributes);
+
+    *key_buffer_size = 0;
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_DRIVER_TEST)
+        case PSA_CRYPTO_TEST_DRIVER_LOCATION:
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+            /* Emulate property 'builtin_key_size' */
+            if( psa_key_id_is_builtin(
+                    MBEDTLS_SVC_KEY_ID_GET_KEY_ID(
+                        psa_get_key_id( attributes ) ) ) )
+            {
+                *key_buffer_size = sizeof( psa_drv_slot_number_t );
+                return( PSA_SUCCESS );
+            }
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+            *key_buffer_size = mbedtls_test_opaque_size_function( key_type,
+                                                                  key_bits );
+            return( ( *key_buffer_size != 0 ) ?
+                    PSA_SUCCESS : PSA_ERROR_NOT_SUPPORTED );
+#endif /* PSA_CRYPTO_DRIVER_TEST */
+
+        default:
+            (void)key_type;
+            (void)key_bits;
+            return( PSA_ERROR_INVALID_ARGUMENT );
+    }
+}
+
+psa_status_t psa_driver_wrapper_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length )
+
+{
+
+    psa_status_t status = PSA_ERROR_INVALID_ARGUMENT;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(
+                                      psa_get_key_lifetime( attributes ) );
+
+    /* Try dynamically-registered SE interface first */
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+
+    if( psa_get_se_driver( psa_get_key_lifetime(attributes), &drv, &drv_context ) )
+    {
+        if( ( drv->key_management == NULL ) ||
+            ( drv->key_management->p_export_public == NULL ) )
+        {
+            return( PSA_ERROR_NOT_SUPPORTED );
+        }
+
+        return( drv->key_management->p_export_public(
+                    drv_context,
+                    *( (psa_key_slot_number_t *)key_buffer ),
+                    data, data_size, data_length ) );
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    switch( location )
+    {
+        case PSA_KEY_LOCATION_LOCAL_STORAGE:
+            /* Key is stored in the slot in export representation, so
+             * cycle through all known transparent accelerators */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+            status = mbedtls_test_transparent_export_public_key
+                (attributes,
+                                key_buffer,
+                                key_buffer_size,
+                                data,
+                                data_size,
+                                data_length
+            );
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif
+
+#if (defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED) )
+            status = p256_transparent_export_public_key
+                (attributes,
+                                key_buffer,
+                                key_buffer_size,
+                                data,
+                                data_size,
+                                data_length
+            );
+
+            if( status != PSA_ERROR_NOT_SUPPORTED )
+                return( status );
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+            /* Fell through, meaning no accelerator supports this operation */
+            return( psa_export_public_key_internal( attributes,
+                                                    key_buffer,
+                                                    key_buffer_size,
+                                                    data,
+                                                    data_size,
+                                                    data_length ) );
+
+        /* Add cases for opaque driver here */
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+        case 0x7fffff:
+            return( mbedtls_test_opaque_export_public_key
+            (attributes,
+                            key_buffer,
+                            key_buffer_size,
+                            data,
+                            data_size,
+                            data_length
+        ));
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            /* Key is declared with a lifetime not known to us */
+            return( status );
+    }
+
+}
+
+psa_status_t psa_driver_wrapper_get_builtin_key(
+    psa_drv_slot_number_t slot_number,
+    psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length )
+{
+
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION( psa_get_key_lifetime(attributes) );
+    switch( location )
+    {
+#if defined(PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT)
+
+#if (defined(PSA_CRYPTO_DRIVER_TEST) )
+        case 0x7fffff:
+            return( mbedtls_test_opaque_get_builtin_key
+            (slot_number,
+                            attributes,
+                            key_buffer,
+                            key_buffer_size,
+                            key_buffer_length
+        ));
+#endif
+
+
+#endif /* PSA_CRYPTO_ACCELERATOR_DRIVER_PRESENT */
+        default:
+            (void) slot_number;
+            (void) key_buffer;
+            (void) key_buffer_size;
+            (void) key_buffer_length;
+            return( PSA_ERROR_DOES_NOT_EXIST );
+    }
+
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.h b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.h
new file mode 100644
index 0000000000000000000000000000000000000000..cd617f60ee6c958c4959b30e09544d444d31ecf8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_driver_wrappers_no_static.h
@@ -0,0 +1,31 @@
+/*
+ *  Function signatures for functionality that can be provided by
+ *  cryptographic accelerators.
+ */
+/*  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
+#define PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H
+
+#include "psa/crypto.h"
+#include "psa/crypto_driver_common.h"
+
+psa_status_t psa_driver_wrapper_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+psa_status_t psa_driver_wrapper_get_key_buffer_size(
+    const psa_key_attributes_t *attributes,
+    size_t *key_buffer_size);
+
+psa_status_t psa_driver_wrapper_get_builtin_key(
+    psa_drv_slot_number_t slot_number,
+    psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+
+#endif /* PSA_CRYPTO_DRIVER_WRAPPERS_NO_STATIC_H */
+
+/* End of automatically generated file. */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.c b/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.c
new file mode 100644
index 0000000000000000000000000000000000000000..95baff6a0fa116db8a7a8f7fbdc19b166df116af
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.c
@@ -0,0 +1,596 @@
+/*
+ *  PSA ECP layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_ecp.h"
+#include "psa_crypto_random_impl.h"
+#include "mbedtls/psa_util.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+
+#include <mbedtls/ecdsa.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/error.h>
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+/* Helper function to verify if the provided EC's family and key bit size are valid.
+ *
+ * Note: "bits" parameter is used both as input and output and it might be updated
+ *       in case provided input value is not multiple of 8 ("sloppy" bits).
+ */
+static int check_ecc_parameters(psa_ecc_family_t family, size_t *bits)
+{
+    switch (family) {
+        case PSA_ECC_FAMILY_SECP_R1:
+            switch (*bits) {
+                case 192:
+                case 224:
+                case 256:
+                case 384:
+                case 521:
+                    return PSA_SUCCESS;
+                case 528:
+                    *bits = 521;
+                    return PSA_SUCCESS;
+            }
+            break;
+
+        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
+            switch (*bits) {
+                case 256:
+                case 384:
+                case 512:
+                    return PSA_SUCCESS;
+            }
+            break;
+
+        case PSA_ECC_FAMILY_MONTGOMERY:
+            switch (*bits) {
+                case 448:
+                case 255:
+                    return PSA_SUCCESS;
+                case 256:
+                    *bits = 255;
+                    return PSA_SUCCESS;
+            }
+            break;
+
+        case PSA_ECC_FAMILY_SECP_K1:
+            switch (*bits) {
+                case 192:
+                /* secp224k1 is not and will not be supported in PSA (#3541). */
+                case 256:
+                    return PSA_SUCCESS;
+            }
+            break;
+    }
+
+    return PSA_ERROR_INVALID_ARGUMENT;
+}
+
+psa_status_t mbedtls_psa_ecp_load_representation(
+    psa_key_type_t type, size_t curve_bits,
+    const uint8_t *data, size_t data_length,
+    mbedtls_ecp_keypair **p_ecp)
+{
+    mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
+    psa_status_t status;
+    mbedtls_ecp_keypair *ecp = NULL;
+    size_t curve_bytes = data_length;
+    int explicit_bits = (curve_bits != 0);
+
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type) &&
+        PSA_KEY_TYPE_ECC_GET_FAMILY(type) != PSA_ECC_FAMILY_MONTGOMERY) {
+        /* A Weierstrass public key is represented as:
+         * - The byte 0x04;
+         * - `x_P` as a `ceiling(m/8)`-byte string, big-endian;
+         * - `y_P` as a `ceiling(m/8)`-byte string, big-endian.
+         * So its data length is 2m+1 where m is the curve size in bits.
+         */
+        if ((data_length & 1) == 0) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+        curve_bytes = data_length / 2;
+
+        /* Montgomery public keys are represented in compressed format, meaning
+         * their curve_bytes is equal to the amount of input. */
+
+        /* Private keys are represented in uncompressed private random integer
+         * format, meaning their curve_bytes is equal to the amount of input. */
+    }
+
+    if (explicit_bits) {
+        /* With an explicit bit-size, the data must have the matching length. */
+        if (curve_bytes != PSA_BITS_TO_BYTES(curve_bits)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    } else {
+        /* We need to infer the bit-size from the data. Since the only
+         * information we have is the length in bytes, the value of curve_bits
+         * at this stage is rounded up to the nearest multiple of 8. */
+        curve_bits = PSA_BYTES_TO_BITS(curve_bytes);
+    }
+
+    /* Allocate and initialize a key representation. */
+    ecp = mbedtls_calloc(1, sizeof(mbedtls_ecp_keypair));
+    if (ecp == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    mbedtls_ecp_keypair_init(ecp);
+
+    status = check_ecc_parameters(PSA_KEY_TYPE_ECC_GET_FAMILY(type), &curve_bits);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* Load the group. */
+    grp_id = mbedtls_ecc_group_from_psa(PSA_KEY_TYPE_ECC_GET_FAMILY(type),
+                                        curve_bits);
+    if (grp_id == MBEDTLS_ECP_DP_NONE) {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecp_group_load(&ecp->grp, grp_id));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* Load the key material. */
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
+        /* Load the public value. */
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_point_read_binary(&ecp->grp, &ecp->Q,
+                                          data,
+                                          data_length));
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+
+        /* Check that the point is on the curve. */
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_check_pubkey(&ecp->grp, &ecp->Q));
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    } else {
+        /* Load and validate the secret value. */
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_read_key(ecp->grp.id,
+                                 ecp,
+                                 data,
+                                 data_length));
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    *p_ecp = ecp;
+exit:
+    if (status != PSA_SUCCESS) {
+        mbedtls_ecp_keypair_free(ecp);
+        mbedtls_free(ecp);
+    }
+
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_BASIC) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY)
+
+psa_status_t mbedtls_psa_ecp_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits)
+{
+    psa_status_t status;
+    mbedtls_ecp_keypair *ecp = NULL;
+
+    /* Parse input */
+    status = mbedtls_psa_ecp_load_representation(attributes->type,
+                                                 attributes->bits,
+                                                 data,
+                                                 data_length,
+                                                 &ecp);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type) ==
+        PSA_ECC_FAMILY_MONTGOMERY) {
+        *bits = ecp->grp.nbits + 1;
+    } else {
+        *bits = ecp->grp.nbits;
+    }
+
+    /* Re-export the data to PSA export format. There is currently no support
+     * for other input formats then the export format, so this is a 1-1
+     * copy operation. */
+    status = mbedtls_psa_ecp_export_key(attributes->type,
+                                        ecp,
+                                        key_buffer,
+                                        key_buffer_size,
+                                        key_buffer_length);
+exit:
+    /* Always free the PK object (will also free contained ECP context) */
+    mbedtls_ecp_keypair_free(ecp);
+    mbedtls_free(ecp);
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
+                                        mbedtls_ecp_keypair *ecp,
+                                        uint8_t *data,
+                                        size_t data_size,
+                                        size_t *data_length)
+{
+    psa_status_t status;
+
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
+        /* Check whether the public part is loaded */
+        if (mbedtls_ecp_is_zero(&ecp->Q)) {
+            /* Calculate the public key */
+            status = mbedtls_to_psa_error(
+                mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, &ecp->grp.G,
+                                mbedtls_psa_get_random,
+                                MBEDTLS_PSA_RANDOM_STATE));
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_point_write_binary(&ecp->grp, &ecp->Q,
+                                           MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                           data_length,
+                                           data,
+                                           data_size));
+        if (status != PSA_SUCCESS) {
+            memset(data, 0, data_size);
+        }
+
+        return status;
+    } else {
+        status = mbedtls_to_psa_error(
+            mbedtls_ecp_write_key_ext(ecp, data_length, data, data_size));
+        return status;
+    }
+}
+
+psa_status_t mbedtls_psa_ecp_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_keypair *ecp = NULL;
+
+    status = mbedtls_psa_ecp_load_representation(
+        attributes->type, attributes->bits,
+        key_buffer, key_buffer_size, &ecp);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = mbedtls_psa_ecp_export_key(
+        PSA_KEY_TYPE_ECC_PUBLIC_KEY(
+            PSA_KEY_TYPE_ECC_GET_FAMILY(attributes->type)),
+        ecp, data, data_size, data_length);
+
+    mbedtls_ecp_keypair_free(ecp);
+    mbedtls_free(ecp);
+
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_IMPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE)
+psa_status_t mbedtls_psa_ecp_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    psa_ecc_family_t curve = PSA_KEY_TYPE_ECC_GET_FAMILY(
+        attributes->type);
+    mbedtls_ecp_group_id grp_id =
+        mbedtls_ecc_group_from_psa(curve, attributes->bits);
+
+    const mbedtls_ecp_curve_info *curve_info =
+        mbedtls_ecp_curve_info_from_grp_id(grp_id);
+    mbedtls_ecp_keypair ecp;
+
+    if (grp_id == MBEDTLS_ECP_DP_NONE || curve_info == NULL) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    mbedtls_ecp_keypair_init(&ecp);
+    ret = mbedtls_ecp_gen_key(grp_id, &ecp,
+                              mbedtls_psa_get_random,
+                              MBEDTLS_PSA_RANDOM_STATE);
+    if (ret != 0) {
+        mbedtls_ecp_keypair_free(&ecp);
+        return mbedtls_to_psa_error(ret);
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecp_write_key_ext(&ecp, key_buffer_length,
+                                  key_buffer, key_buffer_size));
+
+    mbedtls_ecp_keypair_free(&ecp);
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR_GENERATE */
+
+/****************************************************************/
+/* ECDSA sign/verify */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+psa_status_t mbedtls_psa_ecdsa_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_keypair *ecp = NULL;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t curve_bytes;
+    mbedtls_mpi r, s;
+
+    status = mbedtls_psa_ecp_load_representation(attributes->type,
+                                                 attributes->bits,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &ecp);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
+
+    if (signature_size < 2 * curve_bytes) {
+        ret = MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
+        goto cleanup;
+    }
+
+    if (PSA_ALG_ECDSA_IS_DETERMINISTIC(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA)
+        psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
+        mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_ext(
+                            &ecp->grp, &r, &s,
+                            &ecp->d, hash,
+                            hash_length, md_alg,
+                            mbedtls_psa_get_random,
+                            MBEDTLS_PSA_RANDOM_STATE));
+#else
+        ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
+        goto cleanup;
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+    } else {
+        (void) alg;
+        MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ecp->grp, &r, &s, &ecp->d,
+                                           hash, hash_length,
+                                           mbedtls_psa_get_random,
+                                           MBEDTLS_PSA_RANDOM_STATE));
+    }
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&r,
+                                             signature,
+                                             curve_bytes));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&s,
+                                             signature + curve_bytes,
+                                             curve_bytes));
+cleanup:
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
+    if (ret == 0) {
+        *signature_length = 2 * curve_bytes;
+    }
+
+    mbedtls_ecp_keypair_free(ecp);
+    mbedtls_free(ecp);
+
+    return mbedtls_to_psa_error(ret);
+}
+
+psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp)
+{
+    int ret = 0;
+
+    /* Check whether the public part is loaded. If not, load it. */
+    if (mbedtls_ecp_is_zero(&ecp->Q)) {
+        ret = mbedtls_ecp_mul(&ecp->grp, &ecp->Q,
+                              &ecp->d, &ecp->grp.G,
+                              mbedtls_psa_get_random,
+                              MBEDTLS_PSA_RANDOM_STATE);
+    }
+
+    return mbedtls_to_psa_error(ret);
+}
+
+psa_status_t mbedtls_psa_ecdsa_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_ecp_keypair *ecp = NULL;
+    size_t curve_bytes;
+    mbedtls_mpi r, s;
+
+    (void) alg;
+
+    status = mbedtls_psa_ecp_load_representation(attributes->type,
+                                                 attributes->bits,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &ecp);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    curve_bytes = PSA_BITS_TO_BYTES(ecp->grp.pbits);
+    mbedtls_mpi_init(&r);
+    mbedtls_mpi_init(&s);
+
+    if (signature_length != 2 * curve_bytes) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto cleanup;
+    }
+
+    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&r,
+                                                          signature,
+                                                          curve_bytes));
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = mbedtls_to_psa_error(mbedtls_mpi_read_binary(&s,
+                                                          signature + curve_bytes,
+                                                          curve_bytes));
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = mbedtls_psa_ecp_load_public_part(ecp);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = mbedtls_to_psa_error(mbedtls_ecdsa_verify(&ecp->grp, hash,
+                                                       hash_length, &ecp->Q,
+                                                       &r, &s));
+cleanup:
+    mbedtls_mpi_free(&r);
+    mbedtls_mpi_free(&s);
+    mbedtls_ecp_keypair_free(ecp);
+    mbedtls_free(ecp);
+
+    return status;
+}
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_ECDSA) || \
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_DETERMINISTIC_ECDSA) */
+
+/****************************************************************/
+/* ECDH Key Agreement */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_ECDH)
+psa_status_t mbedtls_psa_key_agreement_ecdh(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
+    uint8_t *shared_secret, size_t shared_secret_size,
+    size_t *shared_secret_length)
+{
+    psa_status_t status;
+    if (!PSA_KEY_TYPE_IS_ECC_KEY_PAIR(attributes->type) ||
+        !PSA_ALG_IS_ECDH(alg)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    mbedtls_ecp_keypair *ecp = NULL;
+    status = mbedtls_psa_ecp_load_representation(
+        attributes->type,
+        attributes->bits,
+        key_buffer,
+        key_buffer_size,
+        &ecp);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    mbedtls_ecp_keypair *their_key = NULL;
+    mbedtls_ecdh_context ecdh;
+    size_t bits = 0;
+    psa_ecc_family_t curve = mbedtls_ecc_group_to_psa(ecp->grp.id, &bits);
+    mbedtls_ecdh_init(&ecdh);
+
+    status = mbedtls_psa_ecp_load_representation(
+        PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve),
+        bits,
+        peer_key,
+        peer_key_length,
+        &their_key);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_get_params(&ecdh, their_key, MBEDTLS_ECDH_THEIRS));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_get_params(&ecdh, ecp, MBEDTLS_ECDH_OURS));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = mbedtls_to_psa_error(
+        mbedtls_ecdh_calc_secret(&ecdh,
+                                 shared_secret_length,
+                                 shared_secret, shared_secret_size,
+                                 mbedtls_psa_get_random,
+                                 MBEDTLS_PSA_RANDOM_STATE));
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    if (PSA_BITS_TO_BYTES(bits) != *shared_secret_length) {
+        status = PSA_ERROR_CORRUPTION_DETECTED;
+    }
+exit:
+    if (status != PSA_SUCCESS) {
+        mbedtls_platform_zeroize(shared_secret, shared_secret_size);
+    }
+    mbedtls_ecdh_free(&ecdh);
+    mbedtls_ecp_keypair_free(their_key);
+    mbedtls_free(their_key);
+    mbedtls_ecp_keypair_free(ecp);
+    mbedtls_free(ecp);
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_ECDH */
+
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.h b/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9f5d59de484d14b1f872215e2d549fd6cbc33e7
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_ecp.h
@@ -0,0 +1,267 @@
+/*
+ *  PSA ECP layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ECP_H
+#define PSA_CRYPTO_ECP_H
+
+#include <psa/crypto.h>
+#include <mbedtls/ecp.h>
+
+/** Load the contents of a key buffer into an internal ECP representation
+ *
+ * \param[in] type          The type of key contained in \p data.
+ * \param[in] curve_bits    The nominal bit-size of the curve.
+ *                          It must be consistent with the representation
+ *                          passed in \p data.
+ *                          This can be 0, in which case the bit-size
+ *                          is inferred from \p data_length (which is possible
+ *                          for all key types and representation formats
+ *                          formats that are currently supported or will
+ *                          be in the foreseeable future).
+ * \param[in] data          The buffer from which to load the representation.
+ * \param[in] data_length   The size in bytes of \p data.
+ * \param[out] p_ecp        Returns a pointer to an ECP context on success.
+ *                          The caller is responsible for freeing both the
+ *                          contents of the context and the context itself
+ *                          when done.
+ */
+psa_status_t mbedtls_psa_ecp_load_representation(psa_key_type_t type,
+                                                 size_t curve_bits,
+                                                 const uint8_t *data,
+                                                 size_t data_length,
+                                                 mbedtls_ecp_keypair **p_ecp);
+
+/** Load the public part of an internal ECP, if required.
+ *
+ * \param ecp               The ECP context to load the public part for.
+ *
+ * \return PSA_SUCCESS on success, otherwise an MPI error.
+ */
+
+psa_status_t mbedtls_psa_ecp_load_public_part(mbedtls_ecp_keypair *ecp);
+
+/** Import an ECP key in binary format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       import_key entry point. This function behaves as an import_key
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes for the key to import.
+ * \param[in]  data             The buffer containing the key data in import
+ *                              format.
+ * \param[in]  data_length      Size of the \p data buffer in bytes.
+ * \param[out] key_buffer       The buffer containing the key data in output
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes. This
+ *                              size is greater or equal to \p data_length.
+ * \param[out] key_buffer_length  The length of the data written in \p
+ *                                key_buffer in bytes.
+ * \param[out] bits             The key size in number of bits.
+ *
+ * \retval #PSA_SUCCESS  The ECP key was imported successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key data is not correctly formatted.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_ecp_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits);
+
+/** Export an ECP key to export representation
+ *
+ * \param[in] type          The type of key (public/private) to export
+ * \param[in] ecp           The internal ECP representation from which to export
+ * \param[out] data         The buffer to export to
+ * \param[in] data_size     The length of the buffer to export to
+ * \param[out] data_length  The amount of bytes written to \p data
+ */
+psa_status_t mbedtls_psa_ecp_export_key(psa_key_type_t type,
+                                        mbedtls_ecp_keypair *ecp,
+                                        uint8_t *data,
+                                        size_t data_size,
+                                        size_t *data_length);
+
+/** Export an ECP public key or the public part of an ECP key pair in binary
+ *  format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       export_public_key entry point. This function behaves as an
+ *       export_public_key entry point as defined in the PSA driver interface
+ *       specification.
+ *
+ * \param[in]  attributes       The attributes for the key to export.
+ * \param[in]  key_buffer       Material or context of the key to export.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[out] data             Buffer where the key data is to be written.
+ * \param[in]  data_size        Size of the \p data buffer in bytes.
+ * \param[out] data_length      On success, the number of bytes written in
+ *                              \p data
+ *
+ * \retval #PSA_SUCCESS  The ECP public key was exported successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_ecp_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+/**
+ * \brief Generate an ECP key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ *       entry point.
+ *
+ * \param[in]  attributes         The attributes for the ECP key to generate.
+ * \param[out] key_buffer         Buffer where the key data is to be written.
+ * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length  On success, the number of bytes written in
+ *                                \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was successfully generated.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Key length or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ */
+psa_status_t mbedtls_psa_ecp_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+
+/** Sign an already-calculated hash with ECDSA.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash entry point. This function behaves as a sign_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the ECC key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the ECC key context.
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              Randomized or deterministic ECDSA algorithm.
+ * \param[in]  hash             The hash or message to sign.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param[in]  signature_size   Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_ECC_KEY_PAIR, \c key_bits,
+ *         \p alg) where \c key_bits is the bit-size of the ECC key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ */
+psa_status_t mbedtls_psa_ecdsa_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+/**
+ * \brief Verify an ECDSA hash or short message signature.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash entry point. This function behaves as a verify_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the ECC key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the ECC key context.
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              Randomized or deterministic ECDSA algorithm.
+ * \param[in]  hash             The hash or message whose signature is to be
+ *                              verified.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[in]  signature        Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_ecdsa_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+
+/** Perform a key agreement and return the raw ECDH shared secret.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       key_agreement entry point. This function behaves as a key_agreement
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  context.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in
+ *                                  bytes.
+ * \param[in]  alg                  A key agreement algorithm that is
+ *                                  compatible with the type of the key.
+ * \param[in]  peer_key             The buffer containing the key context
+ *                                  of the peer's public key.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that make
+ *                                  up the returned shared secret.
+ * \retval #PSA_SUCCESS
+ *         Success. Shared secret successfully calculated.
+ * \retval #PSA_ERROR_INVALID_HANDLE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p alg is not a key agreement algorithm, or
+ *         \p private_key is not compatible with \p alg,
+ *         or \p peer_key is not valid for \p alg or not compatible with
+ *         \p private_key.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p shared_secret_size is too small
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not a supported key agreement algorithm.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_key_agreement_ecdh(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *peer_key, size_t peer_key_length,
+    uint8_t *shared_secret, size_t shared_secret_size,
+    size_t *shared_secret_length);
+#endif /* PSA_CRYPTO_ECP_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.c b/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae38f6d7c6da1eab9e5be902d6f2987dde5aa01e
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.c
@@ -0,0 +1,321 @@
+/*
+ *  PSA FFDH layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+/* This header is only needed because it defines
+ * MBEDTLS_DHM_RFC7919_FFDHEXXXX_[P|G]_BIN symbols that are used in
+ * mbedtls_psa_ffdh_set_prime_generator(). Apart from that, this module
+ * only uses bignum functions for arithmetic. */
+#include <mbedtls/dhm.h>
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_ffdh.h"
+#include "psa_crypto_random_impl.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/error.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) ||   \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE) ||   \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
+static psa_status_t mbedtls_psa_ffdh_set_prime_generator(size_t key_size,
+                                                         mbedtls_mpi *P,
+                                                         mbedtls_mpi *G)
+{
+    const unsigned char *dhm_P = NULL;
+    const unsigned char *dhm_G = NULL;
+    size_t dhm_size_P = 0;
+    size_t dhm_size_G = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (P == NULL && G == NULL) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
+    static const unsigned char dhm_P_2048[] =
+        MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
+    static const unsigned char dhm_G_2048[] =
+        MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
+    static const unsigned char dhm_P_3072[] =
+        MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
+    static const unsigned char dhm_G_3072[] =
+        MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
+    static const unsigned char dhm_P_4096[] =
+        MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
+    static const unsigned char dhm_G_4096[] =
+        MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
+    static const unsigned char dhm_P_6144[] =
+        MBEDTLS_DHM_RFC7919_FFDHE6144_P_BIN;
+    static const unsigned char dhm_G_6144[] =
+        MBEDTLS_DHM_RFC7919_FFDHE6144_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
+    static const unsigned char dhm_P_8192[] =
+        MBEDTLS_DHM_RFC7919_FFDHE8192_P_BIN;
+    static const unsigned char dhm_G_8192[] =
+        MBEDTLS_DHM_RFC7919_FFDHE8192_G_BIN;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
+
+    switch (key_size) {
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048)
+        case sizeof(dhm_P_2048):
+            dhm_P = dhm_P_2048;
+            dhm_G = dhm_G_2048;
+            dhm_size_P = sizeof(dhm_P_2048);
+            dhm_size_G = sizeof(dhm_G_2048);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_2048 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072)
+        case sizeof(dhm_P_3072):
+            dhm_P = dhm_P_3072;
+            dhm_G = dhm_G_3072;
+            dhm_size_P = sizeof(dhm_P_3072);
+            dhm_size_G = sizeof(dhm_G_3072);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_3072 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096)
+        case sizeof(dhm_P_4096):
+            dhm_P = dhm_P_4096;
+            dhm_G = dhm_G_4096;
+            dhm_size_P = sizeof(dhm_P_4096);
+            dhm_size_G = sizeof(dhm_G_4096);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_4096 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144)
+        case sizeof(dhm_P_6144):
+            dhm_P = dhm_P_6144;
+            dhm_G = dhm_G_6144;
+            dhm_size_P = sizeof(dhm_P_6144);
+            dhm_size_G = sizeof(dhm_G_6144);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_6144 */
+#if defined(MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192)
+        case sizeof(dhm_P_8192):
+            dhm_P = dhm_P_8192;
+            dhm_G = dhm_G_8192;
+            dhm_size_P = sizeof(dhm_P_8192);
+            dhm_size_G = sizeof(dhm_G_8192);
+            break;
+#endif /* MBEDTLS_PSA_BUILTIN_DH_RFC7919_8192 */
+        default:
+            return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (P != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(P, dhm_P,
+                                                dhm_size_P));
+    }
+    if (G != NULL) {
+        MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(G, dhm_G,
+                                                dhm_size_G));
+    }
+
+cleanup:
+    if (ret != 0) {
+        return mbedtls_to_psa_error(ret);
+    }
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
+          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE ||
+          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY ||
+          MBEDTLS_PSA_BUILTIN_ALG_FFDH */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY)
+psa_status_t mbedtls_psa_ffdh_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    uint8_t *data,
+    size_t data_size,
+    size_t *data_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi GX, G, X, P;
+    psa_key_type_t type = attributes->type;
+
+    if (PSA_KEY_TYPE_IS_PUBLIC_KEY(type)) {
+        if (key_buffer_size > data_size) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+        memcpy(data, key_buffer, key_buffer_size);
+        memset(data + key_buffer_size, 0,
+               data_size - key_buffer_size);
+        *data_length = key_buffer_size;
+        return PSA_SUCCESS;
+    }
+
+    mbedtls_mpi_init(&GX); mbedtls_mpi_init(&G);
+    mbedtls_mpi_init(&X); mbedtls_mpi_init(&P);
+
+    size_t key_len = PSA_BITS_TO_BYTES(attributes->bits);
+
+    status = mbedtls_psa_ffdh_set_prime_generator(key_len, &P, &G);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
+                                            key_buffer_size));
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&GX, &G, &X, &P, NULL));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&GX, data, key_len));
+
+    *data_length = key_len;
+
+    ret = 0;
+cleanup:
+    mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
+    mbedtls_mpi_free(&X); mbedtls_mpi_free(&GX);
+
+    if (status == PSA_SUCCESS && ret != 0) {
+        status = mbedtls_to_psa_error(ret);
+    }
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_EXPORT ||
+          MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_PUBLIC_KEY */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE)
+psa_status_t mbedtls_psa_ffdh_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+    mbedtls_mpi X, P;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi_init(&P); mbedtls_mpi_init(&X);
+    (void) attributes;
+
+    status = mbedtls_psa_ffdh_set_prime_generator(key_buffer_size, &P, NULL);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    /* RFC7919: Traditional finite field Diffie-Hellman has each peer choose their
+        secret exponent from the range [2, P-2].
+        Select random value in range [3, P-1] and decrease it by 1. */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_random(&X, 3, &P, mbedtls_psa_get_random,
+                                       MBEDTLS_PSA_RANDOM_STATE));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&X, &X, 1));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&X, key_buffer, key_buffer_size));
+    *key_buffer_length = key_buffer_size;
+
+cleanup:
+    mbedtls_mpi_free(&P); mbedtls_mpi_free(&X);
+    if (status == PSA_SUCCESS && ret != 0) {
+        return mbedtls_to_psa_error(ret);
+    }
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_GENERATE */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT)
+psa_status_t mbedtls_psa_ffdh_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits)
+{
+    (void) attributes;
+
+    if (key_buffer_size < data_length) {
+        return PSA_ERROR_BUFFER_TOO_SMALL;
+    }
+    memcpy(key_buffer, data, data_length);
+    *key_buffer_length = data_length;
+    *bits = PSA_BYTES_TO_BITS(data_length);
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_KEY_TYPE_DH_KEY_PAIR_IMPORT */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_FFDH)
+psa_status_t mbedtls_psa_ffdh_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_mpi P, G, X, GY, K;
+    const size_t calculated_shared_secret_size = peer_key_length;
+
+    if (peer_key_length != key_buffer_size ||
+        calculated_shared_secret_size > shared_secret_size) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (!PSA_KEY_TYPE_IS_DH_KEY_PAIR(psa_get_key_type(attributes))) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    mbedtls_mpi_init(&P); mbedtls_mpi_init(&G);
+    mbedtls_mpi_init(&X); mbedtls_mpi_init(&GY);
+    mbedtls_mpi_init(&K);
+
+    status = mbedtls_psa_ffdh_set_prime_generator(
+        PSA_BITS_TO_BYTES(attributes->bits), &P, &G);
+
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&X, key_buffer,
+                                            key_buffer_size));
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&GY, peer_key,
+                                            peer_key_length));
+
+    /* Calculate shared secret public key: K = G^(XY) mod P = GY^X mod P */
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &GY, &X, &P, NULL));
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&K, shared_secret,
+                                             calculated_shared_secret_size));
+
+    *shared_secret_length = calculated_shared_secret_size;
+
+    ret = 0;
+
+cleanup:
+    mbedtls_mpi_free(&P); mbedtls_mpi_free(&G);
+    mbedtls_mpi_free(&X); mbedtls_mpi_free(&GY);
+    mbedtls_mpi_free(&K);
+
+    if (status == PSA_SUCCESS && ret != 0) {
+        status = mbedtls_to_psa_error(ret);
+    }
+
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_FFDH */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.h b/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.h
new file mode 100644
index 0000000000000000000000000000000000000000..79accd15ac89aa3d53e8392691f37738f7da4925
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_ffdh.h
@@ -0,0 +1,131 @@
+/*
+ *  PSA FFDH layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_FFDH_H
+#define PSA_CRYPTO_FFDH_H
+
+#include <psa/crypto.h>
+
+/** Perform a key agreement and return the FFDH shared secret.
+ *
+ * \param[in]  attributes           The attributes of the key to use for the
+ *                                  operation.
+ * \param[in]  peer_key             The buffer containing the key context
+ *                                  of the peer's public key.
+ * \param[in]  peer_key_length      Size of the \p peer_key buffer in
+ *                                  bytes.
+ * \param[in]  key_buffer           The buffer containing the private key
+ *                                  context.
+ * \param[in]  key_buffer_size      Size of the \p key_buffer buffer in
+ *                                  bytes.
+ * \param[out] shared_secret        The buffer to which the shared secret
+ *                                  is to be written.
+ * \param[in]  shared_secret_size   Size of the \p shared_secret buffer in
+ *                                  bytes.
+ * \param[out] shared_secret_length On success, the number of bytes that make
+ *                                  up the returned shared secret.
+ * \retval #PSA_SUCCESS
+ *         Success. Shared secret successfully calculated.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         \p key_buffer_size, \p peer_key_length, \p shared_secret_size
+ *         do not match
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ */
+psa_status_t mbedtls_psa_ffdh_key_agreement(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *peer_key,
+    size_t peer_key_length,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    uint8_t *shared_secret,
+    size_t shared_secret_size,
+    size_t *shared_secret_length);
+
+/** Export a public key or the public part of a DH key pair in binary format.
+ *
+ * \param[in]  attributes       The attributes for the key to export.
+ * \param[in]  key_buffer       Material or context of the key to export.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[out] data             Buffer where the key data is to be written.
+ * \param[in]  data_size        Size of the \p data buffer in bytes.
+ * \param[out] data_length      On success, the number of bytes written in
+ *                              \p data
+ *
+ * \retval #PSA_SUCCESS  The public key was exported successfully.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ * \retval #PSA_ERROR_NOT_PERMITTED         \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ */
+psa_status_t mbedtls_psa_ffdh_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    uint8_t *data,
+    size_t data_size,
+    size_t *data_length);
+
+/**
+ * \brief Generate DH key.
+ *
+ * \note The signature of the function is that of a PSA driver generate_key
+ *       entry point.
+ *
+ * \param[in]  attributes         The attributes for the key to generate.
+ * \param[out] key_buffer         Buffer where the key data is to be written.
+ * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length  On success, the number of bytes written in
+ *                                \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was generated successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Key size in bits is invalid.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ */
+psa_status_t mbedtls_psa_ffdh_generate_key(
+    const psa_key_attributes_t *attributes,
+    uint8_t *key_buffer,
+    size_t key_buffer_size,
+    size_t *key_buffer_length);
+
+/**
+ * \brief Import DH key.
+ *
+ * \note The signature of the function is that of a PSA driver import_key
+ *       entry point.
+ *
+ * \param[in]  attributes       The attributes for the key to import.
+ * \param[in]  data             The buffer containing the key data in import
+ *                              format.
+ * \param[in]  data_length      Size of the \p data buffer in bytes.
+ * \param[out] key_buffer       The buffer containing the key data in output
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes. This
+ *                              size is greater or equal to \p data_length.
+ * \param[out] key_buffer_length  The length of the data written in \p
+ *                                key_buffer in bytes.
+ * \param[out] bits             The key size in number of bits.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was generated successfully.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ */
+psa_status_t mbedtls_psa_ffdh_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits);
+
+#endif /* PSA_CRYPTO_FFDH_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_hash.c b/lib/libmbedtls/mbedtls/library/psa_crypto_hash.c
new file mode 100644
index 0000000000000000000000000000000000000000..eeb7666c1cb0b2fc37c2732ddd4299ce39d5ee4d
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_hash.c
@@ -0,0 +1,470 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_hash.h"
+
+#include <mbedtls/error.h>
+#include <string.h>
+
+#if defined(MBEDTLS_PSA_BUILTIN_HASH)
+psa_status_t mbedtls_psa_hash_abort(
+    mbedtls_psa_hash_operation_t *operation)
+{
+    switch (operation->alg) {
+        case 0:
+            /* The object has (apparently) been initialized but it is not
+             * in use. It's ok to call abort on such an object, and there's
+             * nothing to do. */
+            break;
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            mbedtls_md5_free(&operation->ctx.md5);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            mbedtls_ripemd160_free(&operation->ctx.ripemd160);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            mbedtls_sha1_free(&operation->ctx.sha1);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            mbedtls_sha256_free(&operation->ctx.sha256);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            mbedtls_sha256_free(&operation->ctx.sha256);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            mbedtls_sha512_free(&operation->ctx.sha512);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            mbedtls_sha512_free(&operation->ctx.sha512);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
+        case PSA_ALG_SHA3_224:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
+        case PSA_ALG_SHA3_256:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
+        case PSA_ALG_SHA3_384:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        case PSA_ALG_SHA3_512:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+            mbedtls_sha3_free(&operation->ctx.sha3);
+            break;
+#endif
+        default:
+            return PSA_ERROR_BAD_STATE;
+    }
+    operation->alg = 0;
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_hash_setup(
+    mbedtls_psa_hash_operation_t *operation,
+    psa_algorithm_t alg)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* A context must be freshly initialized before it can be set up. */
+    if (operation->alg != 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    switch (alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            mbedtls_md5_init(&operation->ctx.md5);
+            ret = mbedtls_md5_starts(&operation->ctx.md5);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            mbedtls_ripemd160_init(&operation->ctx.ripemd160);
+            ret = mbedtls_ripemd160_starts(&operation->ctx.ripemd160);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            mbedtls_sha1_init(&operation->ctx.sha1);
+            ret = mbedtls_sha1_starts(&operation->ctx.sha1);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            mbedtls_sha256_init(&operation->ctx.sha256);
+            ret = mbedtls_sha256_starts(&operation->ctx.sha256, 1);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            mbedtls_sha256_init(&operation->ctx.sha256);
+            ret = mbedtls_sha256_starts(&operation->ctx.sha256, 0);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            mbedtls_sha512_init(&operation->ctx.sha512);
+            ret = mbedtls_sha512_starts(&operation->ctx.sha512, 1);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            mbedtls_sha512_init(&operation->ctx.sha512);
+            ret = mbedtls_sha512_starts(&operation->ctx.sha512, 0);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
+        case PSA_ALG_SHA3_224:
+            mbedtls_sha3_init(&operation->ctx.sha3);
+            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_224);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
+        case PSA_ALG_SHA3_256:
+            mbedtls_sha3_init(&operation->ctx.sha3);
+            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_256);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
+        case PSA_ALG_SHA3_384:
+            mbedtls_sha3_init(&operation->ctx.sha3);
+            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_384);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        case PSA_ALG_SHA3_512:
+            mbedtls_sha3_init(&operation->ctx.sha3);
+            ret = mbedtls_sha3_starts(&operation->ctx.sha3, MBEDTLS_SHA3_512);
+            break;
+#endif
+        default:
+            return PSA_ALG_IS_HASH(alg) ?
+                   PSA_ERROR_NOT_SUPPORTED :
+                   PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (ret == 0) {
+        operation->alg = alg;
+    } else {
+        mbedtls_psa_hash_abort(operation);
+    }
+    return mbedtls_to_psa_error(ret);
+}
+
+psa_status_t mbedtls_psa_hash_clone(
+    const mbedtls_psa_hash_operation_t *source_operation,
+    mbedtls_psa_hash_operation_t *target_operation)
+{
+    switch (source_operation->alg) {
+        case 0:
+            return PSA_ERROR_BAD_STATE;
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            mbedtls_md5_clone(&target_operation->ctx.md5,
+                              &source_operation->ctx.md5);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            mbedtls_ripemd160_clone(&target_operation->ctx.ripemd160,
+                                    &source_operation->ctx.ripemd160);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            mbedtls_sha1_clone(&target_operation->ctx.sha1,
+                               &source_operation->ctx.sha1);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            mbedtls_sha256_clone(&target_operation->ctx.sha256,
+                                 &source_operation->ctx.sha256);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            mbedtls_sha256_clone(&target_operation->ctx.sha256,
+                                 &source_operation->ctx.sha256);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            mbedtls_sha512_clone(&target_operation->ctx.sha512,
+                                 &source_operation->ctx.sha512);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            mbedtls_sha512_clone(&target_operation->ctx.sha512,
+                                 &source_operation->ctx.sha512);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
+        case PSA_ALG_SHA3_224:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
+        case PSA_ALG_SHA3_256:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
+        case PSA_ALG_SHA3_384:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        case PSA_ALG_SHA3_512:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+            defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+            mbedtls_sha3_clone(&target_operation->ctx.sha3,
+                               &source_operation->ctx.sha3);
+            break;
+#endif
+        default:
+            (void) source_operation;
+            (void) target_operation;
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    target_operation->alg = source_operation->alg;
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_hash_update(
+    mbedtls_psa_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    switch (operation->alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            ret = mbedtls_md5_update(&operation->ctx.md5,
+                                     input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            ret = mbedtls_ripemd160_update(&operation->ctx.ripemd160,
+                                           input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            ret = mbedtls_sha1_update(&operation->ctx.sha1,
+                                      input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            ret = mbedtls_sha256_update(&operation->ctx.sha256,
+                                        input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            ret = mbedtls_sha256_update(&operation->ctx.sha256,
+                                        input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            ret = mbedtls_sha512_update(&operation->ctx.sha512,
+                                        input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            ret = mbedtls_sha512_update(&operation->ctx.sha512,
+                                        input, input_length);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
+        case PSA_ALG_SHA3_224:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
+        case PSA_ALG_SHA3_256:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
+        case PSA_ALG_SHA3_384:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        case PSA_ALG_SHA3_512:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+    ret = mbedtls_sha3_update(&operation->ctx.sha3,
+                              input, input_length);
+    break;
+#endif
+        default:
+            (void) input;
+            (void) input_length;
+            return PSA_ERROR_BAD_STATE;
+    }
+
+    return mbedtls_to_psa_error(ret);
+}
+
+psa_status_t mbedtls_psa_hash_finish(
+    mbedtls_psa_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length)
+{
+    psa_status_t status;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t actual_hash_length = PSA_HASH_LENGTH(operation->alg);
+
+    /* Fill the output buffer with something that isn't a valid hash
+     * (barring an attack on the hash and deliberately-crafted input),
+     * in case the caller doesn't check the return status properly. */
+    *hash_length = hash_size;
+    /* If hash_size is 0 then hash may be NULL and then the
+     * call to memset would have undefined behavior. */
+    if (hash_size != 0) {
+        memset(hash, '!', hash_size);
+    }
+
+    if (hash_size < actual_hash_length) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+    switch (operation->alg) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_MD5)
+        case PSA_ALG_MD5:
+            ret = mbedtls_md5_finish(&operation->ctx.md5, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RIPEMD160)
+        case PSA_ALG_RIPEMD160:
+            ret = mbedtls_ripemd160_finish(&operation->ctx.ripemd160, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_1)
+        case PSA_ALG_SHA_1:
+            ret = mbedtls_sha1_finish(&operation->ctx.sha1, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_224)
+        case PSA_ALG_SHA_224:
+            ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_256)
+        case PSA_ALG_SHA_256:
+            ret = mbedtls_sha256_finish(&operation->ctx.sha256, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_384)
+        case PSA_ALG_SHA_384:
+            ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA_512)
+        case PSA_ALG_SHA_512:
+            ret = mbedtls_sha512_finish(&operation->ctx.sha512, hash);
+            break;
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224)
+        case PSA_ALG_SHA3_224:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256)
+        case PSA_ALG_SHA3_256:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384)
+        case PSA_ALG_SHA3_384:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+        case PSA_ALG_SHA3_512:
+#endif
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_224) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_256) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_384) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_SHA3_512)
+    ret = mbedtls_sha3_finish(&operation->ctx.sha3, hash, hash_size);
+    break;
+#endif
+        default:
+            (void) hash;
+            return PSA_ERROR_BAD_STATE;
+    }
+    status = mbedtls_to_psa_error(ret);
+
+exit:
+    if (status == PSA_SUCCESS) {
+        *hash_length = actual_hash_length;
+    }
+    return status;
+}
+
+psa_status_t mbedtls_psa_hash_compute(
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length)
+{
+    mbedtls_psa_hash_operation_t operation = MBEDTLS_PSA_HASH_OPERATION_INIT;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_status_t abort_status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *hash_length = hash_size;
+    status = mbedtls_psa_hash_setup(&operation, alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = mbedtls_psa_hash_update(&operation, input, input_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = mbedtls_psa_hash_finish(&operation, hash, hash_size, hash_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    abort_status = mbedtls_psa_hash_abort(&operation);
+    if (status == PSA_SUCCESS) {
+        return abort_status;
+    } else {
+        return status;
+    }
+
+}
+#endif /* MBEDTLS_PSA_BUILTIN_HASH */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_hash.h b/lib/libmbedtls/mbedtls/library/psa_crypto_hash.h
new file mode 100644
index 0000000000000000000000000000000000000000..0a7be805520192845de777acaf3e4766f7c839b2
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_hash.h
@@ -0,0 +1,211 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_HASH_H
+#define PSA_CRYPTO_HASH_H
+
+#include <psa/crypto.h>
+
+/** Calculate the hash (digest) of a message using Mbed TLS routines.
+ *
+ * \note The signature of this function is that of a PSA driver hash_compute
+ *       entry point. This function behaves as a hash_compute entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ * \param[in] input         Buffer containing the message to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ * \param[out] hash         Buffer where the hash is to be written.
+ * \param hash_size         Size of the \p hash buffer in bytes.
+ * \param[out] hash_length  On success, the number of bytes
+ *                          that make up the hash value. This is always
+ *                          #PSA_HASH_LENGTH(\p alg).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p hash_size is too small
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_compute(
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length);
+
+/** Set up a multipart hash operation using Mbed TLS routines.
+ *
+ * \note The signature of this function is that of a PSA driver hash_setup
+ *       entry point. This function behaves as a hash_setup entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * If an error occurs at any step after a call to mbedtls_psa_hash_setup(), the
+ * operation will need to be reset by a call to mbedtls_psa_hash_abort(). The
+ * core may call mbedtls_psa_hash_abort() at any time after the operation
+ * has been initialized.
+ *
+ * After a successful call to mbedtls_psa_hash_setup(), the core must
+ * eventually terminate the operation. The following events terminate an
+ * operation:
+ * - A successful call to mbedtls_psa_hash_finish() or mbedtls_psa_hash_verify().
+ * - A call to mbedtls_psa_hash_abort().
+ *
+ * \param[in,out] operation The operation object to set up. It must have
+ *                          been initialized to all-zero and not yet be in use.
+ * \param alg               The hash algorithm to compute (\c PSA_ALG_XXX value
+ *                          such that #PSA_ALG_IS_HASH(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be inactive).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_setup(
+    mbedtls_psa_hash_operation_t *operation,
+    psa_algorithm_t alg);
+
+/** Clone an Mbed TLS hash operation.
+ *
+ * \note The signature of this function is that of a PSA driver hash_clone
+ *       entry point. This function behaves as a hash_clone entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * This function copies the state of an ongoing hash operation to
+ * a new operation object. In other words, this function is equivalent
+ * to calling mbedtls_psa_hash_setup() on \p target_operation with the same
+ * algorithm that \p source_operation was set up for, then
+ * mbedtls_psa_hash_update() on \p target_operation with the same input that
+ * that was passed to \p source_operation. After this function returns, the
+ * two objects are independent, i.e. subsequent calls involving one of
+ * the objects do not affect the other object.
+ *
+ * \param[in] source_operation      The active hash operation to clone.
+ * \param[in,out] target_operation  The operation object to set up.
+ *                                  It must be initialized but not active.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The \p source_operation state is not valid (it must be active).
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The \p target_operation state is not valid (it must be inactive).
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_clone(
+    const mbedtls_psa_hash_operation_t *source_operation,
+    mbedtls_psa_hash_operation_t *target_operation);
+
+/** Add a message fragment to a multipart Mbed TLS hash operation.
+ *
+ * \note The signature of this function is that of a PSA driver hash_update
+ *       entry point. This function behaves as a hash_update entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The application must call mbedtls_psa_hash_setup() before calling this function.
+ *
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling mbedtls_psa_hash_abort().
+ *
+ * \param[in,out] operation Active hash operation.
+ * \param[in] input         Buffer containing the message fragment to hash.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_update(
+    mbedtls_psa_hash_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length);
+
+/** Finish the calculation of the Mbed TLS-calculated hash of a message.
+ *
+ * \note The signature of this function is that of a PSA driver hash_finish
+ *       entry point. This function behaves as a hash_finish entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The application must call mbedtls_psa_hash_setup() before calling this function.
+ * This function calculates the hash of the message formed by concatenating
+ * the inputs passed to preceding calls to mbedtls_psa_hash_update().
+ *
+ * When this function returns successfully, the operation becomes inactive.
+ * If this function returns an error status, the operation enters an error
+ * state and must be aborted by calling mbedtls_psa_hash_abort().
+ *
+ * \param[in,out] operation     Active hash operation.
+ * \param[out] hash             Buffer where the hash is to be written.
+ * \param hash_size             Size of the \p hash buffer in bytes.
+ * \param[out] hash_length      On success, the number of bytes
+ *                              that make up the hash value. This is always
+ *                              #PSA_HASH_LENGTH(\c alg) where \c alg is the
+ *                              hash algorithm that is calculated.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p hash buffer is too small. You can determine a
+ *         sufficient buffer size by calling #PSA_HASH_LENGTH(\c alg)
+ *         where \c alg is the hash algorithm that is calculated.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_finish(
+    mbedtls_psa_hash_operation_t *operation,
+    uint8_t *hash,
+    size_t hash_size,
+    size_t *hash_length);
+
+/** Abort an Mbed TLS hash operation.
+ *
+ * \note The signature of this function is that of a PSA driver hash_abort
+ *       entry point. This function behaves as a hash_abort entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * mbedtls_psa_hash_setup() again.
+ *
+ * You may call this function any time after the operation object has
+ * been initialized by one of the methods described in #psa_hash_operation_t.
+ *
+ * In particular, calling mbedtls_psa_hash_abort() after the operation has been
+ * terminated by a call to mbedtls_psa_hash_abort(), mbedtls_psa_hash_finish() or
+ * mbedtls_psa_hash_verify() is safe and has no effect.
+ *
+ * \param[in,out] operation     Initialized hash operation.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_hash_abort(
+    mbedtls_psa_hash_operation_t *operation);
+
+#endif /* PSA_CRYPTO_HASH_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_invasive.h b/lib/libmbedtls/mbedtls/library/psa_crypto_invasive.h
new file mode 100644
index 0000000000000000000000000000000000000000..51c90c64a4d3327257328abb80bc4b51697d422b
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_invasive.h
@@ -0,0 +1,92 @@
+/**
+ * \file psa_crypto_invasive.h
+ *
+ * \brief PSA cryptography module: invasive interfaces for test only.
+ *
+ * The interfaces in this file are intended for testing purposes only.
+ * They MUST NOT be made available to clients over IPC in integrations
+ * with isolation, and they SHOULD NOT be made available in library
+ * integrations except when building the library for testing.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_INVASIVE_H
+#define PSA_CRYPTO_INVASIVE_H
+
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
+
+#include "psa/crypto.h"
+#include "common.h"
+
+#include "mbedtls/entropy.h"
+
+#if !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+/** \brief Configure entropy sources.
+ *
+ * This function may only be called before a call to psa_crypto_init(),
+ * or after a call to mbedtls_psa_crypto_free() and before any
+ * subsequent call to psa_crypto_init().
+ *
+ * This function is only intended for test purposes. The functionality
+ * it provides is also useful for system integrators, but
+ * system integrators should configure entropy drivers instead of
+ * breaking through to the Mbed TLS API.
+ *
+ * \param entropy_init  Function to initialize the entropy context
+ *                      and set up the desired entropy sources.
+ *                      It is called by psa_crypto_init().
+ *                      By default this is mbedtls_entropy_init().
+ *                      This function cannot report failures directly.
+ *                      To indicate a failure, set the entropy context
+ *                      to a state where mbedtls_entropy_func() will
+ *                      return an error.
+ * \param entropy_free  Function to free the entropy context
+ *                      and associated resources.
+ *                      It is called by mbedtls_psa_crypto_free().
+ *                      By default this is mbedtls_entropy_free().
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The caller does not have the permission to configure
+ *         entropy sources.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has already been initialized.
+ */
+psa_status_t mbedtls_psa_crypto_configure_entropy_sources(
+    void (* entropy_init)(mbedtls_entropy_context *ctx),
+    void (* entropy_free)(mbedtls_entropy_context *ctx));
+#endif /* !defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) */
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_CRYPTO_C)
+psa_status_t psa_mac_key_can_do(
+    psa_algorithm_t algorithm,
+    psa_key_type_t key_type);
+
+psa_status_t psa_crypto_copy_input(const uint8_t *input, size_t input_len,
+                                   uint8_t *input_copy, size_t input_copy_len);
+
+psa_status_t psa_crypto_copy_output(const uint8_t *output_copy, size_t output_copy_len,
+                                    uint8_t *output, size_t output_len);
+
+/*
+ * Test hooks to use for memory unpoisoning/poisoning in copy functions.
+ */
+extern void (*psa_input_pre_copy_hook)(const uint8_t *input, size_t input_len);
+extern void (*psa_input_post_copy_hook)(const uint8_t *input, size_t input_len);
+extern void (*psa_output_pre_copy_hook)(const uint8_t *output, size_t output_len);
+extern void (*psa_output_post_copy_hook)(const uint8_t *output, size_t output_len);
+
+#endif /* MBEDTLS_TEST_HOOKS && MBEDTLS_PSA_CRYPTO_C */
+
+#endif /* PSA_CRYPTO_INVASIVE_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_its.h b/lib/libmbedtls/mbedtls/library/psa_crypto_its.h
new file mode 100644
index 0000000000000000000000000000000000000000..877063b87866c5c0ee49e88216f0e2226f1cf986
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_its.h
@@ -0,0 +1,131 @@
+/** \file psa_crypto_its.h
+ * \brief Interface of trusted storage that crypto is built on.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_ITS_H
+#define PSA_CRYPTO_ITS_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <psa/crypto_types.h>
+#include <psa/crypto_values.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** \brief Flags used when creating a data entry
+ */
+typedef uint32_t psa_storage_create_flags_t;
+
+/** \brief A type for UIDs used for identifying data
+ */
+typedef uint64_t psa_storage_uid_t;
+
+#define PSA_STORAGE_FLAG_NONE        0         /**< No flags to pass */
+#define PSA_STORAGE_FLAG_WRITE_ONCE (1 << 0) /**< The data associated with the uid will not be able to be modified or deleted. Intended to be used to set bits in `psa_storage_create_flags_t`*/
+
+/**
+ * \brief A container for metadata associated with a specific uid
+ */
+struct psa_storage_info_t {
+    uint32_t size;                  /**< The size of the data associated with a uid **/
+    psa_storage_create_flags_t flags;    /**< The flags set when the uid was created **/
+};
+
+/** Flag indicating that \ref psa_storage_create and \ref psa_storage_set_extended are supported */
+#define PSA_STORAGE_SUPPORT_SET_EXTENDED (1 << 0)
+
+#define PSA_ITS_API_VERSION_MAJOR  1  /**< The major version number of the PSA ITS API. It will be incremented on significant updates that may include breaking changes */
+#define PSA_ITS_API_VERSION_MINOR  1  /**< The minor version number of the PSA ITS API. It will be incremented in small updates that are unlikely to include breaking changes */
+
+/**
+ * \brief create a new or modify an existing uid/value pair
+ *
+ * \param[in] uid           the identifier for the data
+ * \param[in] data_length   The size in bytes of the data in `p_data`
+ * \param[in] p_data        A buffer containing the data
+ * \param[in] create_flags  The flags that the data will be stored with
+ *
+ * \return      A status indicating the success/failure of the operation
+ *
+ * \retval      #PSA_SUCCESS                     The operation completed successfully
+ * \retval      #PSA_ERROR_NOT_PERMITTED         The operation failed because the provided `uid` value was already created with PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval      #PSA_ERROR_NOT_SUPPORTED         The operation failed because one or more of the flags provided in `create_flags` is not supported or is not valid
+ * \retval      #PSA_ERROR_INSUFFICIENT_STORAGE  The operation failed because there was insufficient space on the storage medium
+ * \retval      #PSA_ERROR_STORAGE_FAILURE       The operation failed because the physical storage has failed (Fatal error)
+ * \retval      #PSA_ERROR_INVALID_ARGUMENT      The operation failed because one of the provided pointers(`p_data`)
+ *                                               is invalid, for example is `NULL` or references memory the caller cannot access
+ */
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         uint32_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags);
+
+/**
+ * \brief Retrieve the value associated with a provided uid
+ *
+ * \param[in] uid               The uid value
+ * \param[in] data_offset       The starting offset of the data requested
+ * \param[in] data_length       the amount of data requested (and the minimum allocated size of the `p_data` buffer)
+ * \param[out] p_data           The buffer where the data will be placed upon successful completion
+ * \param[out] p_data_length    The amount of data returned in the p_data buffer
+ *
+ *
+ * \return      A status indicating the success/failure of the operation
+ *
+ * \retval      #PSA_SUCCESS                 The operation completed successfully
+ * \retval      #PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided `uid` value was not found in the storage
+ * \retval      #PSA_ERROR_STORAGE_FAILURE   The operation failed because the physical storage has failed (Fatal error)
+ * \retval      #PSA_ERROR_DATA_CORRUPT      The operation failed because stored data has been corrupted
+ * \retval      #PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the provided pointers(`p_data`, `p_data_length`)
+ *                                           is invalid. For example is `NULL` or references memory the caller cannot access.
+ *                                           In addition, this can also happen if an invalid offset was provided.
+ */
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         uint32_t data_offset,
+                         uint32_t data_length,
+                         void *p_data,
+                         size_t *p_data_length);
+
+/**
+ * \brief Retrieve the metadata about the provided uid
+ *
+ * \param[in] uid           The uid value
+ * \param[out] p_info       A pointer to the `psa_storage_info_t` struct that will be populated with the metadata
+ *
+ * \return      A status indicating the success/failure of the operation
+ *
+ * \retval      #PSA_SUCCESS                 The operation completed successfully
+ * \retval      #PSA_ERROR_DOES_NOT_EXIST    The operation failed because the provided uid value was not found in the storage
+ * \retval      #PSA_ERROR_DATA_CORRUPT      The operation failed because stored data has been corrupted
+ * \retval      #PSA_ERROR_INVALID_ARGUMENT  The operation failed because one of the provided pointers(`p_info`)
+ *                                           is invalid, for example is `NULL` or references memory the caller cannot access
+ */
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info);
+
+/**
+ * \brief Remove the provided key and its associated data from the storage
+ *
+ * \param[in] uid   The uid value
+ *
+ * \return  A status indicating the success/failure of the operation
+ *
+ * \retval      #PSA_SUCCESS                  The operation completed successfully
+ * \retval      #PSA_ERROR_DOES_NOT_EXIST     The operation failed because the provided key value was not found in the storage
+ * \retval      #PSA_ERROR_NOT_PERMITTED      The operation failed because the provided key value was created with PSA_STORAGE_FLAG_WRITE_ONCE
+ * \retval      #PSA_ERROR_STORAGE_FAILURE    The operation failed because the physical storage has failed (Fatal error)
+ */
+psa_status_t psa_its_remove(psa_storage_uid_t uid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_CRYPTO_ITS_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_mac.c b/lib/libmbedtls/mbedtls/library/psa_crypto_mac.c
new file mode 100644
index 0000000000000000000000000000000000000000..8fe6218118b0b52459c7adeaca9c355268cd8fc1
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_mac.c
@@ -0,0 +1,496 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_cipher.h"
+#include "psa_crypto_mac.h"
+#include <mbedtls/md.h>
+
+#include <mbedtls/error.h>
+#include "mbedtls/constant_time.h"
+#include <string.h>
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+static psa_status_t psa_hmac_abort_internal(
+    mbedtls_psa_hmac_operation_t *hmac)
+{
+    mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad));
+    return psa_hash_abort(&hmac->hash_ctx);
+}
+
+static psa_status_t psa_hmac_setup_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    const uint8_t *key,
+    size_t key_length,
+    psa_algorithm_t hash_alg)
+{
+    uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
+    size_t i;
+    size_t hash_size = PSA_HASH_LENGTH(hash_alg);
+    size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    psa_status_t status;
+
+    hmac->alg = hash_alg;
+
+    /* Sanity checks on block_size, to guarantee that there won't be a buffer
+     * overflow below. This should never trigger if the hash algorithm
+     * is implemented correctly. */
+    /* The size checks against the ipad and opad buffers cannot be written
+     * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
+     * because that triggers -Wlogical-op on GCC 7.3. */
+    if (block_size > sizeof(ipad)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    if (block_size > sizeof(hmac->opad)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    if (block_size < hash_size) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (key_length > block_size) {
+        status = psa_hash_compute(hash_alg, key, key_length,
+                                  ipad, sizeof(ipad), &key_length);
+        if (status != PSA_SUCCESS) {
+            goto cleanup;
+        }
+    }
+    /* A 0-length key is not commonly used in HMAC when used as a MAC,
+     * but it is permitted. It is common when HMAC is used in HKDF, for
+     * example. Don't call `memcpy` in the 0-length because `key` could be
+     * an invalid pointer which would make the behavior undefined. */
+    else if (key_length != 0) {
+        memcpy(ipad, key, key_length);
+    }
+
+    /* ipad contains the key followed by garbage. Xor and fill with 0x36
+     * to create the ipad value. */
+    for (i = 0; i < key_length; i++) {
+        ipad[i] ^= 0x36;
+    }
+    memset(ipad + key_length, 0x36, block_size - key_length);
+
+    /* Copy the key material from ipad to opad, flipping the requisite bits,
+     * and filling the rest of opad with the requisite constant. */
+    for (i = 0; i < key_length; i++) {
+        hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
+    }
+    memset(hmac->opad + key_length, 0x5C, block_size - key_length);
+
+    status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    status = psa_hash_update(&hmac->hash_ctx, ipad, block_size);
+
+cleanup:
+    mbedtls_platform_zeroize(ipad, sizeof(ipad));
+
+    return status;
+}
+
+static psa_status_t psa_hmac_update_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    const uint8_t *data,
+    size_t data_length)
+{
+    return psa_hash_update(&hmac->hash_ctx, data, data_length);
+}
+
+static psa_status_t psa_hmac_finish_internal(
+    mbedtls_psa_hmac_operation_t *hmac,
+    uint8_t *mac,
+    size_t mac_size)
+{
+    uint8_t tmp[PSA_HASH_MAX_SIZE];
+    psa_algorithm_t hash_alg = hmac->alg;
+    size_t hash_size = 0;
+    size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    psa_status_t status;
+
+    status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    /* From here on, tmp needs to be wiped. */
+
+    status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    memcpy(mac, tmp, mac_size);
+
+exit:
+    mbedtls_platform_zeroize(tmp, hash_size);
+    return status;
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
+                               const psa_key_attributes_t *attributes,
+                               const uint8_t *key_buffer)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(PSA_WANT_KEY_TYPE_DES)
+    /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
+     * to do CMAC with pure DES, so return NOT_SUPPORTED here. */
+    if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
+        (psa_get_key_bits(attributes) == 64 ||
+         psa_get_key_bits(attributes) == 128)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+#endif
+
+    const mbedtls_cipher_info_t *cipher_info =
+        mbedtls_cipher_info_from_psa(
+            PSA_ALG_CMAC,
+            psa_get_key_type(attributes),
+            psa_get_key_bits(attributes),
+            NULL);
+
+    if (cipher_info == NULL) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);
+    if (ret != 0) {
+        goto exit;
+    }
+
+    ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,
+                                     key_buffer,
+                                     psa_get_key_bits(attributes));
+exit:
+    return mbedtls_to_psa_error(ret);
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+
+/* Initialize this driver's MAC operation structure. Once this function has been
+ * called, mbedtls_psa_mac_abort can run and will do the right thing. */
+static psa_status_t mac_init(
+    mbedtls_psa_mac_operation_t *operation,
+    psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    operation->alg = alg;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        mbedtls_cipher_init(&operation->ctx.cmac);
+        status = PSA_SUCCESS;
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+    if (PSA_ALG_IS_HMAC(operation->alg)) {
+        /* We'll set up the hash operation later in psa_hmac_setup_internal. */
+        operation->ctx.hmac.alg = 0;
+        status = PSA_SUCCESS;
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+    {
+        (void) operation;
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status != PSA_SUCCESS) {
+        memset(operation, 0, sizeof(*operation));
+    }
+    return status;
+}
+
+psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)
+{
+    if (operation->alg == 0) {
+        /* The object has (apparently) been initialized but it is not
+         * in use. It's ok to call abort on such an object, and there's
+         * nothing to do. */
+        return PSA_SUCCESS;
+    } else
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        mbedtls_cipher_free(&operation->ctx.cmac);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+    if (PSA_ALG_IS_HMAC(operation->alg)) {
+        psa_hmac_abort_internal(&operation->ctx.hmac);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+    {
+        /* Sanity check (shouldn't happen: operation->alg should
+         * always have been initialized to a valid value). */
+        goto bad_state;
+    }
+
+    operation->alg = 0;
+
+    return PSA_SUCCESS;
+
+bad_state:
+    /* If abort is called on an uninitialized object, we can't trust
+     * anything. Wipe the object in case it contains confidential data.
+     * This may result in a memory leak if a pointer gets overwritten,
+     * but it's too late to do anything about this. */
+    memset(operation, 0, sizeof(*operation));
+    return PSA_ERROR_BAD_STATE;
+}
+
+static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,
+                                  const psa_key_attributes_t *attributes,
+                                  const uint8_t *key_buffer,
+                                  size_t key_buffer_size,
+                                  psa_algorithm_t alg)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    /* A context must be freshly initialized before it can be set up. */
+    if (operation->alg != 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = mac_init(operation, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+    if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
+        /* Key buffer size for CMAC is dictated by the key bits set on the
+         * attributes, and previously validated by the core on key import. */
+        (void) key_buffer_size;
+        status = cmac_setup(operation, attributes, key_buffer);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+    if (PSA_ALG_IS_HMAC(alg)) {
+        status = psa_hmac_setup_internal(&operation->ctx.hmac,
+                                         key_buffer,
+                                         key_buffer_size,
+                                         PSA_ALG_HMAC_GET_HASH(alg));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+    {
+        (void) attributes;
+        (void) key_buffer;
+        (void) key_buffer_size;
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (status != PSA_SUCCESS) {
+        mbedtls_psa_mac_abort(operation);
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_mac_sign_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    return psa_mac_setup(operation, attributes,
+                         key_buffer, key_buffer_size, alg);
+}
+
+psa_status_t mbedtls_psa_mac_verify_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg)
+{
+    return psa_mac_setup(operation, attributes,
+                         key_buffer, key_buffer_size, alg);
+}
+
+psa_status_t mbedtls_psa_mac_update(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length)
+{
+    if (operation->alg == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        return mbedtls_to_psa_error(
+            mbedtls_cipher_cmac_update(&operation->ctx.cmac,
+                                       input, input_length));
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+    if (PSA_ALG_IS_HMAC(operation->alg)) {
+        return psa_hmac_update_internal(&operation->ctx.hmac,
+                                        input, input_length);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+    {
+        /* This shouldn't happen if `operation` was initialized by
+         * a setup function. */
+        (void) input;
+        (void) input_length;
+        return PSA_ERROR_BAD_STATE;
+    }
+}
+
+static psa_status_t psa_mac_finish_internal(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac, size_t mac_size)
+{
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
+    if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
+        uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
+        int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);
+        if (ret == 0) {
+            memcpy(mac, tmp, mac_size);
+        }
+        mbedtls_platform_zeroize(tmp, sizeof(tmp));
+        return mbedtls_to_psa_error(ret);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
+    if (PSA_ALG_IS_HMAC(operation->alg)) {
+        return psa_hmac_finish_internal(&operation->ctx.hmac,
+                                        mac, mac_size);
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
+    {
+        /* This shouldn't happen if `operation` was initialized by
+         * a setup function. */
+        (void) operation;
+        (void) mac;
+        (void) mac_size;
+        return PSA_ERROR_BAD_STATE;
+    }
+}
+
+psa_status_t mbedtls_psa_mac_sign_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->alg == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    status = psa_mac_finish_internal(operation, mac, mac_size);
+    if (status == PSA_SUCCESS) {
+        *mac_length = mac_size;
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_mac_verify_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length)
+{
+    uint8_t actual_mac[PSA_MAC_MAX_SIZE];
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    if (operation->alg == 0) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+    /* Consistency check: requested MAC length fits our local buffer */
+    if (mac_length > sizeof(actual_mac)) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    status = psa_mac_finish_internal(operation, actual_mac, mac_length);
+    if (status != PSA_SUCCESS) {
+        goto cleanup;
+    }
+
+    if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+    }
+
+cleanup:
+    mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;
+
+    status = psa_mac_setup(&operation,
+                           attributes, key_buffer, key_buffer_size,
+                           alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (input_length > 0) {
+        status = mbedtls_psa_mac_update(&operation, input, input_length);
+        if (status != PSA_SUCCESS) {
+            goto exit;
+        }
+    }
+
+    status = psa_mac_finish_internal(&operation, mac, mac_size);
+    if (status == PSA_SUCCESS) {
+        *mac_length = mac_size;
+    }
+
+exit:
+    mbedtls_psa_mac_abort(&operation);
+
+    return status;
+}
+
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_mac.h b/lib/libmbedtls/mbedtls/library/psa_crypto_mac.h
new file mode 100644
index 0000000000000000000000000000000000000000..2f614bcc6e7ec4277ca919e1184e3bc7e800f500
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_mac.h
@@ -0,0 +1,264 @@
+/*
+ *  PSA MAC layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_MAC_H
+#define PSA_CRYPTO_MAC_H
+
+#include <psa/crypto.h>
+
+/** Calculate the MAC (message authentication code) of a message using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_compute
+ *       entry point. This function behaves as a mac_compute entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ * \param[in] input             Buffer containing the input message.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[out] mac              Buffer where the MAC value is to be written.
+ * \param mac_size              Size of the \p mac buffer in bytes.
+ * \param[out] mac_length       On success, the number of bytes
+ *                              that make up the MAC value.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         \p mac_size is too small
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_mac_compute(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg,
+    const uint8_t *input,
+    size_t input_length,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length);
+
+/** Set up a multipart MAC calculation operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_sign_setup
+ *       entry point. This function behaves as a mac_sign_setup entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be inactive).
+ */
+psa_status_t mbedtls_psa_mac_sign_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Set up a multipart MAC verification operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_verify_setup
+ *       entry point. This function behaves as a mac_verify_setup entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized and not yet in use.
+ * \param[in] attributes        The attributes of the key to use for the
+ *                              operation.
+ * \param[in] key_buffer        The buffer containing the key to use for
+ *                              computing the MAC. This buffer contains the key
+ *                              in export representation as defined by
+ *                              psa_export_key() (i.e. the raw key bytes).
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param alg                   The MAC algorithm to use (\c PSA_ALG_XXX value
+ *                              such that #PSA_ALG_IS_MAC(\p alg) is true).
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         \p alg is not supported.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be inactive).
+ */
+psa_status_t mbedtls_psa_mac_verify_setup(
+    mbedtls_psa_mac_operation_t *operation,
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer,
+    size_t key_buffer_size,
+    psa_algorithm_t alg);
+
+/** Add a message fragment to a multipart MAC operation using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_update
+ *       entry point. This function behaves as a mac_update entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_sign_setup() or
+ * mbedtls_psa_mac_verify_setup() before calling this function.
+ *
+ * If this function returns an error status, the PSA core aborts the
+ * operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] input         Buffer containing the message fragment to add to
+ *                          the MAC calculation.
+ * \param input_length      Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be active).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_mac_update(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *input,
+    size_t input_length);
+
+/** Finish the calculation of the MAC of a message using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver mac_sign_finish
+ *       entry point. This function behaves as a mac_sign_finish entry point as
+ *       defined in the PSA driver interface specification for transparent
+ *       drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_sign_setup() before calling this function.
+ * This function calculates the MAC of the message formed by concatenating
+ * the inputs passed to preceding calls to mbedtls_psa_mac_update().
+ *
+ * Whether this function returns successfully or not, the PSA core subsequently
+ * aborts the operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[out] mac          Buffer where the MAC value is to be written.
+ * \param mac_size          Output size requested for the MAC algorithm. The PSA
+ *                          core guarantees this is a valid MAC length for the
+ *                          algorithm and key combination passed to
+ *                          mbedtls_psa_mac_sign_setup(). It also guarantees the
+ *                          \p mac buffer is large enough to contain the
+ *                          requested output size.
+ * \param[out] mac_length   On success, the number of bytes output to buffer
+ *                          \p mac, which will be equal to the requested length
+ *                          \p mac_size.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be an active mac sign
+ *         operation).
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p mac buffer is too small. A sufficient buffer size
+ *         can be determined by calling PSA_MAC_LENGTH().
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_mac_sign_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    uint8_t *mac,
+    size_t mac_size,
+    size_t *mac_length);
+
+/** Finish the calculation of the MAC of a message and compare it with
+ * an expected value using Mbed TLS.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       mac_verify_finish entry point. This function behaves as a
+ *       mac_verify_finish entry point as defined in the PSA driver interface
+ *       specification for transparent drivers.
+ *
+ * The PSA core calls mbedtls_psa_mac_verify_setup() before calling this
+ * function. This function calculates the MAC of the message formed by
+ * concatenating the inputs passed to preceding calls to
+ * mbedtls_psa_mac_update(). It then compares the calculated MAC with the
+ * expected MAC passed as a parameter to this function.
+ *
+ * Whether this function returns successfully or not, the PSA core subsequently
+ * aborts the operation by calling mbedtls_psa_mac_abort().
+ *
+ * \param[in,out] operation Active MAC operation.
+ * \param[in] mac           Buffer containing the expected MAC value.
+ * \param mac_length        Length in bytes of the expected MAC value. The PSA
+ *                          core guarantees that this length is a valid MAC
+ *                          length for the algorithm and key combination passed
+ *                          to mbedtls_psa_mac_verify_setup().
+ *
+ * \retval #PSA_SUCCESS
+ *         The expected MAC is identical to the actual MAC of the message.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The MAC of the message was calculated successfully, but it
+ *         differs from the expected MAC.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The operation state is not valid (it must be an active mac verify
+ *         operation).
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_mac_verify_finish(
+    mbedtls_psa_mac_operation_t *operation,
+    const uint8_t *mac,
+    size_t mac_length);
+
+/** Abort a MAC operation using Mbed TLS.
+ *
+ * Aborting an operation frees all associated resources except for the
+ * \p operation structure itself. Once aborted, the operation object
+ * can be reused for another operation by calling
+ * mbedtls_psa_mac_sign_setup() or mbedtls_psa_mac_verify_setup() again.
+ *
+ * The PSA core may call this function any time after the operation object has
+ * been initialized by one of the methods described in
+ * #mbedtls_psa_mac_operation_t.
+ *
+ * In particular, calling mbedtls_psa_mac_abort() after the operation has been
+ * terminated by a call to mbedtls_psa_mac_abort(),
+ * mbedtls_psa_mac_sign_finish() or mbedtls_psa_mac_verify_finish() is safe and
+ * has no effect.
+ *
+ * \param[in,out] operation Initialized MAC operation.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_mac_abort(
+    mbedtls_psa_mac_operation_t *operation);
+
+#endif /* PSA_CRYPTO_MAC_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_pake.c b/lib/libmbedtls/mbedtls/library/psa_crypto_pake.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ac2e8c486e7d26dc44356195e67b105989c22c8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_pake.c
@@ -0,0 +1,571 @@
+/*
+ *  PSA PAKE layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa_crypto_core.h"
+#include "psa_crypto_pake.h"
+#include "psa_crypto_slot_management.h"
+
+#include <mbedtls/ecjpake.h>
+#include "psa_util_internal.h"
+
+#include <mbedtls/platform.h>
+#include <mbedtls/error.h>
+#include <string.h>
+
+/*
+ * State sequence:
+ *
+ *   psa_pake_setup()
+ *   |
+ *   |-- In any order:
+ *   |   | psa_pake_set_password_key()
+ *   |   | psa_pake_set_user()
+ *   |   | psa_pake_set_peer()
+ *   |   | psa_pake_set_role()
+ *   |
+ *   |--- In any order: (First round input before or after first round output)
+ *   |   |
+ *   |   |------ In Order
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
+ *   |   |
+ *   |   |------ In Order:
+ *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
+ *   |
+ *   |--- In any order: (Second round input before or after second round output)
+ *   |   |
+ *   |   |------ In Order
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_KEY_SHARE)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |   |       | psa_pake_output(PSA_PAKE_STEP_ZK_PROOF)
+ *   |   |
+ *   |   |------ In Order:
+ *   |           | psa_pake_input(PSA_PAKE_STEP_KEY_SHARE)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PUBLIC)
+ *   |           | psa_pake_input(PSA_PAKE_STEP_ZK_PROOF)
+ *   |
+ *   psa_pake_get_implicit_key()
+ *   psa_pake_abort()
+ */
+
+/*
+ * Possible sequence of calls to implementation:
+ *
+ * |--- In any order:
+ * |   |
+ * |   |------ In Order
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_KEY_SHARE)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X1_STEP_ZK_PROOF)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_KEY_SHARE)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2_STEP_ZK_PROOF)
+ * |   |
+ * |   |------ In Order:
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_KEY_SHARE)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PUBLIC)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X1_STEP_ZK_PROOF)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_KEY_SHARE)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PUBLIC)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X2_STEP_ZK_PROOF)
+ * |
+ * |--- In any order:
+ * |   |
+ * |   |------ In Order
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_KEY_SHARE)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PUBLIC)
+ * |   |       | mbedtls_psa_pake_output(PSA_JPAKE_X2S_STEP_ZK_PROOF)
+ * |   |
+ * |   |------ In Order:
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_KEY_SHARE)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PUBLIC)
+ * |           | mbedtls_psa_pake_input(PSA_JPAKE_X4S_STEP_ZK_PROOF)
+ */
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+static psa_status_t mbedtls_ecjpake_to_psa_error(int ret)
+{
+    switch (ret) {
+        case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_ECP_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_ECP_INVALID_KEY:
+        case MBEDTLS_ERR_ECP_VERIFY_FAILED:
+            return PSA_ERROR_DATA_INVALID;
+        case MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL:
+        case MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL:
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
+            return PSA_ERROR_NOT_SUPPORTED;
+        case MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED:
+            return PSA_ERROR_CORRUPTION_DETECTED;
+        default:
+            return PSA_ERROR_GENERIC_ERROR;
+    }
+}
+#endif
+
+#if defined(MBEDTLS_PSA_BUILTIN_PAKE)
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+static psa_status_t psa_pake_ecjpake_setup(mbedtls_psa_pake_operation_t *operation)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_ecjpake_init(&operation->ctx.jpake);
+
+    ret = mbedtls_ecjpake_setup(&operation->ctx.jpake,
+                                operation->role,
+                                MBEDTLS_MD_SHA256,
+                                MBEDTLS_ECP_DP_SECP256R1,
+                                operation->password,
+                                operation->password_len);
+
+    mbedtls_platform_zeroize(operation->password, operation->password_len);
+
+    if (ret != 0) {
+        return mbedtls_ecjpake_to_psa_error(ret);
+    }
+
+    return PSA_SUCCESS;
+}
+#endif
+
+/* The only two JPAKE user/peer identifiers supported in built-in implementation. */
+static const uint8_t jpake_server_id[] = { 's', 'e', 'r', 'v', 'e', 'r' };
+static const uint8_t jpake_client_id[] = { 'c', 'l', 'i', 'e', 'n', 't' };
+
+psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,
+                                    const psa_crypto_driver_pake_inputs_t *inputs)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t user_len = 0, peer_len = 0, password_len = 0;
+    uint8_t *peer = NULL, *user = NULL;
+    size_t actual_user_len = 0, actual_peer_len = 0, actual_password_len = 0;
+    psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init();
+
+    status = psa_crypto_driver_pake_get_password_len(inputs, &password_len);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_crypto_driver_pake_get_user_len(inputs, &user_len);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_crypto_driver_pake_get_peer_len(inputs, &peer_len);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_crypto_driver_pake_get_cipher_suite(inputs, &cipher_suite);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    operation->password = mbedtls_calloc(1, password_len);
+    if (operation->password == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto error;
+    }
+
+    user = mbedtls_calloc(1, user_len);
+    if (user == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto error;
+    }
+
+    peer = mbedtls_calloc(1, peer_len);
+    if (peer == NULL) {
+        status = PSA_ERROR_INSUFFICIENT_MEMORY;
+        goto error;
+    }
+
+    status = psa_crypto_driver_pake_get_password(inputs, operation->password,
+                                                 password_len, &actual_password_len);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    status = psa_crypto_driver_pake_get_user(inputs, user,
+                                             user_len, &actual_user_len);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    status = psa_crypto_driver_pake_get_peer(inputs, peer,
+                                             peer_len, &actual_peer_len);
+    if (status != PSA_SUCCESS) {
+        goto error;
+    }
+
+    operation->password_len = actual_password_len;
+    operation->alg = cipher_suite.algorithm;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+    if (cipher_suite.algorithm == PSA_ALG_JPAKE) {
+        if (cipher_suite.type != PSA_PAKE_PRIMITIVE_TYPE_ECC ||
+            cipher_suite.family != PSA_ECC_FAMILY_SECP_R1 ||
+            cipher_suite.bits != 256 ||
+            cipher_suite.hash != PSA_ALG_SHA_256) {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto error;
+        }
+
+        const size_t user_peer_len = sizeof(jpake_client_id); // client and server have the same length
+        if (actual_user_len != user_peer_len ||
+            actual_peer_len != user_peer_len) {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto error;
+        }
+
+        if (memcmp(user, jpake_client_id, actual_user_len) == 0 &&
+            memcmp(peer, jpake_server_id, actual_peer_len) == 0) {
+            operation->role = MBEDTLS_ECJPAKE_CLIENT;
+        } else
+        if (memcmp(user, jpake_server_id, actual_user_len) == 0 &&
+            memcmp(peer, jpake_client_id, actual_peer_len) == 0) {
+            operation->role = MBEDTLS_ECJPAKE_SERVER;
+        } else {
+            status = PSA_ERROR_NOT_SUPPORTED;
+            goto error;
+        }
+
+        operation->buffer_length = 0;
+        operation->buffer_offset = 0;
+
+        status = psa_pake_ecjpake_setup(operation);
+        if (status != PSA_SUCCESS) {
+            goto error;
+        }
+
+        /* Role has been set, release user/peer buffers. */
+        mbedtls_free(user); mbedtls_free(peer);
+
+        return PSA_SUCCESS;
+    } else
+#else
+    (void) operation;
+    (void) inputs;
+#endif
+    { status = PSA_ERROR_NOT_SUPPORTED; }
+
+error:
+    mbedtls_free(user); mbedtls_free(peer);
+    /* In case of failure of the setup of a multipart operation, the PSA driver interface
+     * specifies that the core does not call any other driver entry point thus does not
+     * call mbedtls_psa_pake_abort(). Therefore call it here to do the needed clean
+     * up like freeing the memory that may have been allocated to store the password.
+     */
+    mbedtls_psa_pake_abort(operation);
+    return status;
+}
+
+static psa_status_t mbedtls_psa_pake_output_internal(
+    mbedtls_psa_pake_operation_t *operation,
+    psa_crypto_driver_pake_step_t step,
+    uint8_t *output,
+    size_t output_size,
+    size_t *output_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t length;
+    (void) step; // Unused parameter
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+    /*
+     * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different
+     * handling of output sequencing.
+     *
+     * The Mbed TLS JPAKE API outputs the whole X1+X2 and X2S steps data
+     * at once, on the other side the PSA CRYPTO PAKE api requires
+     * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X2S to be
+     * retrieved in sequence.
+     *
+     * In order to achieve API compatibility, the whole X1+X2 or X2S steps
+     * data is stored in an intermediate buffer at first step output call,
+     * and data is sliced down by parsing the ECPoint records in order
+     * to return the right parts on each step.
+     */
+    if (operation->alg == PSA_ALG_JPAKE) {
+        /* Initialize & write round on KEY_SHARE sequences */
+        if (step == PSA_JPAKE_X1_STEP_KEY_SHARE) {
+            ret = mbedtls_ecjpake_write_round_one(&operation->ctx.jpake,
+                                                  operation->buffer,
+                                                  sizeof(operation->buffer),
+                                                  &operation->buffer_length,
+                                                  mbedtls_psa_get_random,
+                                                  MBEDTLS_PSA_RANDOM_STATE);
+            if (ret != 0) {
+                return mbedtls_ecjpake_to_psa_error(ret);
+            }
+
+            operation->buffer_offset = 0;
+        } else if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE) {
+            ret = mbedtls_ecjpake_write_round_two(&operation->ctx.jpake,
+                                                  operation->buffer,
+                                                  sizeof(operation->buffer),
+                                                  &operation->buffer_length,
+                                                  mbedtls_psa_get_random,
+                                                  MBEDTLS_PSA_RANDOM_STATE);
+            if (ret != 0) {
+                return mbedtls_ecjpake_to_psa_error(ret);
+            }
+
+            operation->buffer_offset = 0;
+        }
+
+        /*
+         * mbedtls_ecjpake_write_round_xxx() outputs thing in the format
+         * defined by draft-cragie-tls-ecjpake-01 section 7. The summary is
+         * that the data for each step is prepended with a length byte, and
+         * then they're concatenated. Additionally, the server's second round
+         * output is prepended with a 3-bytes ECParameters structure.
+         *
+         * In PSA, we output each step separately, and don't prepend the
+         * output with a length byte, even less a curve identifier, as that
+         * information is already available.
+         */
+        if (step == PSA_JPAKE_X2S_STEP_KEY_SHARE &&
+            operation->role == MBEDTLS_ECJPAKE_SERVER) {
+            /* Skip ECParameters, with is 3 bytes (RFC 8422) */
+            operation->buffer_offset += 3;
+        }
+
+        /* Read the length byte then move past it to the data */
+        length = operation->buffer[operation->buffer_offset];
+        operation->buffer_offset += 1;
+
+        if (operation->buffer_offset + length > operation->buffer_length) {
+            return PSA_ERROR_DATA_CORRUPT;
+        }
+
+        if (output_size < length) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        memcpy(output,
+               operation->buffer + operation->buffer_offset,
+               length);
+        *output_length = length;
+
+        operation->buffer_offset += length;
+
+        /* Reset buffer after ZK_PROOF sequence */
+        if ((step == PSA_JPAKE_X2_STEP_ZK_PROOF) ||
+            (step == PSA_JPAKE_X2S_STEP_ZK_PROOF)) {
+            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
+            operation->buffer_length = 0;
+            operation->buffer_offset = 0;
+        }
+
+        return PSA_SUCCESS;
+    } else
+#else
+    (void) step;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+#endif
+    { return PSA_ERROR_NOT_SUPPORTED; }
+}
+
+psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,
+                                     psa_crypto_driver_pake_step_t step,
+                                     uint8_t *output,
+                                     size_t output_size,
+                                     size_t *output_length)
+{
+    psa_status_t status = mbedtls_psa_pake_output_internal(
+        operation, step, output, output_size, output_length);
+
+    return status;
+}
+
+static psa_status_t mbedtls_psa_pake_input_internal(
+    mbedtls_psa_pake_operation_t *operation,
+    psa_crypto_driver_pake_step_t step,
+    const uint8_t *input,
+    size_t input_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    (void) step; // Unused parameter
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+    /*
+     * The PSA CRYPTO PAKE and Mbed TLS JPAKE API have a different
+     * handling of input sequencing.
+     *
+     * The Mbed TLS JPAKE API takes the whole X1+X2 or X4S steps data
+     * at once as input, on the other side the PSA CRYPTO PAKE api requires
+     * the KEY_SHARE/ZP_PUBLIC/ZK_PROOF parts of X1, X2 & X4S to be
+     * given in sequence.
+     *
+     * In order to achieve API compatibility, each X1+X2 or X4S step data
+     * is stored sequentially in an intermediate buffer and given to the
+     * Mbed TLS JPAKE API on the last step.
+     *
+     * This causes any input error to be only detected on the last step.
+     */
+    if (operation->alg == PSA_ALG_JPAKE) {
+        /*
+         * Copy input to local buffer and format it as the Mbed TLS API
+         * expects, i.e. as defined by draft-cragie-tls-ecjpake-01 section 7.
+         * The summary is that the data for each step is prepended with a
+         * length byte, and then they're concatenated. Additionally, the
+         * server's second round output is prepended with a 3-bytes
+         * ECParameters structure - which means we have to prepend that when
+         * we're a client.
+         */
+        if (step == PSA_JPAKE_X4S_STEP_KEY_SHARE &&
+            operation->role == MBEDTLS_ECJPAKE_CLIENT) {
+            /* We only support secp256r1. */
+            /* This is the ECParameters structure defined by RFC 8422. */
+            unsigned char ecparameters[3] = {
+                3, /* named_curve */
+                0, 23 /* secp256r1 */
+            };
+
+            if (operation->buffer_length + sizeof(ecparameters) >
+                sizeof(operation->buffer)) {
+                return PSA_ERROR_BUFFER_TOO_SMALL;
+            }
+
+            memcpy(operation->buffer + operation->buffer_length,
+                   ecparameters, sizeof(ecparameters));
+            operation->buffer_length += sizeof(ecparameters);
+        }
+
+        /*
+         * The core checks that input_length is smaller than
+         * PSA_PAKE_INPUT_MAX_SIZE.
+         * Thus no risk of integer overflow here.
+         */
+        if (operation->buffer_length + input_length + 1 > sizeof(operation->buffer)) {
+            return PSA_ERROR_BUFFER_TOO_SMALL;
+        }
+
+        /* Write the length byte */
+        operation->buffer[operation->buffer_length] = (uint8_t) input_length;
+        operation->buffer_length += 1;
+
+        /* Finally copy the data */
+        memcpy(operation->buffer + operation->buffer_length,
+               input, input_length);
+        operation->buffer_length += input_length;
+
+        /* Load buffer at each last round ZK_PROOF */
+        if (step == PSA_JPAKE_X2_STEP_ZK_PROOF) {
+            ret = mbedtls_ecjpake_read_round_one(&operation->ctx.jpake,
+                                                 operation->buffer,
+                                                 operation->buffer_length);
+
+            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
+            operation->buffer_length = 0;
+
+            if (ret != 0) {
+                return mbedtls_ecjpake_to_psa_error(ret);
+            }
+        } else if (step == PSA_JPAKE_X4S_STEP_ZK_PROOF) {
+            ret = mbedtls_ecjpake_read_round_two(&operation->ctx.jpake,
+                                                 operation->buffer,
+                                                 operation->buffer_length);
+
+            mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
+            operation->buffer_length = 0;
+
+            if (ret != 0) {
+                return mbedtls_ecjpake_to_psa_error(ret);
+            }
+        }
+
+        return PSA_SUCCESS;
+    } else
+#else
+    (void) step;
+    (void) input;
+    (void) input_length;
+#endif
+    { return PSA_ERROR_NOT_SUPPORTED; }
+}
+
+psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,
+                                    psa_crypto_driver_pake_step_t step,
+                                    const uint8_t *input,
+                                    size_t input_length)
+{
+    psa_status_t status = mbedtls_psa_pake_input_internal(
+        operation, step, input, input_length);
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_pake_get_implicit_key(
+    mbedtls_psa_pake_operation_t *operation,
+    uint8_t *output, size_t output_size,
+    size_t *output_length)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+    if (operation->alg == PSA_ALG_JPAKE) {
+        ret = mbedtls_ecjpake_write_shared_key(&operation->ctx.jpake,
+                                               output,
+                                               output_size,
+                                               output_length,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE);
+        if (ret != 0) {
+            return mbedtls_ecjpake_to_psa_error(ret);
+        }
+
+        return PSA_SUCCESS;
+    } else
+#else
+    (void) output;
+#endif
+    { return PSA_ERROR_NOT_SUPPORTED; }
+}
+
+psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation)
+{
+    mbedtls_zeroize_and_free(operation->password, operation->password_len);
+    operation->password = NULL;
+    operation->password_len = 0;
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_JPAKE)
+    if (operation->alg == PSA_ALG_JPAKE) {
+        operation->role = MBEDTLS_ECJPAKE_NONE;
+        mbedtls_platform_zeroize(operation->buffer, sizeof(operation->buffer));
+        operation->buffer_length = 0;
+        operation->buffer_offset = 0;
+        mbedtls_ecjpake_free(&operation->ctx.jpake);
+    }
+#endif
+
+    operation->alg = PSA_ALG_NONE;
+
+    return PSA_SUCCESS;
+}
+
+#endif /* MBEDTLS_PSA_BUILTIN_PAKE */
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_pake.h b/lib/libmbedtls/mbedtls/library/psa_crypto_pake.h
new file mode 100644
index 0000000000000000000000000000000000000000..3d3ee0cc9af14fdb56d422284231beaaa8321789
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_pake.h
@@ -0,0 +1,159 @@
+/*
+ *  PSA PAKE layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_PAKE_H
+#define PSA_CRYPTO_PAKE_H
+
+#include <psa/crypto.h>
+
+/** Set the session information for a password-authenticated key exchange.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       pake_setup entry point. This function behaves as a pake_setup
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in,out] operation     The operation object to set up. It must have
+ *                              been initialized but not set up yet.
+ * \param[in] inputs            Inputs required for PAKE operation (role, password,
+ *                              key lifetime, cipher suite)
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         The algorithm in \p cipher_suite is not a supported PAKE algorithm,
+ *         or the PAKE primitive in \p cipher_suite is not supported or not
+ *         compatible with the PAKE algorithm, or the hash algorithm in
+ *         \p cipher_suite is not supported or not compatible with the PAKE
+ *         algorithm and primitive.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ */
+psa_status_t mbedtls_psa_pake_setup(mbedtls_psa_pake_operation_t *operation,
+                                    const psa_crypto_driver_pake_inputs_t *inputs);
+
+
+/** Get output for a step of a password-authenticated key exchange.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       pake_output entry point. This function behaves as a pake_output
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param step                 The step of the algorithm for which the output is
+ *                             requested.
+ * \param[out] output          Buffer where the output is to be written in the
+ *                             format appropriate for this driver \p step. Refer to
+ *                             the documentation of psa_crypto_driver_pake_step_t for
+ *                             more information.
+ * \param output_size          Size of the \p output buffer in bytes. This must
+ *                             be at least #PSA_PAKE_OUTPUT_SIZE(\p alg, \p
+ *                             primitive, \p step) where \p alg and
+ *                             \p primitive are the PAKE algorithm and primitive
+ *                             in the operation's cipher suite, and \p step is
+ *                             the output step.
+ *
+ * \param[out] output_length   On success, the number of bytes of the returned
+ *                             output.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small.
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY  \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT          \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID          \emptydescription
+ */
+psa_status_t mbedtls_psa_pake_output(mbedtls_psa_pake_operation_t *operation,
+                                     psa_crypto_driver_pake_step_t step,
+                                     uint8_t *output,
+                                     size_t output_size,
+                                     size_t *output_length);
+
+/** Provide input for a step of a password-authenticated key exchange.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       pake_input entry point. This function behaves as a pake_input
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \note The core checks that input_length is smaller than PSA_PAKE_INPUT_MAX_SIZE.
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param step                 The driver step for which the input is provided.
+ * \param[in] input            Buffer containing the input in the format
+ *                             appropriate for this \p step. Refer to the
+ *                             documentation of psa_crypto_driver_pake_step_t
+ *                             for more information.
+ * \param input_length         Size of the \p input buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The verification fails for a zero-knowledge input step.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         the \p input is not valid for the \p operation's algorithm, cipher suite
+ *         or \p step.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         the \p input is not supported for the \p operation's algorithm, cipher
+ *         suite or \p step.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT          \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID          \emptydescription
+ */
+psa_status_t mbedtls_psa_pake_input(mbedtls_psa_pake_operation_t *operation,
+                                    psa_crypto_driver_pake_step_t step,
+                                    const uint8_t *input,
+                                    size_t input_length);
+
+/** Get implicitly confirmed shared secret from a PAKE.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       pake_get_implicit_key entry point. This function behaves as a
+ *       pake_get_implicit_key entry point as defined in the PSA driver
+ *       interface specification for transparent drivers.
+ *
+ * \param[in,out] operation    Active PAKE operation.
+ * \param[out] output          Output buffer for implicit key.
+ * \param      output_size     Size of the output buffer in bytes.
+ * \param[out] output_length   On success, the number of bytes of the implicit key.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Input from a PAKE is not supported by the algorithm in the \p output
+ *         key derivation operation.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY   \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT          \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID          \emptydescription
+ */
+psa_status_t mbedtls_psa_pake_get_implicit_key(
+    mbedtls_psa_pake_operation_t *operation,
+    uint8_t *output, size_t output_size,
+    size_t *output_length);
+
+/** Abort a PAKE operation.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       pake_abort entry point. This function behaves as a pake_abort
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in,out] operation    The operation to abort.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED   \emptydescription
+ */
+psa_status_t mbedtls_psa_pake_abort(mbedtls_psa_pake_operation_t *operation);
+
+#endif /* PSA_CRYPTO_PAKE_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_random_impl.h b/lib/libmbedtls/mbedtls/library/psa_crypto_random_impl.h
new file mode 100644
index 0000000000000000000000000000000000000000..5b5163111b09b51951a5bc366f76f0db81572234
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_random_impl.h
@@ -0,0 +1,126 @@
+/** \file psa_crypto_random_impl.h
+ *
+ * \brief PSA crypto random generator implementation abstraction.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_RANDOM_IMPL_H
+#define PSA_CRYPTO_RANDOM_IMPL_H
+
+#include "psa_util_internal.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
+
+typedef mbedtls_psa_external_random_context_t mbedtls_psa_random_context_t;
+
+#else /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#include "mbedtls/entropy.h"
+
+/* Choose a DRBG based on configuration and availability */
+#if defined(MBEDTLS_CTR_DRBG_C)
+
+#include "mbedtls/ctr_drbg.h"
+#undef MBEDTLS_PSA_HMAC_DRBG_MD_TYPE
+
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+
+#include "mbedtls/hmac_drbg.h"
+#if defined(MBEDTLS_MD_CAN_SHA512) && defined(MBEDTLS_MD_CAN_SHA256)
+#include <limits.h>
+#if SIZE_MAX > 0xffffffff
+/* Looks like a 64-bit system, so prefer SHA-512. */
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512
+#else
+/* Looks like a 32-bit system, so prefer SHA-256. */
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+#endif
+#elif defined(MBEDTLS_MD_CAN_SHA512)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA512
+#elif defined(MBEDTLS_MD_CAN_SHA256)
+#define MBEDTLS_PSA_HMAC_DRBG_MD_TYPE MBEDTLS_MD_SHA256
+#else
+#error "No hash algorithm available for HMAC_DBRG."
+#endif
+
+#else /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
+#error "No DRBG module available for the psa_crypto module."
+
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C*/
+
+/* The maximum number of bytes that mbedtls_psa_get_random() is expected to return. */
+#if defined(MBEDTLS_CTR_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_CTR_DRBG_MAX_REQUEST
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+#define MBEDTLS_PSA_RANDOM_MAX_REQUEST MBEDTLS_HMAC_DRBG_MAX_REQUEST
+#endif
+
+#if defined(MBEDTLS_CTR_DRBG_C)
+typedef mbedtls_ctr_drbg_context            mbedtls_psa_drbg_context_t;
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+typedef mbedtls_hmac_drbg_context           mbedtls_psa_drbg_context_t;
+#endif /* !MBEDTLS_CTR_DRBG_C && !MBEDTLS_HMAC_DRBG_C */
+
+typedef struct {
+    void (* entropy_init)(mbedtls_entropy_context *ctx);
+    void (* entropy_free)(mbedtls_entropy_context *ctx);
+    mbedtls_entropy_context entropy;
+    mbedtls_psa_drbg_context_t drbg;
+} mbedtls_psa_random_context_t;
+
+/** Initialize the PSA DRBG.
+ *
+ * \param p_rng        Pointer to the Mbed TLS DRBG state.
+ */
+static inline void mbedtls_psa_drbg_init(mbedtls_psa_drbg_context_t *p_rng)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+    mbedtls_ctr_drbg_init(p_rng);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    mbedtls_hmac_drbg_init(p_rng);
+#endif
+}
+
+/** Deinitialize the PSA DRBG.
+ *
+ * \param p_rng        Pointer to the Mbed TLS DRBG state.
+ */
+static inline void mbedtls_psa_drbg_free(mbedtls_psa_drbg_context_t *p_rng)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+    mbedtls_ctr_drbg_free(p_rng);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    mbedtls_hmac_drbg_free(p_rng);
+#endif
+}
+
+/** Seed the PSA DRBG.
+ *
+ * \param entropy       An entropy context to read the seed from.
+ * \param custom        The personalization string.
+ *                      This can be \c NULL, in which case the personalization
+ *                      string is empty regardless of the value of \p len.
+ * \param len           The length of the personalization string.
+ *
+ * \return              \c 0 on success.
+ * \return              An Mbed TLS error code (\c MBEDTLS_ERR_xxx) on failure.
+ */
+static inline int mbedtls_psa_drbg_seed(mbedtls_psa_drbg_context_t *drbg_ctx,
+                                        mbedtls_entropy_context *entropy,
+                                        const unsigned char *custom, size_t len)
+{
+#if defined(MBEDTLS_CTR_DRBG_C)
+    return mbedtls_ctr_drbg_seed(drbg_ctx, mbedtls_entropy_func, entropy, custom, len);
+#elif defined(MBEDTLS_HMAC_DRBG_C)
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_PSA_HMAC_DRBG_MD_TYPE);
+    return mbedtls_hmac_drbg_seed(drbg_ctx, md_info, mbedtls_entropy_func, entropy, custom, len);
+#endif
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
+
+#endif /* PSA_CRYPTO_RANDOM_IMPL_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.c b/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.c
new file mode 100644
index 0000000000000000000000000000000000000000..38dc3b8edc2e900c983e019f893d4e86f260f7ef
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.c
@@ -0,0 +1,705 @@
+/*
+ *  PSA RSA layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include <psa/crypto.h>
+#include "psa/crypto_values.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_random_impl.h"
+#include "psa_crypto_rsa.h"
+#include "psa_crypto_hash.h"
+#include "mbedtls/psa_util.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+
+#include <mbedtls/rsa.h>
+#include <mbedtls/error.h>
+#include "rsa_internal.h"
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+
+/* Mbed TLS doesn't support non-byte-aligned key sizes (i.e. key sizes
+ * that are not a multiple of 8) well. For example, there is only
+ * mbedtls_rsa_get_len(), which returns a number of bytes, and no
+ * way to return the exact bit size of a key.
+ * To keep things simple, reject non-byte-aligned key sizes. */
+static psa_status_t psa_check_rsa_key_byte_aligned(
+    const mbedtls_rsa_context *rsa)
+{
+    mbedtls_mpi n;
+    psa_status_t status;
+    mbedtls_mpi_init(&n);
+    status = mbedtls_to_psa_error(
+        mbedtls_rsa_export(rsa, &n, NULL, NULL, NULL, NULL));
+    if (status == PSA_SUCCESS) {
+        if (mbedtls_mpi_bitlen(&n) % 8 != 0) {
+            status = PSA_ERROR_NOT_SUPPORTED;
+        }
+    }
+    mbedtls_mpi_free(&n);
+    return status;
+}
+
+psa_status_t mbedtls_psa_rsa_load_representation(
+    psa_key_type_t type, const uint8_t *data, size_t data_length,
+    mbedtls_rsa_context **p_rsa)
+{
+    psa_status_t status;
+    size_t bits;
+
+    *p_rsa = mbedtls_calloc(1, sizeof(mbedtls_rsa_context));
+    if (*p_rsa == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+    mbedtls_rsa_init(*p_rsa);
+
+    /* Parse the data. */
+    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        status = mbedtls_to_psa_error(mbedtls_rsa_parse_key(*p_rsa, data, data_length));
+    } else {
+        status = mbedtls_to_psa_error(mbedtls_rsa_parse_pubkey(*p_rsa, data, data_length));
+    }
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* The size of an RSA key doesn't have to be a multiple of 8. Mbed TLS
+     * supports non-byte-aligned key sizes, but not well. For example,
+     * mbedtls_rsa_get_len() returns the key size in bytes, not in bits. */
+    bits = PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(*p_rsa));
+    if (bits > PSA_VENDOR_RSA_MAX_KEY_BITS) {
+        status = PSA_ERROR_NOT_SUPPORTED;
+        goto exit;
+    }
+    status = psa_check_rsa_key_byte_aligned(*p_rsa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) && \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+psa_status_t mbedtls_psa_rsa_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits)
+{
+    psa_status_t status;
+    mbedtls_rsa_context *rsa = NULL;
+
+    /* Parse input */
+    status = mbedtls_psa_rsa_load_representation(attributes->type,
+                                                 data,
+                                                 data_length,
+                                                 &rsa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    *bits = (psa_key_bits_t) PSA_BYTES_TO_BITS(mbedtls_rsa_get_len(rsa));
+
+    /* Re-export the data to PSA export format, such that we can store export
+     * representation in the key slot. Export representation in case of RSA is
+     * the smallest representation that's allowed as input, so a straight-up
+     * allocation of the same size as the input buffer will be large enough. */
+    status = mbedtls_psa_rsa_export_key(attributes->type,
+                                        rsa,
+                                        key_buffer,
+                                        key_buffer_size,
+                                        key_buffer_length);
+exit:
+    /* Always free the RSA object */
+    mbedtls_rsa_free(rsa);
+    mbedtls_free(rsa);
+
+    return status;
+}
+#endif /* (defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_IMPORT) &&
+        *  defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT)) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) || \
+    defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY)
+psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,
+                                        mbedtls_rsa_context *rsa,
+                                        uint8_t *data,
+                                        size_t data_size,
+                                        size_t *data_length)
+{
+    int ret;
+    uint8_t *end = data + data_size;
+
+    /* PSA Crypto API defines the format of an RSA key as a DER-encoded
+     * representation of the non-encrypted PKCS#1 RSAPrivateKey for a
+     * private key and of the RFC3279 RSAPublicKey for a public key. */
+    if (PSA_KEY_TYPE_IS_KEY_PAIR(type)) {
+        ret = mbedtls_rsa_write_key(rsa, data, &end);
+    } else {
+        ret = mbedtls_rsa_write_pubkey(rsa, data, &end);
+    }
+
+    if (ret < 0) {
+        /* Clean up in case pk_write failed halfway through. */
+        memset(data, 0, data_size);
+        return mbedtls_to_psa_error(ret);
+    }
+
+    /* The mbedtls_pk_xxx functions write to the end of the buffer.
+     * Move the data to the beginning and erase remaining data
+     * at the original location. */
+    if (2 * (size_t) ret <= data_size) {
+        memcpy(data, data + data_size - ret, ret);
+        memset(data + data_size - ret, 0, ret);
+    } else if ((size_t) ret < data_size) {
+        memmove(data, data + data_size - ret, ret);
+        memset(data + ret, 0, data_size - ret);
+    }
+
+    *data_length = ret;
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_rsa_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_rsa_context *rsa = NULL;
+
+    status = mbedtls_psa_rsa_load_representation(
+        attributes->type, key_buffer, key_buffer_size, &rsa);
+    if (status == PSA_SUCCESS) {
+        status = mbedtls_psa_rsa_export_key(PSA_KEY_TYPE_RSA_PUBLIC_KEY,
+                                            rsa,
+                                            data,
+                                            data_size,
+                                            data_length);
+    }
+
+    mbedtls_rsa_free(rsa);
+    mbedtls_free(rsa);
+
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_EXPORT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_PUBLIC_KEY) */
+
+#if defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE)
+static psa_status_t psa_rsa_read_exponent(const uint8_t *e_bytes,
+                                          size_t e_length,
+                                          int *exponent)
+{
+    size_t i;
+    uint32_t acc = 0;
+
+    /* Mbed TLS encodes the public exponent as an int. For simplicity, only
+     * support values that fit in a 32-bit integer, which is larger than
+     * int on just about every platform anyway. */
+    if (e_length > sizeof(acc)) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    for (i = 0; i < e_length; i++) {
+        acc = (acc << 8) | e_bytes[i];
+    }
+    if (acc > INT_MAX) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    *exponent = acc;
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_rsa_generate_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *custom_data, size_t custom_data_length,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length)
+{
+    psa_status_t status;
+    mbedtls_rsa_context rsa;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int exponent = 65537;
+
+    if (custom_data_length != 0) {
+        status = psa_rsa_read_exponent(custom_data, custom_data_length,
+                                       &exponent);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    }
+
+    mbedtls_rsa_init(&rsa);
+    ret = mbedtls_rsa_gen_key(&rsa,
+                              mbedtls_psa_get_random,
+                              MBEDTLS_PSA_RANDOM_STATE,
+                              (unsigned int) attributes->bits,
+                              exponent);
+    if (ret != 0) {
+        mbedtls_rsa_free(&rsa);
+        return mbedtls_to_psa_error(ret);
+    }
+
+    status = mbedtls_psa_rsa_export_key(attributes->type,
+                                        &rsa, key_buffer, key_buffer_size,
+                                        key_buffer_length);
+    mbedtls_rsa_free(&rsa);
+
+    return status;
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_KEY_TYPE_RSA_KEY_PAIR_GENERATE) */
+
+/****************************************************************/
+/* Sign/verify hashes */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) || \
+    defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+
+/* Decode the hash algorithm from alg and store the mbedtls encoding in
+ * md_alg. Verify that the hash length is acceptable. */
+static psa_status_t psa_rsa_decode_md_type(psa_algorithm_t alg,
+                                           size_t hash_length,
+                                           mbedtls_md_type_t *md_alg)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_SIGN_GET_HASH(alg);
+    *md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
+
+    /* The Mbed TLS RSA module uses an unsigned int for hash length
+     * parameters. Validate that it fits so that we don't risk an
+     * overflow later. */
+#if SIZE_MAX > UINT_MAX
+    if (hash_length > UINT_MAX) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+#endif
+
+    /* For signatures using a hash, the hash length must be correct. */
+    if (alg != PSA_ALG_RSA_PKCS1V15_SIGN_RAW) {
+        if (*md_alg == MBEDTLS_MD_NONE) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+        if (mbedtls_md_get_size_from_type(*md_alg) != hash_length) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        }
+    }
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t mbedtls_psa_rsa_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_rsa_context *rsa = NULL;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_alg;
+
+    status = mbedtls_psa_rsa_load_representation(attributes->type,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &rsa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (signature_size < mbedtls_rsa_get_len(rsa)) {
+        status = PSA_ERROR_BUFFER_TOO_SMALL;
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
+    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
+        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
+                                      MBEDTLS_MD_NONE);
+        if (ret == 0) {
+            ret = mbedtls_rsa_pkcs1_sign(rsa,
+                                         mbedtls_psa_get_random,
+                                         MBEDTLS_PSA_RANDOM_STATE,
+                                         md_alg,
+                                         (unsigned int) hash_length,
+                                         hash,
+                                         signature);
+        }
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+    if (PSA_ALG_IS_RSA_PSS(alg)) {
+        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
+
+        if (ret == 0) {
+            ret = mbedtls_rsa_rsassa_pss_sign(rsa,
+                                              mbedtls_psa_get_random,
+                                              MBEDTLS_PSA_RANDOM_STATE,
+                                              MBEDTLS_MD_NONE,
+                                              (unsigned int) hash_length,
+                                              hash,
+                                              signature);
+        }
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    if (ret == 0) {
+        *signature_length = mbedtls_rsa_get_len(rsa);
+    }
+    status = mbedtls_to_psa_error(ret);
+
+exit:
+    mbedtls_rsa_free(rsa);
+    mbedtls_free(rsa);
+
+    return status;
+}
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+static int rsa_pss_expected_salt_len(psa_algorithm_t alg,
+                                     const mbedtls_rsa_context *rsa,
+                                     size_t hash_length)
+{
+    if (PSA_ALG_IS_RSA_PSS_ANY_SALT(alg)) {
+        return MBEDTLS_RSA_SALT_LEN_ANY;
+    }
+    /* Otherwise: standard salt length, i.e. largest possible salt length
+     * up to the hash length. */
+    int klen = (int) mbedtls_rsa_get_len(rsa);   // known to fit
+    int hlen = (int) hash_length; // known to fit
+    int room = klen - 2 - hlen;
+    if (room < 0) {
+        return 0;  // there is no valid signature in this case anyway
+    } else if (room > hlen) {
+        return hlen;
+    } else {
+        return room;
+    }
+}
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
+
+psa_status_t mbedtls_psa_rsa_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    mbedtls_rsa_context *rsa = NULL;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_type_t md_alg;
+
+    status = mbedtls_psa_rsa_load_representation(attributes->type,
+                                                 key_buffer,
+                                                 key_buffer_size,
+                                                 &rsa);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_rsa_decode_md_type(alg, hash_length, &md_alg);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (signature_length != mbedtls_rsa_get_len(rsa)) {
+        status = PSA_ERROR_INVALID_SIGNATURE;
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN)
+    if (PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg)) {
+        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V15,
+                                      MBEDTLS_MD_NONE);
+        if (ret == 0) {
+            ret = mbedtls_rsa_pkcs1_verify(rsa,
+                                           md_alg,
+                                           (unsigned int) hash_length,
+                                           hash,
+                                           signature);
+        }
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN */
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS)
+    if (PSA_ALG_IS_RSA_PSS(alg)) {
+        ret = mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
+        if (ret == 0) {
+            int slen = rsa_pss_expected_salt_len(alg, rsa, hash_length);
+            ret = mbedtls_rsa_rsassa_pss_verify_ext(rsa,
+                                                    md_alg,
+                                                    (unsigned) hash_length,
+                                                    hash,
+                                                    md_alg,
+                                                    slen,
+                                                    signature);
+        }
+    } else
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS */
+    {
+        status = PSA_ERROR_INVALID_ARGUMENT;
+        goto exit;
+    }
+
+    /* Mbed TLS distinguishes "invalid padding" from "valid padding but
+     * the rest of the signature is invalid". This has little use in
+     * practice and PSA doesn't report this distinction. */
+    status = (ret == MBEDTLS_ERR_RSA_INVALID_PADDING) ?
+             PSA_ERROR_INVALID_SIGNATURE :
+             mbedtls_to_psa_error(ret);
+
+exit:
+    mbedtls_rsa_free(rsa);
+    mbedtls_free(rsa);
+
+    return status;
+}
+
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_SIGN) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PSS) */
+
+/****************************************************************/
+/* Asymmetric cryptography */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+static int psa_rsa_oaep_set_padding_mode(psa_algorithm_t alg,
+                                         mbedtls_rsa_context *rsa)
+{
+    psa_algorithm_t hash_alg = PSA_ALG_RSA_OAEP_GET_HASH(alg);
+    mbedtls_md_type_t md_alg = mbedtls_md_type_from_psa_alg(hash_alg);
+
+    /* Just to get the error status right, as rsa_set_padding() doesn't
+     * distinguish between "bad RSA algorithm" and "unknown hash". */
+    if (mbedtls_md_info_from_type(md_alg) == NULL) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return mbedtls_rsa_set_padding(rsa, MBEDTLS_RSA_PKCS_V21, md_alg);
+}
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+
+psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,
+                                            const uint8_t *key_buffer,
+                                            size_t key_buffer_size,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *input,
+                                            size_t input_length,
+                                            const uint8_t *salt,
+                                            size_t salt_length,
+                                            uint8_t *output,
+                                            size_t output_size,
+                                            size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) input;
+    (void) input_length;
+    (void) salt;
+    (void) salt_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+
+    if (PSA_KEY_TYPE_IS_RSA(attributes->type)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+        mbedtls_rsa_context *rsa = NULL;
+        status = mbedtls_psa_rsa_load_representation(attributes->type,
+                                                     key_buffer,
+                                                     key_buffer_size,
+                                                     &rsa);
+        if (status != PSA_SUCCESS) {
+            goto rsa_exit;
+        }
+
+        if (output_size < mbedtls_rsa_get_len(rsa)) {
+            status = PSA_ERROR_BUFFER_TOO_SMALL;
+            goto rsa_exit;
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
+            status = mbedtls_to_psa_error(
+                mbedtls_rsa_pkcs1_encrypt(rsa,
+                                          mbedtls_psa_get_random,
+                                          MBEDTLS_PSA_RANDOM_STATE,
+                                          input_length,
+                                          input,
+                                          output));
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
+        } else
+        if (PSA_ALG_IS_RSA_OAEP(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+            status = mbedtls_to_psa_error(
+                psa_rsa_oaep_set_padding_mode(alg, rsa));
+            if (status != PSA_SUCCESS) {
+                goto rsa_exit;
+            }
+
+            status = mbedtls_to_psa_error(
+                mbedtls_rsa_rsaes_oaep_encrypt(rsa,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE,
+                                               salt, salt_length,
+                                               input_length,
+                                               input,
+                                               output));
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
+        } else {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+        }
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+rsa_exit:
+        if (status == PSA_SUCCESS) {
+            *output_length = mbedtls_rsa_get_len(rsa);
+        }
+
+        mbedtls_rsa_free(rsa);
+        mbedtls_free(rsa);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+    } else {
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,
+                                            const uint8_t *key_buffer,
+                                            size_t key_buffer_size,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *input,
+                                            size_t input_length,
+                                            const uint8_t *salt,
+                                            size_t salt_length,
+                                            uint8_t *output,
+                                            size_t output_size,
+                                            size_t *output_length)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    (void) key_buffer;
+    (void) key_buffer_size;
+    (void) input;
+    (void) input_length;
+    (void) salt;
+    (void) salt_length;
+    (void) output;
+    (void) output_size;
+    (void) output_length;
+
+    *output_length = 0;
+
+    if (attributes->type == PSA_KEY_TYPE_RSA_KEY_PAIR) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+        mbedtls_rsa_context *rsa = NULL;
+        status = mbedtls_psa_rsa_load_representation(attributes->type,
+                                                     key_buffer,
+                                                     key_buffer_size,
+                                                     &rsa);
+        if (status != PSA_SUCCESS) {
+            goto rsa_exit;
+        }
+
+        if (input_length != mbedtls_rsa_get_len(rsa)) {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+            goto rsa_exit;
+        }
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+
+        if (alg == PSA_ALG_RSA_PKCS1V15_CRYPT) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT)
+            status = mbedtls_to_psa_error(
+                mbedtls_rsa_pkcs1_decrypt(rsa,
+                                          mbedtls_psa_get_random,
+                                          MBEDTLS_PSA_RANDOM_STATE,
+                                          output_length,
+                                          input,
+                                          output,
+                                          output_size));
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT */
+        } else
+        if (PSA_ALG_IS_RSA_OAEP(alg)) {
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+            status = mbedtls_to_psa_error(
+                psa_rsa_oaep_set_padding_mode(alg, rsa));
+            if (status != PSA_SUCCESS) {
+                goto rsa_exit;
+            }
+
+            status = mbedtls_to_psa_error(
+                mbedtls_rsa_rsaes_oaep_decrypt(rsa,
+                                               mbedtls_psa_get_random,
+                                               MBEDTLS_PSA_RANDOM_STATE,
+                                               salt, salt_length,
+                                               output_length,
+                                               input,
+                                               output,
+                                               output_size));
+#else
+            status = PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP */
+        } else {
+            status = PSA_ERROR_INVALID_ARGUMENT;
+        }
+
+#if defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) || \
+        defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP)
+rsa_exit:
+        mbedtls_rsa_free(rsa);
+        mbedtls_free(rsa);
+#endif /* defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_PKCS1V15_CRYPT) ||
+        * defined(MBEDTLS_PSA_BUILTIN_ALG_RSA_OAEP) */
+    } else {
+        status = PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    return status;
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.h b/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.h
new file mode 100644
index 0000000000000000000000000000000000000000..1a780006a904dd587f513100b852f2cc17610151
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_rsa.h
@@ -0,0 +1,321 @@
+/*
+ *  PSA RSA layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_RSA_H
+#define PSA_CRYPTO_RSA_H
+
+#include <psa/crypto.h>
+#include <mbedtls/rsa.h>
+
+/** Load the contents of a key buffer into an internal RSA representation
+ *
+ * \param[in] type          The type of key contained in \p data.
+ * \param[in] data          The buffer from which to load the representation.
+ * \param[in] data_length   The size in bytes of \p data.
+ * \param[out] p_rsa        Returns a pointer to an RSA context on success.
+ *                          The caller is responsible for freeing both the
+ *                          contents of the context and the context itself
+ *                          when done.
+ */
+psa_status_t mbedtls_psa_rsa_load_representation(psa_key_type_t type,
+                                                 const uint8_t *data,
+                                                 size_t data_length,
+                                                 mbedtls_rsa_context **p_rsa);
+
+/** Import an RSA key in binary format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       import_key entry point. This function behaves as an import_key
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes for the key to import.
+ * \param[in]  data             The buffer containing the key data in import
+ *                              format.
+ * \param[in]  data_length      Size of the \p data buffer in bytes.
+ * \param[out] key_buffer       The buffer containing the key data in output
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes. This
+ *                              size is greater or equal to \p data_length.
+ * \param[out] key_buffer_length  The length of the data written in \p
+ *                                key_buffer in bytes.
+ * \param[out] bits             The key size in number of bits.
+ *
+ * \retval #PSA_SUCCESS  The RSA key was imported successfully.
+ * \retval #PSA_ERROR_INVALID_ARGUMENT
+ *         The key data is not correctly formatted.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ */
+psa_status_t mbedtls_psa_rsa_import_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *data, size_t data_length,
+    uint8_t *key_buffer, size_t key_buffer_size,
+    size_t *key_buffer_length, size_t *bits);
+
+/** Export an RSA key to export representation
+ *
+ * \param[in] type          The type of key (public/private) to export
+ * \param[in] rsa           The internal RSA representation from which to export
+ * \param[out] data         The buffer to export to
+ * \param[in] data_size     The length of the buffer to export to
+ * \param[out] data_length  The amount of bytes written to \p data
+ */
+psa_status_t mbedtls_psa_rsa_export_key(psa_key_type_t type,
+                                        mbedtls_rsa_context *rsa,
+                                        uint8_t *data,
+                                        size_t data_size,
+                                        size_t *data_length);
+
+/** Export a public RSA key or the public part of an RSA key pair in binary
+ *  format.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       export_public_key entry point. This function behaves as an
+ *       export_public_key entry point as defined in the PSA driver interface
+ *       specification.
+ *
+ * \param[in]  attributes       The attributes for the key to export.
+ * \param[in]  key_buffer       Material or context of the key to export.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[out] data             Buffer where the key data is to be written.
+ * \param[in]  data_size        Size of the \p data buffer in bytes.
+ * \param[out] data_length      On success, the number of bytes written in
+ *                              \p data.
+ *
+ * \retval #PSA_SUCCESS  The RSA public key was exported successfully.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_rsa_export_public_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    uint8_t *data, size_t data_size, size_t *data_length);
+
+/**
+ * \brief Generate an RSA key.
+ *
+ * \param[in]  attributes         The attributes for the RSA key to generate.
+ * \param[in]  custom_data        The public exponent to use.
+ *                                This can be a null pointer if
+ *                                \c params_data_length is 0.
+ * \param custom_data_length      Length of \p custom_data in bytes.
+ *                                This can be 0, in which case the
+ *                                public exponent will be 65537.
+ * \param[out] key_buffer         Buffer where the key data is to be written.
+ * \param[in]  key_buffer_size    Size of \p key_buffer in bytes.
+ * \param[out] key_buffer_length  On success, the number of bytes written in
+ *                                \p key_buffer.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was successfully generated.
+ * \retval #PSA_ERROR_NOT_SUPPORTED
+ *         Key length or type not supported.
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of \p key_buffer is too small.
+ */
+psa_status_t mbedtls_psa_rsa_generate_key(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *custom_data, size_t custom_data_length,
+    uint8_t *key_buffer, size_t key_buffer_size, size_t *key_buffer_length);
+
+/** Sign an already-calculated hash with an RSA private key.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       sign_hash entry point. This function behaves as a sign_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the RSA key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the RSA key context.
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              an RSA key.
+ * \param[in]  hash             The hash or message to sign.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[out] signature        Buffer where the signature is to be written.
+ * \param[in]  signature_size   Size of the \p signature buffer in bytes.
+ * \param[out] signature_length On success, the number of bytes
+ *                              that make up the returned signature value.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p signature buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_SIGN_OUTPUT_SIZE(\c PSA_KEY_TYPE_RSA_KEY_PAIR, \c key_bits,
+ *         \p alg) where \c key_bits is the bit-size of the RSA key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ */
+psa_status_t mbedtls_psa_rsa_sign_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    uint8_t *signature, size_t signature_size, size_t *signature_length);
+
+/**
+ * \brief Verify the signature a hash or short message using a public RSA key.
+ *
+ * \note The signature of this function is that of a PSA driver
+ *       verify_hash entry point. This function behaves as a verify_hash
+ *       entry point as defined in the PSA driver interface specification for
+ *       transparent drivers.
+ *
+ * \param[in]  attributes       The attributes of the RSA key to use for the
+ *                              operation.
+ * \param[in]  key_buffer       The buffer containing the RSA key context.
+ *                              format.
+ * \param[in]  key_buffer_size  Size of the \p key_buffer buffer in bytes.
+ * \param[in]  alg              A signature algorithm that is compatible with
+ *                              an RSA key.
+ * \param[in]  hash             The hash or message whose signature is to be
+ *                              verified.
+ * \param[in]  hash_length      Size of the \p hash buffer in bytes.
+ * \param[in]  signature        Buffer containing the signature to verify.
+ * \param[in]  signature_length Size of the \p signature buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS
+ *         The signature is valid.
+ * \retval #PSA_ERROR_INVALID_SIGNATURE
+ *         The calculation was performed successfully, but the passed
+ *         signature is not a valid signature.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ */
+psa_status_t mbedtls_psa_rsa_verify_hash(
+    const psa_key_attributes_t *attributes,
+    const uint8_t *key_buffer, size_t key_buffer_size,
+    psa_algorithm_t alg, const uint8_t *hash, size_t hash_length,
+    const uint8_t *signature, size_t signature_length);
+
+/**
+ * \brief Encrypt a short message with a public key.
+ *
+ * \param attributes            The attributes for the key to import.
+ * \param key_buffer            Buffer where the key data is to be written.
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \param[out] output           Buffer where the encrypted message is to
+ *                              be written.
+ * \param output_size           Size of the \p output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_ENCRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t mbedtls_psa_asymmetric_encrypt(const psa_key_attributes_t *attributes,
+                                            const uint8_t *key_buffer,
+                                            size_t key_buffer_size,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *input,
+                                            size_t input_length,
+                                            const uint8_t *salt,
+                                            size_t salt_length,
+                                            uint8_t *output,
+                                            size_t output_size,
+                                            size_t *output_length);
+
+/**
+ * \brief Decrypt a short message with a private key.
+ *
+ * \param attributes            The attributes for the key to import.
+ * \param key_buffer            Buffer where the key data is to be written.
+ * \param key_buffer_size       Size of the \p key_buffer buffer in bytes.
+ * \param[in] input             The message to decrypt.
+ * \param input_length          Size of the \p input buffer in bytes.
+ * \param[in] salt              A salt or label, if supported by the
+ *                              encryption algorithm.
+ *                              If the algorithm does not support a
+ *                              salt, pass \c NULL.
+ *                              If the algorithm supports an optional
+ *                              salt and you do not want to pass a salt,
+ *                              pass \c NULL.
+ *
+ *                              - For #PSA_ALG_RSA_PKCS1V15_CRYPT, no salt is
+ *                                supported.
+ * \param salt_length           Size of the \p salt buffer in bytes.
+ *                              If \p salt is \c NULL, pass 0.
+ * \param[out] output           Buffer where the decrypted message is to
+ *                              be written.
+ * \param output_size           Size of the \c output buffer in bytes.
+ * \param[out] output_length    On success, the number of bytes
+ *                              that make up the returned output.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_BUFFER_TOO_SMALL
+ *         The size of the \p output buffer is too small. You can
+ *         determine a sufficient buffer size by calling
+ *         #PSA_ASYMMETRIC_DECRYPT_OUTPUT_SIZE(\c key_type, \c key_bits, \p alg)
+ *         where \c key_type and \c key_bits are the type and bit-size
+ *         respectively of \p key.
+ * \retval #PSA_ERROR_NOT_SUPPORTED \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_COMMUNICATION_FAILURE \emptydescription
+ * \retval #PSA_ERROR_HARDWARE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_ENTROPY \emptydescription
+ * \retval #PSA_ERROR_INVALID_PADDING \emptydescription
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been previously initialized by psa_crypto_init().
+ *         It is implementation-dependent whether a failure to initialize
+ *         results in this error code.
+ */
+psa_status_t mbedtls_psa_asymmetric_decrypt(const psa_key_attributes_t *attributes,
+                                            const uint8_t *key_buffer,
+                                            size_t key_buffer_size,
+                                            psa_algorithm_t alg,
+                                            const uint8_t *input,
+                                            size_t input_length,
+                                            const uint8_t *salt,
+                                            size_t salt_length,
+                                            uint8_t *output,
+                                            size_t output_size,
+                                            size_t *output_length);
+
+#endif /* PSA_CRYPTO_RSA_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_se.c b/lib/libmbedtls/mbedtls/library/psa_crypto_se.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a36a4f3a5f5735603598b690b0253a5ca8e8952
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_se.c
@@ -0,0 +1,373 @@
+/*
+ *  PSA crypto support for secure element drivers
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+
+#include <stdint.h>
+#include <string.h>
+
+#include "psa/crypto_se_driver.h"
+
+#include "psa_crypto_se.h"
+
+#if defined(MBEDTLS_PSA_ITS_FILE_C)
+#include "psa_crypto_its.h"
+#else /* Native ITS implementation */
+#include "psa/error.h"
+#include "psa/internal_trusted_storage.h"
+#endif
+
+#include "mbedtls/platform.h"
+
+
+
+/****************************************************************/
+/* Driver lookup */
+/****************************************************************/
+
+/* This structure is identical to psa_drv_se_context_t declared in
+ * `crypto_se_driver.h`, except that some parts are writable here
+ * (non-const, or pointer to non-const). */
+typedef struct {
+    void *persistent_data;
+    size_t persistent_data_size;
+    uintptr_t transient_data;
+} psa_drv_se_internal_context_t;
+
+struct psa_se_drv_table_entry_s {
+    psa_key_location_t location;
+    const psa_drv_se_t *methods;
+    union {
+        psa_drv_se_internal_context_t internal;
+        psa_drv_se_context_t context;
+    } u;
+};
+
+static psa_se_drv_table_entry_t driver_table[PSA_MAX_SE_DRIVERS];
+
+psa_se_drv_table_entry_t *psa_get_se_driver_entry(
+    psa_key_lifetime_t lifetime)
+{
+    size_t i;
+    psa_key_location_t location = PSA_KEY_LIFETIME_GET_LOCATION(lifetime);
+    /* In the driver table, location=0 means an entry that isn't used.
+     * No driver has a location of 0 because it's a reserved value
+     * (which designates transparent keys). Make sure we never return
+     * a driver entry for location 0. */
+    if (location == 0) {
+        return NULL;
+    }
+    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
+        if (driver_table[i].location == location) {
+            return &driver_table[i];
+        }
+    }
+    return NULL;
+}
+
+const psa_drv_se_t *psa_get_se_driver_methods(
+    const psa_se_drv_table_entry_t *driver)
+{
+    return driver->methods;
+}
+
+psa_drv_se_context_t *psa_get_se_driver_context(
+    psa_se_drv_table_entry_t *driver)
+{
+    return &driver->u.context;
+}
+
+int psa_get_se_driver(psa_key_lifetime_t lifetime,
+                      const psa_drv_se_t **p_methods,
+                      psa_drv_se_context_t **p_drv_context)
+{
+    psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
+    if (p_methods != NULL) {
+        *p_methods = (driver ? driver->methods : NULL);
+    }
+    if (p_drv_context != NULL) {
+        *p_drv_context = (driver ? &driver->u.context : NULL);
+    }
+    return driver != NULL;
+}
+
+
+
+/****************************************************************/
+/* Persistent data management */
+/****************************************************************/
+
+static psa_status_t psa_get_se_driver_its_file_uid(
+    const psa_se_drv_table_entry_t *driver,
+    psa_storage_uid_t *uid)
+{
+    if (driver->location > PSA_MAX_SE_LOCATION) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* ITS file sizes are limited to 32 bits. */
+    if (driver->u.internal.persistent_data_size > UINT32_MAX) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    /* See the documentation of PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE. */
+    *uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + driver->location;
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_load_se_persistent_data(
+    const psa_se_drv_table_entry_t *driver)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid;
+    size_t length;
+
+    status = psa_get_se_driver_its_file_uid(driver, &uid);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Read the amount of persistent data that the driver requests.
+     * If the data in storage is larger, it is truncated. If the data
+     * in storage is smaller, silently keep what is already at the end
+     * of the output buffer. */
+    /* psa_get_se_driver_its_file_uid ensures that the size_t
+     * persistent_data_size is in range, but compilers don't know that,
+     * so cast to reassure them. */
+    return psa_its_get(uid, 0,
+                       (uint32_t) driver->u.internal.persistent_data_size,
+                       driver->u.internal.persistent_data,
+                       &length);
+}
+
+psa_status_t psa_save_se_persistent_data(
+    const psa_se_drv_table_entry_t *driver)
+{
+    psa_status_t status;
+    psa_storage_uid_t uid;
+
+    status = psa_get_se_driver_its_file_uid(driver, &uid);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* psa_get_se_driver_its_file_uid ensures that the size_t
+     * persistent_data_size is in range, but compilers don't know that,
+     * so cast to reassure them. */
+    return psa_its_set(uid,
+                       (uint32_t) driver->u.internal.persistent_data_size,
+                       driver->u.internal.persistent_data,
+                       0);
+}
+
+psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location)
+{
+    psa_storage_uid_t uid;
+    if (location > PSA_MAX_SE_LOCATION) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    uid = PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE + location;
+    return psa_its_remove(uid);
+}
+
+psa_status_t psa_find_se_slot_for_key(
+    const psa_key_attributes_t *attributes,
+    psa_key_creation_method_t method,
+    psa_se_drv_table_entry_t *driver,
+    psa_key_slot_number_t *slot_number)
+{
+    psa_status_t status;
+    psa_key_location_t key_location =
+        PSA_KEY_LIFETIME_GET_LOCATION(psa_get_key_lifetime(attributes));
+
+    /* If the location is wrong, it's a bug in the library. */
+    if (driver->location != key_location) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    /* If the driver doesn't support key creation in any way, give up now. */
+    if (driver->methods->key_management == NULL) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    if (psa_get_key_slot_number(attributes, slot_number) == PSA_SUCCESS) {
+        /* The application wants to use a specific slot. Allow it if
+         * the driver supports it. On a system with isolation,
+         * the crypto service must check that the application is
+         * permitted to request this slot. */
+        psa_drv_se_validate_slot_number_t p_validate_slot_number =
+            driver->methods->key_management->p_validate_slot_number;
+        if (p_validate_slot_number == NULL) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+        status = p_validate_slot_number(&driver->u.context,
+                                        driver->u.internal.persistent_data,
+                                        attributes, method,
+                                        *slot_number);
+    } else if (method == PSA_KEY_CREATION_REGISTER) {
+        /* The application didn't specify a slot number. This doesn't
+         * make sense when registering a slot. */
+        return PSA_ERROR_INVALID_ARGUMENT;
+    } else {
+        /* The application didn't tell us which slot to use. Let the driver
+         * choose. This is the normal case. */
+        psa_drv_se_allocate_key_t p_allocate =
+            driver->methods->key_management->p_allocate;
+        if (p_allocate == NULL) {
+            return PSA_ERROR_NOT_SUPPORTED;
+        }
+        status = p_allocate(&driver->u.context,
+                            driver->u.internal.persistent_data,
+                            attributes, method,
+                            slot_number);
+    }
+    return status;
+}
+
+psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,
+                                psa_key_slot_number_t slot_number)
+{
+    psa_status_t status;
+    psa_status_t storage_status;
+    /* Normally a missing method would mean that the action is not
+     * supported. But psa_destroy_key() is not supposed to return
+     * PSA_ERROR_NOT_SUPPORTED: if you can create a key, you should
+     * be able to destroy it. The only use case for a driver that
+     * does not have a way to destroy keys at all is if the keys are
+     * locked in a read-only state: we can use the keys but not
+     * destroy them. Hence, if the driver doesn't support destroying
+     * keys, it's really a lack of permission. */
+    if (driver->methods->key_management == NULL ||
+        driver->methods->key_management->p_destroy == NULL) {
+        return PSA_ERROR_NOT_PERMITTED;
+    }
+    status = driver->methods->key_management->p_destroy(
+        &driver->u.context,
+        driver->u.internal.persistent_data,
+        slot_number);
+    storage_status = psa_save_se_persistent_data(driver);
+    return status == PSA_SUCCESS ? storage_status : status;
+}
+
+psa_status_t psa_init_all_se_drivers(void)
+{
+    size_t i;
+    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
+        psa_se_drv_table_entry_t *driver = &driver_table[i];
+        if (driver->location == 0) {
+            continue; /* skipping unused entry */
+        }
+        const psa_drv_se_t *methods = psa_get_se_driver_methods(driver);
+        if (methods->p_init != NULL) {
+            psa_status_t status = methods->p_init(
+                &driver->u.context,
+                driver->u.internal.persistent_data,
+                driver->location);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+            status = psa_save_se_persistent_data(driver);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
+    }
+    return PSA_SUCCESS;
+}
+
+
+
+/****************************************************************/
+/* Driver registration */
+/****************************************************************/
+
+psa_status_t psa_register_se_driver(
+    psa_key_location_t location,
+    const psa_drv_se_t *methods)
+{
+    size_t i;
+    psa_status_t status;
+
+    if (methods->hal_version != PSA_DRV_SE_HAL_VERSION) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+    /* Driver table entries are 0-initialized. 0 is not a valid driver
+     * location because it means a transparent key. */
+    MBEDTLS_STATIC_ASSERT(PSA_KEY_LOCATION_LOCAL_STORAGE == 0,
+                          "Secure element support requires 0 to mean a local key");
+
+    if (location == PSA_KEY_LOCATION_LOCAL_STORAGE) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+    if (location > PSA_MAX_SE_LOCATION) {
+        return PSA_ERROR_NOT_SUPPORTED;
+    }
+
+    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
+        if (driver_table[i].location == 0) {
+            break;
+        }
+        /* Check that location isn't already in use up to the first free
+         * entry. Since entries are created in order and never deleted,
+         * there can't be a used entry after the first free entry. */
+        if (driver_table[i].location == location) {
+            return PSA_ERROR_ALREADY_EXISTS;
+        }
+    }
+    if (i == PSA_MAX_SE_DRIVERS) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    driver_table[i].location = location;
+    driver_table[i].methods = methods;
+    driver_table[i].u.internal.persistent_data_size =
+        methods->persistent_data_size;
+
+    if (methods->persistent_data_size != 0) {
+        driver_table[i].u.internal.persistent_data =
+            mbedtls_calloc(1, methods->persistent_data_size);
+        if (driver_table[i].u.internal.persistent_data == NULL) {
+            status = PSA_ERROR_INSUFFICIENT_MEMORY;
+            goto error;
+        }
+        /* Load the driver's persistent data. On first use, the persistent
+         * data does not exist in storage, and is initialized to
+         * all-bits-zero by the calloc call just above. */
+        status = psa_load_se_persistent_data(&driver_table[i]);
+        if (status != PSA_SUCCESS && status != PSA_ERROR_DOES_NOT_EXIST) {
+            goto error;
+        }
+    }
+
+    return PSA_SUCCESS;
+
+error:
+    memset(&driver_table[i], 0, sizeof(driver_table[i]));
+    return status;
+}
+
+void psa_unregister_all_se_drivers(void)
+{
+    size_t i;
+    for (i = 0; i < PSA_MAX_SE_DRIVERS; i++) {
+        if (driver_table[i].u.internal.persistent_data != NULL) {
+            mbedtls_free(driver_table[i].u.internal.persistent_data);
+        }
+    }
+    memset(driver_table, 0, sizeof(driver_table));
+}
+
+
+
+/****************************************************************/
+/* The end */
+/****************************************************************/
+
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_se.h b/lib/libmbedtls/mbedtls/library/psa_crypto_se.h
new file mode 100644
index 0000000000000000000000000000000000000000..e0bd5acfb3abec75cda84591bf9e628f61536579
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_se.h
@@ -0,0 +1,192 @@
+/*
+ *  PSA crypto support for secure element drivers
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_SE_H
+#define PSA_CRYPTO_SE_H
+
+/*
+ * Include the build-time configuration information header. Here, we do not
+ * include `"mbedtls/build_info.h"` directly but `"psa/build_info.h"`, which
+ * is basically just an alias to it. This is to ease the maintenance of the
+ * TF-PSA-Crypto repository which has a different build system and
+ * configuration.
+ */
+#include "psa/build_info.h"
+
+#include "psa/crypto.h"
+#include "psa/crypto_se_driver.h"
+
+/** The maximum location value that this implementation supports
+ * for a secure element.
+ *
+ * This is not a characteristic that each PSA implementation has, but a
+ * limitation of the current implementation due to the constraints imposed
+ * by storage. See #PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE.
+ *
+ * The minimum location value for a secure element is 1, like on any
+ * PSA implementation (0 means a transparent key).
+ */
+#define PSA_MAX_SE_LOCATION 255
+
+/** The base of the range of ITS file identifiers for secure element
+ * driver persistent data.
+ *
+ * We use a slice of the implementation reserved range 0xffff0000..0xffffffff,
+ * specifically the range 0xfffffe00..0xfffffeff. The length of this range
+ * drives the value of #PSA_MAX_SE_LOCATION. The identifier 0xfffffe00 is
+ * actually not used since it corresponds to #PSA_KEY_LOCATION_LOCAL_STORAGE
+ * which doesn't have a driver.
+ */
+#define PSA_CRYPTO_SE_DRIVER_ITS_UID_BASE ((psa_key_id_t) 0xfffffe00)
+
+/** The maximum number of registered secure element driver locations. */
+#define PSA_MAX_SE_DRIVERS 4
+
+/** Unregister all secure element drivers.
+ *
+ * \warning Do not call this function while the library is in the initialized
+ *          state. This function is only intended to be called at the end
+ *          of mbedtls_psa_crypto_free().
+ */
+void psa_unregister_all_se_drivers(void);
+
+/** Initialize all secure element drivers.
+ *
+ * Called from psa_crypto_init().
+ */
+psa_status_t psa_init_all_se_drivers(void);
+
+/** A structure that describes a registered secure element driver.
+ *
+ * A secure element driver table entry contains a pointer to the
+ * driver's method table as well as the driver context structure.
+ */
+typedef struct psa_se_drv_table_entry_s psa_se_drv_table_entry_t;
+
+/** Return the secure element driver information for a lifetime value.
+ *
+ * \param lifetime              The lifetime value to query.
+ * \param[out] p_methods        On output, if there is a driver,
+ *                              \c *methods points to its method table.
+ *                              Otherwise \c *methods is \c NULL.
+ * \param[out] p_drv_context    On output, if there is a driver,
+ *                              \c *drv_context points to its context
+ *                              structure.
+ *                              Otherwise \c *drv_context is \c NULL.
+ *
+ * \retval 1
+ *         \p lifetime corresponds to a registered driver.
+ * \retval 0
+ *         \p lifetime does not correspond to a registered driver.
+ */
+int psa_get_se_driver(psa_key_lifetime_t lifetime,
+                      const psa_drv_se_t **p_methods,
+                      psa_drv_se_context_t **p_drv_context);
+
+/** Return the secure element driver table entry for a lifetime value.
+ *
+ * \param lifetime      The lifetime value to query.
+ *
+ * \return The driver table entry for \p lifetime, or
+ *         \p NULL if \p lifetime does not correspond to a registered driver.
+ */
+psa_se_drv_table_entry_t *psa_get_se_driver_entry(
+    psa_key_lifetime_t lifetime);
+
+/** Return the method table for a secure element driver.
+ *
+ * \param[in] driver    The driver table entry to access, or \c NULL.
+ *
+ * \return The driver's method table.
+ *         \c NULL if \p driver is \c NULL.
+ */
+const psa_drv_se_t *psa_get_se_driver_methods(
+    const psa_se_drv_table_entry_t *driver);
+
+/** Return the context of a secure element driver.
+ *
+ * \param[in] driver    The driver table entry to access, or \c NULL.
+ *
+ * \return A pointer to the driver context.
+ *         \c NULL if \p driver is \c NULL.
+ */
+psa_drv_se_context_t *psa_get_se_driver_context(
+    psa_se_drv_table_entry_t *driver);
+
+/** Find a free slot for a key that is to be created.
+ *
+ * This function calls the relevant method in the driver to find a suitable
+ * slot for a key with the given attributes.
+ *
+ * \param[in] attributes    Metadata about the key that is about to be created.
+ * \param[in] driver        The driver table entry to query.
+ * \param[out] slot_number  On success, a slot number that is free in this
+ *                          secure element.
+ */
+psa_status_t psa_find_se_slot_for_key(
+    const psa_key_attributes_t *attributes,
+    psa_key_creation_method_t method,
+    psa_se_drv_table_entry_t *driver,
+    psa_key_slot_number_t *slot_number);
+
+/** Destroy a key in a secure element.
+ *
+ * This function calls the relevant driver method to destroy a key
+ * and updates the driver's persistent data.
+ */
+psa_status_t psa_destroy_se_key(psa_se_drv_table_entry_t *driver,
+                                psa_key_slot_number_t slot_number);
+
+/** Load the persistent data of a secure element driver.
+ *
+ * \param driver        The driver table entry containing the persistent
+ *                      data to load from storage.
+ *
+ * \return #PSA_SUCCESS
+ * \return #PSA_ERROR_NOT_SUPPORTED
+ * \return #PSA_ERROR_DOES_NOT_EXIST
+ * \return #PSA_ERROR_STORAGE_FAILURE
+ * \return #PSA_ERROR_DATA_CORRUPT
+ * \return #PSA_ERROR_INVALID_ARGUMENT
+ */
+psa_status_t psa_load_se_persistent_data(
+    const psa_se_drv_table_entry_t *driver);
+
+/** Save the persistent data of a secure element driver.
+ *
+ * \param[in] driver    The driver table entry containing the persistent
+ *                      data to save to storage.
+ *
+ * \return #PSA_SUCCESS
+ * \return #PSA_ERROR_NOT_SUPPORTED
+ * \return #PSA_ERROR_NOT_PERMITTED
+ * \return #PSA_ERROR_NOT_SUPPORTED
+ * \return #PSA_ERROR_INSUFFICIENT_STORAGE
+ * \return #PSA_ERROR_STORAGE_FAILURE
+ * \return #PSA_ERROR_INVALID_ARGUMENT
+ */
+psa_status_t psa_save_se_persistent_data(
+    const psa_se_drv_table_entry_t *driver);
+
+/** Destroy the persistent data of a secure element driver.
+ *
+ * This is currently only used for testing.
+ *
+ * \param[in] location  The location identifier for the driver whose
+ *                      persistent data is to be erased.
+ */
+psa_status_t psa_destroy_se_persistent_data(psa_key_location_t location);
+
+
+/** The storage representation of a key whose data is in a secure element.
+ */
+typedef struct {
+    uint8_t slot_number[sizeof(psa_key_slot_number_t)];
+} psa_se_key_data_storage_t;
+
+#endif /* PSA_CRYPTO_SE_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.c b/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.c
new file mode 100644
index 0000000000000000000000000000000000000000..9850d8c750537067929a9da6f3217251e2354bdd
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.c
@@ -0,0 +1,1131 @@
+/*
+ *  PSA crypto layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+
+#include "psa/crypto.h"
+
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers_no_static.h"
+#include "psa_crypto_slot_management.h"
+#include "psa_crypto_storage.h"
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+#include "psa_crypto_se.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "mbedtls/platform.h"
+#if defined(MBEDTLS_THREADING_C)
+#include "mbedtls/threading.h"
+#endif
+
+
+
+/* Make sure we have distinct ranges of key identifiers for distinct
+ * purposes. */
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MIN < PSA_KEY_ID_USER_MAX,
+                      "Empty user key ID range");
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN < PSA_KEY_ID_VENDOR_MAX,
+                      "Empty vendor key ID range");
+MBEDTLS_STATIC_ASSERT(MBEDTLS_PSA_KEY_ID_BUILTIN_MIN < MBEDTLS_PSA_KEY_ID_BUILTIN_MAX,
+                      "Empty builtin key ID range");
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MIN < PSA_KEY_ID_VOLATILE_MAX,
+                      "Empty volatile key ID range");
+
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_USER_MAX < PSA_KEY_ID_VENDOR_MIN ||
+                      PSA_KEY_ID_VENDOR_MAX < PSA_KEY_ID_USER_MIN,
+                      "Overlap between user key IDs and vendor key IDs");
+
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= MBEDTLS_PSA_KEY_ID_BUILTIN_MIN &&
+                      MBEDTLS_PSA_KEY_ID_BUILTIN_MAX <= PSA_KEY_ID_VENDOR_MAX,
+                      "Builtin key identifiers are not in the vendor range");
+
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VENDOR_MIN <= PSA_KEY_ID_VOLATILE_MIN &&
+                      PSA_KEY_ID_VOLATILE_MAX <= PSA_KEY_ID_VENDOR_MAX,
+                      "Volatile key identifiers are not in the vendor range");
+
+MBEDTLS_STATIC_ASSERT(PSA_KEY_ID_VOLATILE_MAX < MBEDTLS_PSA_KEY_ID_BUILTIN_MIN ||
+                      MBEDTLS_PSA_KEY_ID_BUILTIN_MAX < PSA_KEY_ID_VOLATILE_MIN,
+                      "Overlap between builtin key IDs and volatile key IDs");
+
+
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+
+/* Dynamic key store.
+ *
+ * The key store consists of multiple slices.
+ *
+ * The volatile keys are stored in variable-sized tables called slices.
+ * Slices are allocated on demand and deallocated when possible.
+ * The size of slices increases exponentially, so the average overhead
+ * (number of slots that are allocated but not used) is roughly
+ * proportional to the number of keys (with a factor that grows
+ * when the key store is fragmented).
+ *
+ * One slice is dedicated to the cache of persistent and built-in keys.
+ * For simplicity, they are separated from volatile keys. This cache
+ * slice has a fixed size and has the slice index KEY_SLOT_CACHE_SLICE_INDEX,
+ * located after the slices for volatile keys.
+ */
+
+/* Size of the last slice containing the cache of persistent and built-in keys. */
+#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
+
+/* Volatile keys are stored in slices 0 through
+ * (KEY_SLOT_VOLATILE_SLICE_COUNT - 1) inclusive.
+ * Each slice is twice the size of the previous slice.
+ * Volatile key identifiers encode the slice number as follows:
+ *     bits 30..31:  0b10 (mandated by the PSA Crypto specification).
+ *     bits 25..29:  slice index (0...KEY_SLOT_VOLATILE_SLICE_COUNT-1)
+ *     bits 0..24:   slot index in slice
+ */
+#define KEY_ID_SLOT_INDEX_WIDTH 25u
+#define KEY_ID_SLICE_INDEX_WIDTH 5u
+
+#define KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH 16u
+#define KEY_SLOT_VOLATILE_SLICE_COUNT 22u
+#define KEY_SLICE_COUNT (KEY_SLOT_VOLATILE_SLICE_COUNT + 1u)
+#define KEY_SLOT_CACHE_SLICE_INDEX KEY_SLOT_VOLATILE_SLICE_COUNT
+
+
+/* Check that the length of the largest slice (calculated as
+ * KEY_SLICE_LENGTH_MAX below) does not overflow size_t. We use
+ * an indirect method in case the calculation of KEY_SLICE_LENGTH_MAX
+ * itself overflows uintmax_t: if (BASE_LENGTH << c)
+ * overflows size_t then BASE_LENGTH > SIZE_MAX >> c.
+ */
+#if (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH >              \
+     SIZE_MAX >> (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
+#error "Maximum slice length overflows size_t"
+#endif
+
+#if KEY_ID_SLICE_INDEX_WIDTH + KEY_ID_SLOT_INDEX_WIDTH > 30
+#error "Not enough room in volatile key IDs for slice index and slot index"
+#endif
+#if KEY_SLOT_VOLATILE_SLICE_COUNT > (1 << KEY_ID_SLICE_INDEX_WIDTH)
+#error "Too many slices to fit the slice index in a volatile key ID"
+#endif
+#define KEY_SLICE_LENGTH_MAX                                            \
+    (KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << (KEY_SLOT_VOLATILE_SLICE_COUNT - 1))
+#if KEY_SLICE_LENGTH_MAX > 1 << KEY_ID_SLOT_INDEX_WIDTH
+#error "Not enough room in volatile key IDs for a slot index in the largest slice"
+#endif
+#if KEY_ID_SLICE_INDEX_WIDTH > 8
+#error "Slice index does not fit in uint8_t for psa_key_slot_t::slice_index"
+#endif
+
+
+/* Calculate the volatile key id to use for a given slot.
+ * This function assumes valid parameter values. */
+static psa_key_id_t volatile_key_id_of_index(size_t slice_idx,
+                                             size_t slot_idx)
+{
+    /* We assert above that the slice and slot indexes fit in separate
+     * bit-fields inside psa_key_id_t, which is a 32-bit type per the
+     * PSA Cryptography specification. */
+    return (psa_key_id_t) (0x40000000u |
+                           (slice_idx << KEY_ID_SLOT_INDEX_WIDTH) |
+                           slot_idx);
+}
+
+/* Calculate the slice containing the given volatile key.
+ * This function assumes valid parameter values. */
+static size_t slice_index_of_volatile_key_id(psa_key_id_t key_id)
+{
+    size_t mask = (1LU << KEY_ID_SLICE_INDEX_WIDTH) - 1;
+    return (key_id >> KEY_ID_SLOT_INDEX_WIDTH) & mask;
+}
+
+/* Calculate the index of the slot containing the given volatile key.
+ * This function assumes valid parameter values. */
+static size_t slot_index_of_volatile_key_id(psa_key_id_t key_id)
+{
+    return key_id & ((1LU << KEY_ID_SLOT_INDEX_WIDTH) - 1);
+}
+
+/* In global_data.first_free_slot_index, use this special value to
+ * indicate that the slice is full. */
+#define FREE_SLOT_INDEX_NONE ((size_t) -1)
+
+#if defined(MBEDTLS_TEST_HOOKS)
+size_t psa_key_slot_volatile_slice_count(void)
+{
+    return KEY_SLOT_VOLATILE_SLICE_COUNT;
+}
+#endif
+
+#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+/* Static key store.
+ *
+ * All the keys (volatile or persistent) are in a single slice.
+ * We only use slices as a concept to allow some differences between
+ * static and dynamic key store management to be buried in auxiliary
+ * functions.
+ */
+
+#define PERSISTENT_KEY_CACHE_COUNT MBEDTLS_PSA_KEY_SLOT_COUNT
+#define KEY_SLICE_COUNT 1u
+#define KEY_SLOT_CACHE_SLICE_INDEX 0
+
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+
+typedef struct {
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    psa_key_slot_t *key_slices[KEY_SLICE_COUNT];
+    size_t first_free_slot_index[KEY_SLOT_VOLATILE_SLICE_COUNT];
+#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+    psa_key_slot_t key_slots[MBEDTLS_PSA_KEY_SLOT_COUNT];
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+    uint8_t key_slots_initialized;
+} psa_global_data_t;
+
+static psa_global_data_t global_data;
+
+static uint8_t psa_get_key_slots_initialized(void)
+{
+    uint8_t initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_lock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    initialized = global_data.key_slots_initialized;
+
+#if defined(MBEDTLS_THREADING_C)
+    mbedtls_mutex_unlock(&mbedtls_threading_psa_globaldata_mutex);
+#endif /* defined(MBEDTLS_THREADING_C) */
+
+    return initialized;
+}
+
+
+
+/** The length of the given slice in the key slot table.
+ *
+ * \param slice_idx     The slice number. It must satisfy
+ *                      0 <= slice_idx < KEY_SLICE_COUNT.
+ *
+ * \return              The number of elements in the given slice.
+ */
+static inline size_t key_slice_length(size_t slice_idx);
+
+/** Get a pointer to the slot where the given volatile key is located.
+ *
+ * \param key_id        The key identifier. It must be a valid volatile key
+ *                      identifier.
+ * \return              A pointer to the only slot that the given key
+ *                      can be in. Note that the slot may be empty or
+ *                      contain a different key.
+ */
+static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id);
+
+/** Get a pointer to an entry in the persistent key cache.
+ *
+ * \param slot_idx      The index in the table. It must satisfy
+ *                      0 <= slot_idx < PERSISTENT_KEY_CACHE_COUNT.
+ * \return              A pointer to the slot containing the given
+ *                      persistent key cache entry.
+ */
+static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx);
+
+/** Get a pointer to a slot given by slice and index.
+ *
+ * \param slice_idx     The slice number. It must satisfy
+ *                      0 <= slice_idx < KEY_SLICE_COUNT.
+ * \param slot_idx      An index in the given slice. It must satisfy
+ *                      0 <= slot_idx < key_slice_length(slice_idx).
+ *
+ * \return              A pointer to the given slot.
+ */
+static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx);
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+
+#if defined(MBEDTLS_TEST_HOOKS)
+size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(size_t slice_idx) = NULL;
+#endif
+
+static inline size_t key_slice_length(size_t slice_idx)
+{
+    if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
+        return PERSISTENT_KEY_CACHE_COUNT;
+    } else {
+#if defined(MBEDTLS_TEST_HOOKS)
+        if (mbedtls_test_hook_psa_volatile_key_slice_length != NULL) {
+            return mbedtls_test_hook_psa_volatile_key_slice_length(slice_idx);
+        }
+#endif
+        return KEY_SLOT_VOLATILE_SLICE_BASE_LENGTH << slice_idx;
+    }
+}
+
+static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
+{
+    size_t slice_idx = slice_index_of_volatile_key_id(key_id);
+    if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
+        return NULL;
+    }
+    size_t slot_idx = slot_index_of_volatile_key_id(key_id);
+    if (slot_idx >= key_slice_length(slice_idx)) {
+        return NULL;
+    }
+    psa_key_slot_t *slice = global_data.key_slices[slice_idx];
+    if (slice == NULL) {
+        return NULL;
+    }
+    return &slice[slot_idx];
+}
+
+static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
+{
+    return &global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX][slot_idx];
+}
+
+static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
+{
+    return &global_data.key_slices[slice_idx][slot_idx];
+}
+
+#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+static inline size_t key_slice_length(size_t slice_idx)
+{
+    (void) slice_idx;
+    return ARRAY_LENGTH(global_data.key_slots);
+}
+
+static inline psa_key_slot_t *get_volatile_key_slot(psa_key_id_t key_id)
+{
+    MBEDTLS_STATIC_ASSERT(ARRAY_LENGTH(global_data.key_slots) <=
+                          PSA_KEY_ID_VOLATILE_MAX - PSA_KEY_ID_VOLATILE_MIN + 1,
+                          "The key slot array is larger than the volatile key ID range");
+    return &global_data.key_slots[key_id - PSA_KEY_ID_VOLATILE_MIN];
+}
+
+static inline psa_key_slot_t *get_persistent_key_slot(size_t slot_idx)
+{
+    return &global_data.key_slots[slot_idx];
+}
+
+static inline psa_key_slot_t *get_key_slot(size_t slice_idx, size_t slot_idx)
+{
+    (void) slice_idx;
+    return &global_data.key_slots[slot_idx];
+}
+
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+
+
+int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok)
+{
+    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
+
+    if ((PSA_KEY_ID_USER_MIN <= key_id) &&
+        (key_id <= PSA_KEY_ID_USER_MAX)) {
+        return 1;
+    }
+
+    if (vendor_ok &&
+        (PSA_KEY_ID_VENDOR_MIN <= key_id) &&
+        (key_id <= PSA_KEY_ID_VENDOR_MAX)) {
+        return 1;
+    }
+
+    return 0;
+}
+
+/** Get the description in memory of a key given its identifier and lock it.
+ *
+ * The descriptions of volatile keys and loaded persistent keys are
+ * stored in key slots. This function returns a pointer to the key slot
+ * containing the description of a key given its identifier.
+ *
+ * The function searches the key slots containing the description of the key
+ * with \p key identifier. The function does only read accesses to the key
+ * slots. The function does not load any persistent key thus does not access
+ * any storage.
+ *
+ * For volatile key identifiers, only one key slot is queried as a volatile
+ * key with identifier key_id can only be stored in slot of index
+ * ( key_id - #PSA_KEY_ID_VOLATILE_MIN ).
+ *
+ * On success, the function locks the key slot. It is the responsibility of
+ * the caller to unlock the key slot when it does not access it anymore.
+ *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param key           Key identifier to query.
+ * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
+ *                      key slot containing the description of the key
+ *                      identified by \p key.
+ *
+ * \retval #PSA_SUCCESS
+ *         The pointer to the key slot containing the description of the key
+ *         identified by \p key was returned.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p key is not a valid key identifier.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no key with key identifier \p key in the key slots.
+ */
+static psa_status_t psa_get_and_lock_key_slot_in_memory(
+    mbedtls_svc_key_id_t key, psa_key_slot_t **p_slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_id_t key_id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
+    size_t slot_idx;
+    psa_key_slot_t *slot = NULL;
+
+    if (psa_key_id_is_volatile(key_id)) {
+        slot = get_volatile_key_slot(key_id);
+
+        /* Check if both the PSA key identifier key_id and the owner
+         * identifier of key match those of the key slot. */
+        if (slot != NULL &&
+            slot->state == PSA_SLOT_FULL &&
+            mbedtls_svc_key_id_equal(key, slot->attr.id)) {
+            status = PSA_SUCCESS;
+        } else {
+            status = PSA_ERROR_DOES_NOT_EXIST;
+        }
+    } else {
+        if (!psa_is_valid_key_id(key, 1)) {
+            return PSA_ERROR_INVALID_HANDLE;
+        }
+
+        for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
+            slot = get_persistent_key_slot(slot_idx);
+            /* Only consider slots which are in a full state. */
+            if ((slot->state == PSA_SLOT_FULL) &&
+                (mbedtls_svc_key_id_equal(key, slot->attr.id))) {
+                break;
+            }
+        }
+        status = (slot_idx < MBEDTLS_PSA_KEY_SLOT_COUNT) ?
+                 PSA_SUCCESS : PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    if (status == PSA_SUCCESS) {
+        status = psa_register_read(slot);
+        if (status == PSA_SUCCESS) {
+            *p_slot = slot;
+        }
+    }
+
+    return status;
+}
+
+psa_status_t psa_initialize_key_slots(void)
+{
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] =
+        mbedtls_calloc(PERSISTENT_KEY_CACHE_COUNT,
+                       sizeof(*global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX]));
+    if (global_data.key_slices[KEY_SLOT_CACHE_SLICE_INDEX] == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+    /* Nothing to do: program startup and psa_wipe_all_key_slots() both
+     * guarantee that the key slots are initialized to all-zero, which
+     * means that all the key slots are in a valid, empty state. The global
+     * data mutex is already held when calling this function, so no need to
+     * lock it here, to set the flag. */
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+    global_data.key_slots_initialized = 1;
+    return PSA_SUCCESS;
+}
+
+void psa_wipe_all_key_slots(void)
+{
+    for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+        if (global_data.key_slices[slice_idx] == NULL) {
+            continue;
+        }
+#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+        for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
+            psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+            /* When MBEDTLS_PSA_KEY_STORE_DYNAMIC is disabled, calling
+             * psa_wipe_key_slot() on an unused slot is useless, but it
+             * happens to work (because we flip the state to PENDING_DELETION).
+             *
+             * When MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled,
+             * psa_wipe_key_slot() needs to have a valid slice_index
+             * field, but that value might not be correct in a
+             * free slot, so we must not call it.
+             *
+             * Bypass the call to psa_wipe_key_slot() if the slot is empty,
+             * but only if MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, to save
+             * a few bytes of code size otherwise.
+             */
+            if (slot->state == PSA_SLOT_EMPTY) {
+                continue;
+            }
+#endif
+            slot->var.occupied.registered_readers = 1;
+            slot->state = PSA_SLOT_PENDING_DELETION;
+            (void) psa_wipe_key_slot(slot);
+        }
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+        mbedtls_free(global_data.key_slices[slice_idx]);
+        global_data.key_slices[slice_idx] = NULL;
+#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+    }
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    for (size_t slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
+        global_data.first_free_slot_index[slice_idx] = 0;
+    }
+#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+    /* The global data mutex is already held when calling this function. */
+    global_data.key_slots_initialized = 0;
+}
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+
+static psa_status_t psa_allocate_volatile_key_slot(psa_key_id_t *key_id,
+                                                   psa_key_slot_t **p_slot)
+{
+    size_t slice_idx;
+    for (slice_idx = 0; slice_idx < KEY_SLOT_VOLATILE_SLICE_COUNT; slice_idx++) {
+        if (global_data.first_free_slot_index[slice_idx] != FREE_SLOT_INDEX_NONE) {
+            break;
+        }
+    }
+    if (slice_idx == KEY_SLOT_VOLATILE_SLICE_COUNT) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    if (global_data.key_slices[slice_idx] == NULL) {
+        global_data.key_slices[slice_idx] =
+            mbedtls_calloc(key_slice_length(slice_idx),
+                           sizeof(psa_key_slot_t));
+        if (global_data.key_slices[slice_idx] == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+    }
+    psa_key_slot_t *slice = global_data.key_slices[slice_idx];
+
+    size_t slot_idx = global_data.first_free_slot_index[slice_idx];
+    *key_id = volatile_key_id_of_index(slice_idx, slot_idx);
+
+    psa_key_slot_t *slot = &slice[slot_idx];
+    size_t next_free = slot_idx + 1 + slot->var.free.next_free_relative_to_next;
+    if (next_free >= key_slice_length(slice_idx)) {
+        next_free = FREE_SLOT_INDEX_NONE;
+    }
+    global_data.first_free_slot_index[slice_idx] = next_free;
+    /* The .next_free field is not meaningful when the slot is not free,
+     * so give it the same content as freshly initialized memory. */
+    slot->var.free.next_free_relative_to_next = 0;
+
+    psa_status_t status = psa_key_slot_state_transition(slot,
+                                                        PSA_SLOT_EMPTY,
+                                                        PSA_SLOT_FILLING);
+    if (status != PSA_SUCCESS) {
+        /* The only reason for failure is if the slot state was not empty.
+         * This indicates that something has gone horribly wrong.
+         * In this case, we leave the slot out of the free list, and stop
+         * modifying it. This minimizes any further corruption. The slot
+         * is a memory leak, but that's a lesser evil. */
+        return status;
+    }
+
+    *p_slot = slot;
+    /* We assert at compile time that the slice index fits in uint8_t. */
+    slot->slice_index = (uint8_t) slice_idx;
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_free_key_slot(size_t slice_idx,
+                               psa_key_slot_t *slot)
+{
+
+    if (slice_idx == KEY_SLOT_CACHE_SLICE_INDEX) {
+        /* This is a cache entry. We don't maintain a free list, so
+         * there's nothing to do. */
+        return PSA_SUCCESS;
+    }
+    if (slice_idx >= KEY_SLOT_VOLATILE_SLICE_COUNT) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    psa_key_slot_t *slice = global_data.key_slices[slice_idx];
+    psa_key_slot_t *slice_end = slice + key_slice_length(slice_idx);
+    if (slot < slice || slot >= slice_end) {
+        /* The slot isn't actually in the slice! We can't detect that
+         * condition for sure, because the pointer comparison itself is
+         * undefined behavior in that case. That same condition makes the
+         * subtraction to calculate the slot index also UB.
+         * Give up now to avoid causing further corruption.
+         */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+    size_t slot_idx = slot - slice;
+
+    size_t next_free = global_data.first_free_slot_index[slice_idx];
+    if (next_free >= key_slice_length(slice_idx)) {
+        /* The slot was full. The newly freed slot thus becomes the
+         * end of the free list. */
+        next_free = key_slice_length(slice_idx);
+    }
+    global_data.first_free_slot_index[slice_idx] = slot_idx;
+    slot->var.free.next_free_relative_to_next =
+        (int32_t) next_free - (int32_t) slot_idx - 1;
+
+    return PSA_SUCCESS;
+}
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
+                                       psa_key_slot_t **p_slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    size_t slot_idx;
+    psa_key_slot_t *selected_slot, *unused_persistent_key_slot;
+
+    if (!psa_get_key_slots_initialized()) {
+        status = PSA_ERROR_BAD_STATE;
+        goto error;
+    }
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    if (volatile_key_id != NULL) {
+        return psa_allocate_volatile_key_slot(volatile_key_id, p_slot);
+    }
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+    /* With a dynamic key store, allocate an entry in the cache slice,
+     * applicable only to non-volatile keys that get cached in RAM.
+     * With a static key store, allocate an entry in the sole slice,
+     * applicable to all keys. */
+    selected_slot = unused_persistent_key_slot = NULL;
+    for (slot_idx = 0; slot_idx < PERSISTENT_KEY_CACHE_COUNT; slot_idx++) {
+        psa_key_slot_t *slot = get_key_slot(KEY_SLOT_CACHE_SLICE_INDEX, slot_idx);
+        if (slot->state == PSA_SLOT_EMPTY) {
+            selected_slot = slot;
+            break;
+        }
+
+        if ((unused_persistent_key_slot == NULL) &&
+            (slot->state == PSA_SLOT_FULL) &&
+            (!psa_key_slot_has_readers(slot)) &&
+            (!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime))) {
+            unused_persistent_key_slot = slot;
+        }
+    }
+
+    /*
+     * If there is no unused key slot and there is at least one unlocked key
+     * slot containing the description of a persistent key, recycle the first
+     * such key slot we encountered. If we later need to operate on the
+     * persistent key we are evicting now, we will reload its description from
+     * storage.
+     */
+    if ((selected_slot == NULL) &&
+        (unused_persistent_key_slot != NULL)) {
+        selected_slot = unused_persistent_key_slot;
+        psa_register_read(selected_slot);
+        status = psa_wipe_key_slot(selected_slot);
+        if (status != PSA_SUCCESS) {
+            goto error;
+        }
+    }
+
+    if (selected_slot != NULL) {
+        status = psa_key_slot_state_transition(selected_slot, PSA_SLOT_EMPTY,
+                                               PSA_SLOT_FILLING);
+        if (status != PSA_SUCCESS) {
+            goto error;
+        }
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+        selected_slot->slice_index = KEY_SLOT_CACHE_SLICE_INDEX;
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+#if !defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+        if (volatile_key_id != NULL) {
+            /* Refresh slot_idx, for when the slot is not the original
+             * selected_slot but rather unused_persistent_key_slot.  */
+            slot_idx = selected_slot - global_data.key_slots;
+            *volatile_key_id = PSA_KEY_ID_VOLATILE_MIN + slot_idx;
+        }
+#endif
+        *p_slot = selected_slot;
+
+        return PSA_SUCCESS;
+    }
+    status = PSA_ERROR_INSUFFICIENT_MEMORY;
+
+error:
+    *p_slot = NULL;
+
+    return status;
+}
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+static psa_status_t psa_load_persistent_key_into_slot(psa_key_slot_t *slot)
+{
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t *key_data = NULL;
+    size_t key_data_length = 0;
+
+    status = psa_load_persistent_key(&slot->attr,
+                                     &key_data, &key_data_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+    /* Special handling is required for loading keys associated with a
+     * dynamically registered SE interface. */
+    const psa_drv_se_t *drv;
+    psa_drv_se_context_t *drv_context;
+    if (psa_get_se_driver(slot->attr.lifetime, &drv, &drv_context)) {
+        psa_se_key_data_storage_t *data;
+
+        if (key_data_length != sizeof(*data)) {
+            status = PSA_ERROR_DATA_INVALID;
+            goto exit;
+        }
+        data = (psa_se_key_data_storage_t *) key_data;
+        status = psa_copy_key_material_into_slot(
+            slot, data->slot_number, sizeof(data->slot_number));
+        goto exit;
+    }
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+    status = psa_copy_key_material_into_slot(slot, key_data, key_data_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+exit:
+    psa_free_persistent_key_data(key_data, key_data_length);
+    return status;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+
+static psa_status_t psa_load_builtin_key_into_slot(psa_key_slot_t *slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
+    psa_drv_slot_number_t slot_number = 0;
+    size_t key_buffer_size = 0;
+    size_t key_buffer_length = 0;
+
+    if (!psa_key_id_is_builtin(
+            MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id))) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    /* Check the platform function to see whether this key actually exists */
+    status = mbedtls_psa_platform_get_builtin_key(
+        slot->attr.id, &lifetime, &slot_number);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Set required key attributes to ensure get_builtin_key can retrieve the
+     * full attributes. */
+    psa_set_key_id(&attributes, slot->attr.id);
+    psa_set_key_lifetime(&attributes, lifetime);
+
+    /* Get the full key attributes from the driver in order to be able to
+     * calculate the required buffer size. */
+    status = psa_driver_wrapper_get_builtin_key(
+        slot_number, &attributes,
+        NULL, 0, NULL);
+    if (status != PSA_ERROR_BUFFER_TOO_SMALL) {
+        /* Builtin keys cannot be defined by the attributes alone */
+        if (status == PSA_SUCCESS) {
+            status = PSA_ERROR_CORRUPTION_DETECTED;
+        }
+        return status;
+    }
+
+    /* If the key should exist according to the platform, then ask the driver
+     * what its expected size is. */
+    status = psa_driver_wrapper_get_key_buffer_size(&attributes,
+                                                    &key_buffer_size);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    /* Allocate a buffer of the required size and load the builtin key directly
+     * into the (now properly sized) slot buffer. */
+    status = psa_allocate_buffer_to_slot(slot, key_buffer_size);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_driver_wrapper_get_builtin_key(
+        slot_number, &attributes,
+        slot->key.data, slot->key.bytes, &key_buffer_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    /* Copy actual key length and core attributes into the slot on success */
+    slot->key.bytes = key_buffer_length;
+    slot->attr = attributes;
+exit:
+    if (status != PSA_SUCCESS) {
+        psa_remove_key_data_from_memory(slot);
+    }
+    return status;
+}
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
+                                       psa_key_slot_t **p_slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    *p_slot = NULL;
+    if (!psa_get_key_slots_initialized()) {
+        return PSA_ERROR_BAD_STATE;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    /* If the key is persistent and not loaded, we cannot unlock the mutex
+     * between checking if the key is loaded and setting the slot as FULL,
+     * as otherwise another thread may load and then destroy the key
+     * in the meantime. */
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    /*
+     * On success, the pointer to the slot is passed directly to the caller
+     * thus no need to unlock the key slot here.
+     */
+    status = psa_get_and_lock_key_slot_in_memory(key, p_slot);
+    if (status != PSA_ERROR_DOES_NOT_EXIST) {
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
+        return status;
+    }
+
+    /* Loading keys from storage requires support for such a mechanism */
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+
+    status = psa_reserve_free_key_slot(NULL, p_slot);
+    if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
+        return status;
+    }
+
+    (*p_slot)->attr.id = key;
+    (*p_slot)->attr.lifetime = PSA_KEY_LIFETIME_PERSISTENT;
+
+    status = PSA_ERROR_DOES_NOT_EXIST;
+#if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+    /* Load keys in the 'builtin' range through their own interface */
+    status = psa_load_builtin_key_into_slot(*p_slot);
+#endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+    if (status == PSA_ERROR_DOES_NOT_EXIST) {
+        status = psa_load_persistent_key_into_slot(*p_slot);
+    }
+#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */
+
+    if (status != PSA_SUCCESS) {
+        psa_wipe_key_slot(*p_slot);
+
+        /* If the key does not exist, we need to return
+         * PSA_ERROR_INVALID_HANDLE. */
+        if (status == PSA_ERROR_DOES_NOT_EXIST) {
+            status = PSA_ERROR_INVALID_HANDLE;
+        }
+    } else {
+        /* Add implicit usage flags. */
+        psa_extend_key_usage_flags(&(*p_slot)->attr.policy.usage);
+
+        psa_key_slot_state_transition((*p_slot), PSA_SLOT_FILLING,
+                                      PSA_SLOT_FULL);
+        status = psa_register_read(*p_slot);
+    }
+
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+    status = PSA_ERROR_INVALID_HANDLE;
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+
+    if (status != PSA_SUCCESS) {
+        *p_slot = NULL;
+    }
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    return status;
+}
+
+psa_status_t psa_unregister_read(psa_key_slot_t *slot)
+{
+    if (slot == NULL) {
+        return PSA_SUCCESS;
+    }
+    if ((slot->state != PSA_SLOT_FULL) &&
+        (slot->state != PSA_SLOT_PENDING_DELETION)) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+
+    /* If we are the last reader and the slot is marked for deletion,
+     * we must wipe the slot here. */
+    if ((slot->state == PSA_SLOT_PENDING_DELETION) &&
+        (slot->var.occupied.registered_readers == 1)) {
+        return psa_wipe_key_slot(slot);
+    }
+
+    if (psa_key_slot_has_readers(slot)) {
+        slot->var.occupied.registered_readers--;
+        return PSA_SUCCESS;
+    }
+
+    /*
+     * As the return error code may not be handled in case of multiple errors,
+     * do our best to report if there are no registered readers. Assert with
+     * MBEDTLS_TEST_HOOK_TEST_ASSERT that there are registered readers:
+     * if the MBEDTLS_TEST_HOOKS configuration option is enabled and
+     * the function is called as part of the execution of a test suite, the
+     * execution of the test suite is stopped in error if the assertion fails.
+     */
+    MBEDTLS_TEST_HOOK_TEST_ASSERT(psa_key_slot_has_readers(slot));
+    return PSA_ERROR_CORRUPTION_DETECTED;
+}
+
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    status = psa_unregister_read(slot);
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    return status;
+}
+
+psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
+                                       psa_se_drv_table_entry_t **p_drv)
+{
+    if (psa_key_lifetime_is_external(lifetime)) {
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+        /* Check whether a driver is registered against this lifetime */
+        psa_se_drv_table_entry_t *driver = psa_get_se_driver_entry(lifetime);
+        if (driver != NULL) {
+            if (p_drv != NULL) {
+                *p_drv = driver;
+            }
+            return PSA_SUCCESS;
+        }
+#else /* MBEDTLS_PSA_CRYPTO_SE_C */
+        (void) p_drv;
+#endif /* MBEDTLS_PSA_CRYPTO_SE_C */
+
+        /* Key location for external keys gets checked by the wrapper */
+        return PSA_SUCCESS;
+    } else {
+        /* Local/internal keys are always valid */
+        return PSA_SUCCESS;
+    }
+}
+
+psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime)
+{
+    if (PSA_KEY_LIFETIME_IS_VOLATILE(lifetime)) {
+        /* Volatile keys are always supported */
+        return PSA_SUCCESS;
+    } else {
+        /* Persistent keys require storage support */
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+        if (PSA_KEY_LIFETIME_IS_READ_ONLY(lifetime)) {
+            return PSA_ERROR_INVALID_ARGUMENT;
+        } else {
+            return PSA_SUCCESS;
+        }
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
+        return PSA_ERROR_NOT_SUPPORTED;
+#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */
+    }
+}
+
+psa_status_t psa_open_key(mbedtls_svc_key_id_t key, psa_key_handle_t *handle)
+{
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) || \
+    defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
+    psa_status_t status;
+    psa_key_slot_t *slot;
+
+    status = psa_get_and_lock_key_slot(key, &slot);
+    if (status != PSA_SUCCESS) {
+        *handle = PSA_KEY_HANDLE_INIT;
+        if (status == PSA_ERROR_INVALID_HANDLE) {
+            status = PSA_ERROR_DOES_NOT_EXIST;
+        }
+
+        return status;
+    }
+
+    *handle = key;
+
+    return psa_unregister_read_under_mutex(slot);
+
+#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+    (void) key;
+    *handle = PSA_KEY_HANDLE_INIT;
+    return PSA_ERROR_NOT_SUPPORTED;
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C || MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
+}
+
+psa_status_t psa_close_key(psa_key_handle_t handle)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+    if (psa_key_handle_is_null(handle)) {
+        return PSA_SUCCESS;
+    }
+
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    status = psa_get_and_lock_key_slot_in_memory(handle, &slot);
+    if (status != PSA_SUCCESS) {
+        if (status == PSA_ERROR_DOES_NOT_EXIST) {
+            status = PSA_ERROR_INVALID_HANDLE;
+        }
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
+        return status;
+    }
+
+    if (slot->var.occupied.registered_readers == 1) {
+        status = psa_wipe_key_slot(slot);
+    } else {
+        status = psa_unregister_read(slot);
+    }
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+
+    return status;
+}
+
+psa_status_t psa_purge_key(mbedtls_svc_key_id_t key)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_key_slot_t *slot;
+
+#if defined(MBEDTLS_THREADING_C)
+    /* We need to set status as success, otherwise CORRUPTION_DETECTED
+     * would be returned if the lock fails. */
+    status = PSA_SUCCESS;
+    PSA_THREADING_CHK_RET(mbedtls_mutex_lock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+    status = psa_get_and_lock_key_slot_in_memory(key, &slot);
+    if (status != PSA_SUCCESS) {
+#if defined(MBEDTLS_THREADING_C)
+        PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                                  &mbedtls_threading_key_slot_mutex));
+#endif
+        return status;
+    }
+
+    if ((!PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) &&
+        (slot->var.occupied.registered_readers == 1)) {
+        status = psa_wipe_key_slot(slot);
+    } else {
+        status = psa_unregister_read(slot);
+    }
+#if defined(MBEDTLS_THREADING_C)
+    PSA_THREADING_CHK_RET(mbedtls_mutex_unlock(
+                              &mbedtls_threading_key_slot_mutex));
+#endif
+
+    return status;
+}
+
+void mbedtls_psa_get_stats(mbedtls_psa_stats_t *stats)
+{
+    memset(stats, 0, sizeof(*stats));
+
+    for (size_t slice_idx = 0; slice_idx < KEY_SLICE_COUNT; slice_idx++) {
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+        if (global_data.key_slices[slice_idx] == NULL) {
+            continue;
+        }
+#endif  /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+        for (size_t slot_idx = 0; slot_idx < key_slice_length(slice_idx); slot_idx++) {
+            const psa_key_slot_t *slot = get_key_slot(slice_idx, slot_idx);
+            if (slot->state == PSA_SLOT_EMPTY) {
+                ++stats->empty_slots;
+                continue;
+            }
+            if (psa_key_slot_has_readers(slot)) {
+                ++stats->locked_slots;
+            }
+            if (PSA_KEY_LIFETIME_IS_VOLATILE(slot->attr.lifetime)) {
+                ++stats->volatile_slots;
+            } else {
+                psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
+                ++stats->persistent_slots;
+                if (id > stats->max_open_internal_key_id) {
+                    stats->max_open_internal_key_id = id;
+                }
+            }
+            if (PSA_KEY_LIFETIME_GET_LOCATION(slot->attr.lifetime) !=
+                PSA_KEY_LOCATION_LOCAL_STORAGE) {
+                psa_key_id_t id = MBEDTLS_SVC_KEY_ID_GET_KEY_ID(slot->attr.id);
+                ++stats->external_slots;
+                if (id > stats->max_open_external_key_id) {
+                    stats->max_open_external_key_id = id;
+                }
+            }
+        }
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.h b/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.h
new file mode 100644
index 0000000000000000000000000000000000000000..af1208e3ae49470d1331059d66b0d60ad5090560
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_slot_management.h
@@ -0,0 +1,344 @@
+/*
+ *  PSA crypto layer on top of Mbed TLS crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H
+#define PSA_CRYPTO_SLOT_MANAGEMENT_H
+
+#include "psa/crypto.h"
+#include "psa_crypto_core.h"
+#include "psa_crypto_se.h"
+
+/** Range of volatile key identifiers.
+ *
+ *  The first #MBEDTLS_PSA_KEY_SLOT_COUNT identifiers of the implementation
+ *  range of key identifiers are reserved for volatile key identifiers.
+ *
+ *  If \c id is a a volatile key identifier, #PSA_KEY_ID_VOLATILE_MIN - \c id
+ *  indicates the key slot containing the volatile key definition. See
+ *  psa_crypto_slot_management.c for details.
+ */
+
+/** The minimum value for a volatile key identifier.
+ */
+#define PSA_KEY_ID_VOLATILE_MIN  PSA_KEY_ID_VENDOR_MIN
+
+/** The maximum value for a volatile key identifier.
+ */
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+#define PSA_KEY_ID_VOLATILE_MAX (MBEDTLS_PSA_KEY_ID_BUILTIN_MIN - 1)
+#else /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+#define PSA_KEY_ID_VOLATILE_MAX                                 \
+    (PSA_KEY_ID_VOLATILE_MIN + MBEDTLS_PSA_KEY_SLOT_COUNT - 1)
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+/** Test whether a key identifier is a volatile key identifier.
+ *
+ * \param key_id  Key identifier to test.
+ *
+ * \retval 1
+ *         The key identifier is a volatile key identifier.
+ * \retval 0
+ *         The key identifier is not a volatile key identifier.
+ */
+static inline int psa_key_id_is_volatile(psa_key_id_t key_id)
+{
+    return (key_id >= PSA_KEY_ID_VOLATILE_MIN) &&
+           (key_id <= PSA_KEY_ID_VOLATILE_MAX);
+}
+
+/** Get the description of a key given its identifier and lock it.
+ *
+ * The descriptions of volatile keys and loaded persistent keys are stored in
+ * key slots. This function returns a pointer to the key slot containing the
+ * description of a key given its identifier.
+ *
+ * In case of a persistent key, the function loads the description of the key
+ * into a key slot if not already done.
+ *
+ * On success, the returned key slot has been registered for reading.
+ * It is the responsibility of the caller to call psa_unregister_read(slot)
+ * when they have finished reading the contents of the slot.
+ *
+ * On failure, `*p_slot` is set to NULL. This ensures that it is always valid
+ * to call psa_unregister_read on the returned slot.
+ *
+ * \param key           Key identifier to query.
+ * \param[out] p_slot   On success, `*p_slot` contains a pointer to the
+ *                      key slot containing the description of the key
+ *                      identified by \p key.
+ *
+ * \retval #PSA_SUCCESS
+ *         \p *p_slot contains a pointer to the key slot containing the
+ *         description of the key identified by \p key.
+ *         The key slot counter has been incremented.
+ * \retval #PSA_ERROR_BAD_STATE
+ *         The library has not been initialized.
+ * \retval #PSA_ERROR_INVALID_HANDLE
+ *         \p key is not a valid key identifier.
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         \p key is a persistent key identifier. The implementation does not
+ *         have sufficient resources to load the persistent key. This can be
+ *         due to a lack of empty key slot, or available memory.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no key with key identifier \p key.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ */
+psa_status_t psa_get_and_lock_key_slot(mbedtls_svc_key_id_t key,
+                                       psa_key_slot_t **p_slot);
+
+/** Initialize the key slot structures.
+ *
+ * \retval #PSA_SUCCESS
+ *         Currently this function always succeeds.
+ */
+psa_status_t psa_initialize_key_slots(void);
+
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+/* Allow test code to customize the key slice length. We use this in tests
+ * that exhaust the key store to reach a full key store in reasonable time
+ * and memory.
+ *
+ * The length of each slice must be between 1 and
+ * (1 << KEY_ID_SLOT_INDEX_WIDTH) inclusive.
+ *
+ * The length for a given slice index must not change while
+ * the key store is initialized.
+ */
+extern size_t (*mbedtls_test_hook_psa_volatile_key_slice_length)(
+    size_t slice_idx);
+
+/* The number of volatile key slices. */
+size_t psa_key_slot_volatile_slice_count(void);
+#endif
+
+/** Delete all data from key slots in memory.
+ * This function is not thread safe, it wipes every key slot regardless of
+ * state and reader count. It should only be called when no slot is in use.
+ *
+ * This does not affect persistent storage. */
+void psa_wipe_all_key_slots(void);
+
+/** Find a free key slot and reserve it to be filled with a key.
+ *
+ * This function finds a key slot that is free,
+ * sets its state to PSA_SLOT_FILLING and then returns the slot.
+ *
+ * On success, the key slot's state is PSA_SLOT_FILLING.
+ * It is the responsibility of the caller to change the slot's state to
+ * PSA_SLOT_EMPTY/FULL once key creation has finished.
+ *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param[out] volatile_key_id   - If null, reserve a cache slot for
+ *                                 a persistent or built-in key.
+ *                               - If non-null, allocate a slot for
+ *                                 a volatile key. On success,
+ *                                 \p *volatile_key_id is the
+ *                                 identifier corresponding to the
+ *                                 returned slot. It is the caller's
+ *                                 responsibility to set this key identifier
+ *                                 in the attributes.
+ * \param[out] p_slot            On success, a pointer to the slot.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY
+ *         There were no free key slots.
+ *         When #MBEDTLS_PSA_KEY_STORE_DYNAMIC is enabled, there was not
+ *         enough memory to allocate more slots.
+ * \retval #PSA_ERROR_BAD_STATE \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *         This function attempted to operate on a key slot which was in an
+ *         unexpected state.
+ */
+psa_status_t psa_reserve_free_key_slot(psa_key_id_t *volatile_key_id,
+                                       psa_key_slot_t **p_slot);
+
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+/** Return a key slot to the free list.
+ *
+ * Call this function when a slot obtained from psa_reserve_free_key_slot()
+ * is no longer in use.
+ *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param slice_idx             The slice containing the slot.
+ *                              This is `slot->slice_index` when the slot
+ *                              is obtained from psa_reserve_free_key_slot().
+ * \param slot                  The key slot.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *         This function attempted to operate on a key slot which was in an
+ *         unexpected state.
+ */
+psa_status_t psa_free_key_slot(size_t slice_idx,
+                               psa_key_slot_t *slot);
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+
+/** Change the state of a key slot.
+ *
+ * This function changes the state of the key slot from expected_state to
+ * new state. If the state of the slot was not expected_state, the state is
+ * unchanged.
+ *
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param[in] slot            The key slot.
+ * \param[in] expected_state  The current state of the slot.
+ * \param[in] new_state       The new state of the slot.
+ *
+ * \retval #PSA_SUCCESS
+               The key slot's state variable is new_state.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The slot's state was not expected_state.
+ */
+static inline psa_status_t psa_key_slot_state_transition(
+    psa_key_slot_t *slot, psa_key_slot_state_t expected_state,
+    psa_key_slot_state_t new_state)
+{
+    if (slot->state != expected_state) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+    slot->state = new_state;
+    return PSA_SUCCESS;
+}
+
+/** Register as a reader of a key slot.
+ *
+ * This function increments the key slot registered reader counter by one.
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \param[in] slot  The key slot.
+ *
+ * \retval #PSA_SUCCESS
+               The key slot registered reader counter was incremented.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The reader counter already reached its maximum value and was not
+ *             increased, or the slot's state was not PSA_SLOT_FULL.
+ */
+static inline psa_status_t psa_register_read(psa_key_slot_t *slot)
+{
+    if ((slot->state != PSA_SLOT_FULL) ||
+        (slot->var.occupied.registered_readers >= SIZE_MAX)) {
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    }
+    slot->var.occupied.registered_readers++;
+
+    return PSA_SUCCESS;
+}
+
+/** Unregister from reading a key slot.
+ *
+ * This function decrements the key slot registered reader counter by one.
+ * If the state of the slot is PSA_SLOT_PENDING_DELETION,
+ * and there is only one registered reader (the caller),
+ * this function will call psa_wipe_key_slot().
+ * If multi-threading is enabled, the caller must hold the
+ * global key slot mutex.
+ *
+ * \note To ease the handling of errors in retrieving a key slot
+ *       a NULL input pointer is valid, and the function returns
+ *       successfully without doing anything in that case.
+ *
+ * \param[in] slot  The key slot.
+ * \retval #PSA_SUCCESS
+ *             \p slot is NULL or the key slot reader counter has been
+ *             decremented (and potentially wiped) successfully.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The slot's state was neither PSA_SLOT_FULL nor
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or a wipe was attempted and the slot's state was not
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or registered_readers was equal to 0.
+ */
+psa_status_t psa_unregister_read(psa_key_slot_t *slot);
+
+/** Wrap a call to psa_unregister_read in the global key slot mutex.
+ *
+ * If threading is disabled, this simply calls psa_unregister_read.
+ *
+ * \note To ease the handling of errors in retrieving a key slot
+ *       a NULL input pointer is valid, and the function returns
+ *       successfully without doing anything in that case.
+ *
+ * \param[in] slot  The key slot.
+ * \retval #PSA_SUCCESS
+ *             \p slot is NULL or the key slot reader counter has been
+ *             decremented (and potentially wiped) successfully.
+ * \retval #PSA_ERROR_CORRUPTION_DETECTED
+ *             The slot's state was neither PSA_SLOT_FULL nor
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or a wipe was attempted and the slot's state was not
+ *             PSA_SLOT_PENDING_DELETION.
+ *             Or registered_readers was equal to 0.
+ */
+psa_status_t psa_unregister_read_under_mutex(psa_key_slot_t *slot);
+
+/** Test whether a lifetime designates a key in an external cryptoprocessor.
+ *
+ * \param lifetime      The lifetime to test.
+ *
+ * \retval 1
+ *         The lifetime designates an external key. There should be a
+ *         registered driver for this lifetime, otherwise the key cannot
+ *         be created or manipulated.
+ * \retval 0
+ *         The lifetime designates a key that is volatile or in internal
+ *         storage.
+ */
+static inline int psa_key_lifetime_is_external(psa_key_lifetime_t lifetime)
+{
+    return PSA_KEY_LIFETIME_GET_LOCATION(lifetime)
+           != PSA_KEY_LOCATION_LOCAL_STORAGE;
+}
+
+/** Validate a key's location.
+ *
+ * This function checks whether the key's attributes point to a location that
+ * is known to the PSA Core, and returns the driver function table if the key
+ * is to be found in an external location.
+ *
+ * \param[in] lifetime      The key lifetime attribute.
+ * \param[out] p_drv        On success, when a key is located in external
+ *                          storage, returns a pointer to the driver table
+ *                          associated with the key's storage location.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ */
+psa_status_t psa_validate_key_location(psa_key_lifetime_t lifetime,
+                                       psa_se_drv_table_entry_t **p_drv);
+
+/** Validate the persistence of a key.
+ *
+ * \param[in] lifetime  The key lifetime attribute.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_NOT_SUPPORTED The key is persistent but persistent keys
+ *             are not supported.
+ */
+psa_status_t psa_validate_key_persistence(psa_key_lifetime_t lifetime);
+
+/** Validate a key identifier.
+ *
+ * \param[in] key           The key identifier.
+ * \param[in] vendor_ok     Non-zero to indicate that key identifiers in the
+ *                          vendor range are allowed, volatile key identifiers
+ *                          excepted \c 0 otherwise.
+ *
+ * \retval <> 0 if the key identifier is valid, 0 otherwise.
+ */
+int psa_is_valid_key_id(mbedtls_svc_key_id_t key, int vendor_ok);
+
+#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_storage.c b/lib/libmbedtls/mbedtls/library/psa_crypto_storage.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d1317b45a11d106272dd1a861cf0a4aea9095b6
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_storage.c
@@ -0,0 +1,481 @@
+/*
+ *  PSA persistent key storage
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "psa/crypto.h"
+#include "psa_crypto_storage.h"
+#include "mbedtls/platform_util.h"
+
+#if defined(MBEDTLS_PSA_ITS_FILE_C)
+#include "psa_crypto_its.h"
+#else /* Native ITS implementation */
+#include "psa/error.h"
+#include "psa/internal_trusted_storage.h"
+#endif
+
+#include "mbedtls/platform.h"
+
+
+
+/****************************************************************/
+/* Key storage */
+/****************************************************************/
+
+/* Determine a file name (ITS file identifier) for the given key identifier.
+ * The file name must be distinct from any file that is used for a purpose
+ * other than storing a key. Currently, the only such file is the random seed
+ * file whose name is PSA_CRYPTO_ITS_RANDOM_SEED_UID and whose value is
+ * 0xFFFFFF52. */
+static psa_storage_uid_t psa_its_identifier_of_slot(mbedtls_svc_key_id_t key)
+{
+#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
+    /* Encode the owner in the upper 32 bits. This means that if
+     * owner values are nonzero (as they are on a PSA platform),
+     * no key file will ever have a value less than 0x100000000, so
+     * the whole range 0..0xffffffff is available for non-key files. */
+    uint32_t unsigned_owner_id = MBEDTLS_SVC_KEY_ID_GET_OWNER_ID(key);
+    return ((uint64_t) unsigned_owner_id << 32) |
+           MBEDTLS_SVC_KEY_ID_GET_KEY_ID(key);
+#else
+    /* Use the key id directly as a file name.
+     * psa_is_key_id_valid() in psa_crypto_slot_management.c
+     * is responsible for ensuring that key identifiers do not have a
+     * value that is reserved for non-key files. */
+    return key;
+#endif
+}
+
+/**
+ * \brief Load persistent data for the given key slot number.
+ *
+ * This function reads data from a storage backend and returns the data in a
+ * buffer.
+ *
+ * \param key               Persistent identifier of the key to be loaded. This
+ *                          should be an occupied storage location.
+ * \param[out] data         Buffer where the data is to be written.
+ * \param data_size         Size of the \c data buffer in bytes.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
+ */
+static psa_status_t psa_crypto_storage_load(
+    const mbedtls_svc_key_id_t key, uint8_t *data, size_t data_size)
+{
+    psa_status_t status;
+    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
+    struct psa_storage_info_t data_identifier_info;
+    size_t data_length = 0;
+
+    status = psa_its_get_info(data_identifier, &data_identifier_info);
+    if (status  != PSA_SUCCESS) {
+        return status;
+    }
+
+    status = psa_its_get(data_identifier, 0, (uint32_t) data_size, data, &data_length);
+    if (data_size  != data_length) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    return status;
+}
+
+int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key)
+{
+    psa_status_t ret;
+    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
+    struct psa_storage_info_t data_identifier_info;
+
+    ret = psa_its_get_info(data_identifier, &data_identifier_info);
+
+    if (ret == PSA_ERROR_DOES_NOT_EXIST) {
+        return 0;
+    }
+    return 1;
+}
+
+/**
+ * \brief Store persistent data for the given key slot number.
+ *
+ * This function stores the given data buffer to a persistent storage.
+ *
+ * \param key           Persistent identifier of the key to be stored. This
+ *                      should be an unoccupied storage location.
+ * \param[in] data      Buffer containing the data to be stored.
+ * \param data_length   The number of bytes
+ *                      that make up the data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ */
+static psa_status_t psa_crypto_storage_store(const mbedtls_svc_key_id_t key,
+                                             const uint8_t *data,
+                                             size_t data_length)
+{
+    psa_status_t status;
+    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
+    struct psa_storage_info_t data_identifier_info;
+
+    if (psa_is_key_present_in_storage(key) == 1) {
+        return PSA_ERROR_ALREADY_EXISTS;
+    }
+
+    status = psa_its_set(data_identifier, (uint32_t) data_length, data, 0);
+    if (status != PSA_SUCCESS) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    status = psa_its_get_info(data_identifier, &data_identifier_info);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    if (data_identifier_info.size != data_length) {
+        status = PSA_ERROR_DATA_INVALID;
+        goto exit;
+    }
+
+exit:
+    if (status != PSA_SUCCESS) {
+        /* Remove the file in case we managed to create it but something
+         * went wrong. It's ok if the file doesn't exist. If the file exists
+         * but the removal fails, we're already reporting an error so there's
+         * nothing else we can do. */
+        (void) psa_its_remove(data_identifier);
+    }
+    return status;
+}
+
+psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key)
+{
+    psa_status_t ret;
+    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
+    struct psa_storage_info_t data_identifier_info;
+
+    ret = psa_its_get_info(data_identifier, &data_identifier_info);
+    if (ret == PSA_ERROR_DOES_NOT_EXIST) {
+        return PSA_SUCCESS;
+    }
+
+    if (psa_its_remove(data_identifier) != PSA_SUCCESS) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    ret = psa_its_get_info(data_identifier, &data_identifier_info);
+    if (ret != PSA_ERROR_DOES_NOT_EXIST) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    return PSA_SUCCESS;
+}
+
+/**
+ * \brief Get data length for given key slot number.
+ *
+ * \param key               Persistent identifier whose stored data length
+ *                          is to be obtained.
+ * \param[out] data_length  The number of bytes that make up the data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ */
+static psa_status_t psa_crypto_storage_get_data_length(
+    const mbedtls_svc_key_id_t key,
+    size_t *data_length)
+{
+    psa_status_t status;
+    psa_storage_uid_t data_identifier = psa_its_identifier_of_slot(key);
+    struct psa_storage_info_t data_identifier_info;
+
+    status = psa_its_get_info(data_identifier, &data_identifier_info);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    *data_length = (size_t) data_identifier_info.size;
+
+    return PSA_SUCCESS;
+}
+
+/**
+ * Persistent key storage magic header.
+ */
+#define PSA_KEY_STORAGE_MAGIC_HEADER "PSA\0KEY"
+#define PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH (sizeof(PSA_KEY_STORAGE_MAGIC_HEADER))
+
+typedef struct {
+    uint8_t magic[PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH];
+    uint8_t version[4];
+    uint8_t lifetime[sizeof(psa_key_lifetime_t)];
+    uint8_t type[2];
+    uint8_t bits[2];
+    uint8_t policy[sizeof(psa_key_policy_t)];
+    uint8_t data_len[4];
+    uint8_t key_data[];
+} psa_persistent_key_storage_format;
+
+void psa_format_key_data_for_storage(const uint8_t *data,
+                                     const size_t data_length,
+                                     const psa_key_attributes_t *attr,
+                                     uint8_t *storage_data)
+{
+    psa_persistent_key_storage_format *storage_format =
+        (psa_persistent_key_storage_format *) storage_data;
+
+    memcpy(storage_format->magic, PSA_KEY_STORAGE_MAGIC_HEADER,
+           PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH);
+    MBEDTLS_PUT_UINT32_LE(0, storage_format->version, 0);
+    MBEDTLS_PUT_UINT32_LE(attr->lifetime, storage_format->lifetime, 0);
+    MBEDTLS_PUT_UINT16_LE((uint16_t) attr->type, storage_format->type, 0);
+    MBEDTLS_PUT_UINT16_LE((uint16_t) attr->bits, storage_format->bits, 0);
+    MBEDTLS_PUT_UINT32_LE(attr->policy.usage, storage_format->policy, 0);
+    MBEDTLS_PUT_UINT32_LE(attr->policy.alg, storage_format->policy, sizeof(uint32_t));
+    MBEDTLS_PUT_UINT32_LE(attr->policy.alg2, storage_format->policy, 2 * sizeof(uint32_t));
+    MBEDTLS_PUT_UINT32_LE(data_length, storage_format->data_len, 0);
+    memcpy(storage_format->key_data, data, data_length);
+}
+
+static psa_status_t check_magic_header(const uint8_t *data)
+{
+    if (memcmp(data, PSA_KEY_STORAGE_MAGIC_HEADER,
+               PSA_KEY_STORAGE_MAGIC_HEADER_LENGTH) != 0) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,
+                                             size_t storage_data_length,
+                                             uint8_t **key_data,
+                                             size_t *key_data_length,
+                                             psa_key_attributes_t *attr)
+{
+    psa_status_t status;
+    const psa_persistent_key_storage_format *storage_format =
+        (const psa_persistent_key_storage_format *) storage_data;
+    uint32_t version;
+
+    if (storage_data_length < sizeof(*storage_format)) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    status = check_magic_header(storage_data);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    version = MBEDTLS_GET_UINT32_LE(storage_format->version, 0);
+    if (version != 0) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    *key_data_length = MBEDTLS_GET_UINT32_LE(storage_format->data_len, 0);
+    if (*key_data_length > (storage_data_length - sizeof(*storage_format)) ||
+        *key_data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+
+    if (*key_data_length == 0) {
+        *key_data = NULL;
+    } else {
+        *key_data = mbedtls_calloc(1, *key_data_length);
+        if (*key_data == NULL) {
+            return PSA_ERROR_INSUFFICIENT_MEMORY;
+        }
+        memcpy(*key_data, storage_format->key_data, *key_data_length);
+    }
+
+    attr->lifetime = MBEDTLS_GET_UINT32_LE(storage_format->lifetime, 0);
+    attr->type = MBEDTLS_GET_UINT16_LE(storage_format->type, 0);
+    attr->bits = MBEDTLS_GET_UINT16_LE(storage_format->bits, 0);
+    attr->policy.usage = MBEDTLS_GET_UINT32_LE(storage_format->policy, 0);
+    attr->policy.alg = MBEDTLS_GET_UINT32_LE(storage_format->policy, sizeof(uint32_t));
+    attr->policy.alg2 = MBEDTLS_GET_UINT32_LE(storage_format->policy, 2 * sizeof(uint32_t));
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
+                                     const uint8_t *data,
+                                     const size_t data_length)
+{
+    size_t storage_data_length;
+    uint8_t *storage_data;
+    psa_status_t status;
+
+    /* All keys saved to persistent storage always have a key context */
+    if (data == NULL || data_length == 0) {
+        return PSA_ERROR_INVALID_ARGUMENT;
+    }
+
+    if (data_length > PSA_CRYPTO_MAX_STORAGE_SIZE) {
+        return PSA_ERROR_INSUFFICIENT_STORAGE;
+    }
+    storage_data_length = data_length + sizeof(psa_persistent_key_storage_format);
+
+    storage_data = mbedtls_calloc(1, storage_data_length);
+    if (storage_data == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    psa_format_key_data_for_storage(data, data_length, attr, storage_data);
+
+    status = psa_crypto_storage_store(attr->id,
+                                      storage_data, storage_data_length);
+
+    mbedtls_zeroize_and_free(storage_data, storage_data_length);
+
+    return status;
+}
+
+void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length)
+{
+    mbedtls_zeroize_and_free(key_data, key_data_length);
+}
+
+psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
+                                     uint8_t **data,
+                                     size_t *data_length)
+{
+    psa_status_t status = PSA_SUCCESS;
+    uint8_t *loaded_data;
+    size_t storage_data_length = 0;
+    mbedtls_svc_key_id_t key = attr->id;
+
+    status = psa_crypto_storage_get_data_length(key, &storage_data_length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+
+    loaded_data = mbedtls_calloc(1, storage_data_length);
+
+    if (loaded_data == NULL) {
+        return PSA_ERROR_INSUFFICIENT_MEMORY;
+    }
+
+    status = psa_crypto_storage_load(key, loaded_data, storage_data_length);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+
+    status = psa_parse_key_data_from_storage(loaded_data, storage_data_length,
+                                             data, data_length, attr);
+
+    /* All keys saved to persistent storage always have a key context */
+    if (status == PSA_SUCCESS &&
+        (*data == NULL || *data_length == 0)) {
+        status = PSA_ERROR_STORAGE_FAILURE;
+    }
+
+exit:
+    mbedtls_zeroize_and_free(loaded_data, storage_data_length);
+    return status;
+}
+
+
+
+/****************************************************************/
+/* Transactions */
+/****************************************************************/
+
+#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
+
+psa_crypto_transaction_t psa_crypto_transaction;
+
+psa_status_t psa_crypto_save_transaction(void)
+{
+    struct psa_storage_info_t p_info;
+    psa_status_t status;
+    status = psa_its_get_info(PSA_CRYPTO_ITS_TRANSACTION_UID, &p_info);
+    if (status == PSA_SUCCESS) {
+        /* This shouldn't happen: we're trying to start a transaction while
+         * there is still a transaction that hasn't been replayed. */
+        return PSA_ERROR_CORRUPTION_DETECTED;
+    } else if (status != PSA_ERROR_DOES_NOT_EXIST) {
+        return status;
+    }
+    return psa_its_set(PSA_CRYPTO_ITS_TRANSACTION_UID,
+                       sizeof(psa_crypto_transaction),
+                       &psa_crypto_transaction,
+                       0);
+}
+
+psa_status_t psa_crypto_load_transaction(void)
+{
+    psa_status_t status;
+    size_t length;
+    status = psa_its_get(PSA_CRYPTO_ITS_TRANSACTION_UID, 0,
+                         sizeof(psa_crypto_transaction),
+                         &psa_crypto_transaction, &length);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
+    if (length != sizeof(psa_crypto_transaction)) {
+        return PSA_ERROR_DATA_INVALID;
+    }
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_crypto_stop_transaction(void)
+{
+    psa_status_t status = psa_its_remove(PSA_CRYPTO_ITS_TRANSACTION_UID);
+    /* Whether or not updating the storage succeeded, the transaction is
+     * finished now. It's too late to go back, so zero out the in-memory
+     * data. */
+    memset(&psa_crypto_transaction, 0, sizeof(psa_crypto_transaction));
+    return status;
+}
+
+#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
+
+
+
+/****************************************************************/
+/* Random generator state */
+/****************************************************************/
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,
+                                                size_t seed_size)
+{
+    psa_status_t status;
+    struct psa_storage_info_t p_info;
+
+    status = psa_its_get_info(PSA_CRYPTO_ITS_RANDOM_SEED_UID, &p_info);
+
+    if (PSA_ERROR_DOES_NOT_EXIST == status) { /* No seed exists */
+        status = psa_its_set(PSA_CRYPTO_ITS_RANDOM_SEED_UID, seed_size, seed, 0);
+    } else if (PSA_SUCCESS == status) {
+        /* You should not be here. Seed needs to be injected only once */
+        status = PSA_ERROR_NOT_PERMITTED;
+    }
+    return status;
+}
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+
+
+
+/****************************************************************/
+/* The end */
+/****************************************************************/
+
+#endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_crypto_storage.h b/lib/libmbedtls/mbedtls/library/psa_crypto_storage.h
new file mode 100644
index 0000000000000000000000000000000000000000..d7f5b1895397cfc38424c46c1ac7eb262170ad91
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_crypto_storage.h
@@ -0,0 +1,385 @@
+/**
+ * \file psa_crypto_storage.h
+ *
+ * \brief PSA cryptography module: Mbed TLS key storage
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef PSA_CRYPTO_STORAGE_H
+#define PSA_CRYPTO_STORAGE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "psa/crypto.h"
+#include "psa/crypto_se_driver.h"
+
+#include <stdint.h>
+#include <string.h>
+
+/* Limit the maximum key size in storage. This should have no effect
+ * since the key size is limited in memory. */
+#define PSA_CRYPTO_MAX_STORAGE_SIZE (PSA_BITS_TO_BYTES(PSA_MAX_KEY_BITS))
+/* Sanity check: a file size must fit in 32 bits. Allow a generous
+ * 64kB of metadata. */
+#if PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000
+#error "PSA_CRYPTO_MAX_STORAGE_SIZE > 0xffff0000"
+#endif
+
+/** The maximum permitted persistent slot number.
+ *
+ * In Mbed Crypto 0.1.0b:
+ * - Using the file backend, all key ids are ok except 0.
+ * - Using the ITS backend, all key ids are ok except 0xFFFFFF52
+ *   (#PSA_CRYPTO_ITS_RANDOM_SEED_UID) for which the file contains the
+ *   device's random seed (if this feature is enabled).
+ * - Only key ids from 1 to #MBEDTLS_PSA_KEY_SLOT_COUNT are actually used.
+ *
+ * Since we need to preserve the random seed, avoid using that key slot.
+ * Reserve a whole range of key slots just in case something else comes up.
+ *
+ * This limitation will probably become moot when we implement client
+ * separation for key storage.
+ */
+#define PSA_MAX_PERSISTENT_KEY_IDENTIFIER PSA_KEY_ID_VENDOR_MAX
+
+/**
+ * \brief Checks if persistent data is stored for the given key slot number
+ *
+ * This function checks if any key data or metadata exists for the key slot in
+ * the persistent storage.
+ *
+ * \param key           Persistent identifier to check.
+ *
+ * \retval 0
+ *         No persistent data present for slot number
+ * \retval 1
+ *         Persistent data present for slot number
+ */
+int psa_is_key_present_in_storage(const mbedtls_svc_key_id_t key);
+
+/**
+ * \brief Format key data and metadata and save to a location for given key
+ *        slot.
+ *
+ * This function formats the key data and metadata and saves it to a
+ * persistent storage backend. The storage location corresponding to the
+ * key slot must be empty, otherwise this function will fail. This function
+ * should be called after loading the key into an internal slot to ensure the
+ * persistent key is not saved into a storage location corresponding to an
+ * already occupied non-persistent key, as well as ensuring the key data is
+ * validated.
+ *
+ * Note: This function will only succeed for key buffers which are not
+ * empty. If passed a NULL pointer or zero-length, the function will fail
+ * with #PSA_ERROR_INVALID_ARGUMENT.
+ *
+ * \param[in] attr          The attributes of the key to save.
+ *                          The key identifier field in the attributes
+ *                          determines the key's location.
+ * \param[in] data          Buffer containing the key data.
+ * \param data_length       The number of bytes that make up the key data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INVALID_ARGUMENT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_ALREADY_EXISTS \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ */
+psa_status_t psa_save_persistent_key(const psa_key_attributes_t *attr,
+                                     const uint8_t *data,
+                                     const size_t data_length);
+
+/**
+ * \brief Parses key data and metadata and load persistent key for given
+ * key slot number.
+ *
+ * This function reads from a storage backend, parses the key data and
+ * metadata and writes them to the appropriate output parameters.
+ *
+ * Note: This function allocates a buffer and returns a pointer to it through
+ * the data parameter. On successful return, the pointer is guaranteed to be
+ * valid and the buffer contains at least one byte of data.
+ * psa_free_persistent_key_data() must be called on the data buffer
+ * afterwards to zeroize and free this buffer.
+ *
+ * \param[in,out] attr      On input, the key identifier field identifies
+ *                          the key to load. Other fields are ignored.
+ *                          On success, the attribute structure contains
+ *                          the key metadata that was loaded from storage.
+ * \param[out] data         Pointer to an allocated key data buffer on return.
+ * \param[out] data_length  The number of bytes that make up the key data.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_DOES_NOT_EXIST \emptydescription
+ */
+psa_status_t psa_load_persistent_key(psa_key_attributes_t *attr,
+                                     uint8_t **data,
+                                     size_t *data_length);
+
+/**
+ * \brief Remove persistent data for the given key slot number.
+ *
+ * \param key           Persistent identifier of the key to remove
+ *                      from persistent storage.
+ *
+ * \retval #PSA_SUCCESS
+ *         The key was successfully removed,
+ *         or the key did not exist.
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ */
+psa_status_t psa_destroy_persistent_key(const mbedtls_svc_key_id_t key);
+
+/**
+ * \brief Free the temporary buffer allocated by psa_load_persistent_key().
+ *
+ * This function must be called at some point after psa_load_persistent_key()
+ * to zeroize and free the memory allocated to the buffer in that function.
+ *
+ * \param key_data        Buffer for the key data.
+ * \param key_data_length Size of the key data buffer.
+ *
+ */
+void psa_free_persistent_key_data(uint8_t *key_data, size_t key_data_length);
+
+/**
+ * \brief Formats key data and metadata for persistent storage
+ *
+ * \param[in] data          Buffer containing the key data.
+ * \param data_length       Length of the key data buffer.
+ * \param[in] attr          The core attributes of the key.
+ * \param[out] storage_data Output buffer for the formatted data.
+ *
+ */
+void psa_format_key_data_for_storage(const uint8_t *data,
+                                     const size_t data_length,
+                                     const psa_key_attributes_t *attr,
+                                     uint8_t *storage_data);
+
+/**
+ * \brief Parses persistent storage data into key data and metadata
+ *
+ * \param[in] storage_data     Buffer for the storage data.
+ * \param storage_data_length  Length of the storage data buffer
+ * \param[out] key_data        On output, pointer to a newly allocated buffer
+ *                             containing the key data. This must be freed
+ *                             using psa_free_persistent_key_data()
+ * \param[out] key_data_length Length of the key data buffer
+ * \param[out] attr            On success, the attribute structure is filled
+ *                             with the loaded key metadata.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_MEMORY \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ */
+psa_status_t psa_parse_key_data_from_storage(const uint8_t *storage_data,
+                                             size_t storage_data_length,
+                                             uint8_t **key_data,
+                                             size_t *key_data_length,
+                                             psa_key_attributes_t *attr);
+
+#if defined(MBEDTLS_PSA_CRYPTO_SE_C)
+/** This symbol is defined if transaction support is required. */
+#define PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS 1
+#endif
+
+#if defined(PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS)
+
+/** The type of transaction that is in progress.
+ */
+/* This is an integer type rather than an enum for two reasons: to support
+ * unknown values when loading a transaction file, and to ensure that the
+ * type has a known size.
+ */
+typedef uint16_t psa_crypto_transaction_type_t;
+
+/** No transaction is in progress.
+ *
+ * This has the value 0, so zero-initialization sets a transaction's type to
+ * this value.
+ */
+#define PSA_CRYPTO_TRANSACTION_NONE             ((psa_crypto_transaction_type_t) 0x0000)
+
+/** A key creation transaction.
+ *
+ * This is only used for keys in an external cryptoprocessor (secure element).
+ * Keys in RAM or in internal storage are created atomically in storage
+ * (simple file creation), so they do not need a transaction mechanism.
+ */
+#define PSA_CRYPTO_TRANSACTION_CREATE_KEY       ((psa_crypto_transaction_type_t) 0x0001)
+
+/** A key destruction transaction.
+ *
+ * This is only used for keys in an external cryptoprocessor (secure element).
+ * Keys in RAM or in internal storage are destroyed atomically in storage
+ * (simple file deletion), so they do not need a transaction mechanism.
+ */
+#define PSA_CRYPTO_TRANSACTION_DESTROY_KEY      ((psa_crypto_transaction_type_t) 0x0002)
+
+/** Transaction data.
+ *
+ * This type is designed to be serialized by writing the memory representation
+ * and reading it back on the same device.
+ *
+ * \note The transaction mechanism is not thread-safe. There can only be one
+ *       single active transaction at a time.
+ *       The transaction object is #psa_crypto_transaction.
+ *
+ * \note If an API call starts a transaction, it must complete this transaction
+ *       before returning to the application.
+ *
+ * The lifetime of a transaction is the following (note that only one
+ * transaction may be active at a time):
+ *
+ * -# Call psa_crypto_prepare_transaction() to initialize the transaction
+ *    object in memory and declare the type of transaction that is starting.
+ * -# Fill in the type-specific fields of #psa_crypto_transaction.
+ * -# Call psa_crypto_save_transaction() to start the transaction. This
+ *    saves the transaction data to internal storage.
+ * -# Perform the work of the transaction by modifying files, contacting
+ *    external entities, or whatever needs doing. Note that the transaction
+ *    may be interrupted by a power failure, so you need to have a way
+ *    recover from interruptions either by undoing what has been done
+ *    so far or by resuming where you left off.
+ * -# If there are intermediate stages in the transaction, update
+ *    the fields of #psa_crypto_transaction and call
+ *    psa_crypto_save_transaction() again when each stage is reached.
+ * -# When the transaction is over, call psa_crypto_stop_transaction() to
+ *    remove the transaction data in storage and in memory.
+ *
+ * If the system crashes while a transaction is in progress, psa_crypto_init()
+ * calls psa_crypto_load_transaction() and takes care of completing or
+ * rewinding the transaction. This is done in psa_crypto_recover_transaction()
+ * in psa_crypto.c. If you add a new type of transaction, be
+ * sure to add code for it in psa_crypto_recover_transaction().
+ */
+typedef union {
+    /* Each element of this union must have the following properties
+     * to facilitate serialization and deserialization:
+     *
+     * - The element is a struct.
+     * - The first field of the struct is `psa_crypto_transaction_type_t type`.
+     * - Elements of the struct are arranged such a way that there is
+     *   no padding.
+     */
+    struct psa_crypto_transaction_unknown_s {
+        psa_crypto_transaction_type_t type;
+        uint16_t unused1;
+        uint32_t unused2;
+        uint64_t unused3;
+        uint64_t unused4;
+    } unknown;
+    /* ::type is #PSA_CRYPTO_TRANSACTION_CREATE_KEY or
+     * #PSA_CRYPTO_TRANSACTION_DESTROY_KEY. */
+    struct psa_crypto_transaction_key_s {
+        psa_crypto_transaction_type_t type;
+        uint16_t unused1;
+        psa_key_lifetime_t lifetime;
+        psa_key_slot_number_t slot;
+        mbedtls_svc_key_id_t id;
+    } key;
+} psa_crypto_transaction_t;
+
+/** The single active transaction.
+ */
+extern psa_crypto_transaction_t psa_crypto_transaction;
+
+/** Prepare for a transaction.
+ *
+ * There must not be an ongoing transaction.
+ *
+ * \param type          The type of transaction to start.
+ */
+static inline void psa_crypto_prepare_transaction(
+    psa_crypto_transaction_type_t type)
+{
+    psa_crypto_transaction.unknown.type = type;
+}
+
+/** Save the transaction data to storage.
+ *
+ * You may call this function multiple times during a transaction to
+ * atomically update the transaction state.
+ *
+ * \retval #PSA_SUCCESS \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ */
+psa_status_t psa_crypto_save_transaction(void);
+
+/** Load the transaction data from storage, if any.
+ *
+ * This function is meant to be called from psa_crypto_init() to recover
+ * in case a transaction was interrupted by a system crash.
+ *
+ * \retval #PSA_SUCCESS
+ *         The data about the ongoing transaction has been loaded to
+ *         #psa_crypto_transaction.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There is no ongoing transaction.
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_DATA_INVALID \emptydescription
+ * \retval #PSA_ERROR_DATA_CORRUPT \emptydescription
+ */
+psa_status_t psa_crypto_load_transaction(void);
+
+/** Indicate that the current transaction is finished.
+ *
+ * Call this function at the very end of transaction processing.
+ * This function does not "commit" or "abort" the transaction: the storage
+ * subsystem has no concept of "commit" and "abort", just saving and
+ * removing the transaction information in storage.
+ *
+ * This function erases the transaction data in storage (if any) and
+ * resets the transaction data in memory.
+ *
+ * \retval #PSA_SUCCESS
+ *         There was transaction data in storage.
+ * \retval #PSA_ERROR_DOES_NOT_EXIST
+ *         There was no transaction data in storage.
+ * \retval #PSA_ERROR_STORAGE_FAILURE
+ *         It was impossible to determine whether there was transaction data
+ *         in storage, or the transaction data could not be erased.
+ */
+psa_status_t psa_crypto_stop_transaction(void);
+
+/** The ITS file identifier for the transaction data.
+ *
+ * 0xffffffNN = special file; 0x74 = 't' for transaction.
+ */
+#define PSA_CRYPTO_ITS_TRANSACTION_UID ((psa_key_id_t) 0xffffff74)
+
+#endif /* PSA_CRYPTO_STORAGE_HAS_TRANSACTIONS */
+
+#if defined(MBEDTLS_PSA_INJECT_ENTROPY)
+/** Backend side of mbedtls_psa_inject_entropy().
+ *
+ * This function stores the supplied data into the entropy seed file.
+ *
+ * \retval #PSA_SUCCESS
+ *         Success
+ * \retval #PSA_ERROR_STORAGE_FAILURE \emptydescription
+ * \retval #PSA_ERROR_INSUFFICIENT_STORAGE \emptydescription
+ * \retval #PSA_ERROR_NOT_PERMITTED
+ *         The entropy seed file already exists.
+ */
+psa_status_t mbedtls_psa_storage_inject_entropy(const unsigned char *seed,
+                                                size_t seed_size);
+#endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PSA_CRYPTO_STORAGE_H */
diff --git a/lib/libmbedtls/mbedtls/library/psa_its_file.c b/lib/libmbedtls/mbedtls/library/psa_its_file.c
new file mode 100644
index 0000000000000000000000000000000000000000..95671374837981e6480bd2b2ca2a01038daae8e2
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_its_file.c
@@ -0,0 +1,254 @@
+/*
+ *  PSA ITS simulator over stdio files.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_PSA_ITS_FILE_C)
+
+#include "mbedtls/platform.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#include "psa_crypto_its.h"
+
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#if !defined(PSA_ITS_STORAGE_PREFIX)
+#define PSA_ITS_STORAGE_PREFIX ""
+#endif
+
+#define PSA_ITS_STORAGE_FILENAME_PATTERN "%08x%08x"
+#define PSA_ITS_STORAGE_SUFFIX ".psa_its"
+#define PSA_ITS_STORAGE_FILENAME_LENGTH         \
+    (sizeof(PSA_ITS_STORAGE_PREFIX) - 1 +    /*prefix without terminating 0*/ \
+     16 +  /*UID (64-bit number in hex)*/                               \
+     sizeof(PSA_ITS_STORAGE_SUFFIX) - 1 +    /*suffix without terminating 0*/ \
+     1 /*terminating null byte*/)
+#define PSA_ITS_STORAGE_TEMP \
+    PSA_ITS_STORAGE_PREFIX "tempfile" PSA_ITS_STORAGE_SUFFIX
+
+/* The maximum value of psa_storage_info_t.size */
+#define PSA_ITS_MAX_SIZE 0xffffffff
+
+#define PSA_ITS_MAGIC_STRING "PSA\0ITS\0"
+#define PSA_ITS_MAGIC_LENGTH 8
+
+/* As rename fails on Windows if the new filepath already exists,
+ * use MoveFileExA with the MOVEFILE_REPLACE_EXISTING flag instead.
+ * Returns 0 on success, nonzero on failure. */
+#if defined(_WIN32)
+#define rename_replace_existing(oldpath, newpath) \
+    (!MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
+#else
+#define rename_replace_existing(oldpath, newpath) rename(oldpath, newpath)
+#endif
+
+typedef struct {
+    uint8_t magic[PSA_ITS_MAGIC_LENGTH];
+    uint8_t size[sizeof(uint32_t)];
+    uint8_t flags[sizeof(psa_storage_create_flags_t)];
+} psa_its_file_header_t;
+
+static void psa_its_fill_filename(psa_storage_uid_t uid, char *filename)
+{
+    /* Break up the UID into two 32-bit pieces so as not to rely on
+     * long long support in snprintf. */
+    mbedtls_snprintf(filename, PSA_ITS_STORAGE_FILENAME_LENGTH,
+                     "%s" PSA_ITS_STORAGE_FILENAME_PATTERN "%s",
+                     PSA_ITS_STORAGE_PREFIX,
+                     (unsigned) (uid >> 32),
+                     (unsigned) (uid & 0xffffffff),
+                     PSA_ITS_STORAGE_SUFFIX);
+}
+
+static psa_status_t psa_its_read_file(psa_storage_uid_t uid,
+                                      struct psa_storage_info_t *p_info,
+                                      FILE **p_stream)
+{
+    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
+    psa_its_file_header_t header;
+    size_t n;
+
+    *p_stream = NULL;
+    psa_its_fill_filename(uid, filename);
+    *p_stream = fopen(filename, "rb");
+    if (*p_stream == NULL) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(*p_stream, NULL);
+
+    n = fread(&header, 1, sizeof(header), *p_stream);
+    if (n != sizeof(header)) {
+        return PSA_ERROR_DATA_CORRUPT;
+    }
+    if (memcmp(header.magic, PSA_ITS_MAGIC_STRING,
+               PSA_ITS_MAGIC_LENGTH) != 0) {
+        return PSA_ERROR_DATA_CORRUPT;
+    }
+
+    p_info->size  = MBEDTLS_GET_UINT32_LE(header.size, 0);
+    p_info->flags = MBEDTLS_GET_UINT32_LE(header.flags, 0);
+
+    return PSA_SUCCESS;
+}
+
+psa_status_t psa_its_get_info(psa_storage_uid_t uid,
+                              struct psa_storage_info_t *p_info)
+{
+    psa_status_t status;
+    FILE *stream = NULL;
+    status = psa_its_read_file(uid, p_info, &stream);
+    if (stream != NULL) {
+        fclose(stream);
+    }
+    return status;
+}
+
+psa_status_t psa_its_get(psa_storage_uid_t uid,
+                         uint32_t data_offset,
+                         uint32_t data_length,
+                         void *p_data,
+                         size_t *p_data_length)
+{
+    psa_status_t status;
+    FILE *stream = NULL;
+    size_t n;
+    struct psa_storage_info_t info;
+
+    status = psa_its_read_file(uid, &info, &stream);
+    if (status != PSA_SUCCESS) {
+        goto exit;
+    }
+    status = PSA_ERROR_INVALID_ARGUMENT;
+    if (data_offset + data_length < data_offset) {
+        goto exit;
+    }
+#if SIZE_MAX < 0xffffffff
+    if (data_offset + data_length > SIZE_MAX) {
+        goto exit;
+    }
+#endif
+    if (data_offset + data_length > info.size) {
+        goto exit;
+    }
+
+    status = PSA_ERROR_STORAGE_FAILURE;
+#if LONG_MAX < 0xffffffff
+    while (data_offset > LONG_MAX) {
+        if (fseek(stream, LONG_MAX, SEEK_CUR) != 0) {
+            goto exit;
+        }
+        data_offset -= LONG_MAX;
+    }
+#endif
+    if (fseek(stream, data_offset, SEEK_CUR) != 0) {
+        goto exit;
+    }
+    n = fread(p_data, 1, data_length, stream);
+    if (n != data_length) {
+        goto exit;
+    }
+    status = PSA_SUCCESS;
+    if (p_data_length != NULL) {
+        *p_data_length = n;
+    }
+
+exit:
+    if (stream != NULL) {
+        fclose(stream);
+    }
+    return status;
+}
+
+psa_status_t psa_its_set(psa_storage_uid_t uid,
+                         uint32_t data_length,
+                         const void *p_data,
+                         psa_storage_create_flags_t create_flags)
+{
+    if (uid == 0) {
+        return PSA_ERROR_INVALID_HANDLE;
+    }
+
+    psa_status_t status = PSA_ERROR_STORAGE_FAILURE;
+    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
+    FILE *stream = NULL;
+    psa_its_file_header_t header;
+    size_t n;
+
+    memcpy(header.magic, PSA_ITS_MAGIC_STRING, PSA_ITS_MAGIC_LENGTH);
+    MBEDTLS_PUT_UINT32_LE(data_length, header.size, 0);
+    MBEDTLS_PUT_UINT32_LE(create_flags, header.flags, 0);
+
+    psa_its_fill_filename(uid, filename);
+    stream = fopen(PSA_ITS_STORAGE_TEMP, "wb");
+
+    if (stream == NULL) {
+        goto exit;
+    }
+
+    /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
+    mbedtls_setbuf(stream, NULL);
+
+    status = PSA_ERROR_INSUFFICIENT_STORAGE;
+    n = fwrite(&header, 1, sizeof(header), stream);
+    if (n != sizeof(header)) {
+        goto exit;
+    }
+    if (data_length != 0) {
+        n = fwrite(p_data, 1, data_length, stream);
+        if (n != data_length) {
+            goto exit;
+        }
+    }
+    status = PSA_SUCCESS;
+
+exit:
+    if (stream != NULL) {
+        int ret = fclose(stream);
+        if (status == PSA_SUCCESS && ret != 0) {
+            status = PSA_ERROR_INSUFFICIENT_STORAGE;
+        }
+    }
+    if (status == PSA_SUCCESS) {
+        if (rename_replace_existing(PSA_ITS_STORAGE_TEMP, filename) != 0) {
+            status = PSA_ERROR_STORAGE_FAILURE;
+        }
+    }
+    /* The temporary file may still exist, but only in failure cases where
+     * we're already reporting an error. So there's nothing we can do on
+     * failure. If the function succeeded, and in some error cases, the
+     * temporary file doesn't exist and so remove() is expected to fail.
+     * Thus we just ignore the return status of remove(). */
+    (void) remove(PSA_ITS_STORAGE_TEMP);
+    return status;
+}
+
+psa_status_t psa_its_remove(psa_storage_uid_t uid)
+{
+    char filename[PSA_ITS_STORAGE_FILENAME_LENGTH];
+    FILE *stream;
+    psa_its_fill_filename(uid, filename);
+    stream = fopen(filename, "rb");
+    if (stream == NULL) {
+        return PSA_ERROR_DOES_NOT_EXIST;
+    }
+    fclose(stream);
+    if (remove(filename) != 0) {
+        return PSA_ERROR_STORAGE_FAILURE;
+    }
+    return PSA_SUCCESS;
+}
+
+#endif /* MBEDTLS_PSA_ITS_FILE_C */
diff --git a/lib/libmbedtls/mbedtls/library/psa_util.c b/lib/libmbedtls/mbedtls/library/psa_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..679d00ea9b908cf7a2b379a872208501eb56f5a0
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_util.c
@@ -0,0 +1,608 @@
+/*
+ *  PSA hashing layer on top of Mbed TLS software crypto
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#include "common.h"
+
+/* This is needed for MBEDTLS_ERR_XXX macros */
+#include <mbedtls/error.h>
+
+#if defined(MBEDTLS_ASN1_WRITE_C)
+#include <mbedtls/asn1write.h>
+#include <psa/crypto_sizes.h>
+#endif
+
+#include "psa_util_internal.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+#include <psa/crypto.h>
+
+#if defined(MBEDTLS_MD_LIGHT)
+#include <mbedtls/md.h>
+#endif
+#if defined(MBEDTLS_LMS_C)
+#include <mbedtls/lms.h>
+#endif
+#if defined(MBEDTLS_SSL_TLS_C) && \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
+#include <mbedtls/ssl.h>
+#endif
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+#include <mbedtls/rsa.h>
+#endif
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+#include <mbedtls/ecp.h>
+#endif
+#if defined(MBEDTLS_PK_C)
+#include <mbedtls/pk.h>
+#endif
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+#include <mbedtls/cipher.h>
+#endif
+#include <mbedtls/entropy.h>
+
+/* PSA_SUCCESS is kept at the top of each error table since
+ * it's the most common status when everything functions properly. */
+#if defined(MBEDTLS_MD_LIGHT)
+const mbedtls_error_pair_t psa_to_md_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_MD_BAD_INPUT_DATA },
+    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_MD_ALLOC_FAILED }
+};
+#endif
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+const mbedtls_error_pair_t psa_to_cipher_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA },
+    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_CIPHER_ALLOC_FAILED }
+};
+#endif
+
+#if defined(MBEDTLS_LMS_C)
+const mbedtls_error_pair_t psa_to_lms_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_LMS_BUFFER_TOO_SMALL },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_LMS_BAD_INPUT_DATA }
+};
+#endif
+
+#if defined(MBEDTLS_SSL_TLS_C) && \
+    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
+const mbedtls_error_pair_t psa_to_ssl_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_INSUFFICIENT_MEMORY,   MBEDTLS_ERR_SSL_ALLOC_FAILED },
+    { PSA_ERROR_NOT_SUPPORTED,         MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_SSL_INVALID_MAC },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_SSL_BAD_INPUT_DATA },
+    { PSA_ERROR_BAD_STATE,             MBEDTLS_ERR_SSL_INTERNAL_ERROR },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL }
+};
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+const mbedtls_error_pair_t psa_to_pk_rsa_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_RSA_BAD_INPUT_DATA },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE },
+    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_RSA_RNG_FAILED },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_RSA_VERIFY_FAILED },
+    { PSA_ERROR_INVALID_PADDING,       MBEDTLS_ERR_RSA_INVALID_PADDING }
+};
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[] =
+{
+    { PSA_SUCCESS,                     0 },
+    { PSA_ERROR_NOT_PERMITTED,         MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_ARGUMENT,      MBEDTLS_ERR_ECP_BAD_INPUT_DATA },
+    { PSA_ERROR_INVALID_HANDLE,        MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE },
+    { PSA_ERROR_BUFFER_TOO_SMALL,      MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL },
+    { PSA_ERROR_INSUFFICIENT_ENTROPY,  MBEDTLS_ERR_ECP_RANDOM_FAILED },
+    { PSA_ERROR_INVALID_SIGNATURE,     MBEDTLS_ERR_ECP_VERIFY_FAILED }
+};
+#endif
+
+int psa_generic_status_to_mbedtls(psa_status_t status)
+{
+    switch (status) {
+        case PSA_SUCCESS:
+            return 0;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;
+        case PSA_ERROR_CORRUPTION_DETECTED:
+            return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        case PSA_ERROR_COMMUNICATION_FAILURE:
+        case PSA_ERROR_HARDWARE_FAILURE:
+            return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+        case PSA_ERROR_NOT_PERMITTED:
+        default:
+            return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
+    }
+}
+
+int psa_status_to_mbedtls(psa_status_t status,
+                          const mbedtls_error_pair_t *local_translations,
+                          size_t local_errors_num,
+                          int (*fallback_f)(psa_status_t))
+{
+    for (size_t i = 0; i < local_errors_num; i++) {
+        if (status == local_translations[i].psa_status) {
+            return local_translations[i].mbedtls_error;
+        }
+    }
+    return fallback_f(status);
+}
+
+#if defined(MBEDTLS_PK_C)
+int psa_pk_status_to_mbedtls(psa_status_t status)
+{
+    switch (status) {
+        case PSA_ERROR_INVALID_HANDLE:
+            return MBEDTLS_ERR_PK_KEY_INVALID_FORMAT;
+        case PSA_ERROR_BUFFER_TOO_SMALL:
+            return MBEDTLS_ERR_PK_BUFFER_TOO_SMALL;
+        case PSA_ERROR_NOT_SUPPORTED:
+            return MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE;
+        case PSA_ERROR_INVALID_ARGUMENT:
+            return MBEDTLS_ERR_PK_INVALID_ALG;
+        case PSA_ERROR_NOT_PERMITTED:
+            return MBEDTLS_ERR_PK_TYPE_MISMATCH;
+        case PSA_ERROR_INSUFFICIENT_MEMORY:
+            return MBEDTLS_ERR_PK_ALLOC_FAILED;
+        case PSA_ERROR_BAD_STATE:
+            return MBEDTLS_ERR_PK_BAD_INPUT_DATA;
+        case PSA_ERROR_DATA_CORRUPT:
+        case PSA_ERROR_DATA_INVALID:
+        case PSA_ERROR_STORAGE_FAILURE:
+            return MBEDTLS_ERR_PK_FILE_IO_ERROR;
+        default:
+            return psa_generic_status_to_mbedtls(status);
+    }
+}
+#endif /* MBEDTLS_PK_C */
+
+/****************************************************************/
+/* Key management */
+/****************************************************************/
+
+#if defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+psa_ecc_family_t mbedtls_ecc_group_to_psa(mbedtls_ecp_group_id grpid,
+                                          size_t *bits)
+{
+    switch (grpid) {
+#if defined(MBEDTLS_ECP_HAVE_SECP192R1)
+        case MBEDTLS_ECP_DP_SECP192R1:
+            *bits = 192;
+            return PSA_ECC_FAMILY_SECP_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP224R1)
+        case MBEDTLS_ECP_DP_SECP224R1:
+            *bits = 224;
+            return PSA_ECC_FAMILY_SECP_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
+        case MBEDTLS_ECP_DP_SECP256R1:
+            *bits = 256;
+            return PSA_ECC_FAMILY_SECP_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
+        case MBEDTLS_ECP_DP_SECP384R1:
+            *bits = 384;
+            return PSA_ECC_FAMILY_SECP_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
+        case MBEDTLS_ECP_DP_SECP521R1:
+            *bits = 521;
+            return PSA_ECC_FAMILY_SECP_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP256R1)
+        case MBEDTLS_ECP_DP_BP256R1:
+            *bits = 256;
+            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP384R1)
+        case MBEDTLS_ECP_DP_BP384R1:
+            *bits = 384;
+            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP512R1)
+        case MBEDTLS_ECP_DP_BP512R1:
+            *bits = 512;
+            return PSA_ECC_FAMILY_BRAINPOOL_P_R1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
+        case MBEDTLS_ECP_DP_CURVE25519:
+            *bits = 255;
+            return PSA_ECC_FAMILY_MONTGOMERY;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP192K1)
+        case MBEDTLS_ECP_DP_SECP192K1:
+            *bits = 192;
+            return PSA_ECC_FAMILY_SECP_K1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP224K1)
+    /* secp224k1 is not and will not be supported in PSA (#3541). */
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP256K1)
+        case MBEDTLS_ECP_DP_SECP256K1:
+            *bits = 256;
+            return PSA_ECC_FAMILY_SECP_K1;
+#endif
+#if defined(MBEDTLS_ECP_HAVE_CURVE448)
+        case MBEDTLS_ECP_DP_CURVE448:
+            *bits = 448;
+            return PSA_ECC_FAMILY_MONTGOMERY;
+#endif
+        default:
+            *bits = 0;
+            return 0;
+    }
+}
+
+mbedtls_ecp_group_id mbedtls_ecc_group_from_psa(psa_ecc_family_t family,
+                                                size_t bits)
+{
+    switch (family) {
+        case PSA_ECC_FAMILY_SECP_R1:
+            switch (bits) {
+#if defined(PSA_WANT_ECC_SECP_R1_192)
+                case 192:
+                    return MBEDTLS_ECP_DP_SECP192R1;
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_224)
+                case 224:
+                    return MBEDTLS_ECP_DP_SECP224R1;
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_256)
+                case 256:
+                    return MBEDTLS_ECP_DP_SECP256R1;
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_384)
+                case 384:
+                    return MBEDTLS_ECP_DP_SECP384R1;
+#endif
+#if defined(PSA_WANT_ECC_SECP_R1_521)
+                case 521:
+                    return MBEDTLS_ECP_DP_SECP521R1;
+#endif
+            }
+            break;
+
+        case PSA_ECC_FAMILY_BRAINPOOL_P_R1:
+            switch (bits) {
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
+                case 256:
+                    return MBEDTLS_ECP_DP_BP256R1;
+#endif
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
+                case 384:
+                    return MBEDTLS_ECP_DP_BP384R1;
+#endif
+#if defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
+                case 512:
+                    return MBEDTLS_ECP_DP_BP512R1;
+#endif
+            }
+            break;
+
+        case PSA_ECC_FAMILY_MONTGOMERY:
+            switch (bits) {
+#if defined(PSA_WANT_ECC_MONTGOMERY_255)
+                case 255:
+                    return MBEDTLS_ECP_DP_CURVE25519;
+#endif
+#if defined(PSA_WANT_ECC_MONTGOMERY_448)
+                case 448:
+                    return MBEDTLS_ECP_DP_CURVE448;
+#endif
+            }
+            break;
+
+        case PSA_ECC_FAMILY_SECP_K1:
+            switch (bits) {
+#if defined(PSA_WANT_ECC_SECP_K1_192)
+                case 192:
+                    return MBEDTLS_ECP_DP_SECP192K1;
+#endif
+#if defined(PSA_WANT_ECC_SECP_K1_224)
+            /* secp224k1 is not and will not be supported in PSA (#3541). */
+#endif
+#if defined(PSA_WANT_ECC_SECP_K1_256)
+                case 256:
+                    return MBEDTLS_ECP_DP_SECP256K1;
+#endif
+            }
+            break;
+    }
+
+    return MBEDTLS_ECP_DP_NONE;
+}
+#endif /* PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY */
+
+/* Wrapper function allowing the classic API to use the PSA RNG.
+ *
+ * `mbedtls_psa_get_random(MBEDTLS_PSA_RANDOM_STATE, ...)` calls
+ * `psa_generate_random(...)`. The state parameter is ignored since the
+ * PSA API doesn't support passing an explicit state.
+ */
+int mbedtls_psa_get_random(void *p_rng,
+                           unsigned char *output,
+                           size_t output_size)
+{
+    /* This function takes a pointer to the RNG state because that's what
+     * classic mbedtls functions using an RNG expect. The PSA RNG manages
+     * its own state internally and doesn't let the caller access that state.
+     * So we just ignore the state parameter, and in practice we'll pass
+     * NULL. */
+    (void) p_rng;
+    psa_status_t status = psa_generate_random(output, output_size);
+    if (status == PSA_SUCCESS) {
+        return 0;
+    } else {
+        return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
+    }
+}
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+
+#if defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
+
+/**
+ * \brief  Convert a single raw coordinate to DER ASN.1 format. The output der
+ *         buffer is filled backward (i.e. starting from its end).
+ *
+ * \param raw_buf           Buffer containing the raw coordinate to be
+ *                          converted.
+ * \param raw_len           Length of raw_buf in bytes. This must be > 0.
+ * \param der_buf_start     Pointer to the beginning of the buffer which
+ *                          will be filled with the DER converted data.
+ * \param der_buf_end       End of the buffer used to store the DER output.
+ *
+ * \return                  On success, the amount of data (in bytes) written to
+ *                          the DER buffer.
+ * \return                  MBEDTLS_ERR_ASN1_BUF_TOO_SMALL if the provided der
+ *                          buffer is too small to contain all the converted data.
+ * \return                  MBEDTLS_ERR_ASN1_INVALID_DATA if the input raw
+ *                          coordinate is null (i.e. all zeros).
+ *
+ * \warning                 Raw and der buffer must not be overlapping.
+ */
+static int convert_raw_to_der_single_int(const unsigned char *raw_buf, size_t raw_len,
+                                         unsigned char *der_buf_start,
+                                         unsigned char *der_buf_end)
+{
+    unsigned char *p = der_buf_end;
+    int len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* ASN.1 DER encoding requires minimal length, so skip leading 0s.
+     * Provided input MPIs should not be 0, but as a failsafe measure, still
+     * detect that and return error in case. */
+    while (*raw_buf == 0x00) {
+        ++raw_buf;
+        --raw_len;
+        if (raw_len == 0) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+    }
+    len = (int) raw_len;
+
+    /* Copy the raw coordinate to the end of der_buf. */
+    if ((p - der_buf_start) < len) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+    p -= len;
+    memcpy(p, raw_buf, len);
+
+    /* If MSb is 1, ASN.1 requires that we prepend a 0. */
+    if (*p & 0x80) {
+        if ((p - der_buf_start) < 1) {
+            return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+        }
+        --p;
+        *p = 0x00;
+        ++len;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der_buf_start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der_buf_start, MBEDTLS_ASN1_INTEGER));
+
+    return len;
+}
+
+int mbedtls_ecdsa_raw_to_der(size_t bits, const unsigned char *raw, size_t raw_len,
+                             unsigned char *der, size_t der_size, size_t *der_len)
+{
+    unsigned char r[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    unsigned char s[PSA_BITS_TO_BYTES(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    const size_t coordinate_len = PSA_BITS_TO_BYTES(bits);
+    size_t len = 0;
+    unsigned char *p = der + der_size;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (raw_len != (2 * coordinate_len)) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    if (coordinate_len > sizeof(r)) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+
+    /* Since raw and der buffers might overlap, dump r and s before starting
+     * the conversion. */
+    memcpy(r, raw, coordinate_len);
+    memcpy(s, raw + coordinate_len, coordinate_len);
+
+    /* der buffer will initially be written starting from its end so we pick s
+     * first and then r. */
+    ret = convert_raw_to_der_single_int(s, coordinate_len, der, p);
+    if (ret < 0) {
+        return ret;
+    }
+    p -= ret;
+    len += ret;
+
+    ret = convert_raw_to_der_single_int(r, coordinate_len, der, p);
+    if (ret < 0) {
+        return ret;
+    }
+    p -= ret;
+    len += ret;
+
+    /* Add ASN.1 header (len + tag). */
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, der, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, der,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    /* memmove the content of der buffer to its beginnig. */
+    memmove(der, p, len);
+    *der_len = len;
+
+    return 0;
+}
+
+/**
+ * \brief Convert a single integer from ASN.1 DER format to raw.
+ *
+ * \param der               Buffer containing the DER integer value to be
+ *                          converted.
+ * \param der_len           Length of the der buffer in bytes.
+ * \param raw               Output buffer that will be filled with the
+ *                          converted data. This should be at least
+ *                          coordinate_size bytes and it must be zeroed before
+ *                          calling this function.
+ * \param coordinate_size   Size (in bytes) of a single coordinate in raw
+ *                          format.
+ *
+ * \return                  On success, the amount of DER data parsed from the
+ *                          provided der buffer.
+ * \return                  MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the integer tag
+ *                          is missing in the der buffer.
+ * \return                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the integer
+ *                          is null (i.e. all zeros) or if the output raw buffer
+ *                          is too small to contain the converted raw value.
+ *
+ * \warning                 Der and raw buffers must not be overlapping.
+ */
+static int convert_der_to_raw_single_int(unsigned char *der, size_t der_len,
+                                         unsigned char *raw, size_t coordinate_size)
+{
+    unsigned char *p = der;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t unpadded_len, padding_len = 0;
+
+    /* Get the length of ASN.1 element (i.e. the integer we need to parse). */
+    ret = mbedtls_asn1_get_tag(&p, p + der_len, &unpadded_len,
+                               MBEDTLS_ASN1_INTEGER);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* It's invalid to have:
+     * - unpadded_len == 0.
+     * - MSb set without a leading 0x00 (leading 0x00 is checked below). */
+    if (((unpadded_len == 0) || (*p & 0x80) != 0)) {
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+
+    /* Skip possible leading zero */
+    if (*p == 0x00) {
+        p++;
+        unpadded_len--;
+        /* It is not allowed to have more than 1 leading zero.
+         * Ignore the case in which unpadded_len = 0 because that's a 0 encoded
+         * in ASN.1 format (i.e. 020100). */
+        if ((unpadded_len > 0) && (*p == 0x00)) {
+            return MBEDTLS_ERR_ASN1_INVALID_DATA;
+        }
+    }
+
+    if (unpadded_len > coordinate_size) {
+        /* Parsed number is longer than the maximum expected value. */
+        return MBEDTLS_ERR_ASN1_INVALID_DATA;
+    }
+    padding_len = coordinate_size - unpadded_len;
+    /* raw buffer was already zeroed by the calling function so zero-padding
+     * operation is skipped here. */
+    memcpy(raw + padding_len, p, unpadded_len);
+    p += unpadded_len;
+
+    return (int) (p - der);
+}
+
+int mbedtls_ecdsa_der_to_raw(size_t bits, const unsigned char *der, size_t der_len,
+                             unsigned char *raw, size_t raw_size, size_t *raw_len)
+{
+    unsigned char raw_tmp[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE];
+    unsigned char *p = (unsigned char *) der;
+    size_t data_len;
+    size_t coordinate_size = PSA_BITS_TO_BYTES(bits);
+    int ret;
+
+    /* The output raw buffer should be at least twice the size of a raw
+     * coordinate in order to store r and s. */
+    if (raw_size < coordinate_size * 2) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+    if (2 * coordinate_size > sizeof(raw_tmp)) {
+        return MBEDTLS_ERR_ASN1_BUF_TOO_SMALL;
+    }
+
+    /* Check that the provided input DER buffer has the right header. */
+    ret = mbedtls_asn1_get_tag(&p, der + der_len, &data_len,
+                               MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    if (ret != 0) {
+        return ret;
+    }
+
+    memset(raw_tmp, 0, 2 * coordinate_size);
+
+    /* Extract r */
+    ret = convert_der_to_raw_single_int(p, data_len, raw_tmp, coordinate_size);
+    if (ret < 0) {
+        return ret;
+    }
+    p += ret;
+    data_len -= ret;
+
+    /* Extract s */
+    ret = convert_der_to_raw_single_int(p, data_len, raw_tmp + coordinate_size,
+                                        coordinate_size);
+    if (ret < 0) {
+        return ret;
+    }
+    p += ret;
+    data_len -= ret;
+
+    /* Check that we consumed all the input der data. */
+    if ((size_t) (p - der) != der_len) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+
+    memcpy(raw, raw_tmp, 2 * coordinate_size);
+    *raw_len = 2 * coordinate_size;
+
+    return 0;
+}
+
+#endif /* MBEDTLS_PSA_UTIL_HAVE_ECDSA */
diff --git a/lib/libmbedtls/mbedtls/library/psa_util_internal.h b/lib/libmbedtls/mbedtls/library/psa_util_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..70a08a02cd8ed7f86641b17cdffc74b3276e3502
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/psa_util_internal.h
@@ -0,0 +1,100 @@
+/**
+ * \file psa_util_internal.h
+ *
+ * \brief Internal utility functions for use of PSA Crypto.
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+
+#ifndef MBEDTLS_PSA_UTIL_INTERNAL_H
+#define MBEDTLS_PSA_UTIL_INTERNAL_H
+
+/* Include the public header so that users only need one include. */
+#include "mbedtls/psa_util.h"
+
+#include "psa/crypto.h"
+
+#if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
+
+/*************************************************************************
+ * FFDH
+ ************************************************************************/
+
+#define MBEDTLS_PSA_MAX_FFDH_PUBKEY_LENGTH \
+    PSA_KEY_EXPORT_FFDH_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_FFDH_MAX_KEY_BITS)
+
+/*************************************************************************
+ * ECC
+ ************************************************************************/
+
+#define MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH \
+    PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+
+#define MBEDTLS_PSA_MAX_EC_KEY_PAIR_LENGTH \
+    PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)
+
+/*************************************************************************
+ * Error translation
+ ************************************************************************/
+
+typedef struct {
+    /* Error codes used by PSA crypto are in -255..-128, fitting in 16 bits. */
+    int16_t psa_status;
+    /* Error codes used by Mbed TLS are in one of the ranges
+     * -127..-1 (low-level) or -32767..-4096 (high-level with a low-level
+     * code optionally added), fitting in 16 bits. */
+    int16_t mbedtls_error;
+} mbedtls_error_pair_t;
+
+#if defined(MBEDTLS_MD_LIGHT)
+extern const mbedtls_error_pair_t psa_to_md_errors[4];
+#endif
+
+#if defined(MBEDTLS_BLOCK_CIPHER_SOME_PSA)
+extern const mbedtls_error_pair_t psa_to_cipher_errors[4];
+#endif
+
+#if defined(MBEDTLS_LMS_C)
+extern const mbedtls_error_pair_t psa_to_lms_errors[3];
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
+extern const mbedtls_error_pair_t psa_to_ssl_errors[7];
+#endif
+
+#if defined(PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) ||    \
+    defined(PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC)
+extern const mbedtls_error_pair_t psa_to_pk_rsa_errors[8];
+#endif
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY)
+extern const mbedtls_error_pair_t psa_to_pk_ecdsa_errors[7];
+#endif
+
+/* Generic fallback function for error translation,
+ * when the received state was not module-specific. */
+int psa_generic_status_to_mbedtls(psa_status_t status);
+
+/* This function iterates over provided local error translations,
+ * and if no match was found - calls the fallback error translation function. */
+int psa_status_to_mbedtls(psa_status_t status,
+                          const mbedtls_error_pair_t *local_translations,
+                          size_t local_errors_num,
+                          int (*fallback_f)(psa_status_t));
+
+/* The second out of three-stage error handling functions of the pk module,
+ * acts as a fallback after RSA / ECDSA error translation, and if no match
+ * is found, it itself calls psa_generic_status_to_mbedtls. */
+int psa_pk_status_to_mbedtls(psa_status_t status);
+
+/* Utility macro to shorten the defines of error translator in modules. */
+#define PSA_TO_MBEDTLS_ERR_LIST(status, error_list, fallback_f)       \
+    psa_status_to_mbedtls(status, error_list,                         \
+                          sizeof(error_list)/sizeof(error_list[0]),   \
+                          fallback_f)
+
+#endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
+#endif /* MBEDTLS_PSA_UTIL_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/ripemd160.c b/lib/libmbedtls/mbedtls/library/ripemd160.c
index ba97c1f390338f65990ae0172f07c8d750aec4bf..b4fc3cdba1fc3f4af072584d8229a565487b5413 100644
--- a/lib/libmbedtls/mbedtls/library/ripemd160.c
+++ b/lib/libmbedtls/mbedtls/library/ripemd160.c
@@ -2,19 +2,7 @@
  *  RIPE MD-160 implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -356,12 +344,12 @@ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx,
 
     ret = mbedtls_ripemd160_update(ctx, ripemd160_padding, padn);
     if (ret != 0) {
-        return ret;
+        goto exit;
     }
 
     ret = mbedtls_ripemd160_update(ctx, msglen, 8);
     if (ret != 0) {
-        return ret;
+        goto exit;
     }
 
     MBEDTLS_PUT_UINT32_LE(ctx->state[0], output,  0);
@@ -370,7 +358,11 @@ int mbedtls_ripemd160_finish(mbedtls_ripemd160_context *ctx,
     MBEDTLS_PUT_UINT32_LE(ctx->state[3], output, 12);
     MBEDTLS_PUT_UINT32_LE(ctx->state[4], output, 16);
 
-    return 0;
+    ret = 0;
+
+exit:
+    mbedtls_ripemd160_free(ctx);
+    return ret;
 }
 
 #endif /* ! MBEDTLS_RIPEMD160_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/rsa.c b/lib/libmbedtls/mbedtls/library/rsa.c
index 40dbcabdc978d64e07f5baf6361e9250ea6aafd3..dbf934f244dbe5b7a291f134723d3552f677e85a 100644
--- a/lib/libmbedtls/mbedtls/library/rsa.c
+++ b/lib/libmbedtls/mbedtls/library/rsa.c
@@ -2,19 +2,7 @@
  *  The RSA public-key cryptosystem
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -40,13 +28,17 @@
 #if defined(MBEDTLS_RSA_C)
 
 #include "mbedtls/rsa.h"
+#include "bignum_core.h"
+#include "bignum_internal.h"
 #include "rsa_alt_helpers.h"
+#include "rsa_internal.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/asn1write.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
 #include "constant_time_internal.h"
 #include "mbedtls/constant_time.h"
-#include "hash_info.h"
+#include "md_psa.h"
 
 #include <string.h>
 
@@ -54,22 +46,529 @@
 #include <stdlib.h>
 #endif
 
-/* We use MD first if it's available (for compatibility reasons)
- * and "fall back" to PSA otherwise (which needs psa_crypto_init()). */
-#if defined(MBEDTLS_PKCS1_V21)
-#if !defined(MBEDTLS_MD_C)
-#include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_md_errors,              \
-                                                           psa_generic_status_to_mbedtls)
-#endif /* !MBEDTLS_MD_C */
-#endif /* MBEDTLS_PKCS1_V21 */
-
 #include "mbedtls/platform.h"
 
 #include <fault_mitigation.h>
 
+/*
+ * Wrapper around mbedtls_asn1_get_mpi() that rejects zero.
+ *
+ * The value zero is:
+ * - never a valid value for an RSA parameter
+ * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete().
+ *
+ * Since values can't be omitted in PKCS#1, passing a zero value to
+ * rsa_complete() would be incorrect, so reject zero values early.
+ */
+static int asn1_get_nonzero_mpi(unsigned char **p,
+                                const unsigned char *end,
+                                mbedtls_mpi *X)
+{
+    int ret;
+
+    ret = mbedtls_asn1_get_mpi(p, end, X);
+    if (ret != 0) {
+        return ret;
+    }
+
+    if (mbedtls_mpi_cmp_int(X, 0) == 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    return 0;
+}
+
+int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
+{
+    int ret, version;
+    size_t len;
+    unsigned char *p, *end;
+
+    mbedtls_mpi T;
+    mbedtls_mpi_init(&T);
+
+    p = (unsigned char *) key;
+    end = p + keylen;
+
+    /*
+     * This function parses the RSAPrivateKey (PKCS#1)
+     *
+     *  RSAPrivateKey ::= SEQUENCE {
+     *      version           Version,
+     *      modulus           INTEGER,  -- n
+     *      publicExponent    INTEGER,  -- e
+     *      privateExponent   INTEGER,  -- d
+     *      prime1            INTEGER,  -- p
+     *      prime2            INTEGER,  -- q
+     *      exponent1         INTEGER,  -- d mod (p-1)
+     *      exponent2         INTEGER,  -- d mod (q-1)
+     *      coefficient       INTEGER,  -- (inverse of q) mod p
+     *      otherPrimeInfos   OtherPrimeInfos OPTIONAL
+     *  }
+     */
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
+
+    if (end != p + len) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    if ((ret = mbedtls_asn1_get_int(&p, end, &version)) != 0) {
+        return ret;
+    }
+
+    if (version != 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    /* Import N */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, &T, NULL, NULL,
+                                  NULL, NULL)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import E */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+                                  NULL, &T)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import D */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, NULL,
+                                  &T, NULL)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import P */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, &T, NULL,
+                                  NULL, NULL)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import Q */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_rsa_import(rsa, NULL, NULL, &T,
+                                  NULL, NULL)) != 0) {
+        goto cleanup;
+    }
+
+#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT)
+    /*
+     * The RSA CRT parameters DP, DQ and QP are nominally redundant, in
+     * that they can be easily recomputed from D, P and Q. However by
+     * parsing them from the PKCS1 structure it is possible to avoid
+     * recalculating them which both reduces the overhead of loading
+     * RSA private keys into memory and also avoids side channels which
+     * can arise when computing those values, since all of D, P, and Q
+     * are secret. See https://eprint.iacr.org/2020/055 for a
+     * description of one such attack.
+     */
+
+    /* Import DP */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->DP, &T)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import DQ */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->DQ, &T)) != 0) {
+        goto cleanup;
+    }
+
+    /* Import QP */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = mbedtls_mpi_copy(&rsa->QP, &T)) != 0) {
+        goto cleanup;
+    }
+
+#else
+    /* Verify existence of the CRT params */
+    if ((ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0 ||
+        (ret = asn1_get_nonzero_mpi(&p, end, &T)) != 0) {
+        goto cleanup;
+    }
+#endif
+
+    /* rsa_complete() doesn't complete anything with the default
+     * implementation but is still called:
+     * - for the benefit of alternative implementation that may want to
+     *   pre-compute stuff beyond what's provided (eg Montgomery factors)
+     * - as is also sanity-checks the key
+     *
+     * Furthermore, we also check the public part for consistency with
+     * mbedtls_pk_parse_pubkey(), as it includes size minima for example.
+     */
+    if ((ret = mbedtls_rsa_complete(rsa)) != 0 ||
+        (ret = mbedtls_rsa_check_pubkey(rsa)) != 0) {
+        goto cleanup;
+    }
+
+    if (p != end) {
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+
+cleanup:
+
+    mbedtls_mpi_free(&T);
+
+    if (ret != 0) {
+        mbedtls_rsa_free(rsa);
+    }
+
+    return ret;
+}
+
+int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen)
+{
+    unsigned char *p = (unsigned char *) key;
+    unsigned char *end = (unsigned char *) (key + keylen);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len;
+
+    /*
+     *  RSAPublicKey ::= SEQUENCE {
+     *      modulus           INTEGER,  -- n
+     *      publicExponent    INTEGER   -- e
+     *  }
+     */
+
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return ret;
+    }
+
+    if (end != p + len) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    /* Import N */
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_rsa_import_raw(rsa, p, len, NULL, 0, NULL, 0,
+                                      NULL, 0, NULL, 0)) != 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    p += len;
+
+    /* Import E */
+    if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER)) != 0) {
+        return ret;
+    }
+
+    if ((ret = mbedtls_rsa_import_raw(rsa, NULL, 0, NULL, 0, NULL, 0,
+                                      NULL, 0, p, len)) != 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    p += len;
+
+    if (mbedtls_rsa_complete(rsa) != 0 ||
+        mbedtls_rsa_check_pubkey(rsa) != 0) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+
+    if (p != end) {
+        return MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+
+    return 0;
+}
+
+int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
+                          unsigned char **p)
+{
+    size_t len = 0;
+    int ret;
+
+    mbedtls_mpi T; /* Temporary holding the exported parameters */
+
+    /*
+     * Export the parameters one after another to avoid simultaneous copies.
+     */
+
+    mbedtls_mpi_init(&T);
+
+    /* Export QP */
+    if ((ret = mbedtls_rsa_export_crt(rsa, NULL, NULL, &T)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export DQ */
+    if ((ret = mbedtls_rsa_export_crt(rsa, NULL, &T, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export DP */
+    if ((ret = mbedtls_rsa_export_crt(rsa, &T, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export Q */
+    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, &T, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export P */
+    if ((ret = mbedtls_rsa_export(rsa, NULL, &T, NULL, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export D */
+    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, &T, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export E */
+    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export N */
+    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+end_of_export:
+
+    mbedtls_mpi_free(&T);
+    if (ret < 0) {
+        return ret;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_int(p, start, 0));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start,
+                                                     MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    return (int) len;
+}
+
+/*
+ *  RSAPublicKey ::= SEQUENCE {
+ *      modulus           INTEGER,  -- n
+ *      publicExponent    INTEGER   -- e
+ *  }
+ */
+int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
+                             unsigned char **p)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0;
+    mbedtls_mpi T;
+
+    mbedtls_mpi_init(&T);
+
+    /* Export E */
+    if ((ret = mbedtls_rsa_export(rsa, NULL, NULL, NULL, NULL, &T)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+    /* Export N */
+    if ((ret = mbedtls_rsa_export(rsa, &T, NULL, NULL, NULL, NULL)) != 0 ||
+        (ret = mbedtls_asn1_write_mpi(p, start, &T)) < 0) {
+        goto end_of_export;
+    }
+    len += ret;
+
+end_of_export:
+
+    mbedtls_mpi_free(&T);
+    if (ret < 0) {
+        return ret;
+    }
+
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(p, start, len));
+    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(p, start, MBEDTLS_ASN1_CONSTRUCTED |
+                                                     MBEDTLS_ASN1_SEQUENCE));
+
+    return (int) len;
+}
+
+#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
+
+/** This function performs the unpadding part of a PKCS#1 v1.5 decryption
+ *  operation (EME-PKCS1-v1_5 decoding).
+ *
+ * \note The return value from this function is a sensitive value
+ *       (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen
+ *       in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING
+ *       is often a situation that an attacker can provoke and leaking which
+ *       one is the result is precisely the information the attacker wants.
+ *
+ * \param input          The input buffer which is the payload inside PKCS#1v1.5
+ *                       encryption padding, called the "encoded message EM"
+ *                       by the terminology.
+ * \param ilen           The length of the payload in the \p input buffer.
+ * \param output         The buffer for the payload, called "message M" by the
+ *                       PKCS#1 terminology. This must be a writable buffer of
+ *                       length \p output_max_len bytes.
+ * \param olen           The address at which to store the length of
+ *                       the payload. This must not be \c NULL.
+ * \param output_max_len The length in bytes of the output buffer \p output.
+ *
+ * \return      \c 0 on success.
+ * \return      #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE
+ *              The output buffer is too small for the unpadded payload.
+ * \return      #MBEDTLS_ERR_RSA_INVALID_PADDING
+ *              The input doesn't contain properly formatted padding.
+ */
+static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input,
+                                                size_t ilen,
+                                                unsigned char *output,
+                                                size_t output_max_len,
+                                                size_t *olen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i, plaintext_max_size;
+
+    /* The following variables take sensitive values: their value must
+     * not leak into the observable behavior of the function other than
+     * the designated outputs (output, olen, return value). Otherwise
+     * this would open the execution of the function to
+     * side-channel-based variants of the Bleichenbacher padding oracle
+     * attack. Potential side channels include overall timing, memory
+     * access patterns (especially visible to an adversary who has access
+     * to a shared memory cache), and branches (especially visible to
+     * an adversary who has access to a shared code cache or to a shared
+     * branch predictor). */
+    size_t pad_count = 0;
+    mbedtls_ct_condition_t bad;
+    mbedtls_ct_condition_t pad_done;
+    size_t plaintext_size = 0;
+    mbedtls_ct_condition_t output_too_large;
+
+    plaintext_max_size = (output_max_len > ilen - 11) ? ilen - 11
+                                                        : output_max_len;
+
+    /* Check and get padding length in constant time and constant
+     * memory trace. The first byte must be 0. */
+    bad = mbedtls_ct_bool(input[0]);
+
+
+    /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
+     * where PS must be at least 8 nonzero bytes. */
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(input[1], MBEDTLS_RSA_CRYPT));
+
+    /* Read the whole buffer. Set pad_done to nonzero if we find
+     * the 0x00 byte and remember the padding length in pad_count. */
+    pad_done = MBEDTLS_CT_FALSE;
+    for (i = 2; i < ilen; i++) {
+        mbedtls_ct_condition_t found = mbedtls_ct_uint_eq(input[i], 0);
+        pad_done   = mbedtls_ct_bool_or(pad_done, found);
+        pad_count += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1);
+    }
+
+    /* If pad_done is still zero, there's no data, only unfinished padding. */
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_not(pad_done));
+
+    /* There must be at least 8 bytes of padding. */
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_gt(8, pad_count));
+
+    /* If the padding is valid, set plaintext_size to the number of
+     * remaining bytes after stripping the padding. If the padding
+     * is invalid, avoid leaking this fact through the size of the
+     * output: use the maximum message size that fits in the output
+     * buffer. Do it without branches to avoid leaking the padding
+     * validity through timing. RSA keys are small enough that all the
+     * size_t values involved fit in unsigned int. */
+    plaintext_size = mbedtls_ct_uint_if(
+        bad, (unsigned) plaintext_max_size,
+        (unsigned) (ilen - pad_count - 3));
+
+    /* Set output_too_large to 0 if the plaintext fits in the output
+     * buffer and to 1 otherwise. */
+    output_too_large = mbedtls_ct_uint_gt(plaintext_size,
+                                          plaintext_max_size);
+
+    /* Set ret without branches to avoid timing attacks. Return:
+     * - INVALID_PADDING if the padding is bad (bad != 0).
+     * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
+     *   plaintext does not fit in the output buffer.
+     * - 0 if the padding is correct. */
+    ret = mbedtls_ct_error_if(
+        bad,
+        MBEDTLS_ERR_RSA_INVALID_PADDING,
+        mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE)
+        );
+
+    /* If the padding is bad or the plaintext is too large, zero the
+     * data that we're about to copy to the output buffer.
+     * We need to copy the same amount of data
+     * from the same buffer whether the padding is good or not to
+     * avoid leaking the padding validity through overall timing or
+     * through memory or cache access patterns. */
+    mbedtls_ct_zeroize_if(mbedtls_ct_bool_or(bad, output_too_large), input + 11, ilen - 11);
+
+    /* If the plaintext is too large, truncate it to the buffer size.
+     * Copy anyway to avoid revealing the length through timing, because
+     * revealing the length is as bad as revealing the padding validity
+     * for a Bleichenbacher attack. */
+    plaintext_size = mbedtls_ct_uint_if(output_too_large,
+                                        (unsigned) plaintext_max_size,
+                                        (unsigned) plaintext_size);
+
+    /* Move the plaintext to the leftmost position where it can start in
+     * the working buffer, i.e. make it start plaintext_max_size from
+     * the end of the buffer. Do this with a memory access trace that
+     * does not depend on the plaintext size. After this move, the
+     * starting location of the plaintext is no longer sensitive
+     * information. */
+    mbedtls_ct_memmove_left(input + ilen - plaintext_max_size,
+                            plaintext_max_size,
+                            plaintext_max_size - plaintext_size);
+
+    /* Finally copy the decrypted plaintext plus trailing zeros into the output
+     * buffer. If output_max_len is 0, then output may be an invalid pointer
+     * and the result of memcpy() would be undefined; prevent undefined
+     * behavior making sure to depend only on output_max_len (the size of the
+     * user-provided output buffer), which is independent from plaintext
+     * length, validity of padding, success of the decryption, and other
+     * secrets. */
+    if (output_max_len != 0) {
+        memcpy(output, input + ilen - plaintext_max_size, plaintext_max_size);
+    }
+
+    /* Report the amount of data we copied to the output buffer. In case
+     * of errors (bad padding or output too large), the value of *olen
+     * when this function returns is not specified. Making it equivalent
+     * to the good case limits the risks of leaking the padding validity. */
+    *olen = plaintext_size;
+
+    return ret;
+}
+
+#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */
+
 #if !defined(MBEDTLS_RSA_ALT)
 
 int mbedtls_rsa_import(mbedtls_rsa_context *ctx,
@@ -492,7 +991,7 @@ int mbedtls_rsa_set_padding(mbedtls_rsa_context *ctx, int padding,
     if ((padding == MBEDTLS_RSA_PKCS_V21) &&
         (hash_id != MBEDTLS_MD_NONE)) {
         /* Just make sure this hash is supported in this build. */
-        if (mbedtls_hash_info_psa_from_md(hash_id) == PSA_ALG_NONE) {
+        if (mbedtls_md_info_from_type(hash_id) == NULL) {
             return MBEDTLS_ERR_RSA_INVALID_PADDING;
         }
     }
@@ -520,6 +1019,14 @@ int mbedtls_rsa_get_md_alg(const mbedtls_rsa_context *ctx)
     return ctx->hash_id;
 }
 
+/*
+ * Get length in bits of RSA modulus
+ */
+size_t mbedtls_rsa_get_bitlen(const mbedtls_rsa_context *ctx)
+{
+    return mbedtls_mpi_bitlen(&ctx->N);
+}
+
 /*
  * Get length in bytes of RSA modulus
  */
@@ -528,7 +1035,6 @@ size_t mbedtls_rsa_get_len(const mbedtls_rsa_context *ctx)
     return ctx->len;
 }
 
-
 #if defined(MBEDTLS_GENPRIME)
 
 /*
@@ -559,7 +1065,12 @@ int mbedtls_rsa_gen_key(mbedtls_rsa_context *ctx,
     mbedtls_mpi_init(&G);
     mbedtls_mpi_init(&L);
 
-    if (nbits < 128 || exponent < 3 || nbits % 2 != 0) {
+    if (exponent < 3 || nbits % 2 != 0) {
+        ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+        goto cleanup;
+    }
+
+    if (nbits < MBEDTLS_RSA_GEN_KEY_MIN_BITS) {
         ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
         goto cleanup;
     }
@@ -751,7 +1262,7 @@ int mbedtls_rsa_public(mbedtls_rsa_context *ctx,
     }
 
     olen = ctx->len;
-    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod_unsafe(&T, &T, &ctx->E, &ctx->N, &ctx->RN));
     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
 
 cleanup:
@@ -834,6 +1345,45 @@ cleanup:
     return ret;
 }
 
+/*
+ * Unblind
+ * T = T * Vf mod N
+ */
+static int rsa_unblind(mbedtls_mpi *T, mbedtls_mpi *Vf, const mbedtls_mpi *N)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N->p);
+    const size_t nlimbs = N->n;
+    const size_t tlimbs = mbedtls_mpi_core_montmul_working_limbs(nlimbs);
+    mbedtls_mpi RR, M_T;
+
+    mbedtls_mpi_init(&RR);
+    mbedtls_mpi_init(&M_T);
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_core_get_mont_r2_unsafe(&RR, N));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(&M_T, tlimbs));
+
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(T, nlimbs));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_grow(Vf, nlimbs));
+
+    /* T = T * Vf mod N
+     * Reminder: montmul(A, B, N) = A * B * R^-1 mod N
+     * Usually both operands are multiplied by R mod N beforehand (by calling
+     * `to_mont_rep()` on them), yielding a result that's also * R mod N (aka
+     * "in the Montgomery domain"). Here we only multiply one operand by R mod
+     * N, so the result is directly what we want - no need to call
+     * `from_mont_rep()` on it. */
+    mbedtls_mpi_core_to_mont_rep(T->p, T->p, N->p, nlimbs, mm, RR.p, M_T.p);
+    mbedtls_mpi_core_montmul(T->p, T->p, Vf->p, nlimbs, N->p, nlimbs, mm, M_T.p);
+
+cleanup:
+
+    mbedtls_mpi_free(&RR);
+    mbedtls_mpi_free(&M_T);
+
+    return ret;
+}
+
 /*
  * Exponent blinding supposed to prevent side-channel attacks using multiple
  * traces of measurements to recover the RSA key. The more collisions are there,
@@ -881,23 +1431,14 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     /* Temporaries holding the blinded exponents for
      * the mod p resp. mod q computation (if used). */
     mbedtls_mpi DP_blind, DQ_blind;
-
-    /* Pointers to actual exponents to be used - either the unblinded
-     * or the blinded ones, depending on the presence of a PRNG. */
-    mbedtls_mpi *DP = &ctx->DP;
-    mbedtls_mpi *DQ = &ctx->DQ;
 #else
     /* Temporary holding the blinded exponent (if used). */
     mbedtls_mpi D_blind;
-
-    /* Pointer to actual exponent to be used - either the unblinded
-     * or the blinded one, depending on the presence of a PRNG. */
-    mbedtls_mpi *D = &ctx->D;
 #endif /* MBEDTLS_RSA_NO_CRT */
 
     /* Temporaries holding the initial input and the double
      * checked result; should be the same in the end. */
-    mbedtls_mpi I, C;
+    mbedtls_mpi input_blinded, check_result_blinded;
 
     if (f_rng == NULL) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
@@ -932,8 +1473,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     mbedtls_mpi_init(&TP); mbedtls_mpi_init(&TQ);
 #endif
 
-    mbedtls_mpi_init(&I);
-    mbedtls_mpi_init(&C);
+    mbedtls_mpi_init(&input_blinded);
+    mbedtls_mpi_init(&check_result_blinded);
 
     /* End of MPI initialization */
 
@@ -943,8 +1484,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
         goto cleanup;
     }
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&I, &T));
-
     /*
      * Blinding
      * T = T * Vi mod N
@@ -953,6 +1492,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vi));
     MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
 
+    MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&input_blinded, &T));
+
     /*
      * Exponent blinding
      */
@@ -968,8 +1509,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &P1, &Q1));
     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&D_blind, &D_blind, &R));
     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&D_blind, &D_blind, &ctx->D));
-
-    D = &D_blind;
 #else
     /*
      * DP_blind = ( P - 1 ) * R + DP
@@ -980,8 +1519,6 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DP_blind, &DP_blind,
                                         &ctx->DP));
 
-    DP = &DP_blind;
-
     /*
      * DQ_blind = ( Q - 1 ) * R + DQ
      */
@@ -990,12 +1527,10 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&DQ_blind, &Q1, &R));
     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&DQ_blind, &DQ_blind,
                                         &ctx->DQ));
-
-    DQ = &DQ_blind;
 #endif /* MBEDTLS_RSA_NO_CRT */
 
 #if defined(MBEDTLS_RSA_NO_CRT)
-    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, D, &ctx->N, &ctx->RN));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&T, &T, &D_blind, &ctx->N, &ctx->RN));
 #else
     /*
      * Faster decryption using the CRT
@@ -1004,8 +1539,8 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
      * TQ = input ^ dQ mod Q
      */
 
-    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, DP, &ctx->P, &ctx->RP));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, DQ, &ctx->Q, &ctx->RQ));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TP, &T, &DP_blind, &ctx->P, &ctx->RP));
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&TQ, &T, &DQ_blind, &ctx->Q, &ctx->RQ));
 
     /*
      * T = (TP - TQ) * (Q^-1 mod P) mod P
@@ -1021,21 +1556,20 @@ int mbedtls_rsa_private(mbedtls_rsa_context *ctx,
     MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&T, &TQ, &TP));
 #endif /* MBEDTLS_RSA_NO_CRT */
 
-    /*
-     * Unblind
-     * T = T * Vf mod N
-     */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, &T, &ctx->Vf));
-    MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&T, &T, &ctx->N));
-
     /* Verify the result to prevent glitching attacks. */
-    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&C, &T, &ctx->E,
+    MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&check_result_blinded, &T, &ctx->E,
                                         &ctx->N, &ctx->RN));
-    if (mbedtls_mpi_cmp_mpi(&C, &I) != 0) {
+    if (mbedtls_mpi_cmp_mpi(&check_result_blinded, &input_blinded) != 0) {
         ret = MBEDTLS_ERR_RSA_VERIFY_FAILED;
         goto cleanup;
     }
 
+    /*
+     * Unblind
+     * T = T * Vf mod N
+     */
+    MBEDTLS_MPI_CHK(rsa_unblind(&T, &ctx->Vf, &ctx->N));
+
     olen = ctx->len;
     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&T, output, olen));
 
@@ -1063,8 +1597,8 @@ cleanup:
     mbedtls_mpi_free(&TP); mbedtls_mpi_free(&TQ);
 #endif
 
-    mbedtls_mpi_free(&C);
-    mbedtls_mpi_free(&I);
+    mbedtls_mpi_free(&check_result_blinded);
+    mbedtls_mpi_free(&input_blinded);
 
     if (ret != 0 && ret >= -0x007f) {
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret);
@@ -1090,8 +1624,7 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
     unsigned char *p;
     unsigned int hlen;
     size_t i, use_len;
-    unsigned char mask[MBEDTLS_HASH_MAX_SIZE];
-#if defined(MBEDTLS_MD_C)
+    unsigned char mask[MBEDTLS_MD_MAX_SIZE];
     int ret = 0;
     const mbedtls_md_info_t *md_info;
     mbedtls_md_context_t md_ctx;
@@ -1108,14 +1641,6 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
     }
 
     hlen = mbedtls_md_get_size(md_info);
-#else
-    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
-    psa_status_t status = PSA_SUCCESS;
-    size_t out_len;
-
-    hlen = PSA_HASH_LENGTH(alg);
-#endif
 
     memset(mask, 0, sizeof(mask));
     memset(counter, 0, 4);
@@ -1129,7 +1654,6 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
             use_len = dlen;
         }
 
-#if defined(MBEDTLS_MD_C)
         if ((ret = mbedtls_md_starts(&md_ctx)) != 0) {
             goto exit;
         }
@@ -1142,21 +1666,6 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
         if ((ret = mbedtls_md_finish(&md_ctx, mask)) != 0) {
             goto exit;
         }
-#else
-        if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
-            goto exit;
-        }
-        if ((status = psa_hash_update(&op, src, slen)) != PSA_SUCCESS) {
-            goto exit;
-        }
-        if ((status = psa_hash_update(&op, counter, 4)) != PSA_SUCCESS) {
-            goto exit;
-        }
-        status = psa_hash_finish(&op, mask, sizeof(mask), &out_len);
-        if (status != PSA_SUCCESS) {
-            goto exit;
-        }
-#endif
 
         for (i = 0; i < use_len; ++i) {
             *p++ ^= mask[i];
@@ -1169,15 +1678,9 @@ static int mgf_mask(unsigned char *dst, size_t dlen, unsigned char *src,
 
 exit:
     mbedtls_platform_zeroize(mask, sizeof(mask));
-#if defined(MBEDTLS_MD_C)
     mbedtls_md_free(&md_ctx);
 
     return ret;
-#else
-    psa_hash_abort(&op);
-
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif
 }
 
 /**
@@ -1196,7 +1699,6 @@ static int hash_mprime(const unsigned char *hash, size_t hlen,
 {
     const unsigned char zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
 
-#if defined(MBEDTLS_MD_C)
     mbedtls_md_context_t md_ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -1229,35 +1731,6 @@ exit:
     mbedtls_md_free(&md_ctx);
 
     return ret;
-#else
-    psa_hash_operation_t op = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    size_t out_size = PSA_HASH_LENGTH(alg);
-    size_t out_len;
-
-    if ((status = psa_hash_setup(&op, alg)) != PSA_SUCCESS) {
-        goto exit;
-    }
-    if ((status = psa_hash_update(&op, zeros, sizeof(zeros))) != PSA_SUCCESS) {
-        goto exit;
-    }
-    if ((status = psa_hash_update(&op, hash, hlen)) != PSA_SUCCESS) {
-        goto exit;
-    }
-    if ((status = psa_hash_update(&op, salt, slen)) != PSA_SUCCESS) {
-        goto exit;
-    }
-    status = psa_hash_finish(&op, out, out_size, &out_len);
-    if (status != PSA_SUCCESS) {
-        goto exit;
-    }
-
-exit:
-    psa_hash_abort(&op);
-
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif /* !MBEDTLS_MD_C */
 }
 
 /**
@@ -1272,7 +1745,6 @@ static int compute_hash(mbedtls_md_type_t md_alg,
                         const unsigned char *input, size_t ilen,
                         unsigned char *output)
 {
-#if defined(MBEDTLS_MD_C)
     const mbedtls_md_info_t *md_info;
 
     md_info = mbedtls_md_info_from_type(md_alg);
@@ -1281,16 +1753,6 @@ static int compute_hash(mbedtls_md_type_t md_alg,
     }
 
     return mbedtls_md(md_info, input, ilen, output);
-#else
-    psa_algorithm_t alg = mbedtls_psa_translate_md(md_alg);
-    psa_status_t status;
-    size_t out_size = PSA_HASH_LENGTH(alg);
-    size_t out_len;
-
-    status = psa_hash_compute(alg, input, ilen, output, out_size, &out_len);
-
-    return PSA_TO_MBEDTLS_ERR(status);
-#endif /* !MBEDTLS_MD_C */
 }
 #endif /* MBEDTLS_PKCS1_V21 */
 
@@ -1315,7 +1777,7 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
-    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id);
     if (hlen == 0) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -1352,13 +1814,13 @@ int mbedtls_rsa_rsaes_oaep_encrypt(mbedtls_rsa_context *ctx,
 
     /* maskedDB: Apply dbMask to DB */
     if ((ret = mgf_mask(output + hlen + 1, olen - hlen - 1, output + 1, hlen,
-                        ctx->hash_id)) != 0) {
+                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {
         return ret;
     }
 
     /* maskedSeed: Apply seedMask to seed */
     if ((ret = mgf_mask(output + 1, hlen, output + hlen + 1, olen - hlen - 1,
-                        ctx->hash_id)) != 0) {
+                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {
         return ret;
     }
 
@@ -1464,9 +1926,10 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t ilen, i, pad_len;
-    unsigned char *p, bad, pad_done;
+    unsigned char *p;
+    mbedtls_ct_condition_t bad, in_padding;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
-    unsigned char lhash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
     unsigned int hlen;
 
     /*
@@ -1482,7 +1945,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
-    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    hlen = mbedtls_md_get_size_from_type((mbedtls_md_type_t) ctx->hash_id);
     if (hlen == 0) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -1509,10 +1972,10 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
      */
     /* seed: Apply seedMask to maskedSeed */
     if ((ret = mgf_mask(buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1,
-                        ctx->hash_id)) != 0 ||
+                        (mbedtls_md_type_t) ctx->hash_id)) != 0 ||
         /* DB: Apply dbMask to maskedDB */
         (ret = mgf_mask(buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen,
-                        ctx->hash_id)) != 0) {
+                        (mbedtls_md_type_t) ctx->hash_id)) != 0) {
         goto cleanup;
     }
 
@@ -1527,28 +1990,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
      * Check contents, in "constant-time"
      */
     p = buf;
-    bad = 0;
 
-    bad |= *p++; /* First byte must be 0 */
+    bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */
 
     p += hlen; /* Skip seed */
 
     /* Check lHash */
-    for (i = 0; i < hlen; i++) {
-        bad |= lhash[i] ^ *p++;
-    }
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(mbedtls_ct_memcmp(lhash, p, hlen)));
+    p += hlen;
 
     /* Get zero-padding len, but always read till end of buffer
      * (minus one, for the 01 byte) */
     pad_len = 0;
-    pad_done = 0;
+    in_padding = MBEDTLS_CT_TRUE;
     for (i = 0; i < ilen - 2 * hlen - 2; i++) {
-        pad_done |= p[i];
-        pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1;
+        in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0));
+        pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1);
     }
 
     p += pad_len;
-    bad |= *p++ ^ 0x01;
+    bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01));
 
     /*
      * The only information "leaked" is whether the padding was correct or not
@@ -1556,17 +2017,17 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx,
      * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
      * the different error conditions.
      */
-    if (bad != 0) {
+    if (bad != MBEDTLS_CT_FALSE) {
         ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
         goto cleanup;
     }
 
-    if (ilen - (p - buf) > output_max_len) {
+    if (ilen - ((size_t) (p - buf)) > output_max_len) {
         ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
         goto cleanup;
     }
 
-    *olen = ilen - (p - buf);
+    *olen = ilen - ((size_t) (p - buf));
     if (*olen != 0) {
         memcpy(output, p, *olen);
     }
@@ -1653,14 +2114,14 @@ int mbedtls_rsa_pkcs1_decrypt(mbedtls_rsa_context *ctx,
 }
 
 #if defined(MBEDTLS_PKCS1_V21)
-static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
-                               int (*f_rng)(void *, unsigned char *, size_t),
-                               void *p_rng,
-                               mbedtls_md_type_t md_alg,
-                               unsigned int hashlen,
-                               const unsigned char *hash,
-                               int saltlen,
-                               unsigned char *sig)
+static int rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,
+                                             int (*f_rng)(void *, unsigned char *, size_t),
+                                             void *p_rng,
+                                             mbedtls_md_type_t md_alg,
+                                             unsigned int hashlen,
+                                             const unsigned char *hash,
+                                             int saltlen,
+                                             unsigned char *sig)
 {
     size_t olen;
     unsigned char *p = sig;
@@ -1668,15 +2129,12 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
     size_t slen, min_slen, hlen, offset = 0;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t msb;
+    mbedtls_md_type_t hash_id;
 
     if ((md_alg != MBEDTLS_MD_NONE || hashlen != 0) && hash == NULL) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
 
-    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
-        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
-    }
-
     if (f_rng == NULL) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -1685,7 +2143,7 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
 
     if (md_alg != MBEDTLS_MD_NONE) {
         /* Gather length of hash to sign */
-        size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
+        size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg);
         if (exp_hashlen == 0) {
             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
         }
@@ -1695,7 +2153,11 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
         }
     }
 
-    hlen = mbedtls_hash_info_get_size((mbedtls_md_type_t) ctx->hash_id);
+    hash_id = (mbedtls_md_type_t) ctx->hash_id;
+    if (hash_id == MBEDTLS_MD_NONE) {
+        hash_id = md_alg;
+    }
+    hlen = mbedtls_md_get_size_from_type(hash_id);
     if (hlen == 0) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -1738,7 +2200,7 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
     p += slen;
 
     /* Generate H = Hash( M' ) */
-    ret = hash_mprime(hash, hashlen, salt, slen, p, ctx->hash_id);
+    ret = hash_mprime(hash, hashlen, salt, slen, p, hash_id);
     if (ret != 0) {
         return ret;
     }
@@ -1749,8 +2211,7 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
     }
 
     /* maskedDB: Apply dbMask to DB */
-    ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen,
-                   ctx->hash_id);
+    ret = mgf_mask(sig + offset, olen - hlen - 1 - offset, p, hlen, hash_id);
     if (ret != 0) {
         return ret;
     }
@@ -1767,6 +2228,37 @@ static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
     return mbedtls_rsa_private(ctx, f_rng, p_rng, sig, sig);
 }
 
+static int rsa_rsassa_pss_sign(mbedtls_rsa_context *ctx,
+                               int (*f_rng)(void *, unsigned char *, size_t),
+                               void *p_rng,
+                               mbedtls_md_type_t md_alg,
+                               unsigned int hashlen,
+                               const unsigned char *hash,
+                               int saltlen,
+                               unsigned char *sig)
+{
+    if (ctx->padding != MBEDTLS_RSA_PKCS_V21) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+    if ((ctx->hash_id == MBEDTLS_MD_NONE) && (md_alg == MBEDTLS_MD_NONE)) {
+        return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
+    }
+    return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg, hashlen, hash, saltlen,
+                                             sig);
+}
+
+int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,
+                                              int (*f_rng)(void *, unsigned char *, size_t),
+                                              void *p_rng,
+                                              mbedtls_md_type_t md_alg,
+                                              unsigned int hashlen,
+                                              const unsigned char *hash,
+                                              unsigned char *sig)
+{
+    return rsa_rsassa_pss_sign_no_mode_check(ctx, f_rng, p_rng, md_alg,
+                                             hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig);
+}
+
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with
  * the option to pass in the salt length.
@@ -1784,7 +2276,6 @@ int mbedtls_rsa_rsassa_pss_sign_ext(mbedtls_rsa_context *ctx,
                                hashlen, hash, saltlen, sig);
 }
 
-
 /*
  * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function
  */
@@ -1836,7 +2327,7 @@ static int rsa_rsassa_pkcs1_v15_encode(mbedtls_md_type_t md_alg,
 
     /* Are we signing hashed or raw data? */
     if (md_alg != MBEDTLS_MD_NONE) {
-        unsigned char md_size = mbedtls_hash_info_get_size(md_alg);
+        unsigned char md_size = mbedtls_md_get_size_from_type(md_alg);
         if (md_size == 0) {
             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
         }
@@ -1997,10 +2488,8 @@ int mbedtls_rsa_rsassa_pkcs1_v15_sign(mbedtls_rsa_context *ctx,
     memcpy(sig, sig_try, ctx->len);
 
 cleanup:
-    mbedtls_platform_zeroize(sig_try, ctx->len);
-    mbedtls_platform_zeroize(verif, ctx->len);
-    mbedtls_free(sig_try);
-    mbedtls_free(verif);
+    mbedtls_zeroize_and_free(sig_try, ctx->len);
+    mbedtls_zeroize_and_free(verif, ctx->len);
 
     if (ret != 0) {
         memset(sig, '!', ctx->len);
@@ -2058,7 +2547,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
     size_t siglen;
     unsigned char *p;
     unsigned char *hash_start;
-    unsigned char result[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char result[MBEDTLS_MD_MAX_SIZE];
     unsigned int hlen;
     size_t observed_salt_len, msb;
     unsigned char buf[MBEDTLS_MPI_MAX_SIZE] = { 0 };
@@ -2087,7 +2576,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
 
     if (md_alg != MBEDTLS_MD_NONE) {
         /* Gather length of hash to sign */
-        size_t exp_hashlen = mbedtls_hash_info_get_size(md_alg);
+        size_t exp_hashlen = mbedtls_md_get_size_from_type(md_alg);
         if (exp_hashlen == 0) {
             return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
         }
@@ -2097,7 +2586,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
         }
     }
 
-    hlen = mbedtls_hash_info_get_size(mgf1_hash_id);
+    hlen = mbedtls_md_get_size_from_type(mgf1_hash_id);
     if (hlen == 0) {
         return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     }
@@ -2137,7 +2626,7 @@ int mbedtls_rsa_rsassa_pss_verify_ext(mbedtls_rsa_context *ctx,
         return MBEDTLS_ERR_RSA_INVALID_PADDING;
     }
 
-    observed_salt_len = hash_start - p;
+    observed_salt_len = (size_t) (hash_start - p);
 
     if (expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY &&
         observed_salt_len != (size_t) expected_salt_len) {
@@ -2244,13 +2733,11 @@ int mbedtls_rsa_rsassa_pkcs1_v15_verify(mbedtls_rsa_context *ctx,
 cleanup:
 
     if (encoded != NULL) {
-        mbedtls_platform_zeroize(encoded, sig_len);
-        mbedtls_free(encoded);
+        mbedtls_zeroize_and_free(encoded, sig_len);
     }
 
     if (encoded_expected != NULL) {
-        mbedtls_platform_zeroize(encoded_expected, sig_len);
-        mbedtls_free(encoded_expected);
+        mbedtls_zeroize_and_free(encoded_expected, sig_len);
     }
 
     return ret;
@@ -2367,7 +2854,6 @@ void mbedtls_rsa_free(mbedtls_rsa_context *ctx)
 
 #if defined(MBEDTLS_SELF_TEST)
 
-#include "mbedtls/md.h"
 
 /*
  * Example RSA-1024 keypair, for test purposes
@@ -2445,7 +2931,7 @@ int mbedtls_rsa_self_test(int verbose)
     unsigned char rsa_plaintext[PT_LEN];
     unsigned char rsa_decrypted[PT_LEN];
     unsigned char rsa_ciphertext[KEY_LEN];
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     unsigned char sha1sum[20];
 #endif
 
@@ -2526,7 +3012,7 @@ int mbedtls_rsa_self_test(int verbose)
         mbedtls_printf("passed\n");
     }
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     if (verbose != 0) {
         mbedtls_printf("  PKCS#1 data sign  : ");
     }
@@ -2568,7 +3054,7 @@ int mbedtls_rsa_self_test(int verbose)
     if (verbose != 0) {
         mbedtls_printf("passed\n");
     }
-#endif /* MBEDTLS_SHA1_C */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
     if (verbose != 0) {
         mbedtls_printf("\n");
diff --git a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c
index 3451469b982c513f943c5b06a8da33c5b95656c1..5c265a9921b5174ce5b20fdc5c5b75377fed7c17 100644
--- a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c
+++ b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.c
@@ -2,19 +2,7 @@
  *  Helper functions for the RSA module
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  *
  */
 
@@ -126,7 +114,7 @@ int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
     }
 
     for (; attempt < num_primes; ++attempt) {
-        mbedtls_mpi_lset(&K, primes[attempt]);
+        MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
 
         /* Check if gcd(K,N) = 1 */
         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
diff --git a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h
index 3b22ba853556169cbe5ed899edc7fa4ab2af44fa..052b02491e10bd3f5c885dd3acabb5b91bbb4ad5 100644
--- a/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h
+++ b/lib/libmbedtls/mbedtls/library/rsa_alt_helpers.h
@@ -36,24 +36,10 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
-
-#ifndef MBEDTLS_RSA_INTERNAL_H
-#define MBEDTLS_RSA_INTERNAL_H
+#ifndef MBEDTLS_RSA_ALT_HELPERS_H
+#define MBEDTLS_RSA_ALT_HELPERS_H
 
 #include "mbedtls/build_info.h"
 
diff --git a/lib/libmbedtls/mbedtls/library/rsa_internal.h b/lib/libmbedtls/mbedtls/library/rsa_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..f79c3b712283b66e92d6726671870cb7928f6a0c
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/rsa_internal.h
@@ -0,0 +1,121 @@
+/**
+ * \file rsa_internal.h
+ *
+ * \brief Internal-only RSA public-key cryptosystem API.
+ *
+ * This file declares RSA-related functions that are to be used
+ * only from within the Mbed TLS library itself.
+ *
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_RSA_INTERNAL_H
+#define MBEDTLS_RSA_INTERNAL_H
+
+#include "mbedtls/rsa.h"
+#include "mbedtls/asn1.h"
+
+/**
+ * \brief           Parse a PKCS#1 (ASN.1) encoded private RSA key.
+ *
+ * \param rsa       The RSA context where parsed data will be stored.
+ * \param key       The buffer that contains the key.
+ * \param keylen    The length of the key buffer in bytes.
+ *
+ * \return          0 on success.
+ * \return          MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
+ * \return          MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
+ *                  parsing data.
+ * \return          MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
+ *                  provided key fail.
+ */
+int mbedtls_rsa_parse_key(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
+
+/**
+ * \brief           Parse a PKCS#1 (ASN.1) encoded public RSA key.
+ *
+ * \param rsa       The RSA context where parsed data will be stored.
+ * \param key       The buffer that contains the key.
+ * \param keylen    The length of the key buffer in bytes.
+ *
+ * \return          0 on success.
+ * \return          MBEDTLS_ERR_ASN1_xxx in case of ASN.1 parsing errors.
+ * \return          MBEDTLS_ERR_RSA_xxx in case of RSA internal failures while
+ *                  parsing data.
+ * \return          MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if validity checks on the
+ *                  provided key fail.
+ */
+int mbedtls_rsa_parse_pubkey(mbedtls_rsa_context *rsa, const unsigned char *key, size_t keylen);
+
+/**
+ * \brief           Write a PKCS#1 (ASN.1) encoded private RSA key.
+ *
+ * \param rsa       The RSA context which contains the data to be written.
+ * \param start     Beginning of the buffer that will be filled with the
+ *                  private key.
+ * \param p         End of the buffer that will be filled with the private key.
+ *                  On successful return, the referenced pointer will be
+ *                  updated in order to point to the beginning of written data.
+ *
+ * \return          On success, the number of bytes written to the output buffer
+ *                  (i.e. a value > 0).
+ * \return          MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
+ *                  contain a valid key pair.
+ * \return          MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
+ *                  output buffer.
+ *
+ * \note            The output buffer is filled backward, i.e. starting from its
+ *                  end and moving toward its start.
+ */
+int mbedtls_rsa_write_key(const mbedtls_rsa_context *rsa, unsigned char *start,
+                          unsigned char **p);
+
+/**
+ * \brief           Parse a PKCS#1 (ASN.1) encoded public RSA key.
+ *
+ * \param rsa       The RSA context which contains the data to be written.
+ * \param start     Beginning of the buffer that will be filled with the
+ *                  private key.
+ * \param p         End of the buffer that will be filled with the private key.
+ *                  On successful return, the referenced pointer will be
+ *                  updated in order to point to the beginning of written data.
+ *
+ * \return          On success, the number of bytes written to the output buffer
+ *                  (i.e. a value > 0).
+ * \return          MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the RSA context does not
+ *                  contain a valid public key.
+ * \return          MBEDTLS_ERR_ASN1_xxx in case of failure while writing to the
+ *                  output buffer.
+ *
+ * \note            The output buffer is filled backward, i.e. starting from its
+ *                  end and moving toward its start.
+ */
+int mbedtls_rsa_write_pubkey(const mbedtls_rsa_context *rsa, unsigned char *start,
+                             unsigned char **p);
+
+#if defined(MBEDTLS_PKCS1_V21)
+/**
+ * \brief This function is analogue to \c mbedtls_rsa_rsassa_pss_sign().
+ *        The only difference between them is that this function is more flexible
+ *        on the parameters of \p ctx that are set with \c mbedtls_rsa_set_padding().
+ *
+ * \note  Compared to its counterpart, this function:
+ *        - does not check the padding setting of \p ctx.
+ *        - allows the hash_id of \p ctx to be MBEDTLS_MD_NONE,
+ *          in which case it uses \p md_alg as the hash_id.
+ *
+ * \note  Refer to \c mbedtls_rsa_rsassa_pss_sign() for a description
+ *        of the functioning and parameters of this function.
+ */
+int mbedtls_rsa_rsassa_pss_sign_no_mode_check(mbedtls_rsa_context *ctx,
+                                              int (*f_rng)(void *, unsigned char *, size_t),
+                                              void *p_rng,
+                                              mbedtls_md_type_t md_alg,
+                                              unsigned int hashlen,
+                                              const unsigned char *hash,
+                                              unsigned char *sig);
+#endif /* MBEDTLS_PKCS1_V21 */
+
+#endif /* rsa_internal.h */
diff --git a/lib/libmbedtls/mbedtls/library/sha1.c b/lib/libmbedtls/mbedtls/library/sha1.c
index 4c9cbf5e85afe37a3f77159cab804c73ff7eef80..dfbe481f39ac4b52bf131c9c104813f259129510 100644
--- a/lib/libmbedtls/mbedtls/library/sha1.c
+++ b/lib/libmbedtls/mbedtls/library/sha1.c
@@ -2,19 +2,7 @@
  *  FIPS-180-1 compliant SHA-1 implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The SHA-1 standard was published by NIST in 1993.
@@ -322,7 +310,7 @@ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx,
         memset(ctx->buffer + used, 0, 64 - used);
 
         if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {
-            return ret;
+            goto exit;
         }
 
         memset(ctx->buffer, 0, 56);
@@ -339,7 +327,7 @@ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx,
     MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
 
     if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) {
-        return ret;
+        goto exit;
     }
 
     /*
@@ -351,7 +339,11 @@ int mbedtls_sha1_finish(mbedtls_sha1_context *ctx,
     MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
     MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
 
-    return 0;
+    ret = 0;
+
+exit:
+    mbedtls_sha1_free(ctx);
+    return ret;
 }
 
 #endif /* !MBEDTLS_SHA1_ALT */
@@ -382,7 +374,6 @@ int mbedtls_sha1(const unsigned char *input,
 
 exit:
     mbedtls_sha1_free(&ctx);
-
     return ret;
 }
 
diff --git a/lib/libmbedtls/mbedtls/library/sha256.c b/lib/libmbedtls/mbedtls/library/sha256.c
index 08822f4413db90e159febeaeb2b2fe0952987027..159acccaeb38a9167195df23a22936c8b2ea7e5a 100644
--- a/lib/libmbedtls/mbedtls/library/sha256.c
+++ b/lib/libmbedtls/mbedtls/library/sha256.c
@@ -2,19 +2,7 @@
  *  FIPS-180-2 compliant SHA-256 implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The SHA-256 Secure Hash Standard was published by NIST in 2002.
@@ -22,8 +10,17 @@
  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
  */
 
-#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
-    defined(__clang__) && __clang_major__ >= 4
+#if defined(__clang__) &&  (__clang_major__ >= 4)
+
+/* Ideally, we would simply use MBEDTLS_ARCH_IS_ARMV8_A in the following #if,
+ * but that is defined by build_info.h, and we need this block to happen first. */
+#if defined(__ARM_ARCH) && (__ARM_ARCH_PROFILE == 'A')
+#if __ARM_ARCH >= 8
+#define MBEDTLS_SHA256_ARCH_IS_ARMV8_A
+#endif
+#endif
+
+#if defined(MBEDTLS_SHA256_ARCH_IS_ARMV8_A) && !defined(__ARM_FEATURE_CRYPTO)
 /* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
  *
  * The intrinsic declaration are guarded by predefined ACLE macros in clang:
@@ -31,7 +28,7 @@
  * By defining the macros ourselves we gain access to those declarations without
  * requiring -march on the command line.
  *
- * `arm_neon.h` could be included by any header file, so we put these defines
+ * `arm_neon.h` is included by common.h, so we put these defines
  * at the top of this file, before any includes.
  */
 #define __ARM_FEATURE_CRYPTO 1
@@ -44,6 +41,13 @@
 #define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
 #endif
 
+#endif /* defined(__clang__) &&  (__clang_major__ >= 4) */
+
+/* Ensure that SIG_SETMASK is defined when -std=c99 is used. */
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+
 #include "common.h"
 
 #if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
@@ -56,14 +60,34 @@
 
 #include "mbedtls/platform.h"
 
-#if defined(__aarch64__)
-#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
-    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#if defined(MBEDTLS_ARCH_IS_ARMV8_A)
+
+#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
+#       if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)
+#           if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
+#               warning "Target does not support NEON instructions"
+#               undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
+#           else
+#               error "Target does not support NEON instructions"
+#           endif
+#       endif
+#   endif
+
+#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 /* *INDENT-OFF* */
-#    if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
-#      if defined(__clang__)
+
+#   if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
+#      if defined(__ARMCOMPILER_VERSION)
+#        if __ARMCOMPILER_VERSION <= 6090000
+#          error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
+#        endif
+#          pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function)
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#      elif defined(__clang__)
 #        if __clang_major__ < 4
-#          error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#          error "A more recent Clang is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
 #        endif
 #        pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
 #        define MBEDTLS_POP_TARGET_PRAGMA
@@ -72,56 +96,65 @@
           *        intrinsics are missing. Missing intrinsics could be worked around.
           */
 #        if __GNUC__ < 6
-#          error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#          error "A more recent GCC is required for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
 #        else
 #          pragma GCC push_options
 #          pragma GCC target ("arch=armv8-a+crypto")
 #          define MBEDTLS_POP_TARGET_PRAGMA
 #        endif
 #      else
-#        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
+#        error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_*"
 #      endif
 #    endif
 /* *INDENT-ON* */
-#    include <arm_neon.h>
+
 #  endif
-#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#  if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 #    if defined(__unix__)
 #      if defined(__linux__)
 /* Our preferred method of detection is getauxval() */
 #        include <sys/auxv.h>
+/* These are not always defined via sys/auxv.h */
+#        if !defined(HWCAP_SHA2)
+#          define HWCAP_SHA2  (1 << 6)
+#        endif
+#        if !defined(HWCAP2_SHA2)
+#          define HWCAP2_SHA2 (1 << 3)
+#        endif
 #      endif
 /* Use SIGILL on Unix, and fall back to it on Linux */
 #      include <signal.h>
 #    endif
 #  endif
-#elif defined(_M_ARM64)
-#  if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
-    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
-#    include <arm64_neon.h>
-#  endif
-#else
-#  undef MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
-#  undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
+#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY
+#  undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
 #endif
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 /*
  * Capability detection code comes early, so we can disable
- * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
+ * MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT if no detection mechanism found
  */
-#if defined(HWCAP_SHA2)
+#if defined(MBEDTLS_ARCH_IS_ARM64) && defined(HWCAP_SHA2)
 static int mbedtls_a64_crypto_sha256_determine_support(void)
 {
     return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
 }
+#elif defined(MBEDTLS_ARCH_IS_ARM32) && defined(HWCAP2_SHA2)
+static int mbedtls_a64_crypto_sha256_determine_support(void)
+{
+    return (getauxval(AT_HWCAP2) & HWCAP2_SHA2) ? 1 : 0;
+}
 #elif defined(__APPLE__)
 static int mbedtls_a64_crypto_sha256_determine_support(void)
 {
     return 1;
 }
-#elif defined(_M_ARM64)
+#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
+#ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
+#endif
 #include <Windows.h>
 #include <processthreadsapi.h>
 
@@ -138,7 +171,7 @@ static int mbedtls_a64_crypto_sha256_determine_support(void)
 static jmp_buf return_from_sigill;
 
 /*
- * A64 SHA256 support detection via SIGILL
+ * Armv8-A SHA256 support detection via SIGILL
  */
 static void sigill_handler(int signal)
 {
@@ -165,7 +198,11 @@ static int mbedtls_a64_crypto_sha256_determine_support(void)
 
     if (setjmp(return_from_sigill) == 0) {         /* First return only */
         /* If this traps, we will return a second time from setjmp() with 1 */
-        asm ("sha256h q0, q0, v0.4s" : : : "v0");
+#if defined(MBEDTLS_ARCH_IS_ARM64)
+        asm volatile ("sha256h q0, q0, v0.4s" : : : "v0");
+#else
+        asm volatile ("sha256h.32 q0, q0, q0" : : : "q0");
+#endif
         ret = 1;
     }
 
@@ -175,11 +212,11 @@ static int mbedtls_a64_crypto_sha256_determine_support(void)
     return ret;
 }
 #else
-#warning "No mechanism to detect A64_CRYPTO found, using C code only"
-#undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+#warning "No mechanism to detect ARMV8_CRYPTO found, using C code only"
+#undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT
 #endif  /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */
 
-#endif  /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
+#endif  /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */
 
 #if !defined(MBEDTLS_SHA256_ALT)
 
@@ -281,10 +318,10 @@ static const uint32_t K[] =
 
 #endif
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
-    defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \
+    defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 #  define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many
 #  define mbedtls_internal_sha256_process_a64_crypto      mbedtls_internal_sha256_process
 #endif
@@ -307,10 +344,10 @@ static size_t mbedtls_internal_sha256_process_many_a64_crypto(
         uint32x4_t abcd_orig = abcd;
         uint32x4_t efgh_orig = efgh;
 
-        uint32x4_t sched0 = (uint32x4_t) vld1q_u8(msg + 16 * 0);
-        uint32x4_t sched1 = (uint32x4_t) vld1q_u8(msg + 16 * 1);
-        uint32x4_t sched2 = (uint32x4_t) vld1q_u8(msg + 16 * 2);
-        uint32x4_t sched3 = (uint32x4_t) vld1q_u8(msg + 16 * 3);
+        uint32x4_t sched0 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 0));
+        uint32x4_t sched1 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 1));
+        uint32x4_t sched2 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 2));
+        uint32x4_t sched3 = vreinterpretq_u32_u8(vld1q_u8(msg + 16 * 3));
 
 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__  /* Will be true if not defined */
                                                /* Untested on BE */
@@ -384,9 +421,9 @@ static size_t mbedtls_internal_sha256_process_many_a64_crypto(
     return processed;
 }
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 /*
- * This function is for internal use only if we are building both C and A64
+ * This function is for internal use only if we are building both C and Armv8-A
  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
  */
 static
@@ -399,6 +436,8 @@ int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
             SHA256_BLOCK_SIZE) ? 0 : -1;
 }
 
+#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
+
 #if defined(MBEDTLS_POP_TARGET_PRAGMA)
 #if defined(__clang__)
 #pragma clang attribute pop
@@ -408,16 +447,14 @@ int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
 #undef MBEDTLS_POP_TARGET_PRAGMA
 #endif
 
-#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
-
-#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 #define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
 #define mbedtls_internal_sha256_process_c      mbedtls_internal_sha256_process
 #endif
 
 
 #if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
-    !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+    !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 
 #define  SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
 #define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
@@ -445,9 +482,9 @@ int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
     } while (0)
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 /*
- * This function is for internal use only if we are building both C and A64
+ * This function is for internal use only if we are building both C and Armv8
  * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
  */
 static
@@ -537,10 +574,10 @@ int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
     return 0;
 }
 
-#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
 
 
-#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
+#if !defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
 
 static size_t mbedtls_internal_sha256_process_many_c(
     mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
@@ -561,10 +598,10 @@ static size_t mbedtls_internal_sha256_process_many_c(
     return processed;
 }
 
-#endif /* !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
+#endif /* !MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
 
 
-#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
 
 static int mbedtls_a64_crypto_sha256_has_support(void)
 {
@@ -599,7 +636,7 @@ int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
     }
 }
 
-#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
+#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */
 
 
 /*
@@ -666,6 +703,7 @@ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     uint32_t used;
     uint32_t high, low;
+    int truncated = 0;
 
     /*
      * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
@@ -682,7 +720,7 @@ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
         memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);
 
         if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
-            return ret;
+            goto exit;
         }
 
         memset(ctx->buffer, 0, 56);
@@ -699,7 +737,7 @@ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
     MBEDTLS_PUT_UINT32_BE(low,  ctx->buffer, 60);
 
     if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
-        return ret;
+        goto exit;
     }
 
     /*
@@ -713,7 +751,6 @@ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
     MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);
     MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);
 
-    int truncated = 0;
 #if defined(MBEDTLS_SHA224_C)
     truncated = ctx->is224;
 #endif
@@ -721,7 +758,11 @@ int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
         MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);
     }
 
-    return 0;
+    ret = 0;
+
+exit:
+    mbedtls_sha256_free(ctx);
+    return ret;
 }
 
 #endif /* !MBEDTLS_SHA256_ALT */
diff --git a/lib/libmbedtls/mbedtls/library/sha3.c b/lib/libmbedtls/mbedtls/library/sha3.c
new file mode 100644
index 0000000000000000000000000000000000000000..57385595f56558dddd61c81d6ad1dc48698a16a9
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/sha3.c
@@ -0,0 +1,721 @@
+/*
+ *  FIPS-202 compliant SHA3 implementation
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+/*
+ *  The SHA-3 Secure Hash Standard was published by NIST in 2015.
+ *
+ *  https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf
+ */
+
+#include "common.h"
+
+#if defined(MBEDTLS_SHA3_C)
+
+/*
+ * These macros select manually unrolled implementations of parts of the main permutation function.
+ *
+ * Unrolling has a major impact on both performance and code size. gcc performance benefits a lot
+ * from manually unrolling at higher optimisation levels.
+ *
+ * Depending on your size/perf priorities, compiler and target, it may be beneficial to adjust
+ * these; the defaults here should give sensible trade-offs for gcc and clang on aarch64 and
+ * x86-64.
+ */
+#if !defined(MBEDTLS_SHA3_THETA_UNROLL)
+    #define MBEDTLS_SHA3_THETA_UNROLL 0 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_CHI_UNROLL)
+    #if defined(__OPTIMIZE_SIZE__)
+        #define MBEDTLS_SHA3_CHI_UNROLL 0 //no-check-names
+    #else
+        #define MBEDTLS_SHA3_CHI_UNROLL 1 //no-check-names
+    #endif
+#endif
+#if !defined(MBEDTLS_SHA3_PI_UNROLL)
+    #define MBEDTLS_SHA3_PI_UNROLL 1 //no-check-names
+#endif
+#if !defined(MBEDTLS_SHA3_RHO_UNROLL)
+    #define MBEDTLS_SHA3_RHO_UNROLL 1 //no-check-names
+#endif
+
+#include "mbedtls/sha3.h"
+#include "mbedtls/platform_util.h"
+#include "mbedtls/error.h"
+
+#include <string.h>
+
+#if defined(MBEDTLS_SELF_TEST)
+#include "mbedtls/platform.h"
+#endif /* MBEDTLS_SELF_TEST */
+
+#define XOR_BYTE 0x6
+
+/* Precomputed masks for the iota transform.
+ *
+ * Each round uses a 64-bit mask value. In each mask values, only
+ * bits whose position is of the form 2^k-1 can be set, thus only
+ * 7 of 64 bits of the mask need to be known for each mask value.
+ *
+ * We use a compressed encoding of the mask where bits 63, 31 and 15
+ * are moved to bits 4-6. This allows us to make each mask value
+ * 1 byte rather than 8 bytes, saving 7*24 = 168 bytes of data (with
+ * perhaps a little variation due to alignment). Decompressing this
+ * requires a little code, but much less than the savings on the table.
+ *
+ * The impact on performance depends on the platform and compiler.
+ * There's a bit more computation, but less memory bandwidth. A quick
+ * benchmark on x86_64 shows a 7% speed improvement with GCC and a
+ * 5% speed penalty with Clang, compared to the naive uint64_t[24] table.
+ * YMMV.
+ */
+/* Helper macro to set the values of the higher bits in unused low positions */
+#define H(b63, b31, b15) (b63 << 6 | b31 << 5 | b15 << 4)
+static const uint8_t iota_r_packed[24] = {
+    H(0, 0, 0) | 0x01, H(0, 0, 1) | 0x82, H(1, 0, 1) | 0x8a, H(1, 1, 1) | 0x00,
+    H(0, 0, 1) | 0x8b, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x09,
+    H(0, 0, 0) | 0x8a, H(0, 0, 0) | 0x88, H(0, 1, 1) | 0x09, H(0, 1, 0) | 0x0a,
+    H(0, 1, 1) | 0x8b, H(1, 0, 0) | 0x8b, H(1, 0, 1) | 0x89, H(1, 0, 1) | 0x03,
+    H(1, 0, 1) | 0x02, H(1, 0, 0) | 0x80, H(0, 0, 1) | 0x0a, H(1, 1, 0) | 0x0a,
+    H(1, 1, 1) | 0x81, H(1, 0, 1) | 0x80, H(0, 1, 0) | 0x01, H(1, 1, 1) | 0x08,
+};
+#undef H
+
+static const uint32_t rho[6] = {
+    0x3f022425, 0x1c143a09, 0x2c3d3615, 0x27191713, 0x312b382e, 0x3e030832
+};
+
+static const uint32_t pi[6] = {
+    0x110b070a, 0x10050312, 0x04181508, 0x0d13170f, 0x0e14020c, 0x01060916
+};
+
+#define ROTR64(x, y) (((x) << (64U - (y))) | ((x) >> (y))) // 64-bit rotate right
+#define ABSORB(ctx, idx, v) do { ctx->state[(idx) >> 3] ^= ((uint64_t) (v)) << (((idx) & 0x7) << 3); \
+} while (0)
+#define SQUEEZE(ctx, idx) ((uint8_t) (ctx->state[(idx) >> 3] >> (((idx) & 0x7) << 3)))
+#define SWAP(x, y) do { uint64_t tmp = (x); (x) = (y); (y) = tmp; } while (0)
+
+/* The permutation function.  */
+static void keccak_f1600(mbedtls_sha3_context *ctx)
+{
+    uint64_t lane[5];
+    uint64_t *s = ctx->state;
+    int i;
+
+    for (int round = 0; round < 24; round++) {
+        uint64_t t;
+
+        /* Theta */
+#if MBEDTLS_SHA3_THETA_UNROLL == 0 //no-check-names
+        for (i = 0; i < 5; i++) {
+            lane[i] = s[i] ^ s[i + 5] ^ s[i + 10] ^ s[i + 15] ^ s[i + 20];
+        }
+        for (i = 0; i < 5; i++) {
+            t = lane[(i + 4) % 5] ^ ROTR64(lane[(i + 1) % 5], 63);
+            s[i] ^= t; s[i + 5] ^= t; s[i + 10] ^= t; s[i + 15] ^= t; s[i + 20] ^= t;
+        }
+#else
+        lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20];
+        lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21];
+        lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22];
+        lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23];
+        lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24];
+
+        t = lane[4] ^ ROTR64(lane[1], 63);
+        s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t;
+
+        t = lane[0] ^ ROTR64(lane[2], 63);
+        s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t;
+
+        t = lane[1] ^ ROTR64(lane[3], 63);
+        s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t;
+
+        t = lane[2] ^ ROTR64(lane[4], 63);
+        s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t;
+
+        t = lane[3] ^ ROTR64(lane[0], 63);
+        s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t;
+#endif
+
+        /* Rho */
+        for (i = 1; i < 25; i += 4) {
+            uint32_t r = rho[(i - 1) >> 2];
+#if MBEDTLS_SHA3_RHO_UNROLL == 0
+            for (int j = i; j < i + 4; j++) {
+                uint8_t r8 = (uint8_t) (r >> 24);
+                r <<= 8;
+                s[j] = ROTR64(s[j], r8);
+            }
+#else
+            s[i + 0] = ROTR64(s[i + 0], MBEDTLS_BYTE_3(r));
+            s[i + 1] = ROTR64(s[i + 1], MBEDTLS_BYTE_2(r));
+            s[i + 2] = ROTR64(s[i + 2], MBEDTLS_BYTE_1(r));
+            s[i + 3] = ROTR64(s[i + 3], MBEDTLS_BYTE_0(r));
+#endif
+        }
+
+        /* Pi */
+        t = s[1];
+#if MBEDTLS_SHA3_PI_UNROLL == 0
+        for (i = 0; i < 24; i += 4) {
+            uint32_t p = pi[i >> 2];
+            for (unsigned j = 0; j < 4; j++) {
+                SWAP(s[p & 0xff], t);
+                p >>= 8;
+            }
+        }
+#else
+        uint32_t p = pi[0];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[1];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[2];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[3];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[4];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+        p = pi[5];
+        SWAP(s[MBEDTLS_BYTE_0(p)], t); SWAP(s[MBEDTLS_BYTE_1(p)], t);
+        SWAP(s[MBEDTLS_BYTE_2(p)], t); SWAP(s[MBEDTLS_BYTE_3(p)], t);
+#endif
+
+        /* Chi */
+#if MBEDTLS_SHA3_CHI_UNROLL == 0 //no-check-names
+        for (i = 0; i <= 20; i += 5) {
+            lane[0] = s[i]; lane[1] = s[i + 1]; lane[2] = s[i + 2];
+            lane[3] = s[i + 3]; lane[4] = s[i + 4];
+            s[i + 0] ^= (~lane[1]) & lane[2];
+            s[i + 1] ^= (~lane[2]) & lane[3];
+            s[i + 2] ^= (~lane[3]) & lane[4];
+            s[i + 3] ^= (~lane[4]) & lane[0];
+            s[i + 4] ^= (~lane[0]) & lane[1];
+        }
+#else
+        lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4];
+        s[0] ^= (~lane[1]) & lane[2];
+        s[1] ^= (~lane[2]) & lane[3];
+        s[2] ^= (~lane[3]) & lane[4];
+        s[3] ^= (~lane[4]) & lane[0];
+        s[4] ^= (~lane[0]) & lane[1];
+
+        lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9];
+        s[5] ^= (~lane[1]) & lane[2];
+        s[6] ^= (~lane[2]) & lane[3];
+        s[7] ^= (~lane[3]) & lane[4];
+        s[8] ^= (~lane[4]) & lane[0];
+        s[9] ^= (~lane[0]) & lane[1];
+
+        lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14];
+        s[10] ^= (~lane[1]) & lane[2];
+        s[11] ^= (~lane[2]) & lane[3];
+        s[12] ^= (~lane[3]) & lane[4];
+        s[13] ^= (~lane[4]) & lane[0];
+        s[14] ^= (~lane[0]) & lane[1];
+
+        lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19];
+        s[15] ^= (~lane[1]) & lane[2];
+        s[16] ^= (~lane[2]) & lane[3];
+        s[17] ^= (~lane[3]) & lane[4];
+        s[18] ^= (~lane[4]) & lane[0];
+        s[19] ^= (~lane[0]) & lane[1];
+
+        lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24];
+        s[20] ^= (~lane[1]) & lane[2];
+        s[21] ^= (~lane[2]) & lane[3];
+        s[22] ^= (~lane[3]) & lane[4];
+        s[23] ^= (~lane[4]) & lane[0];
+        s[24] ^= (~lane[0]) & lane[1];
+#endif
+
+        /* Iota */
+        /* Decompress the round masks (see definition of rc) */
+        s[0] ^= ((iota_r_packed[round] & 0x40ull) << 57 |
+                 (iota_r_packed[round] & 0x20ull) << 26 |
+                 (iota_r_packed[round] & 0x10ull) << 11 |
+                 (iota_r_packed[round] & 0x8f));
+    }
+}
+
+void mbedtls_sha3_init(mbedtls_sha3_context *ctx)
+{
+    memset(ctx, 0, sizeof(mbedtls_sha3_context));
+}
+
+void mbedtls_sha3_free(mbedtls_sha3_context *ctx)
+{
+    if (ctx == NULL) {
+        return;
+    }
+
+    mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha3_context));
+}
+
+void mbedtls_sha3_clone(mbedtls_sha3_context *dst,
+                        const mbedtls_sha3_context *src)
+{
+    *dst = *src;
+}
+
+/*
+ * SHA-3 context setup
+ */
+int mbedtls_sha3_starts(mbedtls_sha3_context *ctx, mbedtls_sha3_id id)
+{
+    switch (id) {
+        case MBEDTLS_SHA3_224:
+            ctx->olen = 224 / 8;
+            ctx->max_block_size = 1152 / 8;
+            break;
+        case MBEDTLS_SHA3_256:
+            ctx->olen = 256 / 8;
+            ctx->max_block_size = 1088 / 8;
+            break;
+        case MBEDTLS_SHA3_384:
+            ctx->olen = 384 / 8;
+            ctx->max_block_size = 832 / 8;
+            break;
+        case MBEDTLS_SHA3_512:
+            ctx->olen = 512 / 8;
+            ctx->max_block_size = 576 / 8;
+            break;
+        default:
+            return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
+    }
+
+    memset(ctx->state, 0, sizeof(ctx->state));
+    ctx->index = 0;
+
+    return 0;
+}
+
+/*
+ * SHA-3 process buffer
+ */
+int mbedtls_sha3_update(mbedtls_sha3_context *ctx,
+                        const uint8_t *input,
+                        size_t ilen)
+{
+    if (ilen >= 8) {
+        // 8-byte align index
+        int align_bytes = 8 - (ctx->index % 8);
+        if (align_bytes) {
+            for (; align_bytes > 0; align_bytes--) {
+                ABSORB(ctx, ctx->index, *input++);
+                ilen--;
+                ctx->index++;
+            }
+            if ((ctx->index = ctx->index % ctx->max_block_size) == 0) {
+                keccak_f1600(ctx);
+            }
+        }
+
+        // process input in 8-byte chunks
+        while (ilen >= 8) {
+            ABSORB(ctx, ctx->index, MBEDTLS_GET_UINT64_LE(input, 0));
+            input += 8;
+            ilen -= 8;
+            if ((ctx->index = (ctx->index + 8) % ctx->max_block_size) == 0) {
+                keccak_f1600(ctx);
+            }
+        }
+    }
+
+    // handle remaining bytes
+    while (ilen-- > 0) {
+        ABSORB(ctx, ctx->index, *input++);
+        if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
+            keccak_f1600(ctx);
+        }
+    }
+
+    return 0;
+}
+
+int mbedtls_sha3_finish(mbedtls_sha3_context *ctx,
+                        uint8_t *output, size_t olen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    /* Catch SHA-3 families, with fixed output length */
+    if (ctx->olen > 0) {
+        if (ctx->olen > olen) {
+            ret = MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
+            goto exit;
+        }
+        olen = ctx->olen;
+    }
+
+    ABSORB(ctx, ctx->index, XOR_BYTE);
+    ABSORB(ctx, ctx->max_block_size - 1, 0x80);
+    keccak_f1600(ctx);
+    ctx->index = 0;
+
+    while (olen-- > 0) {
+        *output++ = SQUEEZE(ctx, ctx->index);
+
+        if ((ctx->index = (ctx->index + 1) % ctx->max_block_size) == 0) {
+            keccak_f1600(ctx);
+        }
+    }
+
+    ret = 0;
+
+exit:
+    mbedtls_sha3_free(ctx);
+    return ret;
+}
+
+/*
+ * output = SHA-3( input buffer )
+ */
+int mbedtls_sha3(mbedtls_sha3_id id, const uint8_t *input,
+                 size_t ilen, uint8_t *output, size_t olen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_sha3_context ctx;
+
+    mbedtls_sha3_init(&ctx);
+
+    /* Sanity checks are performed in every mbedtls_sha3_xxx() */
+    if ((ret = mbedtls_sha3_starts(&ctx, id)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_sha3_update(&ctx, input, ilen)) != 0) {
+        goto exit;
+    }
+
+    if ((ret = mbedtls_sha3_finish(&ctx, output, olen)) != 0) {
+        goto exit;
+    }
+
+exit:
+    mbedtls_sha3_free(&ctx);
+
+    return ret;
+}
+
+/**************** Self-tests ****************/
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_data[2][4] =
+{
+    "",
+    "abc",
+};
+
+static const size_t test_data_len[2] =
+{
+    0, /* "" */
+    3  /* "abc" */
+};
+
+static const unsigned char test_hash_sha3_224[2][28] =
+{
+    { /* "" */
+        0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
+        0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
+        0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
+        0x5B, 0x5A, 0x6B, 0xC7
+    },
+    { /* "abc" */
+        0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
+        0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
+        0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
+        0x73, 0xB4, 0x6F, 0xDF
+    }
+};
+
+static const unsigned char test_hash_sha3_256[2][32] =
+{
+    { /* "" */
+        0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
+        0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
+        0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
+        0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
+    },
+    { /* "abc" */
+        0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
+        0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
+        0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
+        0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
+    }
+};
+
+static const unsigned char test_hash_sha3_384[2][48] =
+{
+    { /* "" */
+        0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
+        0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
+        0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
+        0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
+        0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
+        0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
+    },
+    { /* "abc" */
+        0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
+        0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
+        0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
+        0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
+        0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
+        0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
+    }
+};
+
+static const unsigned char test_hash_sha3_512[2][64] =
+{
+    { /* "" */
+        0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
+        0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
+        0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
+        0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
+        0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
+        0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
+        0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
+        0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
+    },
+    { /* "abc" */
+        0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
+        0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
+        0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
+        0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
+        0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
+        0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
+        0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
+        0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
+    }
+};
+
+static const unsigned char long_kat_hash_sha3_224[28] =
+{
+    0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
+    0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
+    0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
+    0xA7, 0xFD, 0x65, 0x3C
+};
+
+static const unsigned char long_kat_hash_sha3_256[32] =
+{
+    0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
+    0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
+    0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
+    0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
+};
+
+static const unsigned char long_kat_hash_sha3_384[48] =
+{
+    0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
+    0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
+    0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
+    0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
+    0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
+    0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
+};
+
+static const unsigned char long_kat_hash_sha3_512[64] =
+{
+    0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
+    0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
+    0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
+    0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
+    0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
+    0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
+    0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
+    0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
+};
+
+static int mbedtls_sha3_kat_test(int verbose,
+                                 const char *type_name,
+                                 mbedtls_sha3_id id,
+                                 int test_num)
+{
+    uint8_t hash[64];
+    int result;
+
+    result = mbedtls_sha3(id,
+                          test_data[test_num], test_data_len[test_num],
+                          hash, sizeof(hash));
+    if (result != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("  %s test %d error code: %d\n",
+                           type_name, test_num, result);
+        }
+
+        return result;
+    }
+
+    switch (id) {
+        case MBEDTLS_SHA3_224:
+            result = memcmp(hash, test_hash_sha3_224[test_num], 28);
+            break;
+        case MBEDTLS_SHA3_256:
+            result = memcmp(hash, test_hash_sha3_256[test_num], 32);
+            break;
+        case MBEDTLS_SHA3_384:
+            result = memcmp(hash, test_hash_sha3_384[test_num], 48);
+            break;
+        case MBEDTLS_SHA3_512:
+            result = memcmp(hash, test_hash_sha3_512[test_num], 64);
+            break;
+        default:
+            break;
+    }
+
+    if (0 != result) {
+        if (verbose != 0) {
+            mbedtls_printf("  %s test %d failed\n", type_name, test_num);
+        }
+
+        return -1;
+    }
+
+    if (verbose != 0) {
+        mbedtls_printf("  %s test %d passed\n", type_name, test_num);
+    }
+
+    return 0;
+}
+
+static int mbedtls_sha3_long_kat_test(int verbose,
+                                      const char *type_name,
+                                      mbedtls_sha3_id id)
+{
+    mbedtls_sha3_context ctx;
+    unsigned char buffer[1000];
+    unsigned char hash[64];
+    int result = 0;
+
+    memset(buffer, 'a', 1000);
+
+    if (verbose != 0) {
+        mbedtls_printf("  %s long KAT test ", type_name);
+    }
+
+    mbedtls_sha3_init(&ctx);
+
+    result = mbedtls_sha3_starts(&ctx, id);
+    if (result != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("setup failed\n ");
+        }
+    }
+
+    /* Process 1,000,000 (one million) 'a' characters */
+    for (int i = 0; i < 1000; i++) {
+        result = mbedtls_sha3_update(&ctx, buffer, 1000);
+        if (result != 0) {
+            if (verbose != 0) {
+                mbedtls_printf("update error code: %i\n", result);
+            }
+
+            goto cleanup;
+        }
+    }
+
+    result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
+    if (result != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("finish error code: %d\n", result);
+        }
+
+        goto cleanup;
+    }
+
+    switch (id) {
+        case MBEDTLS_SHA3_224:
+            result = memcmp(hash, long_kat_hash_sha3_224, 28);
+            break;
+        case MBEDTLS_SHA3_256:
+            result = memcmp(hash, long_kat_hash_sha3_256, 32);
+            break;
+        case MBEDTLS_SHA3_384:
+            result = memcmp(hash, long_kat_hash_sha3_384, 48);
+            break;
+        case MBEDTLS_SHA3_512:
+            result = memcmp(hash, long_kat_hash_sha3_512, 64);
+            break;
+        default:
+            break;
+    }
+
+    if (result != 0) {
+        if (verbose != 0) {
+            mbedtls_printf("failed\n");
+        }
+    }
+
+    if (verbose != 0) {
+        mbedtls_printf("passed\n");
+    }
+
+cleanup:
+    mbedtls_sha3_free(&ctx);
+    return result;
+}
+
+int mbedtls_sha3_self_test(int verbose)
+{
+    int i;
+
+    /* SHA-3 Known Answer Tests (KAT) */
+    for (i = 0; i < 2; i++) {
+        if (0 != mbedtls_sha3_kat_test(verbose,
+                                       "SHA3-224", MBEDTLS_SHA3_224, i)) {
+            return 1;
+        }
+
+        if (0 != mbedtls_sha3_kat_test(verbose,
+                                       "SHA3-256", MBEDTLS_SHA3_256, i)) {
+            return 1;
+        }
+
+        if (0 != mbedtls_sha3_kat_test(verbose,
+                                       "SHA3-384", MBEDTLS_SHA3_384, i)) {
+            return 1;
+        }
+
+        if (0 != mbedtls_sha3_kat_test(verbose,
+                                       "SHA3-512", MBEDTLS_SHA3_512, i)) {
+            return 1;
+        }
+    }
+
+    /* SHA-3 long KAT tests */
+    if (0 != mbedtls_sha3_long_kat_test(verbose,
+                                        "SHA3-224", MBEDTLS_SHA3_224)) {
+        return 1;
+    }
+
+    if (0 != mbedtls_sha3_long_kat_test(verbose,
+                                        "SHA3-256", MBEDTLS_SHA3_256)) {
+        return 1;
+    }
+
+    if (0 != mbedtls_sha3_long_kat_test(verbose,
+                                        "SHA3-384", MBEDTLS_SHA3_384)) {
+        return 1;
+    }
+
+    if (0 != mbedtls_sha3_long_kat_test(verbose,
+                                        "SHA3-512", MBEDTLS_SHA3_512)) {
+        return 1;
+    }
+
+    if (verbose != 0) {
+        mbedtls_printf("\n");
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_SHA3_C */
diff --git a/lib/libmbedtls/mbedtls/library/sha512.c b/lib/libmbedtls/mbedtls/library/sha512.c
index 67acfee481ce15da071dacae29763c30fbadc89a..6dcea8da5d5c55b3110e403030756c2e65db4d1f 100644
--- a/lib/libmbedtls/mbedtls/library/sha512.c
+++ b/lib/libmbedtls/mbedtls/library/sha512.c
@@ -2,19 +2,7 @@
  *  FIPS-180-2 compliant SHA-384/512 implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The SHA-512 Secure Hash Standard was published by NIST in 2002.
@@ -31,7 +19,7 @@
  * By defining the macros ourselves we gain access to those declarations without
  * requiring -march on the command line.
  *
- * `arm_neon.h` could be included by any header file, so we put these defines
+ * `arm_neon.h` is included by common.h, so we put these defines
  * at the top of this file, before any includes.
  */
 #define __ARM_FEATURE_SHA512 1
@@ -60,6 +48,9 @@
 #  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
     defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
 /* *INDENT-OFF* */
+#   if !defined(MBEDTLS_HAVE_NEON_INTRINSICS)
+#       error "Target does not support NEON instructions"
+#   endif
 /*
  * Best performance comes from most recent compilers, with intrinsics and -O3.
  * Must compile with -march=armv8.2-a+sha3, but we can't detect armv8.2-a, and
@@ -76,7 +67,16 @@
  */
 #    if !defined(__ARM_FEATURE_SHA512) || defined(MBEDTLS_ENABLE_ARM_SHA3_EXTENSIONS_COMPILER_FLAG)
        /* Test Clang first, as it defines __GNUC__ */
-#      if defined(__clang__)
+#      if defined(__ARMCOMPILER_VERSION)
+#        if __ARMCOMPILER_VERSION < 6090000
+#          error "A more recent armclang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        elif __ARMCOMPILER_VERSION == 6090000
+#          error "Must use minimum -march=armv8.2-a+sha3 for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
+#        else
+#          pragma clang attribute push (__attribute__((target("sha3"))), apply_to=function)
+#          define MBEDTLS_POP_TARGET_PRAGMA
+#        endif
+#      elif defined(__clang__)
 #        if __clang_major__ < 7
 #          error "A more recent Clang is required for MBEDTLS_SHA512_USE_A64_CRYPTO_*"
 #        else
@@ -96,24 +96,26 @@
 #      endif
 #    endif
 /* *INDENT-ON* */
-#    include <arm_neon.h>
 #  endif
 #  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
 #    if defined(__unix__)
 #      if defined(__linux__)
 /* Our preferred method of detection is getauxval() */
 #        include <sys/auxv.h>
+#        if !defined(HWCAP_SHA512)
+/* The same header that declares getauxval() should provide the HWCAP_xxx
+ * constants to analyze its return value. However, the libc may be too
+ * old to have the constant that we need. So if it's missing, assume that
+ * the value is the same one used by the Linux kernel ABI.
+ */
+#          define HWCAP_SHA512 (1 << 21)
+#        endif
 #      endif
 /* Use SIGILL on Unix, and fall back to it on Linux */
 #      include <signal.h>
 #    endif
 #  endif
-#elif defined(_M_ARM64)
-#  if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
-    defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
-#    include <arm64_neon.h>
-#  endif
-#else
+#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
 #  undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
 #  undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
 #endif
@@ -141,7 +143,7 @@ static int mbedtls_a64_crypto_sha512_determine_support(void)
                            NULL, 0);
     return ret == 0 && value != 0;
 }
-#elif defined(_M_ARM64)
+#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64)
 /*
  * As of March 2022, there don't appear to be any PF_ARM_V8_* flags
  * available to pass to IsProcessorFeaturePresent() to check for
@@ -569,6 +571,8 @@ int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx,
             SHA512_BLOCK_SIZE) ? 0 : -1;
 }
 
+#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
+
 #if defined(MBEDTLS_POP_TARGET_PRAGMA)
 #if defined(__clang__)
 #pragma clang attribute pop
@@ -578,8 +582,6 @@ int mbedtls_internal_sha512_process_a64_crypto(mbedtls_sha512_context *ctx,
 #undef MBEDTLS_POP_TARGET_PRAGMA
 #endif
 
-#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
-
 
 #if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
 #define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
@@ -815,6 +817,7 @@ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned used;
     uint64_t high, low;
+    int truncated = 0;
 
     /*
      * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
@@ -831,7 +834,7 @@ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
         memset(ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used);
 
         if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {
-            return ret;
+            goto exit;
         }
 
         memset(ctx->buffer, 0, 112);
@@ -848,7 +851,7 @@ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
     sha512_put_uint64_be(low,  ctx->buffer, 120);
 
     if ((ret = mbedtls_internal_sha512_process(ctx, ctx->buffer)) != 0) {
-        return ret;
+        goto exit;
     }
 
     /*
@@ -861,7 +864,6 @@ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
     sha512_put_uint64_be(ctx->state[4], output, 32);
     sha512_put_uint64_be(ctx->state[5], output, 40);
 
-    int truncated = 0;
 #if defined(MBEDTLS_SHA384_C)
     truncated = ctx->is384;
 #endif
@@ -870,7 +872,11 @@ int mbedtls_sha512_finish(mbedtls_sha512_context *ctx,
         sha512_put_uint64_be(ctx->state[7], output, 56);
     }
 
-    return 0;
+    ret = 0;
+
+exit:
+    mbedtls_sha512_free(ctx);
+    return ret;
 }
 
 #endif /* !MBEDTLS_SHA512_ALT */
@@ -1001,8 +1007,6 @@ static sha_test_sum_t sha512_test_sum[] =
 };
 #endif /* MBEDTLS_SHA512_C */
 
-#define ARRAY_LENGTH(a)   (sizeof(a) / sizeof((a)[0]))
-
 static int mbedtls_sha512_common_self_test(int verbose, int is384)
 {
     int i, buflen, ret = 0;
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cache.c b/lib/libmbedtls/mbedtls/library/ssl_cache.c
index 048c21d4f0ea7e111ee38f133824192faaf9cce0..772cb8fdfe6ddbbfe4f78f5b4b3ed69f6b1e33c7 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cache.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cache.c
@@ -2,19 +2,7 @@
  *  SSL session cache implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * These session callbacks use a simple chained list
@@ -29,6 +17,7 @@
 
 #include "mbedtls/ssl_cache.h"
 #include "ssl_misc.h"
+#include "mbedtls/error.h"
 
 #include <string.h>
 
@@ -50,7 +39,7 @@ static int ssl_cache_find_entry(mbedtls_ssl_cache_context *cache,
                                 size_t session_id_len,
                                 mbedtls_ssl_cache_entry **dst)
 {
-    int ret = 1;
+    int ret = MBEDTLS_ERR_SSL_CACHE_ENTRY_NOT_FOUND;
 #if defined(MBEDTLS_HAVE_TIME)
     mbedtls_time_t t = mbedtls_time(NULL);
 #endif
@@ -87,7 +76,7 @@ int mbedtls_ssl_cache_get(void *data,
                           size_t session_id_len,
                           mbedtls_ssl_session *session)
 {
-    int ret = 1;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
     mbedtls_ssl_cache_entry *entry;
 
@@ -130,8 +119,7 @@ static void ssl_cache_entry_zeroize(mbedtls_ssl_cache_entry *entry)
 
     /* zeroize and free session structure */
     if (entry->session != NULL) {
-        mbedtls_platform_zeroize(entry->session, entry->session_len);
-        mbedtls_free(entry->session);
+        mbedtls_zeroize_and_free(entry->session, entry->session_len);
     }
 
     /* zeroize the whole entry structure */
@@ -197,7 +185,7 @@ static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache,
         /* Create new entry */
         cur = mbedtls_calloc(1, sizeof(mbedtls_ssl_cache_entry));
         if (cur == NULL) {
-            return 1;
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
         }
 
         /* Append to the end of the linked list. */
@@ -218,12 +206,13 @@ static int ssl_cache_pick_writing_slot(mbedtls_ssl_cache_context *cache,
     if (old == NULL) {
         /* This should only happen on an ill-configured cache
          * with max_entries == 0. */
-        return 1;
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 #else /* MBEDTLS_HAVE_TIME */
     /* Reuse first entry in chain, but move to last place. */
     if (cache->chain == NULL) {
-        return 1;
+        /* This should never happen */
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     }
 
     old = cache->chain;
@@ -259,11 +248,11 @@ int mbedtls_ssl_cache_set(void *data,
                           size_t session_id_len,
                           const mbedtls_ssl_session *session)
 {
-    int ret = 1;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
     mbedtls_ssl_cache_entry *cur;
 
-    size_t session_serialized_len;
+    size_t session_serialized_len = 0;
     unsigned char *session_serialized = NULL;
 
 #if defined(MBEDTLS_THREADING_C)
@@ -283,7 +272,6 @@ int mbedtls_ssl_cache_set(void *data,
      * and allocate a sufficiently large buffer. */
     ret = mbedtls_ssl_session_save(session, NULL, 0, &session_serialized_len);
     if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
-        ret = 1;
         goto exit;
     }
 
@@ -303,7 +291,7 @@ int mbedtls_ssl_cache_set(void *data,
     }
 
     if (session_id_len > sizeof(cur->session_id)) {
-        ret = 1;
+        ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         goto exit;
     }
     cur->session_id_len = session_id_len;
@@ -323,8 +311,7 @@ exit:
 #endif
 
     if (session_serialized != NULL) {
-        mbedtls_platform_zeroize(session_serialized, session_serialized_len);
-        mbedtls_free(session_serialized);
+        mbedtls_zeroize_and_free(session_serialized, session_serialized_len);
         session_serialized = NULL;
     }
 
@@ -335,7 +322,7 @@ int mbedtls_ssl_cache_remove(void *data,
                              unsigned char const *session_id,
                              size_t session_id_len)
 {
-    int ret = 1;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_cache_context *cache = (mbedtls_ssl_cache_context *) data;
     mbedtls_ssl_cache_entry *entry;
     mbedtls_ssl_cache_entry *prev;
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
index 501608a5a8d3e8bc80fb9f08f9a21112a2b3be31..23619a26c88f6d9cf25144a7e1e5c63b63b86f42 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites.c
@@ -1,22 +1,10 @@
 /**
  * \file ssl_ciphersuites.c
  *
- * \brief SSL ciphersuites for mbed TLS
+ * \brief SSL ciphersuites for Mbed TLS
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -28,8 +16,9 @@
 #include "mbedtls/ssl_ciphersuites.h"
 #include "mbedtls/ssl.h"
 #include "ssl_misc.h"
-
-#include "mbedtls/legacy_or_psa.h"
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "mbedtls/psa_util.h"
+#endif
 
 #include <string.h>
 
@@ -291,24 +280,24 @@ static const int ciphersuite_preference[] =
 static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS1_3_AES_256_GCM_SHA384, "TLS1-3-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384,
       MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
       0,
       MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS1_3_AES_128_GCM_SHA256, "TLS1-3-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
       0,
       MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#if defined(MBEDTLS_CCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#if defined(MBEDTLS_SSL_HAVE_CCM) && defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS1_3_AES_128_CCM_SHA256, "TLS1-3-AES-128-CCM-SHA256",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
@@ -319,20 +308,20 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
-#if defined(MBEDTLS_CHACHAPOLY_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 && MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
+#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS1_3_CHACHA20_POLY1305_SHA256,
       "TLS1-3-CHACHA20-POLY1305-SHA256",
       MBEDTLS_CIPHER_CHACHA20_POLY1305, MBEDTLS_MD_SHA256,
       MBEDTLS_KEY_EXCHANGE_NONE, /* Key exchange not part of ciphersuite in TLS 1.3 */
       0,
       MBEDTLS_SSL_VERSION_TLS1_3, MBEDTLS_SSL_VERSION_TLS1_3 },
-#endif /* MBEDTLS_CHACHAPOLY_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY && MBEDTLS_MD_CAN_SHA256 */
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-#if defined(MBEDTLS_CHACHAPOLY_C) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
+#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY) && \
+    defined(MBEDTLS_MD_CAN_SHA256) && \
     defined(MBEDTLS_SSL_PROTO_TLS1_2)
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
@@ -390,13 +379,13 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#endif /* MBEDTLS_CHACHAPOLY_C &&
-          MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
+#endif /* MBEDTLS_SSL_HAVE_CHACHAPOLY &&
+          MBEDTLS_MD_CAN_SHA256 &&
           MBEDTLS_SSL_PROTO_TLS1_2 */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
@@ -405,37 +394,37 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_CCM_C)
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM, "TLS-ECDHE-ECDSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
@@ -452,59 +441,59 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
       "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
       "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
       "TLS-ECDHE-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
       "TLS-ECDHE-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS-ECDHE-ECDSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
@@ -513,103 +502,103 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDHE-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
       "TLS-ECDHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
       "TLS-ECDHE-RSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256,
       "TLS-ECDHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384,
       "TLS-ECDHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS-ECDHE-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA384) && \
+    defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS-DHE-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS-DHE-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
@@ -619,11 +608,11 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS-DHE-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
@@ -633,9 +622,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_CCM_C)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM, "TLS-DHE-RSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
@@ -652,12 +641,12 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
@@ -667,9 +656,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-DHE-RSA-WITH-CAMELLIA-128-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
@@ -679,46 +668,46 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA384) && \
+    defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA && MBEDTLS_GCM_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 && MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_GCM_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
@@ -728,11 +717,11 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA, "TLS-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
@@ -742,9 +731,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_CCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_RSA_WITH_AES_256_CCM, "TLS-RSA-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
@@ -761,12 +750,12 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
@@ -776,9 +765,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS-RSA-WITH-CAMELLIA-128-CBC-SHA",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
@@ -788,32 +777,32 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
@@ -822,88 +811,88 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-RSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-RSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-RSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-RSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256,
       "TLS-ECDH-RSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384,
       "TLS-ECDH-RSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256,
       "TLS-ECDH-RSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384,
       "TLS-ECDH-RSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA, "TLS-ECDH-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_MD_CAN_SHA1)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
@@ -912,118 +901,118 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS-ECDH-ECDSA-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_GCM_C)
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_GCM)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, "TLS-ECDH-ECDSA-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
       "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
       "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256,
       "TLS-ECDH-ECDSA-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384,
       "TLS-ECDH-ECDSA-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS-ECDH-ECDSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256, "TLS-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384, "TLS-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256, "TLS-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384, "TLS-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA, "TLS-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
@@ -1033,9 +1022,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_CCM_C)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_PSK_WITH_AES_256_CCM, "TLS-PSK-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
@@ -1052,79 +1041,79 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS-DHE-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS-DHE-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-DHE-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA, "TLS-DHE-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
@@ -1134,9 +1123,9 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#if defined(MBEDTLS_CCM_C)
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM, "TLS-DHE-PSK-WITH-AES-256-CCM",
       MBEDTLS_CIPHER_AES_256_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
@@ -1153,64 +1142,64 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-DHE-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-DHE-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-#if defined(MBEDTLS_AES_C)
+#if defined(MBEDTLS_SSL_HAVE_AES)
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384, "TLS-ECDHE-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, "TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
@@ -1220,66 +1209,66 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
       "TLS-ECDHE-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
       "TLS-ECDHE-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, "TLS-RSA-PSK-WITH-AES-128-GCM-SHA256",
       MBEDTLS_CIPHER_AES_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, "TLS-RSA-PSK-WITH-AES-256-GCM-SHA384",
       MBEDTLS_CIPHER_AES_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA256",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, "TLS-RSA-PSK-WITH-AES-256-CBC-SHA384",
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA, "TLS-RSA-PSK-WITH-AES-128-CBC-SHA",
       MBEDTLS_CIPHER_AES_128_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
@@ -1289,74 +1278,74 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
       MBEDTLS_CIPHER_AES_256_CBC, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 
-#if defined(MBEDTLS_CAMELLIA_C)
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_CBC */
 
-#if defined(MBEDTLS_GCM_C)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_SSL_HAVE_GCM)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256, "TLS-RSA-PSK-WITH-CAMELLIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_CAMELLIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384, "TLS-RSA-PSK-WITH-CAMELLIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_CAMELLIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#endif /* MBEDTLS_GCM_C */
-#endif /* MBEDTLS_CAMELLIA_C */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#endif /* MBEDTLS_SSL_HAVE_GCM */
+#endif /* MBEDTLS_SSL_HAVE_CAMELLIA */
 
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-#if defined(MBEDTLS_AES_C)
-#if defined(MBEDTLS_CCM_C)
+#if defined(MBEDTLS_SSL_HAVE_AES)
+#if defined(MBEDTLS_SSL_HAVE_CCM)
     { MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8, "TLS-ECJPAKE-WITH-AES-128-CCM-8",
       MBEDTLS_CIPHER_AES_128_CCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECJPAKE,
       MBEDTLS_CIPHERSUITE_SHORT_TAG,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_CCM_C */
-#endif /* MBEDTLS_AES_C */
+#endif /* MBEDTLS_SSL_HAVE_CCM */
+#endif /* MBEDTLS_SSL_HAVE_AES */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_MD5)
     { MBEDTLS_TLS_RSA_WITH_NULL_MD5, "TLS-RSA-WITH-NULL-MD5",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_MD5, MBEDTLS_KEY_EXCHANGE_RSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_RSA_WITH_NULL_SHA, "TLS-RSA-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_WITH_NULL_SHA256, "TLS-RSA-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       MBEDTLS_CIPHERSUITE_WEAK,
@@ -1365,126 +1354,126 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA, "TLS-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA256, "TLS-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_PSK_WITH_NULL_SHA384, "TLS-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA, "TLS-DHE-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256, "TLS-DHE-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384, "TLS-DHE-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA, "TLS-ECDHE-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256, "TLS-ECDHE-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384, "TLS-ECDHE-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA, "TLS-RSA-PSK-WITH-NULL-SHA",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA1, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256, "TLS-RSA-PSK-WITH-NULL-SHA256",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     { MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384, "TLS-RSA-PSK-WITH-NULL-SHA384",
       MBEDTLS_CIPHER_NULL, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       MBEDTLS_CIPHERSUITE_WEAK,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 
-#if defined(MBEDTLS_ARIA_C)
+#if defined(MBEDTLS_SSL_HAVE_ARIA)
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA,
@@ -1496,30 +1485,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
       "TLS-RSA-PSK-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384,
       "TLS-RSA-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
       "TLS-RSA-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256,
       "TLS-RSA-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_RSA_PSK,
@@ -1531,30 +1520,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
       "TLS-PSK-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384,
       "TLS-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256,
       "TLS-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256,
       "TLS-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_PSK,
@@ -1566,30 +1555,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-ECDH-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-ECDH-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-ECDH-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-ECDH-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_RSA,
@@ -1601,30 +1590,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-ECDHE-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-ECDHE-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-ECDHE-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-ECDHE-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_RSA,
@@ -1636,16 +1625,16 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384,
       "TLS-ECDHE-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256,
       "TLS-ECDHE-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_PSK,
@@ -1657,30 +1646,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-ECDHE-ECDSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-ECDHE-ECDSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-ECDHE-ECDSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-ECDHE-ECDSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA,
@@ -1692,30 +1681,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-ECDH-ECDSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-ECDH-ECDSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-ECDH-ECDSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-ECDH-ECDSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA,
@@ -1727,30 +1716,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
       "TLS-DHE-RSA-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384,
       "TLS-DHE-RSA-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
       "TLS-DHE-RSA-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256,
       "TLS-DHE-RSA-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_RSA,
@@ -1762,30 +1751,30 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
 
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
       "TLS-DHE-PSK-WITH-ARIA-256-GCM-SHA384",
       MBEDTLS_CIPHER_ARIA_256_GCM, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA384))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384,
       "TLS-DHE-PSK-WITH-ARIA-256-CBC-SHA384",
       MBEDTLS_CIPHER_ARIA_256_CBC, MBEDTLS_MD_SHA384, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_GCM_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_GCM) && defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
       "TLS-DHE-PSK-WITH-ARIA-128-GCM-SHA256",
       MBEDTLS_CIPHER_ARIA_128_GCM, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
       0,
       MBEDTLS_SSL_VERSION_TLS1_2, MBEDTLS_SSL_VERSION_TLS1_2 },
 #endif
-#if (defined(MBEDTLS_CIPHER_MODE_CBC) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA))
+#if (defined(MBEDTLS_SSL_HAVE_CBC) && \
+    defined(MBEDTLS_MD_CAN_SHA256))
     { MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256,
       "TLS-DHE-PSK-WITH-ARIA-128-CBC-SHA256",
       MBEDTLS_CIPHER_ARIA_128_CBC, MBEDTLS_MD_SHA256, MBEDTLS_KEY_EXCHANGE_DHE_PSK,
@@ -1795,7 +1784,7 @@ static const mbedtls_ssl_ciphersuite_t ciphersuite_definitions[] =
 
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 
-#endif /* MBEDTLS_ARIA_C */
+#endif /* MBEDTLS_SSL_HAVE_ARIA */
 
 
     { 0, "",
@@ -1919,7 +1908,7 @@ size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersui
     psa_algorithm_t alg;
     size_t key_bits;
 
-    status = mbedtls_ssl_cipher_to_psa(info->cipher,
+    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) info->cipher,
                                        info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16,
                                        &alg, &key_type, &key_bits);
 
@@ -1930,7 +1919,7 @@ size_t mbedtls_ssl_ciphersuite_get_cipher_key_bitlen(const mbedtls_ssl_ciphersui
     return key_bits;
 #else
     const mbedtls_cipher_info_t * const cipher_info =
-        mbedtls_cipher_info_from_type(info->cipher);
+        mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) info->cipher);
 
     return mbedtls_cipher_info_get_key_bitlen(cipher_info);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
@@ -1968,10 +1957,10 @@ psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_cip
         case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
             return PSA_ALG_RSA_PKCS1V15_SIGN(
-                mbedtls_hash_info_psa_from_md(info->mac));
+                mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac));
 
         case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-            return PSA_ALG_ECDSA(mbedtls_hash_info_psa_from_md(info->mac));
+            return PSA_ALG_ECDSA(mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac));
 
         case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
         case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
@@ -2020,7 +2009,8 @@ mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersu
 
 #endif /* MBEDTLS_PK_C */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info)
 {
@@ -2037,7 +2027,9 @@ int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info)
             return 0;
     }
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+        * MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
+        * MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED*/
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
 int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info)
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ciphersuites_internal.h b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..27ff72106ef6b77c49ae6ba45c221ba287c66849
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/ssl_ciphersuites_internal.h
@@ -0,0 +1,154 @@
+/**
+ * \file ssl_ciphersuites_internal.h
+ *
+ * \brief Internal part of the public "ssl_ciphersuites.h".
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H
+#define MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H
+
+#include "mbedtls/pk.h"
+
+#if defined(MBEDTLS_PK_C)
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_pk_alg(const mbedtls_ssl_ciphersuite_t *info);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+psa_algorithm_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_alg(const mbedtls_ssl_ciphersuite_t *info);
+psa_key_usage_t mbedtls_ssl_get_ciphersuite_sig_pk_psa_usage(const mbedtls_ssl_ciphersuite_t *info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+mbedtls_pk_type_t mbedtls_ssl_get_ciphersuite_sig_alg(const mbedtls_ssl_ciphersuite_t *info);
+#endif /* MBEDTLS_PK_C */
+
+int mbedtls_ssl_ciphersuite_uses_ec(const mbedtls_ssl_ciphersuite_t *info);
+int mbedtls_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info);
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_has_pfs(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PFS_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_no_pfs(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_PSK:
+        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_NON_PFS_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_ecdh(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED */
+
+static inline int mbedtls_ssl_ciphersuite_cert_req_allowed(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+
+static inline int mbedtls_ssl_ciphersuite_uses_srv_cert(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_dhe(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_DHE_ENABLED) */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_ecdhe(const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED) */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
+static inline int mbedtls_ssl_ciphersuite_uses_server_signature(
+    const mbedtls_ssl_ciphersuite_t *info)
+{
+    switch (info->MBEDTLS_PRIVATE(key_exchange)) {
+        case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+        case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+            return 1;
+
+        default:
+            return 0;
+    }
+}
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED */
+
+#endif /* MBEDTLS_SSL_CIPHERSUITES_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_client.c b/lib/libmbedtls/mbedtls/library/ssl_client.c
index ea64b216e028d2c039602e811d5b5a0cb47a3437..345e608938294e40d88667056b97b2849e7c9350 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_client.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_client.c
@@ -2,21 +2,7 @@
  *  TLS 1.2 and 1.3 client-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS ( https://tls.mbed.org )
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -26,7 +12,7 @@
 
 #include <string.h>
 
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
 
@@ -169,7 +155,7 @@ static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
         p += protocol_name_len;
     }
 
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
 
     /* List length = *out_len - 2 (ext_type) - 2 (ext_len) - 2 (list_len) */
     MBEDTLS_PUT_UINT16_BE(*out_len - 6, buf, 4);
@@ -184,8 +170,8 @@ static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
 }
 #endif /* MBEDTLS_SSL_ALPN */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
 /*
  * Function for writing a supported groups (TLS 1.3) or supported elliptic
  * curves (TLS 1.2) extension.
@@ -223,12 +209,15 @@ static int ssl_write_alpn_ext(mbedtls_ssl_context *ssl,
  * generalization of the TLS 1.2 supported elliptic curves extension. They both
  * share the same extension identifier.
  *
- * DHE groups are not supported yet.
  */
+#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG 1
+#define SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG 2
+
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,
                                           unsigned char *buf,
                                           const unsigned char *end,
+                                          int flags,
                                           size_t *out_len)
 {
     unsigned char *p = buf;
@@ -255,31 +244,48 @@ static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,
     }
 
     for (; *group_list != 0; group_list++) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("got supported group(%04x)", *group_list));
-
-#if defined(MBEDTLS_ECP_C)
-        if ((mbedtls_ssl_conf_is_tls13_enabled(ssl->conf) &&
-             mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) ||
-            (mbedtls_ssl_conf_is_tls12_enabled(ssl->conf) &&
-             mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list))) {
-            if (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) ==
-                MBEDTLS_ECP_DP_NONE) {
-                continue;
+        int propose_group = 0;
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("got supported group(%04x)", *group_list));
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+        if (flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG) {
+#if defined(PSA_WANT_ALG_ECDH)
+            if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list) &&
+                (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) !=
+                 MBEDTLS_ECP_DP_NONE)) {
+                propose_group = 1;
+            }
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+            if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {
+                propose_group = 1;
             }
+#endif
+        }
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
+
+#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC)
+        if ((flags & SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG) &&
+            mbedtls_ssl_tls12_named_group_is_ecdhe(*group_list) &&
+            (mbedtls_ssl_get_ecp_group_id_from_tls_id(*group_list) !=
+             MBEDTLS_ECP_DP_NONE)) {
+            propose_group = 1;
+        }
+#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC */
+
+        if (propose_group) {
             MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
             MBEDTLS_PUT_UINT16_BE(*group_list, p, 0);
             p += 2;
             MBEDTLS_SSL_DEBUG_MSG(3, ("NamedGroup: %s ( %x )",
-                                      mbedtls_ssl_get_curve_name_from_tls_id(*group_list),
+                                      mbedtls_ssl_named_group_to_str(*group_list),
                                       *group_list));
         }
-#endif /* MBEDTLS_ECP_C */
-        /* Add DHE groups here */
-
     }
 
     /* Length of named_group_list */
-    named_group_list_len = p - named_group_list;
+    named_group_list_len = (size_t) (p - named_group_list);
     if (named_group_list_len == 0) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("No group available."));
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
@@ -295,7 +301,7 @@ static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,
     MBEDTLS_SSL_DEBUG_BUF(3, "Supported groups extension",
                           buf + 4, named_group_list_len + 2);
 
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     mbedtls_ssl_tls13_set_hs_sent_ext_mask(
@@ -304,9 +310,8 @@ static int ssl_write_supported_groups_ext(mbedtls_ssl_context *ssl,
 
     return 0;
 }
-
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
-          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC ||
+          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_client_hello_cipher_suites(
@@ -355,7 +360,8 @@ static int ssl_write_client_hello_cipher_suites(
         }
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
-        (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+        (defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+        defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
         defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED))
         *tls12_uses_ec |= mbedtls_ssl_ciphersuite_uses_ec(ciphersuite_info);
 #endif
@@ -385,14 +391,14 @@ static int ssl_write_client_hello_cipher_suites(
     }
 
     /* Write the cipher_suites length in number of bytes */
-    cipher_suites_len = p - cipher_suites;
+    cipher_suites_len = (size_t) (p - cipher_suites);
     MBEDTLS_PUT_UINT16_BE(cipher_suites_len, buf, 0);
     MBEDTLS_SSL_DEBUG_MSG(3,
                           ("client hello, got %" MBEDTLS_PRINTF_SIZET " cipher suites",
                            cipher_suites_len/2));
 
     /* Output the total length of cipher_suites field. */
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
 
     return 0;
 }
@@ -597,34 +603,47 @@ static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,
     }
 #endif
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    if (
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        (propose_tls13 &&
-         mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) ||
+#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC) || \
+    defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    {
+        int ssl_write_supported_groups_ext_flags = 0;
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+        if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {
+            ssl_write_supported_groups_ext_flags |=
+                SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_3_FLAG;
+        }
 #endif
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        (propose_tls12 && tls12_uses_ec) ||
+#if defined(MBEDTLS_SSL_TLS1_2_SOME_ECC)
+        if (propose_tls12 && tls12_uses_ec) {
+            ssl_write_supported_groups_ext_flags |=
+                SSL_WRITE_SUPPORTED_GROUPS_EXT_TLS1_2_FLAG;
+        }
 #endif
-        0) {
-        ret = ssl_write_supported_groups_ext(ssl, p, end, &output_len);
-        if (ret != 0) {
-            return ret;
+        if (ssl_write_supported_groups_ext_flags != 0) {
+            ret = ssl_write_supported_groups_ext(ssl, p, end,
+                                                 ssl_write_supported_groups_ext_flags,
+                                                 &output_len);
+            if (ret != 0) {
+                return ret;
+            }
+            p += output_len;
         }
-        p += output_len;
     }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+#endif /* MBEDTLS_SSL_TLS1_2_SOME_ECC ||
+          MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-    if (
+    int write_sig_alg_ext = 0;
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        (propose_tls13 && mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl)) ||
+    write_sig_alg_ext = write_sig_alg_ext ||
+                        (propose_tls13 && mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl));
 #endif
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        propose_tls12 ||
+    write_sig_alg_ext = write_sig_alg_ext || propose_tls12;
 #endif
-        0) {
+
+    if (write_sig_alg_ext) {
         ret = mbedtls_ssl_write_sig_alg_ext(ssl, p, end, &output_len);
         if (ret != 0) {
             return ret;
@@ -649,7 +668,7 @@ static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,
     /* The "pre_shared_key" extension (RFC 8446 Section 4.2.11)
      * MUST be the last extension in the ClientHello.
      */
-    if (propose_tls13 && mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) {
+    if (propose_tls13 && mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) {
         ret = mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
             ssl, p, end, &output_len, binders_len);
         if (ret != 0) {
@@ -660,7 +679,7 @@ static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
 
     /* Write the length of the list of extensions. */
-    extensions_len = p - p_extensions_len - 2;
+    extensions_len = (size_t) (p - p_extensions_len) - 2;
 
     if (extensions_len == 0) {
         p = p_extensions_len;
@@ -672,12 +691,7 @@ static int ssl_write_client_hello_body(mbedtls_ssl_context *ssl,
                               p_extensions_len, extensions_len);
     }
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    MBEDTLS_SSL_PRINT_EXTS(
-        3, MBEDTLS_SSL_HS_CLIENT_HELLO, handshake->sent_extensions);
-#endif
-
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
     return 0;
 }
 
@@ -737,10 +751,10 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
     if (ssl->handshake->resume != 0 &&
         session_negotiate->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
         session_negotiate->ticket != NULL) {
-        mbedtls_time_t now = mbedtls_time(NULL);
-        uint64_t age = (uint64_t) (now - session_negotiate->ticket_received);
-        if (session_negotiate->ticket_received > now ||
-            age > session_negotiate->ticket_lifetime) {
+        mbedtls_ms_time_t now = mbedtls_ms_time();
+        mbedtls_ms_time_t age = now - session_negotiate->ticket_reception_time;
+        if (age < 0 ||
+            age > (mbedtls_ms_time_t) session_negotiate->ticket_lifetime * 1000) {
             /* Without valid ticket, disable session resumption.*/
             MBEDTLS_SSL_DEBUG_MSG(
                 3, ("Ticket expired, disable session resumption"));
@@ -751,11 +765,6 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
           MBEDTLS_SSL_SESSION_TICKETS &&
           MBEDTLS_HAVE_TIME */
 
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
-
     /* Bet on the highest configured version if we are not in a TLS 1.2
      * renegotiation or session resumption.
      */
@@ -769,7 +778,6 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
             ssl->tls_version = session_negotiate->tls_version;
             ssl->handshake->min_tls_version = ssl->tls_version;
         } else {
-            ssl->tls_version = ssl->conf->max_tls_version;
             ssl->handshake->min_tls_version = ssl->conf->min_tls_version;
         }
     }
@@ -784,10 +792,15 @@ static int ssl_prepare_client_hello(mbedtls_ssl_context *ssl)
         (ssl->handshake->cookie == NULL))
 #endif
     {
-        ret = ssl_generate_random(ssl);
-        if (ret != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
-            return ret;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (!ssl->handshake->hello_retry_request_flag)
+#endif
+        {
+            ret = ssl_generate_random(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "Random bytes generation failed", ret);
+                return ret;
+            }
         }
     }
 
@@ -989,6 +1002,11 @@ int mbedtls_ssl_write_client_hello(mbedtls_ssl_context *ssl)
 #endif
     }
 
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    MBEDTLS_SSL_PRINT_EXTS(
+        3, MBEDTLS_SSL_HS_CLIENT_HELLO, ssl->handshake->sent_extensions);
+#endif
+
 cleanup:
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= write client hello"));
diff --git a/lib/libmbedtls/mbedtls/library/ssl_client.h b/lib/libmbedtls/mbedtls/library/ssl_client.h
index f57bea33fa9a3699b9aa66c7cd1476c441c63f59..05ee7e4cc31118165b74f33a6fd7d60b152de5a1 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_client.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_client.h
@@ -2,19 +2,7 @@
  *  TLS 1.2 and 1.3 client-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_SSL_CLIENT_H
diff --git a/lib/libmbedtls/mbedtls/library/ssl_cookie.c b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
index ef4d1886d3a373b584246502ef96e4a35df2e6d3..acc9e8c080bf25b5a7b3bfeea1bbf89e7909e31e 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_cookie.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_cookie.c
@@ -2,19 +2,7 @@
  *  DTLS cookie callbacks implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * These session callbacks use a simple chained list
@@ -33,25 +21,30 @@
 #include "mbedtls/platform_util.h"
 #include "mbedtls/constant_time.h"
 
-#include "mbedtls/legacy_or_psa.h"
-
 #include <string.h>
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+#include "mbedtls/psa_util.h"
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 #endif
 
 /*
  * If DTLS is in use, then at least one of SHA-256 or SHA-384 is
  * available. Try SHA-256 first as 384 wastes resources
  */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_LOWLEVEL_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #define COOKIE_MD           MBEDTLS_MD_SHA256
 #define COOKIE_MD_OUTLEN    32
 #define COOKIE_HMAC_LEN     28
-#elif defined(MBEDTLS_HAS_ALG_SHA_384_VIA_LOWLEVEL_OR_PSA)
+#elif defined(MBEDTLS_MD_CAN_SHA384)
 #define COOKIE_MD           MBEDTLS_MD_SHA384
 #define COOKIE_MD_OUTLEN    48
 #define COOKIE_HMAC_LEN     28
@@ -91,6 +84,10 @@ void mbedtls_ssl_cookie_set_timeout(mbedtls_ssl_cookie_ctx *ctx, unsigned long d
 
 void mbedtls_ssl_cookie_free(mbedtls_ssl_cookie_ctx *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_destroy_key(ctx->psa_hmac_key);
 #else
@@ -116,7 +113,7 @@ int mbedtls_ssl_cookie_setup(mbedtls_ssl_cookie_ctx *ctx,
     (void) f_rng;
     (void) p_rng;
 
-    alg = mbedtls_hash_info_psa_from_md(COOKIE_MD);
+    alg = mbedtls_md_psa_alg_from_type(COOKIE_MD);
     if (alg == 0) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
@@ -366,10 +363,7 @@ int mbedtls_ssl_cookie_check(void *p_ctx,
     cur_time = ctx->serial;
 #endif
 
-    cookie_time = ((unsigned long) cookie[0] << 24) |
-                  ((unsigned long) cookie[1] << 16) |
-                  ((unsigned long) cookie[2] <<  8) |
-                  ((unsigned long) cookie[3]);
+    cookie_time = (unsigned long) MBEDTLS_GET_UINT32_BE(cookie, 0);
 
     if (ctx->timeout != 0 && cur_time - cookie_time > ctx->timeout) {
         ret = -1;
diff --git a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h
index 5c22ed221dd4d055c2a8600a3cf4ae982436ad25..4889e77e04b9b50d847f08f3a1cc42e781fdb501 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers.h
@@ -5,19 +5,7 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_SSL_DEBUG_HELPERS_H
@@ -33,6 +21,11 @@
 
 const char *mbedtls_ssl_states_str(mbedtls_ssl_states in);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+const char *mbedtls_ssl_early_data_status_str(mbedtls_ssl_early_data_status in);
+const char *mbedtls_ssl_early_data_state_str(mbedtls_ssl_early_data_state in);
+#endif
+
 const char *mbedtls_ssl_protocol_version_str(mbedtls_ssl_protocol_version in);
 
 const char *mbedtls_tls_prf_types_str(mbedtls_tls_prf_types in);
diff --git a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c
index 9add9db218d97b259c79a905a9b7af2a4123e6ce..734c417b8bdced3275b30f8e8cf818399cb6a12e 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_debug_helpers_generated.c
@@ -7,19 +7,8 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
  */
 
 #include "common.h"
@@ -71,7 +60,7 @@ const char *mbedtls_ssl_named_group_to_str( uint16_t in )
         return "ffdhe8192";
     };
 
-    return "UNKOWN";
+    return "UNKNOWN";
 }
 const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
 {
@@ -117,105 +106,142 @@ const char *mbedtls_ssl_sig_alg_to_str( uint16_t in )
 }
 const char *mbedtls_ssl_states_str( mbedtls_ssl_states in )
 {
-    const char * in_to_str[]=
-    {
-        [MBEDTLS_SSL_HELLO_REQUEST] = "MBEDTLS_SSL_HELLO_REQUEST",
-        [MBEDTLS_SSL_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_HELLO",
-        [MBEDTLS_SSL_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_HELLO",
-        [MBEDTLS_SSL_SERVER_CERTIFICATE] = "MBEDTLS_SSL_SERVER_CERTIFICATE",
-        [MBEDTLS_SSL_SERVER_KEY_EXCHANGE] = "MBEDTLS_SSL_SERVER_KEY_EXCHANGE",
-        [MBEDTLS_SSL_CERTIFICATE_REQUEST] = "MBEDTLS_SSL_CERTIFICATE_REQUEST",
-        [MBEDTLS_SSL_SERVER_HELLO_DONE] = "MBEDTLS_SSL_SERVER_HELLO_DONE",
-        [MBEDTLS_SSL_CLIENT_CERTIFICATE] = "MBEDTLS_SSL_CLIENT_CERTIFICATE",
-        [MBEDTLS_SSL_CLIENT_KEY_EXCHANGE] = "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE",
-        [MBEDTLS_SSL_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CERTIFICATE_VERIFY",
-        [MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC",
-        [MBEDTLS_SSL_CLIENT_FINISHED] = "MBEDTLS_SSL_CLIENT_FINISHED",
-        [MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC] = "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC",
-        [MBEDTLS_SSL_SERVER_FINISHED] = "MBEDTLS_SSL_SERVER_FINISHED",
-        [MBEDTLS_SSL_FLUSH_BUFFERS] = "MBEDTLS_SSL_FLUSH_BUFFERS",
-        [MBEDTLS_SSL_HANDSHAKE_WRAPUP] = "MBEDTLS_SSL_HANDSHAKE_WRAPUP",
-        [MBEDTLS_SSL_NEW_SESSION_TICKET] = "MBEDTLS_SSL_NEW_SESSION_TICKET",
-        [MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT] = "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT",
-        [MBEDTLS_SSL_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_HELLO_RETRY_REQUEST",
-        [MBEDTLS_SSL_ENCRYPTED_EXTENSIONS] = "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS",
-        [MBEDTLS_SSL_END_OF_EARLY_DATA] = "MBEDTLS_SSL_END_OF_EARLY_DATA",
-        [MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY] = "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY",
-        [MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED",
-        [MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO",
-        [MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO] = "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO",
-        [MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO] = "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO",
-        [MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST] = "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST",
-        [MBEDTLS_SSL_HANDSHAKE_OVER] = "MBEDTLS_SSL_HANDSHAKE_OVER",
-        [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET",
-        [MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH] = "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH",
-    };
+    switch (in) {
+        case MBEDTLS_SSL_HELLO_REQUEST:
+            return "MBEDTLS_SSL_HELLO_REQUEST";
+        case MBEDTLS_SSL_CLIENT_HELLO:
+            return "MBEDTLS_SSL_CLIENT_HELLO";
+        case MBEDTLS_SSL_SERVER_HELLO:
+            return "MBEDTLS_SSL_SERVER_HELLO";
+        case MBEDTLS_SSL_SERVER_CERTIFICATE:
+            return "MBEDTLS_SSL_SERVER_CERTIFICATE";
+        case MBEDTLS_SSL_SERVER_KEY_EXCHANGE:
+            return "MBEDTLS_SSL_SERVER_KEY_EXCHANGE";
+        case MBEDTLS_SSL_CERTIFICATE_REQUEST:
+            return "MBEDTLS_SSL_CERTIFICATE_REQUEST";
+        case MBEDTLS_SSL_SERVER_HELLO_DONE:
+            return "MBEDTLS_SSL_SERVER_HELLO_DONE";
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE:
+            return "MBEDTLS_SSL_CLIENT_CERTIFICATE";
+        case MBEDTLS_SSL_CLIENT_KEY_EXCHANGE:
+            return "MBEDTLS_SSL_CLIENT_KEY_EXCHANGE";
+        case MBEDTLS_SSL_CERTIFICATE_VERIFY:
+            return "MBEDTLS_SSL_CERTIFICATE_VERIFY";
+        case MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC:
+            return "MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC";
+        case MBEDTLS_SSL_CLIENT_FINISHED:
+            return "MBEDTLS_SSL_CLIENT_FINISHED";
+        case MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC:
+            return "MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC";
+        case MBEDTLS_SSL_SERVER_FINISHED:
+            return "MBEDTLS_SSL_SERVER_FINISHED";
+        case MBEDTLS_SSL_FLUSH_BUFFERS:
+            return "MBEDTLS_SSL_FLUSH_BUFFERS";
+        case MBEDTLS_SSL_HANDSHAKE_WRAPUP:
+            return "MBEDTLS_SSL_HANDSHAKE_WRAPUP";
+        case MBEDTLS_SSL_NEW_SESSION_TICKET:
+            return "MBEDTLS_SSL_NEW_SESSION_TICKET";
+        case MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT:
+            return "MBEDTLS_SSL_SERVER_HELLO_VERIFY_REQUEST_SENT";
+        case MBEDTLS_SSL_HELLO_RETRY_REQUEST:
+            return "MBEDTLS_SSL_HELLO_RETRY_REQUEST";
+        case MBEDTLS_SSL_ENCRYPTED_EXTENSIONS:
+            return "MBEDTLS_SSL_ENCRYPTED_EXTENSIONS";
+        case MBEDTLS_SSL_END_OF_EARLY_DATA:
+            return "MBEDTLS_SSL_END_OF_EARLY_DATA";
+        case MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY:
+            return "MBEDTLS_SSL_CLIENT_CERTIFICATE_VERIFY";
+        case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
+            return "MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED";
+        case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
+            return "MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO";
+        case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
+            return "MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO";
+        case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
+            return "MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO";
+        case MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST:
+            return "MBEDTLS_SSL_SERVER_CCS_AFTER_HELLO_RETRY_REQUEST";
+        case MBEDTLS_SSL_HANDSHAKE_OVER:
+            return "MBEDTLS_SSL_HANDSHAKE_OVER";
+        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
+            return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET";
+        case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH:
+            return "MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET_FLUSH";
+        default:
+            return "UNKNOWN_VALUE";
+    }
+}
 
-    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
-        in_to_str[ in ] == NULL )
-    {
-        return "UNKNOWN_VALUE";
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+const char *mbedtls_ssl_early_data_status_str( mbedtls_ssl_early_data_status in )
+{
+    switch (in) {
+        case MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED:
+            return "MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED";
+        case MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED:
+            return "MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED";
+        case MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED:
+            return "MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED";
+        default:
+            return "UNKNOWN_VALUE";
     }
-    return in_to_str[ in ];
 }
 
+#endif /* defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C) */
 const char *mbedtls_ssl_protocol_version_str( mbedtls_ssl_protocol_version in )
 {
-    const char * in_to_str[]=
-    {
-        [MBEDTLS_SSL_VERSION_UNKNOWN] = "MBEDTLS_SSL_VERSION_UNKNOWN",
-        [MBEDTLS_SSL_VERSION_TLS1_2] = "MBEDTLS_SSL_VERSION_TLS1_2",
-        [MBEDTLS_SSL_VERSION_TLS1_3] = "MBEDTLS_SSL_VERSION_TLS1_3",
-    };
-
-    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
-        in_to_str[ in ] == NULL )
-    {
-        return "UNKNOWN_VALUE";
+    switch (in) {
+        case MBEDTLS_SSL_VERSION_UNKNOWN:
+            return "MBEDTLS_SSL_VERSION_UNKNOWN";
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            return "MBEDTLS_SSL_VERSION_TLS1_2";
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            return "MBEDTLS_SSL_VERSION_TLS1_3";
+        default:
+            return "UNKNOWN_VALUE";
     }
-    return in_to_str[ in ];
 }
 
 const char *mbedtls_tls_prf_types_str( mbedtls_tls_prf_types in )
 {
-    const char * in_to_str[]=
-    {
-        [MBEDTLS_SSL_TLS_PRF_NONE] = "MBEDTLS_SSL_TLS_PRF_NONE",
-        [MBEDTLS_SSL_TLS_PRF_SHA384] = "MBEDTLS_SSL_TLS_PRF_SHA384",
-        [MBEDTLS_SSL_TLS_PRF_SHA256] = "MBEDTLS_SSL_TLS_PRF_SHA256",
-        [MBEDTLS_SSL_HKDF_EXPAND_SHA384] = "MBEDTLS_SSL_HKDF_EXPAND_SHA384",
-        [MBEDTLS_SSL_HKDF_EXPAND_SHA256] = "MBEDTLS_SSL_HKDF_EXPAND_SHA256",
-    };
-
-    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
-        in_to_str[ in ] == NULL )
-    {
-        return "UNKNOWN_VALUE";
+    switch (in) {
+        case MBEDTLS_SSL_TLS_PRF_NONE:
+            return "MBEDTLS_SSL_TLS_PRF_NONE";
+        case MBEDTLS_SSL_TLS_PRF_SHA384:
+            return "MBEDTLS_SSL_TLS_PRF_SHA384";
+        case MBEDTLS_SSL_TLS_PRF_SHA256:
+            return "MBEDTLS_SSL_TLS_PRF_SHA256";
+        case MBEDTLS_SSL_HKDF_EXPAND_SHA384:
+            return "MBEDTLS_SSL_HKDF_EXPAND_SHA384";
+        case MBEDTLS_SSL_HKDF_EXPAND_SHA256:
+            return "MBEDTLS_SSL_HKDF_EXPAND_SHA256";
+        default:
+            return "UNKNOWN_VALUE";
     }
-    return in_to_str[ in ];
 }
 
 const char *mbedtls_ssl_key_export_type_str( mbedtls_ssl_key_export_type in )
 {
-    const char * in_to_str[]=
-    {
-        [MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET",
+    switch (in) {
+        case MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET";
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET",
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET",
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET",
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET",
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET",
-        [MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET] = "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET",
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_EARLY_SECRET";
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_EARLY_EXPORTER_SECRET";
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET";
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET";
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET";
+        case MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET:
+            return "MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET";
 #endif
-    };
-
-    if( in > ( sizeof( in_to_str )/sizeof( in_to_str[0]) - 1 ) ||
-        in_to_str[ in ] == NULL )
-    {
-        return "UNKNOWN_VALUE";
+        default:
+            return "UNKNOWN_VALUE";
     }
-    return in_to_str[ in ];
 }
 
 
diff --git a/lib/libmbedtls/mbedtls/library/ssl_misc.h b/lib/libmbedtls/mbedtls/library/ssl_misc.h
index 6fe0414f993f264be1c84eb426371bc3fab87743..98668798a876308b82e054c6b1768594a9592add 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_misc.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_misc.h
@@ -5,48 +5,36 @@
  */
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #ifndef MBEDTLS_SSL_MISC_H
 #define MBEDTLS_SSL_MISC_H
 
 #include "mbedtls/build_info.h"
 
+#include "mbedtls/error.h"
+
 #include "mbedtls/ssl.h"
 #include "mbedtls/cipher.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
-#include "hash_info.h"
+#include "psa_util_internal.h"
 #endif
-#include "mbedtls/legacy_or_psa.h"
 
-#if defined(MBEDTLS_MD5_C)
+#if defined(MBEDTLS_MD_CAN_MD5)
 #include "mbedtls/md5.h"
 #endif
 
-#if defined(MBEDTLS_SHA1_C)
+#if defined(MBEDTLS_MD_CAN_SHA1)
 #include "mbedtls/sha1.h"
 #endif
 
-#if defined(MBEDTLS_SHA256_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #include "mbedtls/sha256.h"
 #endif
 
-#if defined(MBEDTLS_SHA512_C)
+#if defined(MBEDTLS_MD_CAN_SHA512)
 #include "mbedtls/sha512.h"
 #endif
 
@@ -56,6 +44,9 @@
 #endif
 
 #include "mbedtls/pk.h"
+#include "ssl_ciphersuites_internal.h"
+#include "x509_internal.h"
+#include "pk_internal.h"
 #include "common.h"
 
 /* Shorthand for restartable ECC */
@@ -263,11 +254,10 @@ uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 
 /* This macro determines whether CBC is supported. */
-#if defined(MBEDTLS_CIPHER_MODE_CBC) &&                               \
-    (defined(MBEDTLS_AES_C)      ||                                  \
-    defined(MBEDTLS_CAMELLIA_C) ||                                  \
-    defined(MBEDTLS_ARIA_C)     ||                                  \
-    defined(MBEDTLS_DES_C))
+#if defined(MBEDTLS_SSL_HAVE_CBC)      &&                                  \
+    (defined(MBEDTLS_SSL_HAVE_AES)     ||                                  \
+    defined(MBEDTLS_SSL_HAVE_CAMELLIA) ||                                  \
+    defined(MBEDTLS_SSL_HAVE_ARIA))
 #define MBEDTLS_SSL_SOME_SUITES_USE_CBC
 #endif
 
@@ -298,9 +288,9 @@ uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
 
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
 /* Ciphersuites using HMAC */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 #define MBEDTLS_SSL_MAC_ADD                 48  /* SHA-384 used for HMAC */
-#elif defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#elif defined(MBEDTLS_MD_CAN_SHA256)
 #define MBEDTLS_SSL_MAC_ADD                 32  /* SHA-256 used for HMAC */
 #else
 #define MBEDTLS_SSL_MAC_ADD                 20  /* SHA-1   used for HMAC */
@@ -310,7 +300,7 @@ uint32_t mbedtls_ssl_get_extension_mask(unsigned int extension_type);
 #define MBEDTLS_SSL_MAC_ADD                 16
 #endif
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
+#if defined(MBEDTLS_SSL_HAVE_CBC)
 #define MBEDTLS_SSL_PADDING_ADD            256
 #else
 #define MBEDTLS_SSL_PADDING_ADD              0
@@ -451,6 +441,19 @@ size_t mbedtls_ssl_get_output_max_frag_len(const mbedtls_ssl_context *ssl);
 size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl);
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+/**
+ * \brief    Get the size limit in bytes for the protected outgoing records
+ *           as defined in RFC 8449
+ *
+ * \param ssl      SSL context
+ *
+ * \return         The size limit in bytes for the protected outgoing
+ *                 records as defined in RFC 8449.
+ */
+size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl);
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
 static inline size_t mbedtls_ssl_get_output_buflen(const mbedtls_ssl_context *ctx)
 {
@@ -649,6 +652,10 @@ struct mbedtls_ssl_handshake_params {
     /* Flag indicating if a CertificateRequest message has been sent
      * to the client or not. */
     uint8_t certificate_request_sent;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    /* Flag indicating if the server has accepted early data or not. */
+    uint8_t early_data_accepted;
+#endif
 #endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
@@ -658,21 +665,21 @@ struct mbedtls_ssl_handshake_params {
 #if defined(MBEDTLS_SSL_CLI_C)
     /** Minimum TLS version to be negotiated.
      *
-     *  It is set up in the ClientHello writing preparation stage and used
-     *  throughout the ClientHello writing. Not relevant anymore as soon as
-     *  the protocol version has been negotiated thus as soon as the
-     *  ServerHello is received.
-     *  For a fresh handshake not linked to any previous handshake, it is
-     *  equal to the configured minimum minor version to be negotiated. When
-     *  renegotiating or resuming a session, it is equal to the previously
-     *  negotiated minor version.
+     * It is set up in the ClientHello writing preparation stage and used
+     * throughout the ClientHello writing. Not relevant anymore as soon as
+     * the protocol version has been negotiated thus as soon as the
+     * ServerHello is received.
+     * For a fresh handshake not linked to any previous handshake, it is
+     * equal to the configured minimum minor version to be negotiated. When
+     * renegotiating or resuming a session, it is equal to the previously
+     * negotiated minor version.
      *
-     *  There is no maximum TLS version field in this handshake context.
-     *  From the start of the handshake, we need to define a current protocol
-     *  version for the record layer which we define as the maximum TLS
-     *  version to be negotiated. The `tls_version` field of the SSL context is
-     *  used to store this maximum value until it contains the actual
-     *  negotiated value.
+     * There is no maximum TLS version field in this handshake context.
+     * From the start of the handshake, we need to define a current protocol
+     * version for the record layer which we define as the maximum TLS
+     * version to be negotiated. The `tls_version` field of the SSL context is
+     * used to store this maximum value until it contains the actual
+     * negotiated value.
      */
     mbedtls_ssl_protocol_version min_tls_version;
 #endif
@@ -723,15 +730,29 @@ struct mbedtls_ssl_handshake_params {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     uint8_t key_exchange_mode; /*!< Selected key exchange mode */
 
-    /** Number of HelloRetryRequest messages received/sent from/to the server. */
-    int hello_retry_request_count;
+    /**
+     * Flag indicating if, in the course of the current handshake, an
+     * HelloRetryRequest message has been sent by the server or received by
+     * the client (<> 0) or not (0).
+     */
+    uint8_t hello_retry_request_flag;
+
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+    /**
+     * Flag indicating if, in the course of the current handshake, a dummy
+     * change_cipher_spec (CCS) record has already been sent. Used to send only
+     * one CCS per handshake while not complicating the handshake state
+     * transitions for that purpose.
+     */
+    uint8_t ccs_sent;
+#endif
 
 #if defined(MBEDTLS_SSL_SRV_C)
-    /** selected_group of key_share extension in HelloRetryRequest message. */
-    uint16_t hrr_selected_group;
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
     uint8_t tls13_kex_modes; /*!< Key exchange modes supported by the client */
 #endif
+    /** selected_group of key_share extension in HelloRetryRequest message. */
+    uint16_t hrr_selected_group;
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
     uint16_t new_session_tickets_count;         /*!< number of session tickets */
 #endif
@@ -752,25 +773,20 @@ struct mbedtls_ssl_handshake_params {
     mbedtls_dhm_context dhm_ctx;                /*!<  DHM key exchange        */
 #endif
 
-/* Adding guard for MBEDTLS_ECDSA_C to ensure no compile errors due
- * to guards in client and server code. There is a gap in functionality that
- * access to ecdh_ctx structure is needed for MBEDTLS_ECDSA_C which does not
- * seem correct.
- */
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
-#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)
     mbedtls_ecdh_context ecdh_ctx;              /*!<  ECDH key exchange       */
-#endif /* !MBEDTLS_USE_PSA_CRYPTO */
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    psa_key_type_t ecdh_psa_type;
-    size_t ecdh_bits;
-    mbedtls_svc_key_id_t ecdh_psa_privkey;
-    uint8_t ecdh_psa_privkey_is_external;
-    unsigned char ecdh_psa_peerkey[MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH];
-    size_t ecdh_psa_peerkey_len;
-#endif /* MBEDTLS_USE_PSA_CRYPTO || MBEDTLS_SSL_PROTO_TLS1_3 */
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO &&
+          MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */
+
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED)
+    psa_key_type_t xxdh_psa_type;
+    size_t xxdh_psa_bits;
+    mbedtls_svc_key_id_t xxdh_psa_privkey;
+    uint8_t xxdh_psa_privkey_is_external;
+    unsigned char xxdh_psa_peerkey[PSA_EXPORT_PUBLIC_KEY_MAX_SIZE];
+    size_t xxdh_psa_peerkey_len;
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
@@ -786,7 +802,8 @@ struct mbedtls_ssl_handshake_params {
 #endif
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) ||      \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     uint16_t *curves_tls_id;      /*!<  List of TLS IDs of supported elliptic curves */
 #endif
@@ -905,14 +922,14 @@ struct mbedtls_ssl_handshake_params {
     /*
      * Checksum contexts
      */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_operation_t fin_sha256_psa;
 #else
     mbedtls_md_context_t fin_sha256;
 #endif
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_hash_operation_t fin_sha384_psa;
 #else
@@ -1425,7 +1442,7 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want);
  * Write handshake message header
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type,
+int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type,
                                     unsigned char **buf, size_t *buf_len);
 
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -1490,7 +1507,7 @@ int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl,
 #endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
 #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
-#if defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C) || defined(MBEDTLS_SSL_SRV_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_conf_has_static_psk(mbedtls_ssl_config const *conf);
 #endif
@@ -1559,16 +1576,16 @@ int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md);
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id);
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id);
-#endif
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
 /**
  * \brief Return PSA EC info for the specified TLS ID.
  *
  * \param tls_id    The TLS ID to look for
- * \param family    If the TLD ID is supported, then proper \c psa_ecc_family_t
+ * \param type      If the TLD ID is supported, then proper \c psa_key_type_t
  *                  value is returned here. Can be NULL.
  * \param bits      If the TLD ID is supported, then proper bit size is returned
  *                  here. Can be NULL.
@@ -1581,7 +1598,7 @@ int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id
  *                  simply to check if a specific TLS ID is supported.
  */
 int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,
-                                               psa_ecc_family_t *family,
+                                               psa_key_type_t *type,
                                                size_t *bits);
 
 /**
@@ -1657,18 +1674,53 @@ static inline mbedtls_x509_crt *mbedtls_ssl_own_cert(mbedtls_ssl_context *ssl)
 }
 
 /*
- * Check usage of a certificate wrt extensions:
- * keyUsage, extendedKeyUsage (later), and nSCertType (later).
+ * Verify a certificate.
+ *
+ * [in/out] ssl: misc. things read
+ *               ssl->session_negotiate->verify_result updated
+ * [in] authmode: one of MBEDTLS_SSL_VERIFY_{NONE,OPTIONAL,REQUIRED}
+ * [in] chain: the certificate chain to verify (ie the peer's chain)
+ * [in] ciphersuite_info: For TLS 1.2, this session's ciphersuite;
+ *                        for TLS 1.3, may be left NULL.
+ * [in] rs_ctx: restart context if restartable ECC is in use;
+ *              leave NULL for no restartable behaviour.
+ *
+ * Return:
+ * - 0 if the handshake should continue. Depending on the
+ *   authmode it means:
+ *   - REQUIRED: the certificate was found to be valid, trusted & acceptable.
+ *     ssl->session_negotiate->verify_result is 0.
+ *   - OPTIONAL: the certificate may or may not be acceptable, but
+ *     ssl->session_negotiate->verify_result was updated with the result.
+ *   - NONE: the certificate wasn't even checked.
+ * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED or MBEDTLS_ERR_SSL_BAD_CERTIFICATE if
+ *   the certificate was found to be invalid/untrusted/unacceptable and the
+ *   handshake should be aborted (can only happen with REQUIRED).
+ * - another error code if another error happened (out-of-memory, etc.)
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
+                                   int authmode,
+                                   mbedtls_x509_crt *chain,
+                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
+                                   void *rs_ctx);
+
+/*
+ * Check usage of a certificate wrt usage extensions:
+ * keyUsage and extendedKeyUsage.
+ * (Note: nSCertType is deprecated and not standard, we don't check it.)
+ *
+ * Note: if tls_version is 1.3, ciphersuite is ignored and can be NULL.
  *
- * Warning: cert_endpoint is the endpoint of the cert (ie, of our peer when we
- * check a cert we received from them)!
+ * Note: recv_endpoint is the receiver's endpoint.
  *
  * Return 0 if everything is OK, -1 if not.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
                                  const mbedtls_ssl_ciphersuite_t *ciphersuite,
-                                 int cert_endpoint,
+                                 int recv_endpoint,
+                                 mbedtls_ssl_protocol_version tls_version,
                                  uint32_t *flags);
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
@@ -1874,6 +1926,26 @@ static inline int mbedtls_ssl_conf_is_hybrid_tls12_tls13(const mbedtls_ssl_confi
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_SSL_PROTO_TLS1_3 */
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+
+/** \brief Initialize the PSA crypto subsystem if necessary.
+ *
+ * Call this function before doing any cryptography in a TLS 1.3 handshake.
+ *
+ * This is necessary in Mbed TLS 3.x for backward compatibility.
+ * Up to Mbed TLS 3.5, in the default configuration, you could perform
+ * a TLS connection with default parameters without having called
+ * psa_crypto_init(), since the TLS layer only supported TLS 1.2 and
+ * did not use PSA crypto. (TLS 1.2 only uses PSA crypto if
+ * MBEDTLS_USE_PSA_CRYPTO is enabled, which is not the case in the default
+ * configuration.) Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled
+ * by default, and the TLS 1.3 layer uses PSA crypto. This means that
+ * applications that are not otherwise using PSA crypto and that worked
+ * with Mbed TLS 3.5 started failing in TLS 3.6.0 if they connected to
+ * a peer that supports TLS 1.3. See
+ * https://github.com/Mbed-TLS/mbedtls/issues/9072
+ */
+int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl);
+
 extern const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
     MBEDTLS_SERVER_HELLO_RANDOM_LEN];
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -1917,89 +1989,89 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl);
 /*
  * Helper functions around key exchange modes.
  */
-static inline unsigned mbedtls_ssl_conf_tls13_check_kex_modes(mbedtls_ssl_context *ssl,
-                                                              int kex_mode_mask)
+static inline int mbedtls_ssl_conf_tls13_is_kex_mode_enabled(mbedtls_ssl_context *ssl,
+                                                             int kex_mode_mask)
 {
     return (ssl->conf->tls13_kex_modes & kex_mode_mask) != 0;
 }
 
-static inline int mbedtls_ssl_conf_tls13_psk_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_conf_tls13_is_psk_enabled(mbedtls_ssl_context *ssl)
 {
-    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
-                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
+    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,
+                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
 }
 
-static inline int mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(mbedtls_ssl_context *ssl)
 {
-    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
-                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
+    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,
+                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
 }
 
-static inline int mbedtls_ssl_conf_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_conf_tls13_is_ephemeral_enabled(mbedtls_ssl_context *ssl)
 {
-    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
-                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
+    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,
+                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
 }
 
-static inline int mbedtls_ssl_conf_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(mbedtls_ssl_context *ssl)
 {
-    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
-                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
+    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,
+                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
 }
 
-static inline int mbedtls_ssl_conf_tls13_some_psk_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_conf_tls13_is_some_psk_enabled(mbedtls_ssl_context *ssl)
 {
-    return mbedtls_ssl_conf_tls13_check_kex_modes(ssl,
-                                                  MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
+    return mbedtls_ssl_conf_tls13_is_kex_mode_enabled(ssl,
+                                                      MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
 }
 
 #if defined(MBEDTLS_SSL_SRV_C) && \
     defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
 /**
  * Given a list of key exchange modes, check if at least one of them is
- * supported.
+ * supported by peer.
  *
  * \param[in] ssl  SSL context
  * \param kex_modes_mask  Mask of the key exchange modes to check
  *
- * \return 0 if at least one of the key exchange modes is supported,
- *         !=0 otherwise.
+ * \return Non-zero if at least one of the key exchange modes is supported by
+ *         the peer, otherwise \c 0.
  */
-static inline unsigned mbedtls_ssl_tls13_check_kex_modes(mbedtls_ssl_context *ssl,
-                                                         int kex_modes_mask)
+static inline int mbedtls_ssl_tls13_is_kex_mode_supported(mbedtls_ssl_context *ssl,
+                                                          int kex_modes_mask)
 {
-    return (ssl->handshake->tls13_kex_modes & kex_modes_mask) == 0;
+    return (ssl->handshake->tls13_kex_modes & kex_modes_mask) != 0;
 }
 
-static inline int mbedtls_ssl_tls13_psk_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_tls13_is_psk_supported(mbedtls_ssl_context *ssl)
 {
-    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
-                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
+    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,
+                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK);
 }
 
-static inline int mbedtls_ssl_tls13_psk_ephemeral_enabled(
+static inline int mbedtls_ssl_tls13_is_psk_ephemeral_supported(
     mbedtls_ssl_context *ssl)
 {
-    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
-                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
+    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,
+                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL);
 }
 
-static inline int mbedtls_ssl_tls13_ephemeral_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_tls13_is_ephemeral_supported(mbedtls_ssl_context *ssl)
 {
-    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
-                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
+    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,
+                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL);
 }
 
-static inline int mbedtls_ssl_tls13_some_ephemeral_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_tls13_is_some_ephemeral_supported(mbedtls_ssl_context *ssl)
 {
-    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
-                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
+    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,
+                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ALL);
 }
 
-static inline int mbedtls_ssl_tls13_some_psk_enabled(mbedtls_ssl_context *ssl)
+static inline int mbedtls_ssl_tls13_is_some_psk_supported(mbedtls_ssl_context *ssl)
 {
-    return !mbedtls_ssl_tls13_check_kex_modes(ssl,
-                                              MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
+    return mbedtls_ssl_tls13_is_kex_mode_supported(ssl,
+                                                   MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL);
 }
 #endif /* MBEDTLS_SSL_SRV_C &&
           MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
@@ -2054,6 +2126,33 @@ int mbedtls_ssl_tls13_fetch_handshake_msg(mbedtls_ssl_context *ssl,
                                           unsigned char **buf,
                                           size_t *buf_len);
 
+/**
+ * \brief Detect if a list of extensions contains a supported_versions
+ *        extension or not.
+ *
+ * \param[in] ssl  SSL context
+ * \param[in] buf  Address of the first byte of the extensions vector.
+ * \param[in] end  End of the buffer containing the list of extensions.
+ * \param[out] supported_versions_data  If the extension is present, address of
+ *                                      its first byte of data, NULL otherwise.
+ * \param[out] supported_versions_data_end  If the extension is present, address
+ *                                          of the first byte immediately
+ *                                          following the extension data, NULL
+ *                                          otherwise.
+ * \return 0  if the list of extensions does not contain a supported_versions
+ *            extension.
+ * \return 1  if the list of extensions contains a supported_versions
+ *            extension.
+ * \return    A negative value if an error occurred while parsing the
+ *            extensions.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *buf, const unsigned char *end,
+    const unsigned char **supported_versions_data,
+    const unsigned char **supported_versions_data_end);
+
 /*
  * Handler of TLS 1.3 server certificate message
  */
@@ -2090,21 +2189,76 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl);
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl);
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
 MBEDTLS_CHECK_RETURN_CRITICAL
-int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(
     mbedtls_ssl_context *ssl,
     uint16_t named_group,
     unsigned char *buf,
     unsigned char *end,
     size_t *out_len);
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+                                           int in_new_session_ticket,
                                            unsigned char *buf,
                                            const unsigned char *end,
                                            size_t *out_len);
+
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+                                           size_t early_data_len);
+
+typedef enum {
+/*
+ * The client has not sent the first ClientHello yet, the negotiation of early
+ * data has not started yet.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_IDLE,
+
+/*
+ * In its ClientHello, the client has not included an early data indication
+ * extension.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * is not set either as for middlebox compatibility a dummy CCS may have to be
+ * sent in clear. Early data cannot be sent to the server yet.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, it has not received the response (ServerHello or
+ * HelloRetryRequest) from the server yet. The transform to protect early data
+ * has been set and early data can be written now.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE,
+
+/*
+ * The client has indicated the use of early data and the server has accepted
+ * it.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED,
+
+/*
+ * The client has indicated the use of early data but the server has rejected
+ * it.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED,
+
+/*
+ * The client has sent an early data indication extension in its first
+ * ClientHello, the server has accepted them and the client has received the
+ * server Finished message. It cannot send early data to the server anymore.
+ */
+    MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED,
+
+} mbedtls_ssl_early_data_state;
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
@@ -2190,7 +2344,7 @@ static inline int mbedtls_ssl_tls13_named_group_is_ecdhe(uint16_t named_group)
            named_group == MBEDTLS_SSL_IANA_TLS_GROUP_X448;
 }
 
-static inline int mbedtls_ssl_tls13_named_group_is_dhe(uint16_t named_group)
+static inline int mbedtls_ssl_tls13_named_group_is_ffdh(uint16_t named_group)
 {
     return named_group >= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048 &&
            named_group <= MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192;
@@ -2216,16 +2370,22 @@ static inline int mbedtls_ssl_named_group_is_offered(
 
 static inline int mbedtls_ssl_named_group_is_supported(uint16_t named_group)
 {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH)
     if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
         if (mbedtls_ssl_get_ecp_group_id_from_tls_id(named_group) !=
             MBEDTLS_ECP_DP_NONE) {
             return 1;
         }
     }
-#else
-    ((void) named_group);
-#endif /* MBEDTLS_ECDH_C */
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+    if (mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) {
+        return 1;
+    }
+#endif
+#if !defined(PSA_WANT_ALG_ECDH) && !defined(PSA_WANT_ALG_FFDH)
+    (void) named_group;
+#endif
     return 0;
 }
 
@@ -2284,15 +2444,15 @@ static inline int mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(
 {
     switch (sig_alg) {
 #if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-#if defined(PSA_WANT_ALG_SHA_256) && defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
+#if defined(PSA_WANT_ALG_SHA_256) && defined(PSA_WANT_ECC_SECP_R1_256)
         case MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256:
             break;
 #endif /* PSA_WANT_ALG_SHA_256 && MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-#if defined(PSA_WANT_ALG_SHA_384) && defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
+#if defined(PSA_WANT_ALG_SHA_384) && defined(PSA_WANT_ECC_SECP_R1_384)
         case MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384:
             break;
 #endif /* PSA_WANT_ALG_SHA_384 && MBEDTLS_ECP_DP_SECP384R1_ENABLED */
-#if defined(PSA_WANT_ALG_SHA_512) && defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
+#if defined(PSA_WANT_ALG_SHA_512) && defined(PSA_WANT_ECC_SECP_R1_521)
         case MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512:
             break;
 #endif /* PSA_WANT_ALG_SHA_512 && MBEDTLS_ECP_DP_SECP521R1_ENABLED */
@@ -2324,18 +2484,18 @@ static inline int mbedtls_ssl_tls13_sig_alg_is_supported(
 {
     switch (sig_alg) {
 #if defined(MBEDTLS_PKCS1_V15)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256:
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256 */
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384:
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512:
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA512 */
 #endif /* MBEDTLS_PKCS1_V15 */
         default:
             return mbedtls_ssl_tls13_sig_alg_for_cert_verify_is_supported(
@@ -2378,24 +2538,24 @@ static inline int mbedtls_ssl_get_pk_type_and_md_alg_from_sig_alg(
 
     switch (sig_alg) {
 #if defined(MBEDTLS_PKCS1_V21)
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256:
             *md_alg = MBEDTLS_MD_SHA256;
             *pk_type = MBEDTLS_PK_RSASSA_PSS;
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA  */
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA256  */
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384:
             *md_alg = MBEDTLS_MD_SHA384;
             *pk_type = MBEDTLS_PK_RSASSA_PSS;
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+#if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512:
             *md_alg = MBEDTLS_MD_SHA512;
             *pk_type = MBEDTLS_PK_RSASSA_PSS;
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA512 */
 #endif /* MBEDTLS_PKCS1_V21 */
         default:
             return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -2412,32 +2572,32 @@ static inline int mbedtls_ssl_tls12_sig_alg_is_supported(
     unsigned char sig = MBEDTLS_BYTE_0(sig_alg);
 
     switch (hash) {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_MD5)
         case MBEDTLS_SSL_HASH_MD5:
             break;
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
         case MBEDTLS_SSL_HASH_SHA1:
             break;
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA224)
         case MBEDTLS_SSL_HASH_SHA224:
             break;
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_SSL_HASH_SHA256:
             break;
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_SSL_HASH_SHA384:
             break;
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_SSL_HASH_SHA512:
             break;
 #endif
@@ -2452,7 +2612,7 @@ static inline int mbedtls_ssl_tls12_sig_alg_is_supported(
             break;
 #endif
 
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
         case MBEDTLS_SSL_SIG_ECDSA:
             break;
 #endif
@@ -2618,14 +2778,14 @@ mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
     const mbedtls_ssl_ciphersuite_t *suite);
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
+int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t buf_len);
 
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
 
 static inline int mbedtls_ssl_tls13_cipher_suite_is_offered(
     mbedtls_ssl_context *ssl, int cipher_suite)
@@ -2667,12 +2827,18 @@ int mbedtls_ssl_parse_server_name_ext(mbedtls_ssl_context *ssl,
 
 #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
 #define MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH (2)
-#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64)
+#define MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN (64)      /* As defined in RFC 8449 */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
                                                   const unsigned char *buf,
                                                   const unsigned char *end);
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,
+                                                  unsigned char *buf,
+                                                  const unsigned char *end,
+                                                  size_t *out_len);
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
 #if defined(MBEDTLS_SSL_ALPN)
@@ -2741,29 +2907,161 @@ int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
                                      const char *hostname);
 #endif
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
+    defined(MBEDTLS_SSL_ALPN)
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
+                                        const char *alpn);
+#endif
+
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-static inline unsigned int mbedtls_ssl_session_get_ticket_flags(
+
+#define MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME (604800)
+
+static inline unsigned int mbedtls_ssl_tls13_session_get_ticket_flags(
     mbedtls_ssl_session *session, unsigned int flags)
 {
     return session->ticket_flags &
            (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
 }
 
-static inline void mbedtls_ssl_session_set_ticket_flags(
+/**
+ * Check if at least one of the given flags is set in
+ * the session ticket. See the definition of
+ * `MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK` to get all
+ * permitted flags.
+ */
+static inline int mbedtls_ssl_tls13_session_ticket_has_flags(
+    mbedtls_ssl_session *session, unsigned int flags)
+{
+    return mbedtls_ssl_tls13_session_get_ticket_flags(session, flags) != 0;
+}
+
+static inline int mbedtls_ssl_tls13_session_ticket_allow_psk(
+    mbedtls_ssl_session *session)
+{
+    return mbedtls_ssl_tls13_session_ticket_has_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_RESUMPTION);
+}
+
+static inline int mbedtls_ssl_tls13_session_ticket_allow_psk_ephemeral(
+    mbedtls_ssl_session *session)
+{
+    return mbedtls_ssl_tls13_session_ticket_has_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_PSK_EPHEMERAL_RESUMPTION);
+}
+
+static inline unsigned int mbedtls_ssl_tls13_session_ticket_allow_early_data(
+    mbedtls_ssl_session *session)
+{
+    return mbedtls_ssl_tls13_session_ticket_has_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+}
+
+static inline void mbedtls_ssl_tls13_session_set_ticket_flags(
     mbedtls_ssl_session *session, unsigned int flags)
 {
     session->ticket_flags |= (flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
 }
 
-static inline void mbedtls_ssl_session_clear_ticket_flags(
+static inline void mbedtls_ssl_tls13_session_clear_ticket_flags(
     mbedtls_ssl_session *session, unsigned int flags)
 {
     session->ticket_flags &= ~(flags & MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
 }
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 && MBEDTLS_SSL_SESSION_TICKETS */
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT 0
+#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT 1
+
+#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK \
+    (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT)
+#define MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK \
+    (1 << MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT)
+
+static inline int mbedtls_ssl_conf_get_session_tickets(
+    const mbedtls_ssl_config *conf)
+{
+    return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK ?
+           MBEDTLS_SSL_SESSION_TICKETS_ENABLED :
+           MBEDTLS_SSL_SESSION_TICKETS_DISABLED;
+}
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+static inline int mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(
+    const mbedtls_ssl_config *conf)
+{
+    return conf->session_tickets & MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK ?
+           MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED :
+           MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+
 #if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
 int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl);
 #endif
 
+#if defined(MBEDTLS_TEST_HOOKS) && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+
+/** Compute the HMAC of variable-length data with constant flow.
+ *
+ * This function computes the HMAC of the concatenation of \p add_data and \p
+ * data, and does with a code flow and memory access pattern that does not
+ * depend on \p data_len_secret, but only on \p min_data_len and \p
+ * max_data_len. In particular, this function always reads exactly \p
+ * max_data_len bytes from \p data.
+ *
+ * \param ctx               The HMAC context. It must have keys configured
+ *                          with mbedtls_md_hmac_starts() and use one of the
+ *                          following hashes: SHA-384, SHA-256, SHA-1 or MD-5.
+ *                          It is reset using mbedtls_md_hmac_reset() after
+ *                          the computation is complete to prepare for the
+ *                          next computation.
+ * \param add_data          The first part of the message whose HMAC is being
+ *                          calculated. This must point to a readable buffer
+ *                          of \p add_data_len bytes.
+ * \param add_data_len      The length of \p add_data in bytes.
+ * \param data              The buffer containing the second part of the
+ *                          message. This must point to a readable buffer
+ *                          of \p max_data_len bytes.
+ * \param data_len_secret   The length of the data to process in \p data.
+ *                          This must be no less than \p min_data_len and no
+ *                          greater than \p max_data_len.
+ * \param min_data_len      The minimal length of the second part of the
+ *                          message, read from \p data.
+ * \param max_data_len      The maximal length of the second part of the
+ *                          message, read from \p data.
+ * \param output            The HMAC will be written here. This must point to
+ *                          a writable buffer of sufficient size to hold the
+ *                          HMAC value.
+ *
+ * \retval 0 on success.
+ * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED
+ *         The hardware accelerator failed.
+ */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
+                    psa_algorithm_t mac_alg,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output);
+#else
+int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output);
+#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */
+#endif /* MBEDTLS_TEST_HOOKS && defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC) */
+
 #endif /* ssl_misc.h */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_msg.c b/lib/libmbedtls/mbedtls/library/ssl_msg.c
index 18c19f93effd4be6f88603516693e840571aeeab..ef722d7bdce731cb620a9fa13ad7c315d7ee1bde 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_msg.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_msg.c
@@ -3,19 +3,7 @@
  *  (record layer + retransmission state machine)
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  http://www.ietf.org/rfc/rfc2246.txt
@@ -30,7 +18,7 @@
 
 #include "mbedtls/ssl.h"
 #include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/version.h"
@@ -40,7 +28,7 @@
 #include <string.h>
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 #include "psa/crypto.h"
 #endif
 
@@ -49,11 +37,245 @@
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 #endif
 
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+#if defined(PSA_WANT_ALG_SHA_384)
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_384)
+#elif defined(PSA_WANT_ALG_SHA_256)
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_256)
+#else /* See check_config.h */
+#define MAX_HASH_BLOCK_LENGTH PSA_HASH_BLOCK_LENGTH(PSA_ALG_SHA_1)
+#endif
+
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ct_hmac(mbedtls_svc_key_id_t key,
+                    psa_algorithm_t mac_alg,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output)
+{
+    /*
+     * This function breaks the HMAC abstraction and uses psa_hash_clone()
+     * extension in order to get constant-flow behaviour.
+     *
+     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
+     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
+     * patterns (see RFC 2104, sec. 2).
+     *
+     * We'll first compute ikey/okey, then inner_hash = HASH(ikey + msg) by
+     * hashing up to minlen, then cloning the context, and for each byte up
+     * to maxlen finishing up the hash computation, keeping only the
+     * correct result.
+     *
+     * Then we only need to compute HASH(okey + inner_hash) and we're done.
+     */
+    psa_algorithm_t hash_alg = PSA_ALG_HMAC_GET_HASH(mac_alg);
+    const size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
+    unsigned char key_buf[MAX_HASH_BLOCK_LENGTH];
+    const size_t hash_size = PSA_HASH_LENGTH(hash_alg);
+    psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
+    size_t hash_length;
+
+    unsigned char aux_out[PSA_HASH_MAX_SIZE];
+    psa_hash_operation_t aux_operation = PSA_HASH_OPERATION_INIT;
+    size_t offset;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+
+    size_t mac_key_length;
+    size_t i;
+
+#define PSA_CHK(func_call)        \
+    do {                            \
+        status = (func_call);       \
+        if (status != PSA_SUCCESS) \
+        goto cleanup;           \
+    } while (0)
+
+    /* Export MAC key
+     * We assume key length is always exactly the output size
+     * which is never more than the block size, thus we use block_size
+     * as the key buffer size.
+     */
+    PSA_CHK(psa_export_key(key, key_buf, block_size, &mac_key_length));
+
+    /* Calculate ikey */
+    for (i = 0; i < mac_key_length; i++) {
+        key_buf[i] = (unsigned char) (key_buf[i] ^ 0x36);
+    }
+    for (; i < block_size; ++i) {
+        key_buf[i] = 0x36;
+    }
+
+    PSA_CHK(psa_hash_setup(&operation, hash_alg));
+
+    /* Now compute inner_hash = HASH(ikey + msg) */
+    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
+    PSA_CHK(psa_hash_update(&operation, add_data, add_data_len));
+    PSA_CHK(psa_hash_update(&operation, data, min_data_len));
+
+    /* Fill the hash buffer in advance with something that is
+     * not a valid hash (barring an attack on the hash and
+     * deliberately-crafted input), in case the caller doesn't
+     * check the return status properly. */
+    memset(output, '!', hash_size);
+
+    /* For each possible length, compute the hash up to that point */
+    for (offset = min_data_len; offset <= max_data_len; offset++) {
+        PSA_CHK(psa_hash_clone(&operation, &aux_operation));
+        PSA_CHK(psa_hash_finish(&aux_operation, aux_out,
+                                PSA_HASH_MAX_SIZE, &hash_length));
+        /* Keep only the correct inner_hash in the output buffer */
+        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),
+                             output, aux_out, NULL, hash_size);
+
+        if (offset < max_data_len) {
+            PSA_CHK(psa_hash_update(&operation, data + offset, 1));
+        }
+    }
+
+    /* Abort current operation to prepare for final operation */
+    PSA_CHK(psa_hash_abort(&operation));
+
+    /* Calculate okey */
+    for (i = 0; i < mac_key_length; i++) {
+        key_buf[i] = (unsigned char) ((key_buf[i] ^ 0x36) ^ 0x5C);
+    }
+    for (; i < block_size; ++i) {
+        key_buf[i] = 0x5C;
+    }
+
+    /* Now compute HASH(okey + inner_hash) */
+    PSA_CHK(psa_hash_setup(&operation, hash_alg));
+    PSA_CHK(psa_hash_update(&operation, key_buf, block_size));
+    PSA_CHK(psa_hash_update(&operation, output, hash_size));
+    PSA_CHK(psa_hash_finish(&operation, output, hash_size, &hash_length));
+
+#undef PSA_CHK
+
+cleanup:
+    mbedtls_platform_zeroize(key_buf, MAX_HASH_BLOCK_LENGTH);
+    mbedtls_platform_zeroize(aux_out, PSA_HASH_MAX_SIZE);
+
+    psa_hash_abort(&operation);
+    psa_hash_abort(&aux_operation);
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+
+#undef MAX_HASH_BLOCK_LENGTH
+
+#else
+MBEDTLS_STATIC_TESTABLE
+int mbedtls_ct_hmac(mbedtls_md_context_t *ctx,
+                    const unsigned char *add_data,
+                    size_t add_data_len,
+                    const unsigned char *data,
+                    size_t data_len_secret,
+                    size_t min_data_len,
+                    size_t max_data_len,
+                    unsigned char *output)
+{
+    /*
+     * This function breaks the HMAC abstraction and uses the md_clone()
+     * extension to the MD API in order to get constant-flow behaviour.
+     *
+     * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means
+     * concatenation, and okey/ikey are the XOR of the key with some fixed bit
+     * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx.
+     *
+     * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to
+     * minlen, then cloning the context, and for each byte up to maxlen
+     * finishing up the hash computation, keeping only the correct result.
+     *
+     * Then we only need to compute HASH(okey + inner_hash) and we're done.
+     */
+    const mbedtls_md_type_t md_alg = mbedtls_md_get_type(ctx->md_info);
+    /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5,
+     * all of which have the same block size except SHA-384. */
+    const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64;
+    const unsigned char * const ikey = ctx->hmac_ctx;
+    const unsigned char * const okey = ikey + block_size;
+    const size_t hash_size = mbedtls_md_get_size(ctx->md_info);
+
+    unsigned char aux_out[MBEDTLS_MD_MAX_SIZE];
+    mbedtls_md_context_t aux;
+    size_t offset;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    mbedtls_md_init(&aux);
+
+#define MD_CHK(func_call) \
+    do {                    \
+        ret = (func_call);  \
+        if (ret != 0)      \
+        goto cleanup;   \
+    } while (0)
+
+    MD_CHK(mbedtls_md_setup(&aux, ctx->md_info, 0));
+
+    /* After hmac_start() of hmac_reset(), ikey has already been hashed,
+     * so we can start directly with the message */
+    MD_CHK(mbedtls_md_update(ctx, add_data, add_data_len));
+    MD_CHK(mbedtls_md_update(ctx, data, min_data_len));
+
+    /* Fill the hash buffer in advance with something that is
+     * not a valid hash (barring an attack on the hash and
+     * deliberately-crafted input), in case the caller doesn't
+     * check the return status properly. */
+    memset(output, '!', hash_size);
+
+    /* For each possible length, compute the hash up to that point */
+    for (offset = min_data_len; offset <= max_data_len; offset++) {
+        MD_CHK(mbedtls_md_clone(&aux, ctx));
+        MD_CHK(mbedtls_md_finish(&aux, aux_out));
+        /* Keep only the correct inner_hash in the output buffer */
+        mbedtls_ct_memcpy_if(mbedtls_ct_uint_eq(offset, data_len_secret),
+                             output, aux_out, NULL, hash_size);
+
+        if (offset < max_data_len) {
+            MD_CHK(mbedtls_md_update(ctx, data + offset, 1));
+        }
+    }
+
+    /* The context needs to finish() before it starts() again */
+    MD_CHK(mbedtls_md_finish(ctx, aux_out));
+
+    /* Now compute HASH(okey + inner_hash) */
+    MD_CHK(mbedtls_md_starts(ctx));
+    MD_CHK(mbedtls_md_update(ctx, okey, block_size));
+    MD_CHK(mbedtls_md_update(ctx, output, hash_size));
+    MD_CHK(mbedtls_md_finish(ctx, output));
+
+    /* Done, get ready for next time */
+    MD_CHK(mbedtls_md_hmac_reset(ctx));
+
+#undef MD_CHK
+
+cleanup:
+    mbedtls_md_free(&aux);
+    return ret;
+}
+
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+
 static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl);
 
 /*
@@ -626,12 +848,10 @@ static void ssl_extract_add_data_from_record(unsigned char *add_data,
         cur += 2;
     }
 
-    *add_data_len = cur - add_data;
+    *add_data_len = (size_t) (cur - add_data);
 }
 
-#if defined(MBEDTLS_GCM_C) || \
-    defined(MBEDTLS_CCM_C) || \
-    defined(MBEDTLS_CHACHAPOLY_C)
+#if defined(MBEDTLS_SSL_HAVE_AEAD)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_transform_aead_dynamic_iv_is_explicit(
     mbedtls_ssl_transform const *transform)
@@ -676,7 +896,7 @@ static void ssl_build_record_nonce(unsigned char *dst_iv,
     dst_iv += dst_iv_len - dynamic_iv_len;
     mbedtls_xor(dst_iv, dst_iv, dynamic_iv, dynamic_iv_len);
 }
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
+#endif /* MBEDTLS_SSL_HAVE_AEAD */
 
 int mbedtls_ssl_encrypt_buf(mbedtls_ssl_context *ssl,
                             mbedtls_ssl_transform *transform,
@@ -912,9 +1132,7 @@ hmac_failed_etm_disabled:
     } else
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */
 
-#if defined(MBEDTLS_GCM_C) || \
-    defined(MBEDTLS_CCM_C) || \
-    defined(MBEDTLS_CHACHAPOLY_C)
+#if defined(MBEDTLS_SSL_HAVE_AEAD)
     if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
         unsigned char iv[12];
         unsigned char *dynamic_iv;
@@ -994,7 +1212,7 @@ hmac_failed_etm_disabled:
                                                    iv, transform->ivlen,
                                                    add_data, add_data_len,
                                                    data, rec->data_len, /* src */
-                                                   data, rec->buf_len - (data - rec->buf), /* dst */
+                                                   data, rec->buf_len - (size_t) (data - rec->buf), /* dst */
                                                    &rec->data_len,
                                                    transform->taglen)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_encrypt_ext", ret);
@@ -1024,7 +1242,7 @@ hmac_failed_etm_disabled:
 
         auth_done++;
     } else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
+#endif /* MBEDTLS_SSL_HAVE_AEAD */
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
     if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||
         ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
@@ -1262,15 +1480,16 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
                             mbedtls_ssl_transform *transform,
                             mbedtls_record *rec)
 {
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_CIPHER_MODE_AEAD)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC) || defined(MBEDTLS_SSL_HAVE_AEAD)
     size_t olen;
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_CIPHER_MODE_AEAD */
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC || MBEDTLS_SSL_HAVE_AEAD */
     mbedtls_ssl_mode_t ssl_mode;
     int ret;
 
     int auth_done = 0;
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-    size_t padlen = 0, correct = 1;
+    size_t padlen = 0;
+    mbedtls_ct_condition_t correct = MBEDTLS_CT_TRUE;
 #endif
     unsigned char *data;
     /* For an explanation of the additional data length see
@@ -1312,13 +1531,19 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
 
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_STREAM)
     if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
+        if (rec->data_len < transform->maclen) {
+            MBEDTLS_SSL_DEBUG_MSG(1,
+                                  ("Record too short for MAC:"
+                                   " %" MBEDTLS_PRINTF_SIZET " < %" MBEDTLS_PRINTF_SIZET,
+                                   rec->data_len, transform->maclen));
+            return MBEDTLS_ERR_SSL_INVALID_MAC;
+        }
+
         /* The only supported stream cipher is "NULL",
-         * so there's nothing to do here.*/
+         * so there's no encryption to do here.*/
     } else
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_STREAM */
-#if defined(MBEDTLS_GCM_C) || \
-    defined(MBEDTLS_CCM_C) || \
-    defined(MBEDTLS_CHACHAPOLY_C)
+#if defined(MBEDTLS_SSL_HAVE_AEAD)
     if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
         unsigned char iv[12];
         unsigned char *dynamic_iv;
@@ -1410,12 +1635,13 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
             return ret;
         }
 #else
-        if ((ret = mbedtls_cipher_auth_decrypt_ext(&transform->cipher_ctx_dec,
-                                                   iv, transform->ivlen,
-                                                   add_data, add_data_len,
-                                                   data, rec->data_len + transform->taglen, /* src */
-                                                   data, rec->buf_len - (data - rec->buf), &olen, /* dst */
-                                                   transform->taglen)) != 0) {
+        if ((ret = mbedtls_cipher_auth_decrypt_ext
+                       (&transform->cipher_ctx_dec,
+                       iv, transform->ivlen,
+                       add_data, add_data_len,
+                       data, rec->data_len + transform->taglen, /* src */
+                       data, rec->buf_len - (size_t) (data - rec->buf), &olen, /* dst */
+                       transform->taglen)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_auth_decrypt_ext", ret);
 
             if (ret == MBEDTLS_ERR_CIPHER_AUTH_FAILED) {
@@ -1434,7 +1660,7 @@ int mbedtls_ssl_decrypt_buf(mbedtls_ssl_context const *ssl,
             return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
     } else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C */
+#endif /* MBEDTLS_SSL_HAVE_AEAD */
 #if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC)
     if (ssl_mode == MBEDTLS_SSL_MODE_CBC ||
         ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
@@ -1684,11 +1910,11 @@ hmac_failed_etm_enabled:
         padlen = data[rec->data_len - 1];
 
         if (auth_done == 1) {
-            const size_t mask = mbedtls_ct_size_mask_ge(
+            const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(
                 rec->data_len,
                 padlen + 1);
-            correct &= mask;
-            padlen  &= mask;
+            correct = mbedtls_ct_bool_and(ge, correct);
+            padlen  = mbedtls_ct_size_if_else_0(ge, padlen);
         } else {
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             if (rec->data_len < transform->maclen + padlen + 1) {
@@ -1700,12 +1926,11 @@ hmac_failed_etm_enabled:
                                           padlen + 1));
             }
 #endif
-
-            const size_t mask = mbedtls_ct_size_mask_ge(
+            const mbedtls_ct_condition_t ge = mbedtls_ct_uint_ge(
                 rec->data_len,
                 transform->maclen + padlen + 1);
-            correct &= mask;
-            padlen  &= mask;
+            correct = mbedtls_ct_bool_and(ge, correct);
+            padlen  = mbedtls_ct_size_if_else_0(ge, padlen);
         }
 
         padlen++;
@@ -1734,19 +1959,20 @@ hmac_failed_etm_enabled:
             /* pad_count += (idx >= padding_idx) &&
              *              (check[idx] == padlen - 1);
              */
-            const size_t mask = mbedtls_ct_size_mask_ge(idx, padding_idx);
-            const size_t equal = mbedtls_ct_size_bool_eq(check[idx],
-                                                         padlen - 1);
-            pad_count += mask & equal;
+            const mbedtls_ct_condition_t a = mbedtls_ct_uint_ge(idx, padding_idx);
+            size_t increment = mbedtls_ct_size_if_else_0(a, 1);
+            const mbedtls_ct_condition_t b = mbedtls_ct_uint_eq(check[idx], padlen - 1);
+            increment = mbedtls_ct_size_if_else_0(b, increment);
+            pad_count += increment;
         }
-        correct &= mbedtls_ct_size_bool_eq(pad_count, padlen);
+        correct = mbedtls_ct_bool_and(mbedtls_ct_uint_eq(pad_count, padlen), correct);
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-        if (padlen > 0 && correct == 0) {
+        if (padlen > 0 && correct == MBEDTLS_CT_FALSE) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("bad padding byte detected"));
         }
 #endif
-        padlen &= mbedtls_ct_size_mask(correct);
+        padlen = mbedtls_ct_size_if_else_0(correct, padlen);
 
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
@@ -1776,7 +2002,7 @@ hmac_failed_etm_enabled:
         unsigned char mac_expect[MBEDTLS_SSL_MAC_ADD] = { 0 };
         unsigned char mac_peer[MBEDTLS_SSL_MAC_ADD] = { 0 };
 
-        /* If the initial value of padlen was such that
+        /* For CBC+MAC, If the initial value of padlen was such that
          * data_len < maclen + padlen + 1, then padlen
          * got reset to 1, and the initial check
          * data_len >= minlen + maclen + 1
@@ -1788,6 +2014,9 @@ hmac_failed_etm_enabled:
          * subtracted either padlen + 1 (if the padding was correct)
          * or 0 (if the padding was incorrect) since then,
          * hence data_len >= maclen in any case.
+         *
+         * For stream ciphers, we checked above that
+         * data_len >= maclen.
          */
         rec->data_len -= transform->maclen;
         ssl_extract_add_data_from_record(add_data, &add_data_len, rec,
@@ -1841,7 +2070,7 @@ hmac_failed_etm_enabled:
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
             MBEDTLS_SSL_DEBUG_MSG(1, ("message mac does not match"));
 #endif
-            correct = 0;
+            correct = MBEDTLS_CT_FALSE;
         }
         auth_done++;
 
@@ -1856,7 +2085,7 @@ hmac_failed_etm_disabled:
     /*
      * Finally check the correct flag
      */
-    if (correct == 0) {
+    if (correct == MBEDTLS_CT_FALSE) {
         return MBEDTLS_ERR_SSL_INVALID_MAC;
     }
 #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
@@ -2000,7 +2229,7 @@ int mbedtls_ssl_fetch_input(mbedtls_ssl_context *ssl, size_t nb_want)
             MBEDTLS_SSL_DEBUG_MSG(2, ("timer has expired"));
             ret = MBEDTLS_ERR_SSL_TIMEOUT;
         } else {
-            len = in_buf_len - (ssl->in_hdr - ssl->in_buf);
+            len = in_buf_len - (size_t) (ssl->in_hdr - ssl->in_buf);
 
             if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
                 timeout = ssl->handshake->retransmit_timeout;
@@ -2364,7 +2593,7 @@ int mbedtls_ssl_flight_transmit(mbedtls_ssl_context *ssl)
         } else {
             const unsigned char * const p = ssl->handshake->cur_msg_p;
             const size_t hs_len = cur->len - 12;
-            const size_t frag_off = p - (cur->p + 12);
+            const size_t frag_off = (size_t) (p - (cur->p + 12));
             const size_t rem_len = hs_len - frag_off;
             size_t cur_hs_frag_len, max_hs_frag_len;
 
@@ -2502,7 +2731,7 @@ void mbedtls_ssl_send_flight_completed(mbedtls_ssl_context *ssl)
 /*
  * Handshake layer functions
  */
-int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned hs_type,
+int mbedtls_ssl_start_handshake_msg(mbedtls_ssl_context *ssl, unsigned char hs_type,
                                     unsigned char **buf, size_t *buf_len)
 {
     /*
@@ -2741,9 +2970,9 @@ int mbedtls_ssl_write_record(mbedtls_ssl_context *ssl, int force_flush)
             mbedtls_record rec;
 
             rec.buf         = ssl->out_iv;
-            rec.buf_len     = out_buf_len - (ssl->out_iv - ssl->out_buf);
+            rec.buf_len     = out_buf_len - (size_t) (ssl->out_iv - ssl->out_buf);
             rec.data_len    = ssl->out_msglen;
-            rec.data_offset = ssl->out_msg - rec.buf;
+            rec.data_offset = (size_t) (ssl->out_msg - rec.buf);
 
             memcpy(&rec.ctr[0], ssl->out_ctr, sizeof(rec.ctr));
             mbedtls_ssl_write_version(rec.ver, ssl->conf->transport, tls_ver);
@@ -2868,16 +3097,12 @@ static int ssl_hs_is_proper_fragment(mbedtls_ssl_context *ssl)
 
 static uint32_t ssl_get_hs_frag_len(mbedtls_ssl_context const *ssl)
 {
-    return (ssl->in_msg[9] << 16) |
-           (ssl->in_msg[10] << 8) |
-           ssl->in_msg[11];
+    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 9);
 }
 
 static uint32_t ssl_get_hs_frag_off(mbedtls_ssl_context const *ssl)
 {
-    return (ssl->in_msg[6] << 16) |
-           (ssl->in_msg[7] << 8) |
-           ssl->in_msg[8];
+    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 6);
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -2990,9 +3215,7 @@ static size_t ssl_get_reassembly_buffer_size(size_t msg_len,
 
 static uint32_t ssl_get_hs_total_len(mbedtls_ssl_context const *ssl)
 {
-    return (ssl->in_msg[1] << 16) |
-           (ssl->in_msg[2] << 8) |
-           ssl->in_msg[3];
+    return MBEDTLS_GET_UINT24_BE(ssl->in_msg, 1);
 }
 
 int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
@@ -3013,7 +3236,7 @@ int mbedtls_ssl_prepare_handshake_record(mbedtls_ssl_context *ssl)
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        unsigned int recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5];
+        unsigned int recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);
 
         if (ssl_check_hs_header(ssl) != 0) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("invalid handshake header"));
@@ -3366,7 +3589,7 @@ int mbedtls_ssl_check_dtls_clihlo_cookie(
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    *olen = p - obuf;
+    *olen = (size_t) (p - obuf);
 
     /* Go back and fill length fields */
     obuf[27] = (unsigned char) (*olen - 28);
@@ -3404,7 +3627,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_handle_possible_reconnect(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len;
+    size_t len = 0;
 
     if (ssl->conf->f_cookie_write == NULL ||
         ssl->conf->f_cookie_check == NULL) {
@@ -3596,8 +3819,9 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
      */
     rec->ver[0] = buf[rec_hdr_version_offset + 0];
     rec->ver[1] = buf[rec_hdr_version_offset + 1];
-    tls_version = mbedtls_ssl_read_version(buf + rec_hdr_version_offset,
-                                           ssl->conf->transport);
+    tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(
+        buf + rec_hdr_version_offset,
+        ssl->conf->transport);
 
     if (tls_version > ssl->conf->max_tls_version) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("TLS version mismatch: got %u, expected max %u",
@@ -3627,8 +3851,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
      */
 
     rec->data_offset = rec_hdr_len_offset + rec_hdr_len_len;
-    rec->data_len    = ((size_t) buf[rec_hdr_len_offset + 0] << 8) |
-                       ((size_t) buf[rec_hdr_len_offset + 1] << 0);
+    rec->data_len    = MBEDTLS_GET_UINT16_BE(buf, rec_hdr_len_offset);
     MBEDTLS_SSL_DEBUG_BUF(4, "input record header", buf, rec->data_offset);
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("input record: msgtype = %u, "
@@ -3656,7 +3879,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
      */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        rec_epoch = (rec->ctr[0] << 8) | rec->ctr[1];
+        rec_epoch = MBEDTLS_GET_UINT16_BE(rec->ctr, 0);
 
         /* Check that the datagram is large enough to contain a record
          * of the advertised length. */
@@ -3706,7 +3929,7 @@ static int ssl_parse_record_header(mbedtls_ssl_context const *ssl,
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_client_reconnect(mbedtls_ssl_context *ssl)
 {
-    unsigned int rec_epoch = (ssl->in_ctr[0] << 8) | ssl->in_ctr[1];
+    unsigned int rec_epoch = MBEDTLS_GET_UINT16_BE(ssl->in_ctr, 0);
 
     /*
      * Check for an epoch 0 ClientHello. We can't use in_msg here to
@@ -3762,6 +3985,35 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
                                            rec)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "ssl_decrypt_buf", ret);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+            /*
+             * Although the server rejected early data, it might receive early
+             * data as long as it has not received the client Finished message.
+             * It is encrypted with early keys and should be ignored as stated
+             * in section 4.2.10 of RFC 8446:
+             *
+             * "Ignore the extension and return a regular 1-RTT response. The
+             * server then skips past early data by attempting to deprotect
+             * received records using the handshake traffic key, discarding
+             * records which fail deprotection (up to the configured
+             * max_early_data_size). Once a record is deprotected successfully,
+             * it is treated as the start of the client's second flight and the
+             * server proceeds as with an ordinary 1-RTT handshake."
+             */
+            if ((old_msg_type == MBEDTLS_SSL_MSG_APPLICATION_DATA) &&
+                (ssl->discard_early_data_record ==
+                 MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD)) {
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3, ("EarlyData: deprotect and discard app data records."));
+
+                ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+                if (ret != 0) {
+                    return ret;
+                }
+                ret = MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+            }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
             if (ret == MBEDTLS_ERR_SSL_UNEXPECTED_CID &&
                 ssl->conf->ignore_unexpected_cid
@@ -3771,9 +4023,27 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
             }
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
+            /*
+             * The decryption of the record failed, no reason to ignore it,
+             * return in error with the decryption error code.
+             */
             return ret;
         }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+        /*
+         * If the server were discarding protected records that it fails to
+         * deprotect because it has rejected early data, as we have just
+         * deprotected successfully a record, the server has to resume normal
+         * operation and fail the connection if the deprotection of a record
+         * fails.
+         */
+        if (ssl->discard_early_data_record ==
+            MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD) {
+            ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+        }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
         if (old_msg_type != rec->type) {
             MBEDTLS_SSL_DEBUG_MSG(4, ("record type after decrypt (before %d): %d",
                                       old_msg_type, rec->type));
@@ -3847,6 +4117,38 @@ static int ssl_prepare_record_content(mbedtls_ssl_context *ssl,
 
     }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_SRV_C)
+    /*
+     * Although the server rejected early data because it needed to send an
+     * HelloRetryRequest message, it might receive early data as long as it has
+     * not received the client Finished message.
+     * The early data is encrypted with early keys and should be ignored as
+     * stated in section 4.2.10 of RFC 8446 (second case):
+     *
+     * "The server then ignores early data by skipping all records with an
+     * external content type of "application_data" (indicating that they are
+     * encrypted), up to the configured max_early_data_size. Ignore application
+     * data message before 2nd ClientHello when early_data was received in 1st
+     * ClientHello."
+     */
+    if (ssl->discard_early_data_record == MBEDTLS_SSL_EARLY_DATA_DISCARD) {
+        if (rec->type == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+
+            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, rec->data_len);
+            if (ret != 0) {
+                return ret;
+            }
+
+            MBEDTLS_SSL_DEBUG_MSG(
+                3, ("EarlyData: Ignore application message before 2nd ClientHello"));
+
+            return MBEDTLS_ERR_SSL_CONTINUE_PROCESSING;
+        } else if (rec->type == MBEDTLS_SSL_MSG_HANDSHAKE) {
+            ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+        }
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_SRV_C */
+
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
     if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
         mbedtls_ssl_dtls_replay_update(ssl);
@@ -4028,9 +4330,7 @@ static int ssl_load_buffered_message(mbedtls_ssl_context *ssl)
     hs_buf = &hs->buffering.hs[0];
     if ((hs_buf->is_valid == 1) && (hs_buf->is_complete == 1)) {
         /* Synthesize a record containing the buffered HS message. */
-        size_t msg_len = (hs_buf->data[1] << 16) |
-                         (hs_buf->data[2] << 8) |
-                         hs_buf->data[3];
+        size_t msg_len = MBEDTLS_GET_UINT24_BE(hs_buf->data, 1);
 
         /* Double-check that we haven't accidentally buffered
          * a message that doesn't fit into the input buffer. */
@@ -4127,7 +4427,7 @@ static int ssl_buffer_message(mbedtls_ssl_context *ssl)
         case MBEDTLS_SSL_MSG_HANDSHAKE:
         {
             unsigned recv_msg_seq_offset;
-            unsigned recv_msg_seq = (ssl->in_msg[4] << 8) | ssl->in_msg[5];
+            unsigned recv_msg_seq = MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);
             mbedtls_ssl_hs_buffer *hs_buf;
             size_t msg_len = ssl->in_hslen - 12;
 
@@ -5270,9 +5570,9 @@ static int ssl_check_ctr_renegotiate(mbedtls_ssl_context *ssl)
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
+static int ssl_tls13_is_new_session_ticket(mbedtls_ssl_context *ssl)
 {
 
     if ((ssl->in_hslen == mbedtls_ssl_hs_hdr_len(ssl)) ||
@@ -5280,15 +5580,9 @@ static int ssl_tls13_check_new_session_ticket(mbedtls_ssl_context *ssl)
         return 0;
     }
 
-    ssl->keep_current_message = 1;
-
-    MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
-    mbedtls_ssl_handshake_set_state(ssl,
-                                    MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
-
-    return MBEDTLS_ERR_SSL_WANT_READ;
+    return 1;
 }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
@@ -5296,14 +5590,29 @@ static int ssl_tls13_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("received post-handshake message"));
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_CLI_C)
     if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        int ret = ssl_tls13_check_new_session_ticket(ssl);
-        if (ret != 0) {
-            return ret;
+        if (ssl_tls13_is_new_session_ticket(ssl)) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            MBEDTLS_SSL_DEBUG_MSG(3, ("NewSessionTicket received"));
+            if (mbedtls_ssl_conf_is_signal_new_session_tickets_enabled(ssl->conf) ==
+                MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_ENABLED) {
+                ssl->keep_current_message = 1;
+
+                mbedtls_ssl_handshake_set_state(ssl,
+                                                MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+                return MBEDTLS_ERR_SSL_WANT_READ;
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, handling disabled."));
+                return 0;
+            }
+#else
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Ignoring NewSessionTicket, not supported."));
+            return 0;
+#endif
         }
     }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+#endif /* MBEDTLS_SSL_CLI_C */
 
     /* Fail in all other cases. */
     return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
@@ -5426,13 +5735,54 @@ static int ssl_handle_hs_message_post_handshake(mbedtls_ssl_context *ssl)
     return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
 }
 
+/*
+ * brief          Read at most 'len' application data bytes from the input
+ *                buffer.
+ *
+ * param ssl      SSL context:
+ *                - First byte of application data not read yet in the input
+ *                  buffer located at address `in_offt`.
+ *                - The number of bytes of data not read yet is `in_msglen`.
+ * param buf      buffer that will hold the data
+ * param len      maximum number of bytes to read
+ *
+ * note           The function updates the fields `in_offt` and `in_msglen`
+ *                according to the number of bytes read.
+ *
+ * return         The number of bytes read.
+ */
+static int ssl_read_application_data(
+    mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
+{
+    size_t n = (len < ssl->in_msglen) ? len : ssl->in_msglen;
+
+    if (len != 0) {
+        memcpy(buf, ssl->in_offt, n);
+        ssl->in_msglen -= n;
+    }
+
+    /* Zeroising the plaintext buffer to erase unused application data
+       from the memory. */
+    mbedtls_platform_zeroize(ssl->in_offt, n);
+
+    if (ssl->in_msglen == 0) {
+        /* all bytes consumed */
+        ssl->in_offt = NULL;
+        ssl->keep_current_message = 0;
+    } else {
+        /* more data available */
+        ssl->in_offt += n;
+    }
+
+    return (int) n;
+}
+
 /*
  * Receive application data decrypted from the SSL layer
  */
 int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t n;
 
     if (ssl == NULL || ssl->conf == NULL) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
@@ -5596,31 +5946,33 @@ int mbedtls_ssl_read(mbedtls_ssl_context *ssl, unsigned char *buf, size_t len)
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     }
 
-    n = (len < ssl->in_msglen)
-        ? len : ssl->in_msglen;
+    ret = ssl_read_application_data(ssl, buf, len);
 
-    if (len != 0) {
-        memcpy(buf, ssl->in_offt, n);
-        ssl->in_msglen -= n;
-    }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= read"));
 
-    /* Zeroising the plaintext buffer to erase unused application data
-       from the memory. */
-    mbedtls_platform_zeroize(ssl->in_offt, n);
+    return ret;
+}
 
-    if (ssl->in_msglen == 0) {
-        /* all bytes consumed */
-        ssl->in_offt = NULL;
-        ssl->keep_current_message = 0;
-    } else {
-        /* more data available */
-        ssl->in_offt += n;
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA)
+int mbedtls_ssl_read_early_data(mbedtls_ssl_context *ssl,
+                                unsigned char *buf, size_t len)
+{
+    if (ssl == NULL || (ssl->conf == NULL)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= read"));
+    /*
+     * The server may receive early data only while waiting for the End of
+     * Early Data handshake message.
+     */
+    if ((ssl->state != MBEDTLS_SSL_END_OF_EARLY_DATA) ||
+        (ssl->in_offt == NULL)) {
+        return MBEDTLS_ERR_SSL_CANNOT_READ_EARLY_DATA;
+    }
 
-    return (int) n;
+    return ssl_read_application_data(ssl, buf, len);
 }
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA */
 
 /*
  * Send application data to be encrypted by the SSL layer, taking care of max
@@ -5725,6 +6077,111 @@ int mbedtls_ssl_write(mbedtls_ssl_context *ssl, const unsigned char *buf, size_t
     return ret;
 }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_CLI_C)
+int mbedtls_ssl_write_early_data(mbedtls_ssl_context *ssl,
+                                 const unsigned char *buf, size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    const struct mbedtls_ssl_config *conf;
+    uint32_t remaining;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write early_data"));
+
+    if (ssl == NULL || (conf = ssl->conf) == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    if (conf->endpoint != MBEDTLS_SSL_IS_CLIENT) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    if ((!mbedtls_ssl_conf_is_tls13_enabled(conf)) ||
+        (conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) ||
+        (conf->early_data_enabled != MBEDTLS_SSL_EARLY_DATA_ENABLED)) {
+        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+    }
+
+    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+    }
+
+    /*
+     * If we are at the beginning of the handshake, the early data state being
+     * equal to MBEDTLS_SSL_EARLY_DATA_STATE_IDLE or
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT advance the handshake just
+     * enough to be able to send early data if possible. That way, we can
+     * guarantee that when starting the handshake with this function we will
+     * send at least one record of early data. Note that when the state is
+     * MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT and not yet
+     * MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE, we cannot send early data
+     * as the early data outbound transform has not been set as we may have to
+     * first send a dummy CCS in clear.
+     */
+    if ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
+        (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
+        while ((ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IDLE) ||
+               (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT)) {
+            ret = mbedtls_ssl_handshake_step(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake_step", ret);
+                return ret;
+            }
+
+            ret = mbedtls_ssl_flush_output(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flush_output", ret);
+                return ret;
+            }
+        }
+        remaining = ssl->session_negotiate->max_early_data_size;
+    } else {
+        /*
+         * If we are past the point where we can send early data or we have
+         * already reached the maximum early data size, return immediatly.
+         * Otherwise, progress the handshake as much as possible to not delay
+         * it too much. If we reach a point where we can still send early data,
+         * then we will send some.
+         */
+        if ((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
+            (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED)) {
+            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+        }
+
+        remaining = ssl->session_negotiate->max_early_data_size -
+                    ssl->total_early_data_size;
+
+        if (remaining == 0) {
+            return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+        }
+
+        ret = mbedtls_ssl_handshake(ssl);
+        if ((ret != 0) && (ret != MBEDTLS_ERR_SSL_WANT_READ)) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+            return ret;
+        }
+    }
+
+    if (((ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE) &&
+         (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED))
+        || (remaining == 0)) {
+        return MBEDTLS_ERR_SSL_CANNOT_WRITE_EARLY_DATA;
+    }
+
+    if (len > remaining) {
+        len = remaining;
+    }
+
+    ret = ssl_write_real(ssl, buf, len);
+    if (ret >= 0) {
+        ssl->total_early_data_size += ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write early_data, ret=%d", ret));
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_CLI_C */
+
 /*
  * Notify the peer that the connection is being closed
  */
@@ -5823,8 +6280,7 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
 
     if (hs_buf->is_valid == 1) {
         hs->buffering.total_bytes_buffered -= hs_buf->data_len;
-        mbedtls_platform_zeroize(hs_buf->data, hs_buf->data_len);
-        mbedtls_free(hs_buf->data);
+        mbedtls_zeroize_and_free(hs_buf->data, hs_buf->data_len);
         memset(hs_buf, 0, sizeof(mbedtls_ssl_hs_buffer));
     }
 }
@@ -5843,15 +6299,19 @@ static void ssl_buffering_free_slot(mbedtls_ssl_context *ssl,
 void mbedtls_ssl_write_version(unsigned char version[2], int transport,
                                mbedtls_ssl_protocol_version tls_version)
 {
+    uint16_t tls_version_formatted;
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        tls_version =
+        tls_version_formatted =
             ~(tls_version - (tls_version == 0x0302 ? 0x0202 : 0x0201));
-    }
+    } else
 #else
     ((void) transport);
 #endif
-    MBEDTLS_PUT_UINT16_BE(tls_version, version, 0);
+    {
+        tls_version_formatted = (uint16_t) tls_version;
+    }
+    MBEDTLS_PUT_UINT16_BE(tls_version_formatted, version, 0);
 }
 
 uint16_t mbedtls_ssl_read_version(const unsigned char version[2],
diff --git a/lib/libmbedtls/mbedtls/library/ssl_ticket.c b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
index 7d07d191fd7fe8a7ea57762523333c919611b20a..bfb656cf62c9ac8ec21bcd75382ed72b3d052ab4 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_ticket.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_ticket.c
@@ -2,19 +2,7 @@
  *  TLS server tickets callbacks implementation
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -31,9 +19,15 @@
 #include <string.h>
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 #endif
 
 /*
@@ -81,6 +75,10 @@ static int ssl_ticket_gen_key(mbedtls_ssl_ticket_context *ctx,
 #if defined(MBEDTLS_HAVE_TIME)
     key->generation_time = mbedtls_time(NULL);
 #endif
+    /* The lifetime of a key is the configured lifetime of the tickets when
+     * the key is created.
+     */
+    key->lifetime = ctx->ticket_lifetime;
 
     if ((ret = ctx->f_rng(ctx->p_rng, key->name, sizeof(key->name))) != 0) {
         return ret;
@@ -122,16 +120,17 @@ static int ssl_ticket_update_keys(mbedtls_ssl_ticket_context *ctx)
 #if !defined(MBEDTLS_HAVE_TIME)
     ((void) ctx);
 #else
-    if (ctx->ticket_lifetime != 0) {
+    mbedtls_ssl_ticket_key * const key = ctx->keys + ctx->active;
+    if (key->lifetime != 0) {
         mbedtls_time_t current_time = mbedtls_time(NULL);
-        mbedtls_time_t key_time = ctx->keys[ctx->active].generation_time;
+        mbedtls_time_t key_time = key->generation_time;
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 #endif
 
         if (current_time >= key_time &&
-            (uint64_t) (current_time - key_time) < ctx->ticket_lifetime) {
+            (uint64_t) (current_time - key_time) < key->lifetime) {
             return 0;
         }
 
@@ -204,6 +203,8 @@ int mbedtls_ssl_ticket_rotate(mbedtls_ssl_ticket_context *ctx,
 #if defined(MBEDTLS_HAVE_TIME)
     key->generation_time = mbedtls_time(NULL);
 #endif
+    key->lifetime = lifetime;
+
     return 0;
 }
 
@@ -337,7 +338,7 @@ int mbedtls_ssl_ticket_write(void *p_ticket,
 
     key = &ctx->keys[ctx->active];
 
-    *ticket_lifetime = ctx->ticket_lifetime;
+    *ticket_lifetime = key->lifetime;
 
     memcpy(key_name, key->name, TICKET_KEY_NAME_BYTES);
 
@@ -347,7 +348,7 @@ int mbedtls_ssl_ticket_write(void *p_ticket,
 
     /* Dump session state */
     if ((ret = mbedtls_ssl_session_save(session,
-                                        state, end - state,
+                                        state, (size_t) (end - state),
                                         &clear_len)) != 0 ||
         (unsigned long) clear_len > 65535) {
         goto cleanup;
@@ -370,7 +371,7 @@ int mbedtls_ssl_ticket_write(void *p_ticket,
                                                /* Additional data: key name, IV and length */
                                                key_name, TICKET_ADD_DATA_LEN,
                                                state, clear_len,
-                                               state, end - state, &ciph_len,
+                                               state, (size_t) (end - state), &ciph_len,
                                                TICKET_AUTH_TAG_BYTES)) != 0) {
         goto cleanup;
     }
@@ -450,7 +451,7 @@ int mbedtls_ssl_ticket_parse(void *p_ticket,
         goto cleanup;
     }
 
-    enc_len = (enc_len_p[0] << 8) | enc_len_p[1];
+    enc_len = MBEDTLS_GET_UINT16_BE(enc_len_p, 0);
 
     if (len != TICKET_MIN_LEN + enc_len) {
         ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
@@ -501,15 +502,20 @@ int mbedtls_ssl_ticket_parse(void *p_ticket,
     }
 
 #if defined(MBEDTLS_HAVE_TIME)
-    {
-        /* Check for expiration */
-        mbedtls_time_t current_time = mbedtls_time(NULL);
+    mbedtls_ms_time_t ticket_creation_time, ticket_age;
+    mbedtls_ms_time_t ticket_lifetime =
+        (mbedtls_ms_time_t) key->lifetime * 1000;
 
-        if (current_time < session->start ||
-            (uint32_t) (current_time - session->start) > ctx->ticket_lifetime) {
-            ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
-            goto cleanup;
-        }
+    ret = mbedtls_ssl_session_get_ticket_creation_time(session,
+                                                       &ticket_creation_time);
+    if (ret != 0) {
+        goto cleanup;
+    }
+
+    ticket_age = mbedtls_ms_time() - ticket_creation_time;
+    if (ticket_age < 0 || ticket_age > ticket_lifetime) {
+        ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
+        goto cleanup;
     }
 #endif
 
@@ -528,6 +534,10 @@ cleanup:
  */
 void mbedtls_ssl_ticket_free(mbedtls_ssl_ticket_context *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_destroy_key(ctx->keys[0].key);
     psa_destroy_key(ctx->keys[1].key);
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls.c b/lib/libmbedtls/mbedtls/library/ssl_tls.c
index a6129da397d0b404c3aaa5b7bc9984ede5e49732..c773365bf61a2b7d79c02bef45de02f15cb636ca 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls.c
@@ -2,19 +2,7 @@
  *  TLS shared functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  http://www.ietf.org/rfc/rfc2246.txt
@@ -32,7 +20,7 @@
 #include "ssl_debug_helpers.h"
 #include "ssl_misc.h"
 
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/version.h"
@@ -42,21 +30,25 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "mbedtls/psa_util.h"
+#include "md_psa.h"
+#include "psa_util_internal.h"
 #include "psa/crypto.h"
 #endif
-#include "mbedtls/legacy_or_psa.h"
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 #include "mbedtls/oid.h"
 #endif
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
-                                                           psa_to_ssl_errors, \
-                                                           psa_generic_status_to_mbedtls)
-#define PSA_TO_MD_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status, \
-                                                      psa_to_md_errors, \
-                                                      psa_generic_status_to_mbedtls)
+/* Define local translating functions to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 #endif
 
 #if defined(MBEDTLS_TEST_HOOKS)
@@ -140,7 +132,7 @@ int mbedtls_ssl_set_cid(mbedtls_ssl_context *ssl,
 
 int mbedtls_ssl_get_own_cid(mbedtls_ssl_context *ssl,
                             int *enabled,
-                            unsigned char own_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX],
+                            unsigned char own_cid[MBEDTLS_SSL_CID_IN_LEN_MAX],
                             size_t *own_cid_len)
 {
     *enabled = MBEDTLS_SSL_CID_DISABLED;
@@ -246,6 +238,11 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
 #endif
 #endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+    dst->ticket_alpn = NULL;
+#endif
+
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@@ -283,6 +280,16 @@ int mbedtls_ssl_session_copy(mbedtls_ssl_session *dst,
 
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+    {
+        int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN && MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
     if (src->ticket != NULL) {
         dst->ticket = mbedtls_calloc(1, src->ticket_len);
@@ -315,7 +322,7 @@ static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old
 {
     unsigned char *resized_buffer = mbedtls_calloc(1, len_new);
     if (resized_buffer == NULL) {
-        return -1;
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
     /* We want to copy len_new bytes when downsizing the buffer, and
@@ -324,8 +331,7 @@ static int resize_buffer(unsigned char **buffer, size_t len_new, size_t *len_old
      * lost, are done outside of this function. */
     memcpy(resized_buffer, *buffer,
            (len_new < *len_old) ? len_new : *len_old);
-    mbedtls_platform_zeroize(*buffer, *len_old);
-    mbedtls_free(*buffer);
+    mbedtls_zeroize_and_free(*buffer, *len_old);
 
     *buffer = resized_buffer;
     *len_old = len_new;
@@ -419,7 +425,7 @@ static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,
                                         unsigned endpoint,
                                         const mbedtls_ssl_context *ssl);
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha256(const unsigned char *secret, size_t slen,
                           const char *label,
@@ -428,9 +434,9 @@ static int tls_prf_sha256(const unsigned char *secret, size_t slen,
 static int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *, unsigned char *, size_t *);
 static int ssl_calc_finished_tls_sha256(mbedtls_ssl_context *, unsigned char *, int);
 
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int tls_prf_sha384(const unsigned char *secret, size_t slen,
                           const char *label,
@@ -439,11 +445,7 @@ static int tls_prf_sha384(const unsigned char *secret, size_t slen,
 
 static int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *, unsigned char *, size_t *);
 static int ssl_calc_finished_tls_sha384(mbedtls_ssl_context *, unsigned char *, int);
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-
-static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
-                                     unsigned char *buf,
-                                     size_t buf_len);
+#endif /* MBEDTLS_MD_CAN_SHA384*/
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls12_session_load(mbedtls_ssl_session *session,
@@ -453,13 +455,13 @@ static int ssl_tls12_session_load(mbedtls_ssl_session *session,
 
 static int ssl_update_checksum_start(mbedtls_ssl_context *, const unsigned char *, size_t);
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 static int ssl_update_checksum_sha256(mbedtls_ssl_context *, const unsigned char *, size_t);
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 static int ssl_update_checksum_sha384(mbedtls_ssl_context *, const unsigned char *, size_t);
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#endif /* MBEDTLS_MD_CAN_SHA384*/
 
 int  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,
                          const unsigned char *secret, size_t slen,
@@ -471,16 +473,16 @@ int  mbedtls_ssl_tls_prf(const mbedtls_tls_prf_types prf,
 
     switch (prf) {
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_SSL_TLS_PRF_SHA384:
             tls_prf = tls_prf_sha384;
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#endif /* MBEDTLS_MD_CAN_SHA384*/
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_SSL_TLS_PRF_SHA256:
             tls_prf = tls_prf_sha256;
             break;
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
         default:
             return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -640,7 +642,7 @@ static const char *extension_name_table[] = {
     [MBEDTLS_SSL_EXT_ID_RECORD_SIZE_LIMIT] = "record_size_limit"
 };
 
-static unsigned int extension_type_table[] = {
+static const unsigned int extension_type_table[] = {
     [MBEDTLS_SSL_EXT_ID_UNRECOGNIZED] = 0xff,
     [MBEDTLS_SSL_EXT_ID_SERVERNAME] = MBEDTLS_TLS_EXT_SERVERNAME,
     [MBEDTLS_SSL_EXT_ID_MAX_FRAGMENT_LENGTH] = MBEDTLS_TLS_EXT_MAX_FRAGMENT_LENGTH,
@@ -748,8 +750,6 @@ void mbedtls_ssl_print_extensions(const mbedtls_ssl_context *ssl,
 }
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(*(a)))
-
 static const char *ticket_flag_name_table[] =
 {
     [0] = "ALLOW_PSK_RESUMPTION",
@@ -784,12 +784,12 @@ void mbedtls_ssl_optimize_checksum(mbedtls_ssl_context *ssl,
 {
     ((void) ciphersuite_info);
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
     if (ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
         ssl->handshake->update_checksum = ssl_update_checksum_sha384;
     } else
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
     if (ciphersuite_info->mac != MBEDTLS_MD_SHA384) {
         ssl->handshake->update_checksum = ssl_update_checksum_sha256;
     } else
@@ -830,8 +830,8 @@ int mbedtls_ssl_add_hs_msg_to_checksum(mbedtls_ssl_context *ssl,
 
 int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
 {
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256) || \
+    defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status;
 #else
@@ -840,15 +840,15 @@ int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
 #else /* SHA-256 or SHA-384 */
     ((void) ssl);
 #endif /* SHA-256 or SHA-384 */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_abort(&ssl->handshake->fin_sha256_psa);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
     status = psa_hash_setup(&ssl->handshake->fin_sha256_psa, PSA_ALG_SHA_256);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
 #else
     mbedtls_md_free(&ssl->handshake->fin_sha256);
@@ -865,15 +865,15 @@ int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
     }
 #endif
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_abort(&ssl->handshake->fin_sha384_psa);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
     status = psa_hash_setup(&ssl->handshake->fin_sha384_psa, PSA_ALG_SHA_384);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
 #else
     mbedtls_md_free(&ssl->handshake->fin_sha384);
@@ -895,8 +895,8 @@ int mbedtls_ssl_reset_checksum(mbedtls_ssl_context *ssl)
 static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
                                      const unsigned char *buf, size_t len)
 {
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) || \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256) || \
+    defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status;
 #else
@@ -907,11 +907,11 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
     (void) buf;
     (void) len;
 #endif /* SHA-256 or SHA-384 */
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_update(&ssl->handshake->fin_sha256_psa, buf, len);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
 #else
     ret = mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
@@ -920,11 +920,11 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
     }
 #endif
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     status = psa_hash_update(&ssl->handshake->fin_sha384_psa, buf, len);
     if (status != PSA_SUCCESS) {
-        return PSA_TO_MD_ERR(status);
+        return mbedtls_md_error_from_psa(status);
     }
 #else
     ret = mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
@@ -936,26 +936,26 @@ static int ssl_update_checksum_start(mbedtls_ssl_context *ssl,
     return 0;
 }
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 static int ssl_update_checksum_sha256(mbedtls_ssl_context *ssl,
                                       const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    return PSA_TO_MD_ERR(psa_hash_update(
-                             &ssl->handshake->fin_sha256_psa, buf, len));
+    return mbedtls_md_error_from_psa(psa_hash_update(
+                                         &ssl->handshake->fin_sha256_psa, buf, len));
 #else
     return mbedtls_md_update(&ssl->handshake->fin_sha256, buf, len);
 #endif
 }
 #endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 static int ssl_update_checksum_sha384(mbedtls_ssl_context *ssl,
                                       const unsigned char *buf, size_t len)
 {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    return PSA_TO_MD_ERR(psa_hash_update(
-                             &ssl->handshake->fin_sha384_psa, buf, len));
+    return mbedtls_md_error_from_psa(psa_hash_update(
+                                         &ssl->handshake->fin_sha384_psa, buf, len));
 #else
     return mbedtls_md_update(&ssl->handshake->fin_sha384, buf, len);
 #endif
@@ -966,14 +966,14 @@ static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake)
 {
     memset(handshake, 0, sizeof(mbedtls_ssl_handshake_params));
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha256_psa = psa_hash_operation_init();
 #else
     mbedtls_md_init(&handshake->fin_sha256);
 #endif
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     handshake->fin_sha384_psa = psa_hash_operation_init();
 #else
@@ -986,7 +986,8 @@ static void ssl_handshake_params_init(mbedtls_ssl_handshake_params *handshake)
 #if defined(MBEDTLS_DHM_C)
     mbedtls_dhm_init(&handshake->dhm_ctx);
 #endif
-#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)
     mbedtls_ecdh_init(&handshake->ecdh_ctx);
 #endif
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1108,6 +1109,16 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#if defined(MBEDTLS_SSL_CLI_C)
+    ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IDLE;
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+    ssl->discard_early_data_record = MBEDTLS_SSL_EARLY_DATA_NO_DISCARD;
+#endif
+    ssl->total_early_data_size = 0;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
     /* Initialize structures */
     mbedtls_ssl_session_init(ssl->session_negotiate);
     ssl_handshake_params_init(ssl->handshake);
@@ -1156,8 +1167,7 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
         size_t length;
         const mbedtls_ecp_group_id *curve_list = ssl->conf->curve_list;
 
-        for (length = 0;  (curve_list[length] != MBEDTLS_ECP_DP_NONE) &&
-             (length < MBEDTLS_ECP_DP_MAX); length++) {
+        for (length = 0;  (curve_list[length] != MBEDTLS_ECP_DP_NONE); length++) {
         }
 
         /* Leave room for zero termination */
@@ -1207,7 +1217,7 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
             if (mbedtls_ssl_hash_from_md_alg(*md) == MBEDTLS_SSL_HASH_NONE) {
                 continue;
             }
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
             sig_algs_len += sizeof(uint16_t);
 #endif
 
@@ -1235,7 +1245,7 @@ static int ssl_handshake_init(mbedtls_ssl_context *ssl)
             if (hash == MBEDTLS_SSL_HASH_NONE) {
                 continue;
             }
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
             *p = ((hash << 8) | MBEDTLS_SSL_SIG_ECDSA);
             p++;
 #endif
@@ -1326,12 +1336,6 @@ static int ssl_conf_version_check(const mbedtls_ssl_context *ssl)
             return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
         }
 
-        if (conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 server is not supported yet."));
-            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-        }
-
-
         MBEDTLS_SSL_DEBUG_MSG(4, ("The SSL configuration is TLS 1.3 or TLS 1.2."));
         return 0;
     }
@@ -1350,28 +1354,10 @@ static int ssl_conf_check(const mbedtls_ssl_context *ssl)
         return ret;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    /* RFC 8446 section 4.4.3
-     *
-     * If the verification fails, the receiver MUST terminate the handshake with
-     * a "decrypt_error" alert.
-     *
-     * If the client is configured as TLS 1.3 only with optional verify, return
-     * bad config.
-     *
-     */
-    if (mbedtls_ssl_conf_tls13_ephemeral_enabled(
-            (mbedtls_ssl_context *) ssl)                            &&
-        ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT                &&
-        ssl->conf->max_tls_version == MBEDTLS_SSL_VERSION_TLS1_3    &&
-        ssl->conf->min_tls_version == MBEDTLS_SSL_VERSION_TLS1_3    &&
-        ssl->conf->authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
-        MBEDTLS_SSL_DEBUG_MSG(
-            1, ("Optional verify auth mode "
-                "is not available for TLS 1.3 client"));
-        return MBEDTLS_ERR_SSL_BAD_CONFIG;
+    if (ssl->conf->f_rng == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
+        return MBEDTLS_ERR_SSL_NO_RNG;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
     /* Space for further checks */
 
@@ -1394,6 +1380,7 @@ int mbedtls_ssl_setup(mbedtls_ssl_context *ssl,
     if ((ret = ssl_conf_check(ssl)) != 0) {
         return ret;
     }
+    ssl->tls_version = ssl->conf->max_tls_version;
 
     /*
      * Prepare base structures
@@ -1556,6 +1543,7 @@ int mbedtls_ssl_session_reset_int(mbedtls_ssl_context *ssl, int partial)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
+    ssl->tls_version = ssl->conf->max_tls_version;
 
     mbedtls_ssl_session_reset_msg_layer(ssl, partial);
 
@@ -1749,6 +1737,7 @@ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     if (session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
         const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
             mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
 
@@ -1759,6 +1748,14 @@ int mbedtls_ssl_set_session(mbedtls_ssl_context *ssl, const mbedtls_ssl_session
                                       session->ciphersuite));
             return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
+#else
+        /*
+         * If session tickets are not enabled, it is not possible to resume a
+         * TLS 1.3 session, thus do not make any change to the SSL context in
+         * the first place.
+         */
+        return 0;
+#endif
     }
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
@@ -1787,14 +1784,14 @@ void mbedtls_ssl_conf_tls13_key_exchange_modes(mbedtls_ssl_config *conf,
 }
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-void mbedtls_ssl_tls13_conf_early_data(mbedtls_ssl_config *conf,
-                                       int early_data_enabled)
+void mbedtls_ssl_conf_early_data(mbedtls_ssl_config *conf,
+                                 int early_data_enabled)
 {
     conf->early_data_enabled = early_data_enabled;
 }
 
 #if defined(MBEDTLS_SSL_SRV_C)
-void mbedtls_ssl_tls13_conf_max_early_data_size(
+void mbedtls_ssl_conf_max_early_data_size(
     mbedtls_ssl_config *conf, uint32_t max_early_data_size)
 {
     conf->max_early_data_size = max_early_data_size;
@@ -2128,9 +2125,7 @@ static void ssl_conf_remove_psk(mbedtls_ssl_config *conf)
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
     if (conf->psk != NULL) {
-        mbedtls_platform_zeroize(conf->psk, conf->psk_len);
-
-        mbedtls_free(conf->psk);
+        mbedtls_zeroize_and_free(conf->psk, conf->psk_len);
         conf->psk = NULL;
         conf->psk_len = 0;
     }
@@ -2222,10 +2217,10 @@ static void ssl_remove_psk(mbedtls_ssl_context *ssl)
     }
 #else
     if (ssl->handshake->psk != NULL) {
-        mbedtls_platform_zeroize(ssl->handshake->psk,
+        mbedtls_zeroize_and_free(ssl->handshake->psk,
                                  ssl->handshake->psk_len);
-        mbedtls_free(ssl->handshake->psk);
         ssl->handshake->psk_len = 0;
+        ssl->handshake->psk = NULL;
     }
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
@@ -2435,13 +2430,14 @@ mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
     psa_algorithm_t alg;
     psa_key_type_t type;
     size_t size;
-    status = mbedtls_ssl_cipher_to_psa(suite->cipher, 0, &alg, &type, &size);
+    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) suite->cipher,
+                                       0, &alg, &type, &size);
     if (status == PSA_SUCCESS) {
         base_mode = mbedtls_ssl_get_base_mode(alg);
     }
 #else
     const mbedtls_cipher_info_t *cipher =
-        mbedtls_cipher_info_from_type(suite->cipher);
+        mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) suite->cipher);
     if (cipher != NULL) {
         base_mode =
             mbedtls_ssl_get_base_mode(
@@ -2457,391 +2453,191 @@ mbedtls_ssl_mode_t mbedtls_ssl_get_mode_from_ciphersuite(
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-/* Serialization of TLS 1.3 sessions:
- *
- *     struct {
- *       opaque hostname<0..2^16-1>;
- *       uint64 ticket_received;
- *       uint32 ticket_lifetime;
- *       opaque ticket<1..2^16-1>;
- *     } ClientOnlyData;
- *
- *     struct {
- *       uint8 endpoint;
- *       uint8 ciphersuite[2];
- *       uint32 ticket_age_add;
- *       uint8 ticket_flags;
- *       opaque resumption_key<0..255>;
- *       select ( endpoint ) {
- *            case client: ClientOnlyData;
- *            case server: uint64 start_time;
- *        };
- *     } serialized_session_tls13;
- *
- */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
-                                  unsigned char *buf,
-                                  size_t buf_len,
-                                  size_t *olen)
-{
-    unsigned char *p = buf;
-#if defined(MBEDTLS_SSL_CLI_C) && \
-    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    size_t hostname_len = (session->hostname == NULL) ?
-                          0 : strlen(session->hostname) + 1;
-#endif
-    size_t needed =   1                             /* endpoint */
-                    + 2                             /* ciphersuite */
-                    + 4                             /* ticket_age_add */
-                    + 1                             /* ticket_flags */
-                    + 1;                            /* resumption_key length */
-    *olen = 0;
-
-    if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    needed += session->resumption_key_len;  /* resumption_key */
-
-#if defined(MBEDTLS_HAVE_TIME)
-    needed += 8; /* start_time or ticket_received */
-#endif
-
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        needed +=  2                        /* hostname_len */
-                  + hostname_len;           /* hostname */
-#endif
-
-        needed +=   4                       /* ticket_lifetime */
-                  + 2;                      /* ticket_len */
-
-        /* Check size_t overflow */
-        if (session->ticket_len > SIZE_MAX - needed) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-
-        needed += session->ticket_len;      /* ticket */
-    }
-#endif /* MBEDTLS_SSL_CLI_C */
-
-    *olen = needed;
-    if (needed > buf_len) {
-        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
-    }
-
-    p[0] = session->endpoint;
-    MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 1);
-    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 3);
-    p[7] = session->ticket_flags;
-
-    /* save resumption_key */
-    p[8] = session->resumption_key_len;
-    p += 9;
-    memcpy(p, session->resumption_key, session->resumption_key_len);
-    p += session->resumption_key_len;
-
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
-    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        MBEDTLS_PUT_UINT64_BE((uint64_t) session->start, p, 0);
-        p += 8;
-    }
-#endif /* MBEDTLS_HAVE_TIME */
-
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
-        p += 2;
-        if (hostname_len > 0) {
-            /* save host name */
-            memcpy(p, session->hostname, hostname_len);
-            p += hostname_len;
-        }
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-
-#if defined(MBEDTLS_HAVE_TIME)
-        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_received, p, 0);
-        p += 8;
-#endif
-        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
-        p += 4;
-
-        MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);
-        p += 2;
-
-        if (session->ticket != NULL && session->ticket_len > 0) {
-            memcpy(p, session->ticket, session->ticket_len);
-            p += session->ticket_len;
-        }
-    }
-#endif /* MBEDTLS_SSL_CLI_C */
-    return 0;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_load(mbedtls_ssl_session *session,
-                                  const unsigned char *buf,
-                                  size_t len)
-{
-    const unsigned char *p = buf;
-    const unsigned char *end = buf + len;
-
-    if (end - p < 9) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    session->endpoint = p[0];
-    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 1);
-    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 3);
-    session->ticket_flags = p[7];
-
-    /* load resumption_key */
-    session->resumption_key_len = p[8];
-    p += 9;
-
-    if (end - p < session->resumption_key_len) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-
-    if (sizeof(session->resumption_key) < session->resumption_key_len) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    memcpy(session->resumption_key, p, session->resumption_key_len);
-    p += session->resumption_key_len;
-
-#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
-    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        if (end - p < 8) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        session->start = MBEDTLS_GET_UINT64_BE(p, 0);
-        p += 8;
-    }
-#endif /* MBEDTLS_HAVE_TIME */
-
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \
-        defined(MBEDTLS_SSL_SESSION_TICKETS)
-        size_t hostname_len;
-        /* load host name */
-        if (end - p < 2) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);
-        p += 2;
-
-        if (end - p < (long int) hostname_len) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        if (hostname_len > 0) {
-            session->hostname = mbedtls_calloc(1, hostname_len);
-            if (session->hostname == NULL) {
-                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-            }
-            memcpy(session->hostname, p, hostname_len);
-            p += hostname_len;
-        }
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION &&
-          MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_HAVE_TIME)
-        if (end - p < 8) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        session->ticket_received = MBEDTLS_GET_UINT64_BE(p, 0);
-        p += 8;
-#endif
-        if (end - p < 4) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
-        p += 4;
-
-        if (end - p <  2) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
-        p += 2;
-
-        if (end - p < (long int) session->ticket_len) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        if (session->ticket_len > 0) {
-            session->ticket = mbedtls_calloc(1, session->ticket_len);
-            if (session->ticket == NULL) {
-                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-            }
-            memcpy(session->ticket, p, session->ticket_len);
-            p += session->ticket_len;
-        }
-    }
-#endif /* MBEDTLS_SSL_CLI_C */
-
-    return 0;
-
-}
-#else /* MBEDTLS_SSL_SESSION_TICKETS */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
-                                  unsigned char *buf,
-                                  size_t buf_len,
-                                  size_t *olen)
-{
-    ((void) session);
-    ((void) buf);
-    ((void) buf_len);
-    *olen = 0;
-    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-}
-
-static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
-                                  unsigned char *buf,
-                                  size_t buf_len)
-{
-    ((void) session);
-    ((void) buf);
-    ((void) buf_len);
-    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-}
-#endif /* !MBEDTLS_SSL_SESSION_TICKETS */
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
 psa_status_t mbedtls_ssl_cipher_to_psa(mbedtls_cipher_type_t mbedtls_cipher_type,
                                        size_t taglen,
                                        psa_algorithm_t *alg,
                                        psa_key_type_t *key_type,
                                        size_t *key_size)
 {
+#if !defined(MBEDTLS_SSL_HAVE_CCM)
+    (void) taglen;
+#endif
     switch (mbedtls_cipher_type) {
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_AES_128_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_AES_128_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_AES_128_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_AES_192_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_AES_192_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_AES_256_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_AES_256_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_AES) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_AES_256_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_AES;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_ARIA_128_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_ARIA_128_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_ARIA_128_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_ARIA_192_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_ARIA_192_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_ARIA_256_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_ARIA_256_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_ARIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_ARIA_256_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_ARIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_CAMELLIA_128_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_CAMELLIA_128_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_CAMELLIA_128_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 128;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_CAMELLIA_192_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_CAMELLIA_192_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 192;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CBC)
         case MBEDTLS_CIPHER_CAMELLIA_256_CBC:
             *alg = PSA_ALG_CBC_NO_PADDING;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_CCM)
         case MBEDTLS_CIPHER_CAMELLIA_256_CCM:
             *alg = taglen ? PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, taglen) : PSA_ALG_CCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CAMELLIA) && defined(MBEDTLS_SSL_HAVE_GCM)
         case MBEDTLS_CIPHER_CAMELLIA_256_GCM:
             *alg = PSA_ALG_GCM;
             *key_type = PSA_KEY_TYPE_CAMELLIA;
             *key_size = 256;
             break;
+#endif
+#if defined(MBEDTLS_SSL_HAVE_CHACHAPOLY)
         case MBEDTLS_CIPHER_CHACHA20_POLY1305:
             *alg = PSA_ALG_CHACHA20_POLY1305;
             *key_type = PSA_KEY_TYPE_CHACHA20;
             *key_size = 256;
             break;
+#endif
         case MBEDTLS_CIPHER_NULL:
             *alg = MBEDTLS_SSL_NULL_CIPHER;
             *key_type = 0;
@@ -2980,8 +2776,7 @@ int mbedtls_ssl_set_hostname(mbedtls_ssl_context *ssl, const char *hostname)
      * so we can free it safely */
 
     if (ssl->hostname != NULL) {
-        mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname));
-        mbedtls_free(ssl->hostname);
+        mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname));
     }
 
     /* Passing NULL as hostname shall clear the old one */
@@ -3121,12 +2916,12 @@ void mbedtls_ssl_get_dtls_srtp_negotiation_result(const mbedtls_ssl_context *ssl
 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
 void mbedtls_ssl_conf_max_version(mbedtls_ssl_config *conf, int major, int minor)
 {
-    conf->max_tls_version = (major << 8) | minor;
+    conf->max_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor);
 }
 
 void mbedtls_ssl_conf_min_version(mbedtls_ssl_config *conf, int major, int minor)
 {
-    conf->min_tls_version = (major << 8) | minor;
+    conf->min_tls_version = (mbedtls_ssl_protocol_version) ((major << 8) | minor);
 }
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 
@@ -3191,11 +2986,24 @@ void mbedtls_ssl_conf_renegotiation_period(mbedtls_ssl_config *conf,
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 #if defined(MBEDTLS_SSL_CLI_C)
+
 void mbedtls_ssl_conf_session_tickets(mbedtls_ssl_config *conf, int use_tickets)
 {
-    conf->session_tickets = use_tickets;
+    conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_MASK;
+    conf->session_tickets |= (use_tickets != 0) <<
+                             MBEDTLS_SSL_SESSION_TICKETS_TLS1_2_BIT;
 }
-#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+void mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
+    mbedtls_ssl_config *conf, int signal_new_session_tickets)
+{
+    conf->session_tickets &= ~MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_MASK;
+    conf->session_tickets |= (signal_new_session_tickets != 0) <<
+                             MBEDTLS_SSL_SESSION_TICKETS_TLS1_3_BIT;
+}
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_SSL_CLI_C */
 
 #if defined(MBEDTLS_SSL_SRV_C)
 
@@ -3323,6 +3131,31 @@ const char *mbedtls_ssl_get_version(const mbedtls_ssl_context *ssl)
     }
 }
 
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+
+size_t mbedtls_ssl_get_output_record_size_limit(const mbedtls_ssl_context *ssl)
+{
+    const size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
+    size_t record_size_limit = max_len;
+
+    if (ssl->session != NULL &&
+        ssl->session->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN &&
+        ssl->session->record_size_limit < max_len) {
+        record_size_limit = ssl->session->record_size_limit;
+    }
+
+    // TODO: this is currently untested
+    /* During a handshake, use the value being negotiated */
+    if (ssl->session_negotiate != NULL &&
+        ssl->session_negotiate->record_size_limit >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN &&
+        ssl->session_negotiate->record_size_limit < max_len) {
+        record_size_limit = ssl->session_negotiate->record_size_limit;
+    }
+
+    return record_size_limit;
+}
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
 size_t mbedtls_ssl_get_input_max_frag_len(const mbedtls_ssl_context *ssl)
 {
@@ -3409,6 +3242,7 @@ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
     size_t max_len = MBEDTLS_SSL_OUT_CONTENT_LEN;
 
 #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) && \
+    !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT) && \
     !defined(MBEDTLS_SSL_PROTO_DTLS)
     (void) ssl;
 #endif
@@ -3421,6 +3255,30 @@ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
     }
 #endif
 
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    const size_t record_size_limit = mbedtls_ssl_get_output_record_size_limit(ssl);
+
+    if (max_len > record_size_limit) {
+        max_len = record_size_limit;
+    }
+#endif
+
+    if (ssl->transform_out != NULL &&
+        ssl->transform_out->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        /*
+         * In TLS 1.3 case, when records are protected, `max_len` as computed
+         * above is the maximum length of the TLSInnerPlaintext structure that
+         * along the plaintext payload contains the inner content type (one byte)
+         * and some zero padding. Given the algorithm used for padding
+         * in mbedtls_ssl_encrypt_buf(), compute the maximum length for
+         * the plaintext payload. Round down to a multiple of
+         * MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY and
+         * subtract 1.
+         */
+        max_len = ((max_len / MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) *
+                   MBEDTLS_SSL_CID_TLS1_3_PADDING_GRANULARITY) - 1;
+    }
+
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
     if (mbedtls_ssl_get_current_mtu(ssl) != 0) {
         const size_t mtu = mbedtls_ssl_get_current_mtu(ssl);
@@ -3443,7 +3301,8 @@ int mbedtls_ssl_get_max_out_record_payload(const mbedtls_ssl_context *ssl)
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
 #if !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) &&        \
-    !defined(MBEDTLS_SSL_PROTO_DTLS)
+    !defined(MBEDTLS_SSL_PROTO_DTLS) &&                 \
+    !defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
     ((void) ssl);
 #endif
 
@@ -3523,3212 +3382,3062 @@ int mbedtls_ssl_get_session(const mbedtls_ssl_context *ssl,
 }
 #endif /* MBEDTLS_SSL_CLI_C */
 
-/*
- * Define ticket header determining Mbed TLS version
- * and structure of the ticket.
- */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 
-/*
- * Define bitflag determining compile-time settings influencing
- * structure of serialized SSL sessions.
+/* Serialization of TLS 1.2 sessions
+ *
+ * For more detail, see the description of ssl_session_save().
  */
+static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
+                                     unsigned char *buf,
+                                     size_t buf_len)
+{
+    unsigned char *p = buf;
+    size_t used = 0;
 
 #if defined(MBEDTLS_HAVE_TIME)
-#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0
-#endif /* MBEDTLS_HAVE_TIME */
-
+    uint64_t start;
+#endif
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0
-#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */
-
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0
-#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
+    /*
+     * Time
+     */
+#if defined(MBEDTLS_HAVE_TIME)
+    used += 8;
 
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0
-#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+    if (used <= buf_len) {
+        start = (uint64_t) session->start;
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1
-#else
-#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+        MBEDTLS_PUT_UINT64_BE(start, p, 0);
+        p += 8;
+    }
+#endif /* MBEDTLS_HAVE_TIME */
 
-#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT          0
-#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           1
-#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
-#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT           3
-#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           4
-#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        5
+    /*
+     * Basic mandatory fields
+     */
+    used += 1 /* id_len */
+            + sizeof(session->id)
+            + sizeof(session->master)
+            + 4; /* verify_result */
 
-#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG                           \
-    ((uint16_t) (                                                      \
-         (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \
-         (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \
-         (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \
-             SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \
-         (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \
-         (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \
-         (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT)))
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_0(session->id_len);
+        memcpy(p, session->id, 32);
+        p += 32;
 
-static unsigned char ssl_serialized_session_header[] = {
-    MBEDTLS_VERSION_MAJOR,
-    MBEDTLS_VERSION_MINOR,
-    MBEDTLS_VERSION_PATCH,
-    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
-    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
-};
+        memcpy(p, session->master, 48);
+        p += 48;
 
-/*
- * Serialize a session in the following format:
- * (in the presentation language of TLS, RFC 8446 section 3)
- *
- *  struct {
- *
- *    opaque mbedtls_version[3];   // library version: major, minor, patch
- *    opaque session_format[2];    // library-version specific 16-bit field
- *                                 // determining the format of the remaining
- *                                 // serialized data.
- *
- *          Note: When updating the format, remember to keep
- *          these version+format bytes.
- *
- *                                 // In this version, `session_format` determines
- *                                 // the setting of those compile-time
- *                                 // configuration options which influence
- *                                 // the structure of mbedtls_ssl_session.
- *
- *    uint8_t minor_ver;           // Protocol minor version. Possible values:
- *                                 // - TLS 1.2 (0x0303)
- *                                 // - TLS 1.3 (0x0304)
- *
- *    select (serialized_session.tls_version) {
- *
- *      case MBEDTLS_SSL_VERSION_TLS1_2:
- *        serialized_session_tls12 data;
- *      case MBEDTLS_SSL_VERSION_TLS1_3:
- *        serialized_session_tls13 data;
- *
- *   };
- *
- * } serialized_session;
- *
- */
+        MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);
+        p += 4;
+    }
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_session_save(const mbedtls_ssl_session *session,
-                            unsigned char omit_header,
-                            unsigned char *buf,
-                            size_t buf_len,
-                            size_t *olen)
-{
-    unsigned char *p = buf;
-    size_t used = 0;
-    size_t remaining_len;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    size_t out_len;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-#endif
-    if (session == NULL) {
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    /*
+     * Peer's end-entity certificate
+     */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    if (session->peer_cert == NULL) {
+        cert_len = 0;
+    } else {
+        cert_len = session->peer_cert->raw.len;
     }
 
-    if (!omit_header) {
-        /*
-         * Add Mbed TLS version identifier
-         */
-        used += sizeof(ssl_serialized_session_header);
+    used += 3 + cert_len;
+
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_2(cert_len);
+        *p++ = MBEDTLS_BYTE_1(cert_len);
+        *p++ = MBEDTLS_BYTE_0(cert_len);
 
+        if (session->peer_cert != NULL) {
+            memcpy(p, session->peer_cert->raw.p, cert_len);
+            p += cert_len;
+        }
+    }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    if (session->peer_cert_digest != NULL) {
+        used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
         if (used <= buf_len) {
-            memcpy(p, ssl_serialized_session_header,
-                   sizeof(ssl_serialized_session_header));
-            p += sizeof(ssl_serialized_session_header);
+            *p++ = (unsigned char) session->peer_cert_digest_type;
+            *p++ = (unsigned char) session->peer_cert_digest_len;
+            memcpy(p, session->peer_cert_digest,
+                   session->peer_cert_digest_len);
+            p += session->peer_cert_digest_len;
+        }
+    } else {
+        used += 2;
+        if (used <= buf_len) {
+            *p++ = (unsigned char) MBEDTLS_MD_NONE;
+            *p++ = 0;
         }
     }
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
     /*
-     * TLS version identifier
+     * Session ticket if any, plus associated data
      */
-    used += 1;
-    if (used <= buf_len) {
-        *p++ = MBEDTLS_BYTE_0(session->tls_version);
-    }
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
 
-    /* Forward to version-specific serialization routine. */
-    remaining_len = (buf_len >= used) ? buf_len - used : 0;
-    switch (session->tls_version) {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        case MBEDTLS_SSL_VERSION_TLS1_2:
-            used += ssl_tls12_session_save(session, p, remaining_len);
-            break;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+        if (used <= buf_len) {
+            *p++ = MBEDTLS_BYTE_2(session->ticket_len);
+            *p++ = MBEDTLS_BYTE_1(session->ticket_len);
+            *p++ = MBEDTLS_BYTE_0(session->ticket_len);
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        case MBEDTLS_SSL_VERSION_TLS1_3:
-            ret = ssl_tls13_session_save(session, p, remaining_len, &out_len);
-            if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
-                return ret;
+            if (session->ticket != NULL) {
+                memcpy(p, session->ticket, session->ticket_len);
+                p += session->ticket_len;
             }
-            used += out_len;
-            break;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-        default:
-            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+            MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+            p += 4;
+        }
     }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        used += 8;
 
-    *olen = used;
-    if (used > buf_len) {
-        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        if (used <= buf_len) {
+            MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
+            p += 8;
+        }
     }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-    return 0;
-}
+    /*
+     * Misc extension-related info
+     */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    used += 1;
 
-/*
- * Public wrapper for ssl_session_save()
- */
-int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
-                             unsigned char *buf,
-                             size_t buf_len,
-                             size_t *olen)
-{
-    return ssl_session_save(session, 0, buf, buf_len, olen);
+    if (used <= buf_len) {
+        *p++ = session->mfl_code;
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    used += 1;
+
+    if (used <= buf_len) {
+        *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);
+    }
+#endif
+
+    return used;
 }
 
-/*
- * Deserialize session, see mbedtls_ssl_session_save() for format.
- *
- * This internal version is wrapped by a public function that cleans up in
- * case of error, and has an extra option omit_header.
- */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_session_load(mbedtls_ssl_session *session,
-                            unsigned char omit_header,
-                            const unsigned char *buf,
-                            size_t len)
+static int ssl_tls12_session_load(mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t len)
 {
+#if defined(MBEDTLS_HAVE_TIME)
+    uint64_t start;
+#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    size_t cert_len;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
-    size_t remaining_len;
-
 
-    if (session == NULL) {
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    /*
+     * Time
+     */
+#if defined(MBEDTLS_HAVE_TIME)
+    if (8 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    if (!omit_header) {
-        /*
-         * Check Mbed TLS version identifier
-         */
-
-        if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    start = MBEDTLS_GET_UINT64_BE(p, 0);
+    p += 8;
 
-        if (memcmp(p, ssl_serialized_session_header,
-                   sizeof(ssl_serialized_session_header)) != 0) {
-            return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
-        }
-        p += sizeof(ssl_serialized_session_header);
-    }
+    session->start = (time_t) start;
+#endif /* MBEDTLS_HAVE_TIME */
 
     /*
-     * TLS version identifier
+     * Basic mandatory fields
      */
-    if (1 > (size_t) (end - p)) {
+    if (1 + 32 + 48 + 4 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    session->tls_version = 0x0300 | *p++;
 
-    /* Dispatch according to TLS version. */
-    remaining_len = (end - p);
-    switch (session->tls_version) {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        case MBEDTLS_SSL_VERSION_TLS1_2:
-            return ssl_tls12_session_load(session, p, remaining_len);
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    session->id_len = *p++;
+    memcpy(session->id, p, 32);
+    p += 32;
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        case MBEDTLS_SSL_VERSION_TLS1_3:
-            return ssl_tls13_session_load(session, p, remaining_len);
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+    memcpy(session->master, p, 48);
+    p += 48;
 
-        default:
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-}
+    session->verify_result = MBEDTLS_GET_UINT32_BE(p, 0);
+    p += 4;
 
-/*
- * Deserialize session: public wrapper for error cleaning
- */
-int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
-                             const unsigned char *buf,
-                             size_t len)
-{
-    int ret = ssl_session_load(session, 0, buf, len);
+    /* Immediately clear invalid pointer values that have been read, in case
+     * we exit early before we replaced them with valid ones. */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    session->peer_cert = NULL;
+#else
+    session->peer_cert_digest = NULL;
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+    session->ticket = NULL;
+#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
 
-    if (ret != 0) {
-        mbedtls_ssl_session_free(session);
+    /*
+     * Peer certificate
+     */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    /* Deserialize CRT from the end of the ticket. */
+    if (3 > (size_t) (end - p)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    return ret;
-}
+    cert_len = MBEDTLS_GET_UINT24_BE(p, 0);
+    p += 3;
 
-/*
- * Perform a single step of the SSL handshake
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    if (cert_len != 0) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    /*
-     * We may have not been able to send to the peer all the handshake data
-     * that were written into the output buffer by the previous handshake step,
-     * if the write to the network callback returned with the
-     * #MBEDTLS_ERR_SSL_WANT_WRITE error code.
-     * We proceed to the next handshake step only when all data from the
-     * previous one have been sent to the peer, thus we make sure that this is
-     * the case here by calling `mbedtls_ssl_flush_output()`. The function may
-     * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case
-     * we have to wait before to go ahead.
-     * In the case of TLS 1.3, handshake step handlers do not send data to the
-     * peer. Data are only sent here and through
-     * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an
-     * alert occurred.
-     */
-    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
-        return ret;
-    }
+        if (cert_len > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {
-        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
-            return ret;
+        session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+
+        if (session->peer_cert == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
         }
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    return ret;
-}
+        mbedtls_x509_crt_init(session->peer_cert);
 
-int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,
+                                              p, cert_len)) != 0) {
+            mbedtls_x509_crt_free(session->peer_cert);
+            mbedtls_free(session->peer_cert);
+            session->peer_cert = NULL;
+            return ret;
+        }
 
-    if (ssl            == NULL                       ||
-        ssl->conf      == NULL                       ||
-        ssl->handshake == NULL                       ||
-        ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {
+        p += cert_len;
+    }
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    /* Deserialize CRT digest from the end of the ticket. */
+    if (2 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    ret = ssl_prepare_handshake_step(ssl);
-    if (ret != 0) {
-        return ret;
-    }
+    session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
+    session->peer_cert_digest_len  = (size_t) *p++;
 
-    ret = mbedtls_ssl_handle_pending_alert(ssl);
-    if (ret != 0) {
-        goto cleanup;
-    }
+    if (session->peer_cert_digest_len != 0) {
+        const mbedtls_md_info_t *md_info =
+            mbedtls_md_info_from_type(session->peer_cert_digest_type);
+        if (md_info == NULL) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-    /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or
-     * MBEDTLS_SSL_IS_SERVER, this is the return code we give */
-    ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        if (session->peer_cert_digest_len > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s",
-                                  mbedtls_ssl_states_str(ssl->state)));
+        session->peer_cert_digest =
+            mbedtls_calloc(1, session->peer_cert_digest_len);
+        if (session->peer_cert_digest == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
 
-        switch (ssl->state) {
-            case MBEDTLS_SSL_HELLO_REQUEST:
-                ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
-                ret = 0;
-                break;
-
-            case MBEDTLS_SSL_CLIENT_HELLO:
-                ret = mbedtls_ssl_write_client_hello(ssl);
-                break;
+        memcpy(session->peer_cert_digest, p,
+               session->peer_cert_digest_len);
+        p += session->peer_cert_digest_len;
+    }
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-            default:
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
-                if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-                    ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
-                } else {
-                    ret = mbedtls_ssl_handshake_client_step(ssl);
-                }
-#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
-                ret = mbedtls_ssl_handshake_client_step(ssl);
-#else
-                ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
-#endif
+    /*
+     * Session ticket and associated data
+     */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        if (3 > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
-    }
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        if (mbedtls_ssl_conf_is_tls13_only(ssl->conf)) {
-            ret = mbedtls_ssl_tls13_handshake_server_step(ssl);
+
+        session->ticket_len = MBEDTLS_GET_UINT24_BE(p, 0);
+        p += 3;
+
+        if (session->ticket_len != 0) {
+            if (session->ticket_len > (size_t) (end - p)) {
+                return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+            }
+
+            session->ticket = mbedtls_calloc(1, session->ticket_len);
+            if (session->ticket == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+
+            memcpy(session->ticket, p, session->ticket_len);
+            p += session->ticket_len;
         }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if (mbedtls_ssl_conf_is_tls12_only(ssl->conf)) {
-            ret = mbedtls_ssl_handshake_server_step(ssl);
+        if (4 > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    }
-#endif
 
-    if (ret != 0) {
-        /* handshake_step return error. And it is same
-         * with alert_reason.
-         */
-        if (ssl->send_alert) {
-            ret = mbedtls_ssl_handle_pending_alert(ssl);
-            goto cleanup;
+        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+        p += 4;
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_HAVE_TIME) && defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (8 > (size_t) (end - p)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
+        session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
     }
+#endif /* MBEDTLS_HAVE_TIME && MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-cleanup:
-    return ret;
-}
-
-/*
- * Perform the SSL handshake
- */
-int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl)
-{
-    int ret = 0;
-
-    /* Sanity checks */
-
-    if (ssl == NULL || ssl->conf == NULL) {
+    /*
+     * Misc extension-related info
+     */
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+    if (1 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("You must use "
-                                  "mbedtls_ssl_set_timer_cb() for DTLS"));
+    session->mfl_code = *p++;
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    if (1 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake"));
-
-    /* Main handshake loop */
-    while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
-        ret = mbedtls_ssl_handshake_step(ssl);
+    session->encrypt_then_mac = *p++;
+#endif
 
-        if (ret != 0) {
-            break;
-        }
+    /* Done, should have consumed entire buffer */
+    if (p != end) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake"));
-
-    return ret;
+    return 0;
 }
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-#if defined(MBEDTLS_SSL_SRV_C)
-/*
- * Write HelloRequest to request renegotiation on server
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+/* Serialization of TLS 1.3 sessions:
+ *
+ * For more detail, see the description of ssl_session_save().
  */
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hello_request(mbedtls_ssl_context *ssl)
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+                                  unsigned char *buf,
+                                  size_t buf_len,
+                                  size_t *olen)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char *p = buf;
+#if defined(MBEDTLS_SSL_CLI_C) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    size_t hostname_len = (session->hostname == NULL) ?
+                          0 : strlen(session->hostname) + 1;
+#endif
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request"));
+#if defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+    const size_t alpn_len = (session->ticket_alpn == NULL) ?
+                            0 : strlen(session->ticket_alpn) + 1;
+#endif
+    size_t needed =   4  /* ticket_age_add */
+                    + 1  /* ticket_flags */
+                    + 1; /* resumption_key length */
 
-    ssl->out_msglen  = 4;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_REQUEST;
+    *olen = 0;
 
-    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
-        return ret;
+    if (session->resumption_key_len > MBEDTLS_SSL_TLS1_3_TICKET_RESUMPTION_KEY_LEN) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+    needed += session->resumption_key_len;  /* resumption_key */
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request"));
-
-    return 0;
-}
-#endif /* MBEDTLS_SSL_SRV_C */
-
-/*
- * Actually renegotiate current connection, triggered by either:
- * - any side: calling mbedtls_ssl_renegotiate(),
- * - client: receiving a HelloRequest during mbedtls_ssl_read(),
- * - server: receiving any handshake message on server during mbedtls_ssl_read() after
- *   the initial handshake is completed.
- * If the handshake doesn't complete due to waiting for I/O, it will continue
- * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.
- */
-int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    needed += 4;                            /* max_early_data_size */
+#endif
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    needed += 2;                            /* record_size_limit */
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate"));
+#if defined(MBEDTLS_HAVE_TIME)
+    needed += 8; /* ticket_creation_time or ticket_reception_time */
+#endif
 
-    if ((ret = ssl_handshake_init(ssl)) != 0) {
-        return ret;
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        needed +=   2                         /* alpn_len */
+                  + alpn_len;                 /* alpn */
+#endif
     }
+#endif /* MBEDTLS_SSL_SRV_C */
 
-    /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and
-     * the ServerHello will have message_seq = 1" */
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
-        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-            ssl->handshake->out_msg_seq = 1;
-        } else {
-            ssl->handshake->in_msg_seq = 1;
-        }
-    }
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        needed +=  2                        /* hostname_len */
+                  + hostname_len;           /* hostname */
 #endif
 
-    ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
-    ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS;
+        needed +=   4                       /* ticket_lifetime */
+                  + 2;                      /* ticket_len */
 
-    if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
-        return ret;
+        /* Check size_t overflow */
+        if (session->ticket_len > SIZE_MAX - needed) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+
+        needed += session->ticket_len;      /* ticket */
     }
+#endif /* MBEDTLS_SSL_CLI_C */
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate"));
+    *olen = needed;
+    if (needed > buf_len) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
 
-    return 0;
-}
+    MBEDTLS_PUT_UINT32_BE(session->ticket_age_add, p, 0);
+    p[4] = session->ticket_flags;
 
-/*
- * Renegotiate current connection on client,
- * or request renegotiation on server
- */
-int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl)
-{
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    /* save resumption_key */
+    p[5] = session->resumption_key_len;
+    p += 6;
+    memcpy(p, session->resumption_key, session->resumption_key_len);
+    p += session->resumption_key_len;
 
-    if (ssl == NULL || ssl->conf == NULL) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    MBEDTLS_PUT_UINT32_BE(session->max_early_data_size, p, 0);
+    p += 4;
+#endif
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    MBEDTLS_PUT_UINT16_BE(session->record_size_limit, p, 0);
+    p += 2;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
 #if defined(MBEDTLS_SSL_SRV_C)
-    /* On server, just send the request */
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_HAVE_TIME)
+        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_creation_time, p, 0);
+        p += 8;
+#endif /* MBEDTLS_HAVE_TIME */
 
-        ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        MBEDTLS_PUT_UINT16_BE(alpn_len, p, 0);
+        p += 2;
 
-        /* Did we already try/start sending HelloRequest? */
-        if (ssl->out_left != 0) {
-            return mbedtls_ssl_flush_output(ssl);
+        if (alpn_len > 0) {
+            /* save chosen alpn */
+            memcpy(p, session->ticket_alpn, alpn_len);
+            p += alpn_len;
         }
-
-        return ssl_write_hello_request(ssl);
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
     }
 #endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_CLI_C)
-    /*
-     * On client, either start the renegotiation process or,
-     * if already in progress, continue the handshake
-     */
-    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
-        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        MBEDTLS_PUT_UINT16_BE(hostname_len, p, 0);
+        p += 2;
+        if (hostname_len > 0) {
+            /* save host name */
+            memcpy(p, session->hostname, hostname_len);
+            p += hostname_len;
         }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
-        if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret);
-            return ret;
-        }
-    } else {
-        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
-            return ret;
+#if defined(MBEDTLS_HAVE_TIME)
+        MBEDTLS_PUT_UINT64_BE((uint64_t) session->ticket_reception_time, p, 0);
+        p += 8;
+#endif
+        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
+        p += 4;
+
+        MBEDTLS_PUT_UINT16_BE(session->ticket_len, p, 0);
+        p += 2;
+
+        if (session->ticket != NULL && session->ticket_len > 0) {
+            memcpy(p, session->ticket, session->ticket_len);
+            p += session->ticket_len;
         }
     }
 #endif /* MBEDTLS_SSL_CLI_C */
-
-    return ret;
+    return 0;
 }
-#endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_load(mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t len)
 {
-    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
+    const unsigned char *p = buf;
+    const unsigned char *end = buf + len;
 
-    if (handshake == NULL) {
-        return;
+    if (end - p < 6) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+    session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 0);
+    session->ticket_flags = p[4];
 
-#if defined(MBEDTLS_ECP_C)
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-    if (ssl->handshake->group_list_heap_allocated) {
-        mbedtls_free((void *) handshake->group_list);
-    }
-    handshake->group_list = NULL;
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-#endif /* MBEDTLS_ECP_C */
+    /* load resumption_key */
+    session->resumption_key_len = p[5];
+    p += 6;
 
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-#if !defined(MBEDTLS_DEPRECATED_REMOVED)
-    if (ssl->handshake->sig_algs_heap_allocated) {
-        mbedtls_free((void *) handshake->sig_algs);
-    }
-    handshake->sig_algs = NULL;
-#endif /* MBEDTLS_DEPRECATED_REMOVED */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    if (ssl->handshake->certificate_request_context) {
-        mbedtls_free((void *) handshake->certificate_request_context);
+    if (end - p < session->resumption_key_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) {
-        ssl->conf->f_async_cancel(ssl);
-        handshake->async_in_progress = 0;
+    if (sizeof(session->resumption_key) < session->resumption_key_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
-
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&handshake->fin_sha256_psa);
-#else
-    mbedtls_md_free(&handshake->fin_sha256);
-#endif
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&handshake->fin_sha384_psa);
-#else
-    mbedtls_md_free(&handshake->fin_sha384);
-#endif
-#endif
-
-#if defined(MBEDTLS_DHM_C)
-    mbedtls_dhm_free(&handshake->dhm_ctx);
-#endif
-#if !defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_ECDH_C)
-    mbedtls_ecdh_free(&handshake->ecdh_ctx);
-#endif
+    memcpy(session->resumption_key, p, session->resumption_key_len);
+    p += session->resumption_key_len;
 
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_pake_abort(&handshake->psa_pake_ctx);
-    /*
-     * Opaque keys are not stored in the handshake's data and it's the user
-     * responsibility to destroy them. Clear ones, instead, are created by
-     * the TLS library and should be destroyed at the same level
-     */
-    if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) {
-        psa_destroy_key(handshake->psa_pake_password);
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (end - p < 4) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;
-#else
-    mbedtls_ecjpake_free(&handshake->ecjpake_ctx);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-#if defined(MBEDTLS_SSL_CLI_C)
-    mbedtls_free(handshake->ecjpake_cache);
-    handshake->ecjpake_cache = NULL;
-    handshake->ecjpake_cache_len = 0;
-#endif
-#endif
-
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    /* explicit void pointer cast for buggy MS compiler */
-    mbedtls_free((void *) handshake->curves_tls_id);
+    session->max_early_data_size = MBEDTLS_GET_UINT32_BE(p, 0);
+    p += 4;
 #endif
-
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
-        /* The maintenance of the external PSK key slot is the
-         * user's responsibility. */
-        if (ssl->handshake->psk_opaque_is_internal) {
-            psa_destroy_key(ssl->handshake->psk_opaque);
-            ssl->handshake->psk_opaque_is_internal = 0;
-        }
-        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
-    }
-#else
-    if (handshake->psk != NULL) {
-        mbedtls_platform_zeroize(handshake->psk, handshake->psk_len);
-        mbedtls_free(handshake->psk);
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    if (end - p < 2) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
+    session->record_size_limit = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    /*
-     * Free only the linked list wrapper, not the keys themselves
-     * since the belong to the SNI callback
-     */
-    ssl_key_cert_free(handshake->sni_key_cert);
-#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if  defined(MBEDTLS_SSL_SRV_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_HAVE_TIME)
+        if (end - p < 8) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_creation_time = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
+#endif /* MBEDTLS_HAVE_TIME */
 
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx);
-    if (handshake->ecrs_peer_cert != NULL) {
-        mbedtls_x509_crt_free(handshake->ecrs_peer_cert);
-        mbedtls_free(handshake->ecrs_peer_cert);
-    }
-#endif
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+        size_t alpn_len;
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
-    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    mbedtls_pk_free(&handshake->peer_pubkey);
-#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_SSL_CLI_C) && \
-    (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
-    mbedtls_free(handshake->cookie);
-#endif /* MBEDTLS_SSL_CLI_C &&
-          ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */
+        alpn_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    mbedtls_ssl_flight_free(handshake->flight);
-    mbedtls_ssl_buffering_free(ssl);
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
+        if (end - p < (long int) alpn_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_ECDH_C) && \
-    (defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
-    if (handshake->ecdh_psa_privkey_is_external == 0) {
-        psa_destroy_key(handshake->ecdh_psa_privkey);
+        if (alpn_len > 0) {
+            int ret = mbedtls_ssl_session_set_ticket_alpn(session, (char *) p);
+            if (ret != 0) {
+                return ret;
+            }
+            p += alpn_len;
+        }
+#endif /* MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
     }
-#endif /* MBEDTLS_ECDH_C && MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_SSL_SRV_C */
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    mbedtls_ssl_transform_free(handshake->transform_handshake);
-    mbedtls_free(handshake->transform_handshake);
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-    mbedtls_ssl_transform_free(handshake->transform_earlydata);
-    mbedtls_free(handshake->transform_earlydata);
-#endif
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (session->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        size_t hostname_len;
+        /* load host name */
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        hostname_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
 
+        if (end - p < (long int) hostname_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (hostname_len > 0) {
+            session->hostname = mbedtls_calloc(1, hostname_len);
+            if (session->hostname == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+            memcpy(session->hostname, p, hostname_len);
+            p += hostname_len;
+        }
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    /* If the buffers are too big - reallocate. Because of the way Mbed TLS
-     * processes datagrams and the fact that a datagram is allowed to have
-     * several records in it, it is possible that the I/O buffers are not
-     * empty at this stage */
-    handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl),
-                           mbedtls_ssl_get_output_buflen(ssl));
+#if defined(MBEDTLS_HAVE_TIME)
+        if (end - p < 8) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_reception_time = MBEDTLS_GET_UINT64_BE(p, 0);
+        p += 8;
 #endif
+        if (end - p < 4) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_lifetime = MBEDTLS_GET_UINT32_BE(p, 0);
+        p += 4;
 
-    /* mbedtls_platform_zeroize MUST be last one in this function */
-    mbedtls_platform_zeroize(handshake,
-                             sizeof(mbedtls_ssl_handshake_params));
-}
-
-void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
-{
-    if (session == NULL) {
-        return;
-    }
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-    ssl_clear_peer_cert(session);
-#endif
+        if (end - p <  2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        session->ticket_len = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
-    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    mbedtls_free(session->hostname);
-#endif
-    mbedtls_free(session->ticket);
-#endif
+        if (end - p < (long int) session->ticket_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+        if (session->ticket_len > 0) {
+            session->ticket = mbedtls_calloc(1, session->ticket_len);
+            if (session->ticket == NULL) {
+                return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+            }
+            memcpy(session->ticket, p, session->ticket_len);
+            p += session->ticket_len;
+        }
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
 
-    mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));
+    return 0;
+
+}
+#else /* MBEDTLS_SSL_SESSION_TICKETS */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_session_save(const mbedtls_ssl_session *session,
+                                  unsigned char *buf,
+                                  size_t buf_len,
+                                  size_t *olen)
+{
+    ((void) session);
+    ((void) buf);
+    ((void) buf_len);
+    *olen = 0;
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 }
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+static int ssl_tls13_session_load(const mbedtls_ssl_session *session,
+                                  const unsigned char *buf,
+                                  size_t buf_len)
+{
+    ((void) session);
+    ((void) buf);
+    ((void) buf_len);
+    return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+}
+#endif /* !MBEDTLS_SSL_SESSION_TICKETS */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u
+/*
+ * Define ticket header determining Mbed TLS version
+ * and structure of the ticket.
+ */
+
+/*
+ * Define bitflag determining compile-time settings influencing
+ * structure of serialized SSL sessions.
+ */
+
+#if defined(MBEDTLS_HAVE_TIME)
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME 1
 #else
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME 0
+#endif /* MBEDTLS_HAVE_TIME */
 
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT 0
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 1
 #else
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u
-#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT 0
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_SSL_ALPN)
-#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u
+#if defined(MBEDTLS_SSL_CLI_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 1
 #else
-#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u
-#endif /* MBEDTLS_SSL_ALPN */
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET 0
+#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_SESSION_TICKETS */
 
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT    0
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT     1
-#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT      2
-#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT                  3
+#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL 0
+#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
-#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG   \
-    ((uint32_t) (                              \
-         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \
-             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \
-         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \
-             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \
-         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \
-             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \
-         (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \
-         0u))
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM 0
+#endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
+
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0
+#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI 0
+#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA 0
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE 0
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+#if defined(MBEDTLS_SSL_ALPN) && defined(MBEDTLS_SSL_SRV_C) && \
+    defined(MBEDTLS_SSL_EARLY_DATA)
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 1
+#else
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN 0
+#endif /* MBEDTLS_SSL_ALPN */
+
+#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT          0
+#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT           1
+#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
+#define SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT           3
+#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT           4
+#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT        5
+#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT 6
+#define SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT           7
+#define SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT    8
+#define SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT   9
+#define SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT          10
 
-static unsigned char ssl_serialized_context_header[] = {
+#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG                           \
+    ((uint16_t) (                                                      \
+         (SSL_SERIALIZED_SESSION_CONFIG_TIME << SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_CRT << SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET << \
+             SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT << \
+             SSL_SERIALIZED_SESSION_CONFIG_KEEP_PEER_CRT_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_SNI << SSL_SERIALIZED_SESSION_CONFIG_SNI_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA << \
+             SSL_SERIALIZED_SESSION_CONFIG_EARLY_DATA_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE << \
+             SSL_SERIALIZED_SESSION_CONFIG_RECORD_SIZE_BIT) | \
+         (SSL_SERIALIZED_SESSION_CONFIG_ALPN << \
+             SSL_SERIALIZED_SESSION_CONFIG_ALPN_BIT)))
+
+static const unsigned char ssl_serialized_session_header[] = {
     MBEDTLS_VERSION_MAJOR,
     MBEDTLS_VERSION_MINOR,
     MBEDTLS_VERSION_PATCH,
     MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
     MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
-    MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
-    MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
-    MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
 };
 
 /*
- * Serialize a full SSL context
- *
- * The format of the serialized data is:
+ * Serialize a session in the following format:
  * (in the presentation language of TLS, RFC 8446 section 3)
  *
- *  // header
- *  opaque mbedtls_version[3];   // major, minor, patch
- *  opaque context_format[5];    // version-specific field determining
- *                               // the format of the remaining
- *                               // serialized data.
- *  Note: When updating the format, remember to keep these
- *        version+format bytes. (We may make their size part of the API.)
+ * TLS 1.2 session:
  *
- *  // session sub-structure
- *  opaque session<1..2^32-1>;  // see mbedtls_ssl_session_save()
- *  // transform sub-structure
- *  uint8 random[64];           // ServerHello.random+ClientHello.random
- *  uint8 in_cid<0..2^8-1>      // Connection ID: expected incoming value
- *  uint8 out_cid<0..2^8-1>     // Connection ID: outgoing value to use
- *  // fields from ssl_context
- *  uint32 badmac_seen;         // DTLS: number of records with failing MAC
- *  uint64 in_window_top;       // DTLS: last validated record seq_num
- *  uint64 in_window;           // DTLS: bitmask for replay protection
- *  uint8 disable_datagram_packing; // DTLS: only one record per datagram
- *  uint64 cur_out_ctr;         // Record layer: outgoing sequence number
- *  uint16 mtu;                 // DTLS: path mtu (max outgoing fragment size)
- *  uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
+ * struct {
+ * #if defined(MBEDTLS_SSL_SESSION_TICKETS)
+ *    opaque ticket<0..2^24-1>;       // length 0 means no ticket
+ *    uint32 ticket_lifetime;
+ * #endif
+ * } ClientOnlyData;
  *
- * Note that many fields of the ssl_context or sub-structures are not
- * serialized, as they fall in one of the following categories:
+ * struct {
+ * #if defined(MBEDTLS_HAVE_TIME)
+ *    uint64 start_time;
+ * #endif
+ *     uint8 session_id_len;           // at most 32
+ *     opaque session_id[32];
+ *     opaque master[48];              // fixed length in the standard
+ *     uint32 verify_result;
+ * #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+ *    opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert
+ * #else
+ *    uint8 peer_cert_digest_type;
+ *    opaque peer_cert_digest<0..2^8-1>
+ * #endif
+ *     select (endpoint) {
+ *         case client: ClientOnlyData;
+ *         case server: uint64 ticket_creation_time;
+ *     };
+ * #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
+ *    uint8 mfl_code;                 // up to 255 according to standard
+ * #endif
+ * #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+ *    uint8 encrypt_then_mac;         // 0 or 1
+ * #endif
+ * } serialized_session_tls12;
+ *
+ *
+ * TLS 1.3 Session:
+ *
+ * struct {
+ * #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+ *    opaque hostname<0..2^16-1>;
+ * #endif
+ * #if defined(MBEDTLS_HAVE_TIME)
+ *    uint64 ticket_reception_time;
+ * #endif
+ *    uint32 ticket_lifetime;
+ *    opaque ticket<1..2^16-1>;
+ * } ClientOnlyData;
+ *
+ * struct {
+ *    uint32 ticket_age_add;
+ *    uint8 ticket_flags;
+ *    opaque resumption_key<0..255>;
+ * #if defined(MBEDTLS_SSL_EARLY_DATA)
+ *    uint32 max_early_data_size;
+ * #endif
+ * #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+ *    uint16 record_size_limit;
+ * #endif
+ *    select ( endpoint ) {
+ *         case client: ClientOnlyData;
+ *         case server:
+ * #if defined(MBEDTLS_HAVE_TIME)
+ *                      uint64 ticket_creation_time;
+ * #endif
+ * #if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+ *                      opaque ticket_alpn<0..256>;
+ * #endif
+ *     };
+ * } serialized_session_tls13;
+ *
+ *
+ * SSL session:
+ *
+ * struct {
+ *
+ *    opaque mbedtls_version[3];   // library version: major, minor, patch
+ *    opaque session_format[2];    // library-version specific 16-bit field
+ *                                 // determining the format of the remaining
+ *                                 // serialized data.
+ *
+ *          Note: When updating the format, remember to keep
+ *          these version+format bytes.
+ *
+ *                                 // In this version, `session_format` determines
+ *                                 // the setting of those compile-time
+ *                                 // configuration options which influence
+ *                                 // the structure of mbedtls_ssl_session.
+ *
+ *    uint8_t minor_ver;           // Protocol minor version. Possible values:
+ *                                 // - TLS 1.2 (0x0303)
+ *                                 // - TLS 1.3 (0x0304)
+ *    uint8_t endpoint;
+ *    uint16_t ciphersuite;
+ *
+ *    select (serialized_session.tls_version) {
+ *
+ *      case MBEDTLS_SSL_VERSION_TLS1_2:
+ *        serialized_session_tls12 data;
+ *      case MBEDTLS_SSL_VERSION_TLS1_3:
+ *        serialized_session_tls13 data;
+ *
+ *   };
+ *
+ * } serialized_session;
  *
- *  1. forced value (eg in_left must be 0)
- *  2. pointer to dynamically-allocated memory (eg session, transform)
- *  3. value can be re-derived from other data (eg session keys from MS)
- *  4. value was temporary (eg content of input buffer)
- *  5. value will be provided by the user again (eg I/O callbacks and context)
  */
-int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl,
-                             unsigned char *buf,
-                             size_t buf_len,
-                             size_t *olen)
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_session_save(const mbedtls_ssl_session *session,
+                            unsigned char omit_header,
+                            unsigned char *buf,
+                            size_t buf_len,
+                            size_t *olen)
 {
     unsigned char *p = buf;
     size_t used = 0;
-    size_t session_len;
-    int ret = 0;
+    size_t remaining_len;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    size_t out_len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#endif
+    if (session == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
 
-    /*
-     * Enforce usage restrictions, see "return BAD_INPUT_DATA" in
-     * this function's documentation.
-     *
-     * These are due to assumptions/limitations in the implementation. Some of
-     * them are likely to stay (no handshake in progress) some might go away
-     * (only DTLS) but are currently used to simplify the implementation.
-     */
-    /* The initial handshake must be over */
-    if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    if (ssl->handshake != NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* Double-check that sub-structures are indeed ready */
-    if (ssl->transform == NULL || ssl->session == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* There must be no pending incoming or outgoing data */
-    if (mbedtls_ssl_check_pending(ssl) != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    if (ssl->out_left != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* Protocol must be DTLS, not TLS */
-    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* Version must be 1.2 */
-    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* We must be using an AEAD ciphersuite */
-    if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-    /* Renegotiation must not be enabled */
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled"));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-#endif
-
-    /*
-     * Version and format identifier
-     */
-    used += sizeof(ssl_serialized_context_header);
-
-    if (used <= buf_len) {
-        memcpy(p, ssl_serialized_context_header,
-               sizeof(ssl_serialized_context_header));
-        p += sizeof(ssl_serialized_context_header);
-    }
-
-    /*
-     * Session (length + data)
-     */
-    ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len);
-    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
-        return ret;
-    }
-
-    used += 4 + session_len;
-    if (used <= buf_len) {
-        MBEDTLS_PUT_UINT32_BE(session_len, p, 0);
-        p += 4;
+    if (!omit_header) {
+        /*
+         * Add Mbed TLS version identifier
+         */
+        used += sizeof(ssl_serialized_session_header);
 
-        ret = ssl_session_save(ssl->session, 1,
-                               p, session_len, &session_len);
-        if (ret != 0) {
-            return ret;
+        if (used <= buf_len) {
+            memcpy(p, ssl_serialized_session_header,
+                   sizeof(ssl_serialized_session_header));
+            p += sizeof(ssl_serialized_session_header);
         }
-
-        p += session_len;
-    }
-
-    /*
-     * Transform
-     */
-    used += sizeof(ssl->transform->randbytes);
-    if (used <= buf_len) {
-        memcpy(p, ssl->transform->randbytes,
-               sizeof(ssl->transform->randbytes));
-        p += sizeof(ssl->transform->randbytes);
-    }
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    used += 2 + ssl->transform->in_cid_len + ssl->transform->out_cid_len;
-    if (used <= buf_len) {
-        *p++ = ssl->transform->in_cid_len;
-        memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len);
-        p += ssl->transform->in_cid_len;
-
-        *p++ = ssl->transform->out_cid_len;
-        memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len);
-        p += ssl->transform->out_cid_len;
     }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
     /*
-     * Saved fields from top-level ssl_context structure
+     * TLS version identifier, endpoint, ciphersuite
      */
-    used += 4;
-    if (used <= buf_len) {
-        MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0);
-        p += 4;
-    }
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    used += 16;
-    if (used <= buf_len) {
-        MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0);
-        p += 8;
-
-        MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0);
-        p += 8;
-    }
-#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    used += 1;
-    if (used <= buf_len) {
-        *p++ = ssl->disable_datagram_packing;
-    }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
-    if (used <= buf_len) {
-        memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
-        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
-    }
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    used += 2;
+    used += 1    /* TLS version */
+            + 1  /* endpoint */
+            + 2; /* ciphersuite */
     if (used <= buf_len) {
-        MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0);
+        *p++ = MBEDTLS_BYTE_0(session->tls_version);
+        *p++ = session->endpoint;
+        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
         p += 2;
     }
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-
-#if defined(MBEDTLS_SSL_ALPN)
-    {
-        const uint8_t alpn_len = ssl->alpn_chosen
-                               ? (uint8_t) strlen(ssl->alpn_chosen)
-                               : 0;
 
-        used += 1 + alpn_len;
-        if (used <= buf_len) {
-            *p++ = alpn_len;
+    /* Forward to version-specific serialization routine. */
+    remaining_len = (buf_len >= used) ? buf_len - used : 0;
+    switch (session->tls_version) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            used += ssl_tls12_session_save(session, p, remaining_len);
+            break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-            if (ssl->alpn_chosen != NULL) {
-                memcpy(p, ssl->alpn_chosen, alpn_len);
-                p += alpn_len;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            ret = ssl_tls13_session_save(session, p, remaining_len, &out_len);
+            if (ret != 0 && ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
+                return ret;
             }
-        }
+            used += out_len;
+            break;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+        default:
+            return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
     }
-#endif /* MBEDTLS_SSL_ALPN */
 
-    /*
-     * Done
-     */
     *olen = used;
-
     if (used > buf_len) {
         return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
     }
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used);
+    return 0;
+}
 
-    return mbedtls_ssl_session_reset_int(ssl, 0);
+/*
+ * Public wrapper for ssl_session_save()
+ */
+int mbedtls_ssl_session_save(const mbedtls_ssl_session *session,
+                             unsigned char *buf,
+                             size_t buf_len,
+                             size_t *olen)
+{
+    return ssl_session_save(session, 0, buf, buf_len, olen);
 }
 
 /*
- * Deserialize context, see mbedtls_ssl_context_save() for format.
+ * Deserialize session, see mbedtls_ssl_session_save() for format.
  *
  * This internal version is wrapped by a public function that cleans up in
- * case of error.
+ * case of error, and has an extra option omit_header.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_context_load(mbedtls_ssl_context *ssl,
+static int ssl_session_load(mbedtls_ssl_session *session,
+                            unsigned char omit_header,
                             const unsigned char *buf,
                             size_t len)
 {
     const unsigned char *p = buf;
     const unsigned char * const end = buf + len;
-    size_t session_len;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    tls_prf_fn prf_func = NULL;
-#endif
+    size_t remaining_len;
 
-    /*
-     * The context should have been freshly setup or reset.
-     * Give the user an error in case of obvious misuse.
-     * (Checking session is useful because it won't be NULL if we're
-     * renegotiating, or if the user mistakenly loaded a session first.)
-     */
-    if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||
-        ssl->session != NULL) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
 
-    /*
-     * We can't check that the config matches the initial one, but we can at
-     * least check it matches the requirements for serializing.
-     */
-    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
-        ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 ||
-        ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2 ||
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-        ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
-#endif
-        0) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    if (session == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len);
+    if (!omit_header) {
+        /*
+         * Check Mbed TLS version identifier
+         */
 
-    /*
-     * Check version identifier
-     */
-    if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+        if ((size_t) (end - p) < sizeof(ssl_serialized_session_header)) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-    if (memcmp(p, ssl_serialized_context_header,
-               sizeof(ssl_serialized_context_header)) != 0) {
-        return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
+        if (memcmp(p, ssl_serialized_session_header,
+                   sizeof(ssl_serialized_session_header)) != 0) {
+            return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
+        }
+        p += sizeof(ssl_serialized_session_header);
     }
-    p += sizeof(ssl_serialized_context_header);
 
     /*
-     * Session
+     * TLS version identifier, endpoint, ciphersuite
      */
-    if ((size_t) (end - p) < 4) {
+    if (4 > (size_t) (end - p)) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+    session->tls_version = (mbedtls_ssl_protocol_version) (0x0300 | *p++);
+    session->endpoint = *p++;
+    session->ciphersuite = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
 
-    session_len = ((size_t) p[0] << 24) |
-                  ((size_t) p[1] << 16) |
-                  ((size_t) p[2] <<  8) |
-                  ((size_t) p[3]);
-    p += 4;
+    /* Dispatch according to TLS version. */
+    remaining_len = (size_t) (end - p);
+    switch (session->tls_version) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        case MBEDTLS_SSL_VERSION_TLS1_2:
+            return ssl_tls12_session_load(session, p, remaining_len);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-    /* This has been allocated by ssl_handshake_init(), called by
-     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
-    ssl->session = ssl->session_negotiate;
-    ssl->session_in = ssl->session;
-    ssl->session_out = ssl->session;
-    ssl->session_negotiate = NULL;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        case MBEDTLS_SSL_VERSION_TLS1_3:
+            return ssl_tls13_session_load(session, p, remaining_len);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-    if ((size_t) (end - p) < session_len) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        default:
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+}
+
+/*
+ * Deserialize session: public wrapper for error cleaning
+ */
+int mbedtls_ssl_session_load(mbedtls_ssl_session *session,
+                             const unsigned char *buf,
+                             size_t len)
+{
+    int ret = ssl_session_load(session, 0, buf, len);
 
-    ret = ssl_session_load(ssl->session, 1, p, session_len);
     if (ret != 0) {
-        mbedtls_ssl_session_free(ssl->session);
-        return ret;
+        mbedtls_ssl_session_free(session);
     }
 
-    p += session_len;
+    return ret;
+}
+
+/*
+ * Perform a single step of the SSL handshake
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_prepare_handshake_step(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
     /*
-     * Transform
+     * We may have not been able to send to the peer all the handshake data
+     * that were written into the output buffer by the previous handshake step,
+     * if the write to the network callback returned with the
+     * #MBEDTLS_ERR_SSL_WANT_WRITE error code.
+     * We proceed to the next handshake step only when all data from the
+     * previous one have been sent to the peer, thus we make sure that this is
+     * the case here by calling `mbedtls_ssl_flush_output()`. The function may
+     * return with the #MBEDTLS_ERR_SSL_WANT_WRITE error code in which case
+     * we have to wait before to go ahead.
+     * In the case of TLS 1.3, handshake step handlers do not send data to the
+     * peer. Data are only sent here and through
+     * `mbedtls_ssl_handle_pending_alert` in case an error that triggered an
+     * alert occurred.
      */
+    if ((ret = mbedtls_ssl_flush_output(ssl)) != 0) {
+        return ret;
+    }
 
-    /* This has been allocated by ssl_handshake_init(), called by
-     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    ssl->transform = ssl->transform_negotiate;
-    ssl->transform_in = ssl->transform;
-    ssl->transform_out = ssl->transform;
-    ssl->transform_negotiate = NULL;
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite);
-    if (prf_func == NULL) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake->retransmit_state == MBEDTLS_SSL_RETRANS_SENDING) {
+        if ((ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+            return ret;
+        }
     }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    /* Read random bytes and populate structure */
-    if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) {
+    return ret;
+}
+
+int mbedtls_ssl_handshake_step(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if (ssl            == NULL                       ||
+        ssl->conf      == NULL                       ||
+        ssl->handshake == NULL                       ||
+        ssl->state == MBEDTLS_SSL_HANDSHAKE_OVER) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    ret = ssl_tls12_populate_transform(ssl->transform,
-                                       ssl->session->ciphersuite,
-                                       ssl->session->master,
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-                                       ssl->session->encrypt_then_mac,
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
-                                       prf_func,
-                                       p, /* currently pointing to randbytes */
-                                       MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */
-                                       ssl->conf->endpoint,
-                                       ssl);
+    ret = ssl_prepare_handshake_step(ssl);
     if (ret != 0) {
         return ret;
     }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-    p += sizeof(ssl->transform->randbytes);
 
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    /* Read connection IDs and store them */
-    if ((size_t) (end - p) < 1) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    ret = mbedtls_ssl_handle_pending_alert(ssl);
+    if (ret != 0) {
+        goto cleanup;
     }
 
-    ssl->transform->in_cid_len = *p++;
+    /* If ssl->conf->endpoint is not one of MBEDTLS_SSL_IS_CLIENT or
+     * MBEDTLS_SSL_IS_SERVER, this is the return code we give */
+    ret = MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
 
-    if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("client state: %s",
+                                  mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state)));
 
-    memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len);
-    p += ssl->transform->in_cid_len;
+        switch (ssl->state) {
+            case MBEDTLS_SSL_HELLO_REQUEST:
+                ssl->state = MBEDTLS_SSL_CLIENT_HELLO;
+                ret = 0;
+                break;
 
-    ssl->transform->out_cid_len = *p++;
+            case MBEDTLS_SSL_CLIENT_HELLO:
+                ret = mbedtls_ssl_write_client_hello(ssl);
+                break;
 
-    if ((size_t) (end - p) < ssl->transform->out_cid_len) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+            default:
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+                if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+                    ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
+                } else {
+                    ret = mbedtls_ssl_handshake_client_step(ssl);
+                }
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
+                ret = mbedtls_ssl_handshake_client_step(ssl);
+#else
+                ret = mbedtls_ssl_tls13_handshake_client_step(ssl);
+#endif
+        }
     }
+#endif /* MBEDTLS_SSL_CLI_C */
 
-    memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len);
-    p += ssl->transform->out_cid_len;
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-    /*
-     * Saved fields from top-level ssl_context structure
-     */
-    if ((size_t) (end - p) < 4) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+            ret = mbedtls_ssl_tls13_handshake_server_step(ssl);
+        } else {
+            ret = mbedtls_ssl_handshake_server_step(ssl);
+        }
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        ret = mbedtls_ssl_handshake_server_step(ssl);
+#else
+        ret = mbedtls_ssl_tls13_handshake_server_step(ssl);
+#endif
     }
+#endif /* MBEDTLS_SSL_SRV_C */
 
-    ssl->badmac_seen = ((uint32_t) p[0] << 24) |
-                       ((uint32_t) p[1] << 16) |
-                       ((uint32_t) p[2] <<  8) |
-                       ((uint32_t) p[3]);
-    p += 4;
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    if ((size_t) (end - p) < 16) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    if (ret != 0) {
+        /* handshake_step return error. And it is same
+         * with alert_reason.
+         */
+        if (ssl->send_alert) {
+            ret = mbedtls_ssl_handle_pending_alert(ssl);
+            goto cleanup;
+        }
     }
 
-    ssl->in_window_top = ((uint64_t) p[0] << 56) |
-                         ((uint64_t) p[1] << 48) |
-                         ((uint64_t) p[2] << 40) |
-                         ((uint64_t) p[3] << 32) |
-                         ((uint64_t) p[4] << 24) |
-                         ((uint64_t) p[5] << 16) |
-                         ((uint64_t) p[6] <<  8) |
-                         ((uint64_t) p[7]);
-    p += 8;
-
-    ssl->in_window = ((uint64_t) p[0] << 56) |
-                     ((uint64_t) p[1] << 48) |
-                     ((uint64_t) p[2] << 40) |
-                     ((uint64_t) p[3] << 32) |
-                     ((uint64_t) p[4] << 24) |
-                     ((uint64_t) p[5] << 16) |
-                     ((uint64_t) p[6] <<  8) |
-                     ((uint64_t) p[7]);
-    p += 8;
-#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
+cleanup:
+    return ret;
+}
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if ((size_t) (end - p) < 1) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+/*
+ * Perform the SSL handshake
+ */
+int mbedtls_ssl_handshake(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
 
-    ssl->disable_datagram_packing = *p++;
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    /* Sanity checks */
 
-    if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) {
+    if (ssl == NULL || ssl->conf == NULL) {
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr));
-    p += sizeof(ssl->cur_out_ctr);
 
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if ((size_t) (end - p) < 2) {
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ssl->f_set_timer == NULL || ssl->f_get_timer == NULL)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("You must use "
+                                  "mbedtls_ssl_set_timer_cb() for DTLS"));
         return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-
-    ssl->mtu = (p[0] << 8) | p[1];
-    p += 2;
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_ALPN)
-    {
-        uint8_t alpn_len;
-        const char **cur;
-
-        if ((size_t) (end - p) < 1) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> handshake"));
 
-        alpn_len = *p++;
+    /* Main handshake loop */
+    while (ssl->state != MBEDTLS_SSL_HANDSHAKE_OVER) {
+        ret = mbedtls_ssl_handshake_step(ssl);
 
-        if (alpn_len != 0 && ssl->conf->alpn_list != NULL) {
-            /* alpn_chosen should point to an item in the configured list */
-            for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
-                if (strlen(*cur) == alpn_len &&
-                    memcmp(p, cur, alpn_len) == 0) {
-                    ssl->alpn_chosen = *cur;
-                    break;
-                }
-            }
+        if (ret != 0) {
+            break;
         }
+    }
 
-        /* can only happen on conf mismatch */
-        if (alpn_len != 0 && ssl->alpn_chosen == NULL) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= handshake"));
 
-        p += alpn_len;
-    }
-#endif /* MBEDTLS_SSL_ALPN */
+    return ret;
+}
 
-    /*
-     * Forced fields from top-level ssl_context structure
-     *
-     * Most of them already set to the correct value by mbedtls_ssl_init() and
-     * mbedtls_ssl_reset(), so we only need to set the remaining ones.
-     */
-    ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
-    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+#if defined(MBEDTLS_SSL_SRV_C)
+/*
+ * Write HelloRequest to request renegotiation on server
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_hello_request(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    /* Adjust pointers for header fields of outgoing records to
-     * the given transform, accounting for explicit IV and CID. */
-    mbedtls_ssl_update_out_pointers(ssl, ssl->transform);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write hello request"));
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    ssl->in_epoch = 1;
-#endif
+    ssl->out_msglen  = 4;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_REQUEST;
 
-    /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated,
-     * which we don't want - otherwise we'd end up freeing the wrong transform
-     * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform()
-     * inappropriately. */
-    if (ssl->handshake != NULL) {
-        mbedtls_ssl_handshake_free(ssl);
-        mbedtls_free(ssl->handshake);
-        ssl->handshake = NULL;
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
     }
 
-    /*
-     * Done - should have consumed entire buffer
-     */
-    if (p != end) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write hello request"));
 
     return 0;
 }
+#endif /* MBEDTLS_SSL_SRV_C */
 
 /*
- * Deserialize context: public wrapper for error cleaning
+ * Actually renegotiate current connection, triggered by either:
+ * - any side: calling mbedtls_ssl_renegotiate(),
+ * - client: receiving a HelloRequest during mbedtls_ssl_read(),
+ * - server: receiving any handshake message on server during mbedtls_ssl_read() after
+ *   the initial handshake is completed.
+ * If the handshake doesn't complete due to waiting for I/O, it will continue
+ * during the next calls to mbedtls_ssl_renegotiate() or mbedtls_ssl_read() respectively.
  */
-int mbedtls_ssl_context_load(mbedtls_ssl_context *context,
-                             const unsigned char *buf,
-                             size_t len)
+int mbedtls_ssl_start_renegotiation(mbedtls_ssl_context *ssl)
 {
-    int ret = ssl_context_load(context, buf, len);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    if (ret != 0) {
-        mbedtls_ssl_free(context);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> renegotiate"));
+
+    if ((ret = ssl_handshake_init(ssl)) != 0) {
+        return ret;
     }
 
-    return ret;
+    /* RFC 6347 4.2.2: "[...] the HelloRequest will have message_seq = 0 and
+     * the ServerHello will have message_seq = 1" */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_PENDING) {
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            ssl->handshake->out_msg_seq = 1;
+        } else {
+            ssl->handshake->in_msg_seq = 1;
+        }
+    }
+#endif
+
+    ssl->state = MBEDTLS_SSL_HELLO_REQUEST;
+    ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS;
+
+    if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+        return ret;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= renegotiate"));
+
+    return 0;
 }
-#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
 /*
- * Free an SSL context
+ * Renegotiate current connection on client,
+ * or request renegotiation on server
  */
-void mbedtls_ssl_free(mbedtls_ssl_context *ssl)
+int mbedtls_ssl_renegotiate(mbedtls_ssl_context *ssl)
 {
-    if (ssl == NULL) {
-        return;
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+
+    if (ssl == NULL || ssl->conf == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> free"));
+#if defined(MBEDTLS_SSL_SRV_C)
+    /* On server, just send the request */
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-    if (ssl->out_buf != NULL) {
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-        size_t out_buf_len = ssl->out_buf_len;
-#else
-        size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
-#endif
+        ssl->renego_status = MBEDTLS_SSL_RENEGOTIATION_PENDING;
 
-        mbedtls_platform_zeroize(ssl->out_buf, out_buf_len);
-        mbedtls_free(ssl->out_buf);
-        ssl->out_buf = NULL;
+        /* Did we already try/start sending HelloRequest? */
+        if (ssl->out_left != 0) {
+            return mbedtls_ssl_flush_output(ssl);
+        }
+
+        return ssl_write_hello_request(ssl);
     }
+#endif /* MBEDTLS_SSL_SRV_C */
 
-    if (ssl->in_buf != NULL) {
-#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-        size_t in_buf_len = ssl->in_buf_len;
-#else
-        size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
-#endif
+#if defined(MBEDTLS_SSL_CLI_C)
+    /*
+     * On client, either start the renegotiation process or,
+     * if already in progress, continue the handshake
+     */
+    if (ssl->renego_status != MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+        if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-        mbedtls_platform_zeroize(ssl->in_buf, in_buf_len);
-        mbedtls_free(ssl->in_buf);
-        ssl->in_buf = NULL;
+        if ((ret = mbedtls_ssl_start_renegotiation(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_start_renegotiation", ret);
+            return ret;
+        }
+    } else {
+        if ((ret = mbedtls_ssl_handshake(ssl)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_handshake", ret);
+            return ret;
+        }
     }
+#endif /* MBEDTLS_SSL_CLI_C */
 
-    if (ssl->transform) {
-        mbedtls_ssl_transform_free(ssl->transform);
-        mbedtls_free(ssl->transform);
-    }
+    return ret;
+}
+#endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-    if (ssl->handshake) {
-        mbedtls_ssl_handshake_free(ssl);
-        mbedtls_free(ssl->handshake);
+void mbedtls_ssl_handshake_free(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        mbedtls_ssl_transform_free(ssl->transform_negotiate);
-        mbedtls_free(ssl->transform_negotiate);
-#endif
+    if (handshake == NULL) {
+        return;
+    }
 
-        mbedtls_ssl_session_free(ssl->session_negotiate);
-        mbedtls_free(ssl->session_negotiate);
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if (ssl->handshake->group_list_heap_allocated) {
+        mbedtls_free((void *) handshake->group_list);
     }
+    handshake->group_list = NULL;
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if !defined(MBEDTLS_DEPRECATED_REMOVED)
+    if (ssl->handshake->sig_algs_heap_allocated) {
+        mbedtls_free((void *) handshake->sig_algs);
+    }
+    handshake->sig_algs = NULL;
+#endif /* MBEDTLS_DEPRECATED_REMOVED */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    mbedtls_ssl_transform_free(ssl->transform_application);
-    mbedtls_free(ssl->transform_application);
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
-    if (ssl->session) {
-        mbedtls_ssl_session_free(ssl->session);
-        mbedtls_free(ssl->session);
+    if (ssl->handshake->certificate_request_context) {
+        mbedtls_free((void *) handshake->certificate_request_context);
     }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-    if (ssl->hostname != NULL) {
-        mbedtls_platform_zeroize(ssl->hostname, strlen(ssl->hostname));
-        mbedtls_free(ssl->hostname);
+#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
+    if (ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0) {
+        ssl->conf->f_async_cancel(ssl);
+        handshake->async_in_progress = 0;
     }
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
-    mbedtls_free(ssl->cli_id);
-#endif
-
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= free"));
-
-    /* Actually clear after last debug message */
-    mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context));
-}
-
-/*
- * Initialize mbedtls_ssl_config
- */
-void mbedtls_ssl_config_init(mbedtls_ssl_config *conf)
-{
-    memset(conf, 0, sizeof(mbedtls_ssl_config));
-}
+#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 
-/* The selection should be the same as mbedtls_x509_crt_profile_default in
- * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters:
- * curves with a lower resource usage come first.
- * See the documentation of mbedtls_ssl_conf_curves() for what we promise
- * about this list.
- */
-static uint16_t ssl_preset_default_groups[] = {
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_X25519,
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&handshake->fin_sha256_psa);
+#else
+    mbedtls_md_free(&handshake->fin_sha256);
 #endif
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_X448,
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1,
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_hash_abort(&handshake->fin_sha384_psa);
+#else
+    mbedtls_md_free(&handshake->fin_sha384);
 #endif
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1,
 #endif
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1,
+
+#if defined(MBEDTLS_DHM_C)
+    mbedtls_dhm_free(&handshake->dhm_ctx);
 #endif
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1,
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)
+    mbedtls_ecdh_free(&handshake->ecdh_ctx);
 #endif
-    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
-};
-
-static int ssl_preset_suiteb_ciphersuites[] = {
-    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-    0
-};
 
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-
-/* NOTICE:
- *   For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following
- *   rules SHOULD be upheld.
- *   - No duplicate entries.
- *   - But if there is a good reason, do not change the order of the algorithms.
- *   - ssl_tls12_preset* is for TLS 1.2 use only.
- *   - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.
- */
-static uint16_t ssl_preset_default_sig_algs[] = {
-
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) &&  \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
-#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA &&
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
-
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
-#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
-          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_pake_abort(&handshake->psa_pake_ctx);
+    /*
+     * Opaque keys are not stored in the handshake's data and it's the user
+     * responsibility to destroy them. Clear ones, instead, are created by
+     * the TLS library and should be destroyed at the same level
+     */
+    if (!mbedtls_svc_key_id_is_null(handshake->psa_pake_password)) {
+        psa_destroy_key(handshake->psa_pake_password);
+    }
+    handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT;
+#else
+    mbedtls_ecjpake_free(&handshake->ecjpake_ctx);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#if defined(MBEDTLS_SSL_CLI_C)
+    mbedtls_free(handshake->ecjpake_cache);
+    handshake->ecjpake_cache = NULL;
+    handshake->ecjpake_cache_len = 0;
+#endif
+#endif
 
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME) && \
-    defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
-#endif /* MBEDTLS_PK_CAN_ECDSA_SOME && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
-          MBEDTLS_ECP_DP_SECP521R1_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_ANY_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_WITH_ECDSA_ANY_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+    /* explicit void pointer cast for buggy MS compiler */
+    mbedtls_free((void *) handshake->curves_tls_id);
+#endif
 
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
-    defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
-#endif \
-    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(ssl->handshake->psk_opaque)) {
+        /* The maintenance of the external PSK key slot is the
+         * user's responsibility. */
+        if (ssl->handshake->psk_opaque_is_internal) {
+            psa_destroy_key(ssl->handshake->psk_opaque);
+            ssl->handshake->psk_opaque_is_internal = 0;
+        }
+        ssl->handshake->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
+    }
+#else
+    if (handshake->psk != NULL) {
+        mbedtls_zeroize_and_free(handshake->psk, handshake->psk_len);
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
 
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
-    defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
-#endif \
-    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    /*
+     * Free only the linked list wrapper, not the keys themselves
+     * since the belong to the SNI callback
+     */
+    ssl_key_cert_free(handshake->sni_key_cert);
+#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
-#endif \
-    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    mbedtls_x509_crt_restart_free(&handshake->ecrs_ctx);
+    if (handshake->ecrs_peer_cert != NULL) {
+        mbedtls_x509_crt_free(handshake->ecrs_peer_cert);
+        mbedtls_free(handshake->ecrs_peer_cert);
+    }
+#endif
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
-#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_X509_CRT_PARSE_C) &&        \
+    !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    mbedtls_pk_free(&handshake->peer_pubkey);
+#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
-#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA384_C */
+#if defined(MBEDTLS_SSL_CLI_C) && \
+    (defined(MBEDTLS_SSL_PROTO_DTLS) || defined(MBEDTLS_SSL_PROTO_TLS1_3))
+    mbedtls_free(handshake->cookie);
+#endif /* MBEDTLS_SSL_CLI_C &&
+          ( MBEDTLS_SSL_PROTO_DTLS || MBEDTLS_SSL_PROTO_TLS1_3 ) */
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
-#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    mbedtls_ssl_flight_free(handshake->flight);
+    mbedtls_ssl_buffering_free(ssl);
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    MBEDTLS_TLS_SIG_NONE
-};
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED)
+    if (handshake->xxdh_psa_privkey_is_external == 0) {
+        psa_destroy_key(handshake->xxdh_psa_privkey);
+    }
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_XXDH_PSA_ANY_ENABLED */
 
-/* NOTICE: see above */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-static uint16_t ssl_tls12_preset_default_sig_algs[] = {
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512),
-#endif
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
-#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-#if defined(MBEDTLS_RSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512),
-#endif
-#endif /* MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
-#endif
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
-#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-#if defined(MBEDTLS_RSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),
-#endif
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
-#endif
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
-#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
-#if defined(MBEDTLS_RSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_transform_free(handshake->transform_handshake);
+    mbedtls_free(handshake->transform_handshake);
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_transform_free(handshake->transform_earlydata);
+    mbedtls_free(handshake->transform_earlydata);
 #endif
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-    MBEDTLS_TLS_SIG_NONE
-};
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-/* NOTICE: see above */
-static uint16_t ssl_preset_suiteb_sig_algs[] = {
-
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
-#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
-          MBEDTLS_ECP_DP_SECP256R1_ENABLED */
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
-#endif /* MBEDTLS_ECDSA_C && MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA&&
-          MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 
-#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \
-    defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
-#endif \
-    /* MBEDTLS_X509_RSASSA_PSS_SUPPORT && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+    /* If the buffers are too big - reallocate. Because of the way Mbed TLS
+     * processes datagrams and the fact that a datagram is allowed to have
+     * several records in it, it is possible that the I/O buffers are not
+     * empty at this stage */
+    handle_buffer_resizing(ssl, 1, mbedtls_ssl_get_input_buflen(ssl),
+                           mbedtls_ssl_get_output_buflen(ssl));
+#endif
 
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
-#endif /* MBEDTLS_RSA_C && MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    /* mbedtls_platform_zeroize MUST be last one in this function */
+    mbedtls_platform_zeroize(handshake,
+                             sizeof(mbedtls_ssl_handshake_params));
+}
 
-    MBEDTLS_TLS_SIG_NONE
-};
+void mbedtls_ssl_session_free(mbedtls_ssl_session *session)
+{
+    if (session == NULL) {
+        return;
+    }
 
-/* NOTICE: see above */
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_ECDSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
-#endif
-#if defined(MBEDTLS_RSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),
-#endif
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-#if defined(MBEDTLS_ECDSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
-#endif
-#if defined(MBEDTLS_RSA_C)
-    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    ssl_clear_peer_cert(session);
 #endif
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-    MBEDTLS_TLS_SIG_NONE
-};
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-
-static uint16_t ssl_preset_suiteb_groups[] = {
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
+#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \
+    defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    mbedtls_free(session->hostname);
 #endif
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+    mbedtls_free(session->ticket);
 #endif
-    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
-};
 
-#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
- * to make sure there are no duplicated signature algorithm entries. */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_no_sig_alg_duplication(uint16_t *sig_algs)
-{
-    size_t i, j;
-    int ret = 0;
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN) && \
+    defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_free(session->ticket_alpn);
+#endif
 
-    for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
-        for (j = 0; j < i; j++) {
-            if (sig_algs[i] != sig_algs[j]) {
-                continue;
-            }
-            mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET
-                           ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n",
-                           sig_algs[i], j, i);
-            ret = -1;
-        }
-    }
-    return ret;
+    mbedtls_platform_zeroize(session, sizeof(mbedtls_ssl_session));
 }
 
-#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-
-/*
- * Load default in mbedtls_ssl_config
- */
-int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,
-                                int endpoint, int transport, int preset)
-{
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-#endif
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
 
-#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-    if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) {
-        mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n");
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    }
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID 0u
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-    if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) {
-        mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n");
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    }
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT 1u
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) {
-        mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n");
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    }
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY 0u
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
-    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) {
-        mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n");
-        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+#if defined(MBEDTLS_SSL_ALPN)
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 1u
+#else
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN 0u
+#endif /* MBEDTLS_SSL_ALPN */
 
-    /* Use the functions here so that they are covered in tests,
-     * but otherwise access member directly for efficiency */
-    mbedtls_ssl_conf_endpoint(conf, endpoint);
-    mbedtls_ssl_conf_transport(conf, transport);
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT    0
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT     1
+#define SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT      2
+#define SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT                  3
 
-    /*
-     * Things that are common to all presets
-     */
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-        conf->session_tickets = MBEDTLS_SSL_SESSION_TICKETS_ENABLED;
-#endif
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
-#endif
-
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
-    conf->f_cookie_write = ssl_cookie_write_dummy;
-    conf->f_cookie_check = ssl_cookie_check_dummy;
-#endif
-
-#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED;
-#endif
-
-#if defined(MBEDTLS_SSL_SRV_C)
-    conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;
-    conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER;
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;
-    conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
-#endif
-
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;
-    memset(conf->renego_period,     0x00, 2);
-    memset(conf->renego_period + 2, 0xFF, 6);
-#endif
-
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
-    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
-        const unsigned char dhm_p[] =
-            MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;
-        const unsigned char dhm_g[] =
-            MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;
-
-        if ((ret = mbedtls_ssl_conf_dh_param_bin(conf,
-                                                 dhm_p, sizeof(dhm_p),
-                                                 dhm_g, sizeof(dhm_g))) != 0) {
-            return ret;
-        }
-    }
-#endif
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-    mbedtls_ssl_tls13_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED);
-#if defined(MBEDTLS_SSL_SRV_C)
-    mbedtls_ssl_tls13_conf_max_early_data_size(
-        conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE);
-#endif
-#endif /* MBEDTLS_SSL_EARLY_DATA */
-
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
-    mbedtls_ssl_conf_new_session_tickets(
-        conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS);
-#endif
-    /*
-     * Allow all TLS 1.3 key exchange modes by default.
-     */
-    conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
-    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-#else
-        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-#endif
-    } else {
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
-            conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-            conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-        } else {
-            /* Hybrid TLS 1.2 / 1.3 is not supported on server side yet */
-            conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-            conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-        }
-#elif defined(MBEDTLS_SSL_PROTO_TLS1_3)
-        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-#else
-        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-#endif
-    }
-
-    /*
-     * Preset-specific defaults
-     */
-    switch (preset) {
-        /*
-         * NSA Suite B
-         */
-        case MBEDTLS_SSL_PRESET_SUITEB:
-
-            conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites;
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-            conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;
-#endif
-
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
-                conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;
-            } else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-            conf->sig_algs = ssl_preset_suiteb_sig_algs;
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
-            conf->curve_list = NULL;
-#endif
-            conf->group_list = ssl_preset_suiteb_groups;
-            break;
-
-        /*
-         * Default
-         */
-        default:
-
-            conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites();
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-            conf->cert_profile = &mbedtls_x509_crt_profile_default;
-#endif
-
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
-                conf->sig_algs = ssl_tls12_preset_default_sig_algs;
-            } else
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
-            conf->sig_algs = ssl_preset_default_sig_algs;
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
-            conf->curve_list = NULL;
-#endif
-            conf->group_list = ssl_preset_default_groups;
-
-#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
-            conf->dhm_min_bitlen = 1024;
-#endif
-    }
-
-    return 0;
-}
-
-/*
- * Free mbedtls_ssl_config
- */
-void mbedtls_ssl_config_free(mbedtls_ssl_config *conf)
-{
-#if defined(MBEDTLS_DHM_C)
-    mbedtls_mpi_free(&conf->dhm_P);
-    mbedtls_mpi_free(&conf->dhm_G);
-#endif
-
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
-        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
-    }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-    if (conf->psk != NULL) {
-        mbedtls_platform_zeroize(conf->psk, conf->psk_len);
-        mbedtls_free(conf->psk);
-        conf->psk = NULL;
-        conf->psk_len = 0;
-    }
-
-    if (conf->psk_identity != NULL) {
-        mbedtls_platform_zeroize(conf->psk_identity, conf->psk_identity_len);
-        mbedtls_free(conf->psk_identity);
-        conf->psk_identity = NULL;
-        conf->psk_identity_len = 0;
-    }
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-    ssl_key_cert_free(conf->key_cert);
-#endif
-
-    mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config));
-}
-
-#if defined(MBEDTLS_PK_C) && \
-    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_CAN_ECDSA_SOME))
-/*
- * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX
- */
-unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk)
-{
-#if defined(MBEDTLS_RSA_C)
-    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) {
-        return MBEDTLS_SSL_SIG_RSA;
-    }
-#endif
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) {
-        return MBEDTLS_SSL_SIG_ECDSA;
-    }
-#endif
-    return MBEDTLS_SSL_SIG_ANON;
-}
-
-unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type)
-{
-    switch (type) {
-        case MBEDTLS_PK_RSA:
-            return MBEDTLS_SSL_SIG_RSA;
-        case MBEDTLS_PK_ECDSA:
-        case MBEDTLS_PK_ECKEY:
-            return MBEDTLS_SSL_SIG_ECDSA;
-        default:
-            return MBEDTLS_SSL_SIG_ANON;
-    }
-}
-
-mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig)
-{
-    switch (sig) {
-#if defined(MBEDTLS_RSA_C)
-        case MBEDTLS_SSL_SIG_RSA:
-            return MBEDTLS_PK_RSA;
-#endif
-#if defined(MBEDTLS_PK_CAN_ECDSA_SOME)
-        case MBEDTLS_SSL_SIG_ECDSA:
-            return MBEDTLS_PK_ECDSA;
-#endif
-        default:
-            return MBEDTLS_PK_NONE;
-    }
-}
-#endif /* MBEDTLS_PK_C && ( MBEDTLS_RSA_C || MBEDTLS_PK_CAN_ECDSA_SOME ) */
-
-/*
- * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX
- */
-mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash)
-{
-    switch (hash) {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_MD5:
-            return MBEDTLS_MD_MD5;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA1:
-            return MBEDTLS_MD_SHA1;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA224:
-            return MBEDTLS_MD_SHA224;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA256:
-            return MBEDTLS_MD_SHA256;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA384:
-            return MBEDTLS_MD_SHA384;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA512:
-            return MBEDTLS_MD_SHA512;
-#endif
-        default:
-            return MBEDTLS_MD_NONE;
-    }
-}
+#define SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG   \
+    ((uint32_t) (                              \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_CONNECTION_ID_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_BADMAC_LIMIT_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY << \
+             SSL_SERIALIZED_CONTEXT_CONFIG_DTLS_ANTI_REPLAY_BIT) | \
+         (SSL_SERIALIZED_CONTEXT_CONFIG_ALPN << SSL_SERIALIZED_CONTEXT_CONFIG_ALPN_BIT) | \
+         0u))
 
-/*
- * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX
- */
-unsigned char mbedtls_ssl_hash_from_md_alg(int md)
-{
-    switch (md) {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_MD5:
-            return MBEDTLS_SSL_HASH_MD5;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA1:
-            return MBEDTLS_SSL_HASH_SHA1;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA224:
-            return MBEDTLS_SSL_HASH_SHA224;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA256:
-            return MBEDTLS_SSL_HASH_SHA256;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA384:
-            return MBEDTLS_SSL_HASH_SHA384;
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA512:
-            return MBEDTLS_SSL_HASH_SHA512;
-#endif
-        default:
-            return MBEDTLS_SSL_HASH_NONE;
-    }
-}
+static const unsigned char ssl_serialized_context_header[] = {
+    MBEDTLS_VERSION_MAJOR,
+    MBEDTLS_VERSION_MINOR,
+    MBEDTLS_VERSION_PATCH,
+    MBEDTLS_BYTE_1(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_0(SSL_SERIALIZED_SESSION_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_2(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_1(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
+    MBEDTLS_BYTE_0(SSL_SERIALIZED_CONTEXT_CONFIG_BITFLAG),
+};
 
 /*
- * Check if a curve proposed by the peer is in our list.
- * Return 0 if we're willing to use it, -1 otherwise.
+ * Serialize a full SSL context
+ *
+ * The format of the serialized data is:
+ * (in the presentation language of TLS, RFC 8446 section 3)
+ *
+ *  // header
+ *  opaque mbedtls_version[3];   // major, minor, patch
+ *  opaque context_format[5];    // version-specific field determining
+ *                               // the format of the remaining
+ *                               // serialized data.
+ *  Note: When updating the format, remember to keep these
+ *        version+format bytes. (We may make their size part of the API.)
+ *
+ *  // session sub-structure
+ *  opaque session<1..2^32-1>;  // see mbedtls_ssl_session_save()
+ *  // transform sub-structure
+ *  uint8 random[64];           // ServerHello.random+ClientHello.random
+ *  uint8 in_cid<0..2^8-1>      // Connection ID: expected incoming value
+ *  uint8 out_cid<0..2^8-1>     // Connection ID: outgoing value to use
+ *  // fields from ssl_context
+ *  uint32 badmac_seen;         // DTLS: number of records with failing MAC
+ *  uint64 in_window_top;       // DTLS: last validated record seq_num
+ *  uint64 in_window;           // DTLS: bitmask for replay protection
+ *  uint8 disable_datagram_packing; // DTLS: only one record per datagram
+ *  uint64 cur_out_ctr;         // Record layer: outgoing sequence number
+ *  uint16 mtu;                 // DTLS: path mtu (max outgoing fragment size)
+ *  uint8 alpn_chosen<0..2^8-1> // ALPN: negotiated application protocol
+ *
+ * Note that many fields of the ssl_context or sub-structures are not
+ * serialized, as they fall in one of the following categories:
+ *
+ *  1. forced value (eg in_left must be 0)
+ *  2. pointer to dynamically-allocated memory (eg session, transform)
+ *  3. value can be re-derived from other data (eg session keys from MS)
+ *  4. value was temporary (eg content of input buffer)
+ *  5. value will be provided by the user again (eg I/O callbacks and context)
  */
-int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id)
+int mbedtls_ssl_context_save(mbedtls_ssl_context *ssl,
+                             unsigned char *buf,
+                             size_t buf_len,
+                             size_t *olen)
 {
-    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+    unsigned char *p = buf;
+    size_t used = 0;
+    size_t session_len;
+    int ret = 0;
 
-    if (group_list == NULL) {
-        return -1;
+    /*
+     * Enforce usage restrictions, see "return BAD_INPUT_DATA" in
+     * this function's documentation.
+     *
+     * These are due to assumptions/limitations in the implementation. Some of
+     * them are likely to stay (no handshake in progress) some might go away
+     * (only DTLS) but are currently used to simplify the implementation.
+     */
+    /* The initial handshake must be over */
+    if (mbedtls_ssl_is_handshake_over(ssl) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Initial handshake isn't over"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-
-    for (; *group_list != 0; group_list++) {
-        if (*group_list == tls_id) {
-            return 0;
-        }
+    if (ssl->handshake != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Handshake isn't completed"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* Double-check that sub-structures are indeed ready */
+    if (ssl->transform == NULL || ssl->session == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Serialised structures aren't ready"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* There must be no pending incoming or outgoing data */
+    if (mbedtls_ssl_check_pending(ssl) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending incoming data"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    if (ssl->out_left != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("There is pending outgoing data"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* Protocol must be DTLS, not TLS */
+    if (ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only DTLS is supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* Version must be 1.2 */
+    if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only version 1.2 supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* We must be using an AEAD ciphersuite */
+    if (mbedtls_ssl_transform_uses_aead(ssl->transform) != 1) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Only AEAD ciphersuites supported"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    /* Renegotiation must not be enabled */
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Renegotiation must not be enabled"));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+#endif
 
-    return -1;
-}
+    /*
+     * Version and format identifier
+     */
+    used += sizeof(ssl_serialized_context_header);
 
-#if defined(MBEDTLS_ECP_C)
-/*
- * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id.
- */
-int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id)
-{
-    uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
+    if (used <= buf_len) {
+        memcpy(p, ssl_serialized_context_header,
+               sizeof(ssl_serialized_context_header));
+        p += sizeof(ssl_serialized_context_header);
+    }
 
-    if (tls_id == 0) {
-        return -1;
+    /*
+     * Session (length + data)
+     */
+    ret = ssl_session_save(ssl->session, 1, NULL, 0, &session_len);
+    if (ret != MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) {
+        return ret;
     }
 
-    return mbedtls_ssl_check_curve_tls_id(ssl, tls_id);
-}
-#endif /* MBEDTLS_ECP_C */
+    used += 4 + session_len;
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT32_BE(session_len, p, 0);
+        p += 4;
 
-#if defined(MBEDTLS_DEBUG_C)
-#define EC_NAME(_name_)     _name_
-#else
-#define EC_NAME(_name_)     NULL
-#endif
+        ret = ssl_session_save(ssl->session, 1,
+                               p, session_len, &session_len);
+        if (ret != 0) {
+            return ret;
+        }
 
-static const struct {
-    uint16_t tls_id;
-    mbedtls_ecp_group_id ecp_group_id;
-    psa_ecc_family_t psa_family;
-    uint16_t bits;
-    const char *name;
-} tls_id_match_table[] =
-{
-#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_521)
-    { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521, EC_NAME("secp521r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_512)
-    { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512, EC_NAME("brainpoolP512r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_384)
-    { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384, EC_NAME("secp384r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_384)
-    { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384, EC_NAME("brainpoolP384r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_256)
-    { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256, EC_NAME("secp256r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_256)
-    { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256, EC_NAME("secp256k1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || defined(PSA_WANT_ECC_BRAINPOOL_P_R1_256)
-    { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256, EC_NAME("brainpoolP256r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_224)
-    { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224, EC_NAME("secp224r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_224)
-    { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224, EC_NAME("secp224k1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || defined(PSA_WANT_ECC_SECP_R1_192)
-    { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192, EC_NAME("secp192r1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || defined(PSA_WANT_ECC_SECP_K1_192)
-    { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192, EC_NAME("secp192k1") },
-#endif
-#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_255)
-    { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255, EC_NAME("x25519") },
-#endif
-#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) || defined(PSA_WANT_ECC_MONTGOMERY_448)
-    { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448, EC_NAME("x448") },
-#endif
-    { 0, MBEDTLS_ECP_DP_NONE, 0, 0, NULL },
-};
+        p += session_len;
+    }
 
-int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,
-                                               psa_ecc_family_t *family,
-                                               size_t *bits)
-{
-    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
-        if (tls_id_match_table[i].tls_id == tls_id) {
-            if (family != NULL) {
-                *family = tls_id_match_table[i].psa_family;
-            }
-            if (bits != NULL) {
-                *bits = tls_id_match_table[i].bits;
-            }
-            return PSA_SUCCESS;
-        }
+    /*
+     * Transform
+     */
+    used += sizeof(ssl->transform->randbytes);
+    if (used <= buf_len) {
+        memcpy(p, ssl->transform->randbytes,
+               sizeof(ssl->transform->randbytes));
+        p += sizeof(ssl->transform->randbytes);
     }
 
-    return PSA_ERROR_NOT_SUPPORTED;
-}
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    used += 2U + ssl->transform->in_cid_len + ssl->transform->out_cid_len;
+    if (used <= buf_len) {
+        *p++ = ssl->transform->in_cid_len;
+        memcpy(p, ssl->transform->in_cid, ssl->transform->in_cid_len);
+        p += ssl->transform->in_cid_len;
 
-mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id)
-{
-    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
-        if (tls_id_match_table[i].tls_id == tls_id) {
-            return tls_id_match_table[i].ecp_group_id;
-        }
+        *p++ = ssl->transform->out_cid_len;
+        memcpy(p, ssl->transform->out_cid, ssl->transform->out_cid_len);
+        p += ssl->transform->out_cid_len;
     }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
-    return MBEDTLS_ECP_DP_NONE;
-}
-
-uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
-{
-    for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE;
-         i++) {
-        if (tls_id_match_table[i].ecp_group_id == grp_id) {
-            return tls_id_match_table[i].tls_id;
-        }
+    /*
+     * Saved fields from top-level ssl_context structure
+     */
+    used += 4;
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT32_BE(ssl->badmac_seen, p, 0);
+        p += 4;
     }
 
-    return 0;
-}
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    used += 16;
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT64_BE(ssl->in_window_top, p, 0);
+        p += 8;
 
-#if defined(MBEDTLS_DEBUG_C)
-const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)
-{
-    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
-        if (tls_id_match_table[i].tls_id == tls_id) {
-            return tls_id_match_table[i].name;
-        }
+        MBEDTLS_PUT_UINT64_BE(ssl->in_window, p, 0);
+        p += 8;
     }
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
-    return NULL;
-}
-#endif
-
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
-                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,
-                                 int cert_endpoint,
-                                 uint32_t *flags)
-{
-    int ret = 0;
-    int usage = 0;
-    const char *ext_oid;
-    size_t ext_len;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    used += 1;
+    if (used <= buf_len) {
+        *p++ = ssl->disable_datagram_packing;
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
-        /* Server part of the key exchange */
-        switch (ciphersuite->key_exchange) {
-            case MBEDTLS_KEY_EXCHANGE_RSA:
-            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
-                usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
-                break;
+    used += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+    if (used <= buf_len) {
+        memcpy(p, ssl->cur_out_ctr, MBEDTLS_SSL_SEQUENCE_NUMBER_LEN);
+        p += MBEDTLS_SSL_SEQUENCE_NUMBER_LEN;
+    }
 
-            case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
-            case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
-            case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
-                usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
-                break;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    used += 2;
+    if (used <= buf_len) {
+        MBEDTLS_PUT_UINT16_BE(ssl->mtu, p, 0);
+        p += 2;
+    }
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-            case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
-            case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
-                usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
-                break;
+#if defined(MBEDTLS_SSL_ALPN)
+    {
+        const uint8_t alpn_len = ssl->alpn_chosen
+                               ? (uint8_t) strlen(ssl->alpn_chosen)
+                               : 0;
 
-            /* Don't use default: we want warnings when adding new values */
-            case MBEDTLS_KEY_EXCHANGE_NONE:
-            case MBEDTLS_KEY_EXCHANGE_PSK:
-            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
-            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
-            case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
-                usage = 0;
+        used += 1 + alpn_len;
+        if (used <= buf_len) {
+            *p++ = alpn_len;
+
+            if (ssl->alpn_chosen != NULL) {
+                memcpy(p, ssl->alpn_chosen, alpn_len);
+                p += alpn_len;
+            }
         }
-    } else {
-        /* Client auth: we only implement rsa_sign and mbedtls_ecdsa_sign for now */
-        usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
     }
+#endif /* MBEDTLS_SSL_ALPN */
 
-    if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
-        *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
-        ret = -1;
-    }
+    /*
+     * Done
+     */
+    *olen = used;
 
-    if (cert_endpoint == MBEDTLS_SSL_IS_SERVER) {
-        ext_oid = MBEDTLS_OID_SERVER_AUTH;
-        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
-    } else {
-        ext_oid = MBEDTLS_OID_CLIENT_AUTH;
-        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
+    if (used > buf_len) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
     }
 
-    if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
-        *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
-        ret = -1;
-    }
+    MBEDTLS_SSL_DEBUG_BUF(4, "saved context", buf, used);
 
-    return ret;
+    return mbedtls_ssl_session_reset_int(ssl, 0);
 }
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
-                                         const mbedtls_md_type_t md,
-                                         unsigned char *dst,
-                                         size_t dst_len,
-                                         size_t *olen)
+/*
+ * Deserialize context, see mbedtls_ssl_context_save() for format.
+ *
+ * This internal version is wrapped by a public function that cleans up in
+ * case of error.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_context_load(mbedtls_ssl_context *ssl,
+                            const unsigned char *buf,
+                            size_t len)
 {
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    psa_hash_operation_t *hash_operation_to_clone;
-    psa_hash_operation_t hash_operation = psa_hash_operation_init();
+    const unsigned char *p = buf;
+    const unsigned char * const end = buf + len;
+    size_t session_len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    tls_prf_fn prf_func = NULL;
+#endif
 
-    *olen = 0;
+    /*
+     * The context should have been freshly setup or reset.
+     * Give the user an error in case of obvious misuse.
+     * (Checking session is useful because it won't be NULL if we're
+     * renegotiating, or if the user mistakenly loaded a session first.)
+     */
+    if (ssl->state != MBEDTLS_SSL_HELLO_REQUEST ||
+        ssl->session != NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    switch (md) {
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA384:
-            hash_operation_to_clone = &ssl->handshake->fin_sha384_psa;
-            break;
+    /*
+     * We can't check that the config matches the initial one, but we can at
+     * least check it matches the requirements for serializing.
+     */
+    if (
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+        ssl->conf->disable_renegotiation != MBEDTLS_SSL_RENEGOTIATION_DISABLED ||
 #endif
+        ssl->conf->transport != MBEDTLS_SSL_TRANSPORT_DATAGRAM ||
+        ssl->conf->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2 ||
+        ssl->conf->min_tls_version > MBEDTLS_SSL_VERSION_TLS1_2
+        ) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA256:
-            hash_operation_to_clone = &ssl->handshake->fin_sha256_psa;
-            break;
-#endif
+    MBEDTLS_SSL_DEBUG_BUF(4, "context to load", buf, len);
 
-        default:
-            goto exit;
+    /*
+     * Check version identifier
+     */
+    if ((size_t) (end - p) < sizeof(ssl_serialized_context_header)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    status = psa_hash_clone(hash_operation_to_clone, &hash_operation);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    if (memcmp(p, ssl_serialized_context_header,
+               sizeof(ssl_serialized_context_header)) != 0) {
+        return MBEDTLS_ERR_SSL_VERSION_MISMATCH;
     }
+    p += sizeof(ssl_serialized_context_header);
 
-    status = psa_hash_finish(&hash_operation, dst, dst_len, olen);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    /*
+     * Session
+     */
+    if ((size_t) (end - p) < 4) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-exit:
-#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    (void) ssl;
-#endif
-    return PSA_TO_MBEDTLS_ERR(status);
-}
-#else /* MBEDTLS_USE_PSA_CRYPTO */
+    session_len = MBEDTLS_GET_UINT32_BE(p, 0);
+    p += 4;
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl,
-                                               unsigned char *dst,
-                                               size_t dst_len,
-                                               size_t *olen)
-{
-    int ret;
-    mbedtls_md_context_t sha384;
+    /* This has been allocated by ssl_handshake_init(), called by
+     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
+    ssl->session = ssl->session_negotiate;
+    ssl->session_in = ssl->session;
+    ssl->session_out = ssl->session;
+    ssl->session_negotiate = NULL;
 
-    if (dst_len < 48) {
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    if ((size_t) (end - p) < session_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    mbedtls_md_init(&sha384);
-    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
+    ret = ssl_session_load(ssl->session, 1, p, session_len);
     if (ret != 0) {
-        goto exit;
-    }
-
-    if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
-        goto exit;
+        mbedtls_ssl_session_free(ssl->session);
+        return ret;
     }
 
-    *olen = 48;
+    p += session_len;
 
-exit:
+    /*
+     * Transform
+     */
 
-    mbedtls_md_free(&sha384);
-    return ret;
-}
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+    /* This has been allocated by ssl_handshake_init(), called by
+     * by either mbedtls_ssl_session_reset_int() or mbedtls_ssl_setup(). */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    ssl->transform = ssl->transform_negotiate;
+    ssl->transform_in = ssl->transform;
+    ssl->transform_out = ssl->transform;
+    ssl->transform_negotiate = NULL;
+#endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl,
-                                               unsigned char *dst,
-                                               size_t dst_len,
-                                               size_t *olen)
-{
-    int ret;
-    mbedtls_md_context_t sha256;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    prf_func = ssl_tls12prf_from_cs(ssl->session->ciphersuite);
+    if (prf_func == NULL) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-    if (dst_len < 32) {
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    /* Read random bytes and populate structure */
+    if ((size_t) (end - p) < sizeof(ssl->transform->randbytes)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    mbedtls_md_init(&sha256);
-    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    ret = ssl_tls12_populate_transform(ssl->transform,
+                                       ssl->session->ciphersuite,
+                                       ssl->session->master,
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                       ssl->session->encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                       prf_func,
+                                       p, /* currently pointing to randbytes */
+                                       MBEDTLS_SSL_VERSION_TLS1_2, /* (D)TLS 1.2 is forced */
+                                       ssl->conf->endpoint,
+                                       ssl);
     if (ret != 0) {
-        goto exit;
+        return ret;
     }
-    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
-    if (ret != 0) {
-        goto exit;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+    p += sizeof(ssl->transform->randbytes);
+
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* Read connection IDs and store them */
+    if ((size_t) (end - p) < 1) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
-        goto exit;
+    ssl->transform->in_cid_len = *p++;
+
+    if ((size_t) (end - p) < ssl->transform->in_cid_len + 1u) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    *olen = 32;
+    memcpy(ssl->transform->in_cid, p, ssl->transform->in_cid_len);
+    p += ssl->transform->in_cid_len;
 
-exit:
+    ssl->transform->out_cid_len = *p++;
 
-    mbedtls_md_free(&sha256);
-    return ret;
-}
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+    if ((size_t) (end - p) < ssl->transform->out_cid_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
-                                         const mbedtls_md_type_t md,
-                                         unsigned char *dst,
-                                         size_t dst_len,
-                                         size_t *olen)
-{
-    switch (md) {
+    memcpy(ssl->transform->out_cid, p, ssl->transform->out_cid_len);
+    p += ssl->transform->out_cid_len;
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
+
+    /*
+     * Saved fields from top-level ssl_context structure
+     */
+    if ((size_t) (end - p) < 4) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    ssl->badmac_seen = MBEDTLS_GET_UINT32_BE(p, 0);
+    p += 4;
+
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    if ((size_t) (end - p) < 16) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA384:
-            return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen);
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    ssl->in_window_top = MBEDTLS_GET_UINT64_BE(p, 0);
+    p += 8;
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_MD_SHA256:
-            return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen);
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    ssl->in_window = MBEDTLS_GET_UINT64_BE(p, 0);
+    p += 8;
+#endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 
-        default:
-#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-            !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-            (void) ssl;
-            (void) dst;
-            (void) dst_len;
-            (void) olen;
-#endif
-            break;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if ((size_t) (end - p) < 1) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-}
 
-#endif /* !MBEDTLS_USE_PSA_CRYPTO */
+    ssl->disable_datagram_packing = *p++;
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
-/* mbedtls_ssl_parse_sig_alg_ext()
- *
- * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`
- * value (TLS 1.3 RFC8446):
- *      enum {
- *         ....
- *        ecdsa_secp256r1_sha256( 0x0403 ),
- *        ecdsa_secp384r1_sha384( 0x0503 ),
- *        ecdsa_secp521r1_sha512( 0x0603 ),
- *         ....
- *      } SignatureScheme;
- *
- *      struct {
- *         SignatureScheme supported_signature_algorithms<2..2^16-2>;
- *      } SignatureSchemeList;
- *
- * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`
- * value (TLS 1.2 RFC5246):
- *      enum {
- *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
- *          sha512(6), (255)
- *      } HashAlgorithm;
- *
- *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
- *        SignatureAlgorithm;
- *
- *      struct {
- *          HashAlgorithm hash;
- *          SignatureAlgorithm signature;
- *      } SignatureAndHashAlgorithm;
- *
- *      SignatureAndHashAlgorithm
- *        supported_signature_algorithms<2..2^16-2>;
- *
- * The TLS 1.3 signature algorithm extension was defined to be a compatible
- * generalization of the TLS 1.2 signature algorithm extension.
- * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by
- * `SignatureScheme` field of TLS 1.3
- *
- */
-int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,
-                                  const unsigned char *buf,
-                                  const unsigned char *end)
-{
-    const unsigned char *p = buf;
-    size_t supported_sig_algs_len = 0;
-    const unsigned char *supported_sig_algs_end;
-    uint16_t sig_alg;
-    uint32_t common_idx = 0;
+    if ((size_t) (end - p) < sizeof(ssl->cur_out_ctr)) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+    memcpy(ssl->cur_out_ctr, p, sizeof(ssl->cur_out_ctr));
+    p += sizeof(ssl->cur_out_ctr);
 
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
-    supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0);
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if ((size_t) (end - p) < 2) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    ssl->mtu = MBEDTLS_GET_UINT16_BE(p, 0);
     p += 2;
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    memset(ssl->handshake->received_sig_algs, 0,
-           sizeof(ssl->handshake->received_sig_algs));
+#if defined(MBEDTLS_SSL_ALPN)
+    {
+        uint8_t alpn_len;
+        const char **cur;
 
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len);
-    supported_sig_algs_end = p + supported_sig_algs_len;
-    while (p < supported_sig_algs_end) {
-        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2);
-        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
-        p += 2;
-        MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s",
-                                  sig_alg,
-                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
-            (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) &&
-               mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) {
-            continue;
+        if ((size_t) (end - p) < 1) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-        MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s",
-                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
+        alpn_len = *p++;
 
-        if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) {
-            ssl->handshake->received_sig_algs[common_idx] = sig_alg;
-            common_idx += 1;
+        if (alpn_len != 0 && ssl->conf->alpn_list != NULL) {
+            /* alpn_chosen should point to an item in the configured list */
+            for (cur = ssl->conf->alpn_list; *cur != NULL; cur++) {
+                if (strlen(*cur) == alpn_len &&
+                    memcmp(p, *cur, alpn_len) == 0) {
+                    ssl->alpn_chosen = *cur;
+                    break;
+                }
+            }
+        }
+
+        /* can only happen on conf mismatch */
+        if (alpn_len != 0 && ssl->alpn_chosen == NULL) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
         }
+
+        p += alpn_len;
     }
-    /* Check that we consumed all the message. */
-    if (p != end) {
-        MBEDTLS_SSL_DEBUG_MSG(1,
-                              ("Signature algorithms extension length misaligned"));
-        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
-                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
-        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+#endif /* MBEDTLS_SSL_ALPN */
+
+    /*
+     * Forced fields from top-level ssl_context structure
+     *
+     * Most of them already set to the correct value by mbedtls_ssl_init() and
+     * mbedtls_ssl_reset(), so we only need to set the remaining ones.
+     */
+    ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
+    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+
+    /* Adjust pointers for header fields of outgoing records to
+     * the given transform, accounting for explicit IV and CID. */
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform);
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    ssl->in_epoch = 1;
+#endif
+
+    /* mbedtls_ssl_reset() leaves the handshake sub-structure allocated,
+     * which we don't want - otherwise we'd end up freeing the wrong transform
+     * by calling mbedtls_ssl_handshake_wrapup_free_hs_transform()
+     * inappropriately. */
+    if (ssl->handshake != NULL) {
+        mbedtls_ssl_handshake_free(ssl);
+        mbedtls_free(ssl->handshake);
+        ssl->handshake = NULL;
     }
 
-    if (common_idx == 0) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common"));
-        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
-                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
-        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    /*
+     * Done - should have consumed entire buffer
+     */
+    if (p != end) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE;
     return 0;
 }
 
-#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
-
-#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-
-static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation,
-                                             mbedtls_svc_key_id_t key,
-                                             psa_algorithm_t alg,
-                                             const unsigned char *raw_psk, size_t raw_psk_length,
-                                             const unsigned char *seed, size_t seed_length,
-                                             const unsigned char *label, size_t label_length,
-                                             const unsigned char *other_secret,
-                                             size_t other_secret_length,
-                                             size_t capacity)
+/*
+ * Deserialize context: public wrapper for error cleaning
+ */
+int mbedtls_ssl_context_load(mbedtls_ssl_context *context,
+                             const unsigned char *buf,
+                             size_t len)
 {
-    psa_status_t status;
+    int ret = ssl_context_load(context, buf, len);
 
-    status = psa_key_derivation_setup(derivation, alg);
-    if (status != PSA_SUCCESS) {
-        return status;
+    if (ret != 0) {
+        mbedtls_ssl_free(context);
     }
 
-    if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
-        status = psa_key_derivation_input_bytes(derivation,
-                                                PSA_KEY_DERIVATION_INPUT_SEED,
-                                                seed, seed_length);
-        if (status != PSA_SUCCESS) {
-            return status;
-        }
+    return ret;
+}
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
-        if (other_secret != NULL) {
-            status = psa_key_derivation_input_bytes(derivation,
-                                                    PSA_KEY_DERIVATION_INPUT_OTHER_SECRET,
-                                                    other_secret, other_secret_length);
-            if (status != PSA_SUCCESS) {
-                return status;
-            }
-        }
+/*
+ * Free an SSL context
+ */
+void mbedtls_ssl_free(mbedtls_ssl_context *ssl)
+{
+    if (ssl == NULL) {
+        return;
+    }
 
-        if (mbedtls_svc_key_id_is_null(key)) {
-            status = psa_key_derivation_input_bytes(
-                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
-                raw_psk, raw_psk_length);
-        } else {
-            status = psa_key_derivation_input_key(
-                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key);
-        }
-        if (status != PSA_SUCCESS) {
-            return status;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> free"));
 
-        status = psa_key_derivation_input_bytes(derivation,
-                                                PSA_KEY_DERIVATION_INPUT_LABEL,
-                                                label, label_length);
-        if (status != PSA_SUCCESS) {
-            return status;
-        }
-    } else {
-        return PSA_ERROR_NOT_SUPPORTED;
-    }
+    if (ssl->out_buf != NULL) {
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+        size_t out_buf_len = ssl->out_buf_len;
+#else
+        size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN;
+#endif
 
-    status = psa_key_derivation_set_capacity(derivation, capacity);
-    if (status != PSA_SUCCESS) {
-        return status;
+        mbedtls_zeroize_and_free(ssl->out_buf, out_buf_len);
+        ssl->out_buf = NULL;
     }
 
-    return PSA_SUCCESS;
-}
+    if (ssl->in_buf != NULL) {
+#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
+        size_t in_buf_len = ssl->in_buf_len;
+#else
+        size_t in_buf_len = MBEDTLS_SSL_IN_BUFFER_LEN;
+#endif
 
-#if defined(PSA_WANT_ALG_SHA_384) || \
-    defined(PSA_WANT_ALG_SHA_256)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_generic(mbedtls_md_type_t md_type,
-                           const unsigned char *secret, size_t slen,
-                           const char *label,
-                           const unsigned char *random, size_t rlen,
-                           unsigned char *dstbuf, size_t dlen)
-{
-    psa_status_t status;
-    psa_algorithm_t alg;
-    mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;
-    psa_key_derivation_operation_t derivation =
-        PSA_KEY_DERIVATION_OPERATION_INIT;
+        mbedtls_zeroize_and_free(ssl->in_buf, in_buf_len);
+        ssl->in_buf = NULL;
+    }
 
-    if (md_type == MBEDTLS_MD_SHA384) {
-        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
-    } else {
-        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
+    if (ssl->transform) {
+        mbedtls_ssl_transform_free(ssl->transform);
+        mbedtls_free(ssl->transform);
     }
 
-    /* Normally a "secret" should be long enough to be impossible to
-     * find by brute force, and in particular should not be empty. But
-     * this PRF is also used to derive an IV, in particular in EAP-TLS,
-     * and for this use case it makes sense to have a 0-length "secret".
-     * Since the key API doesn't allow importing a key of length 0,
-     * keep master_key=0, which setup_psa_key_derivation() understands
-     * to mean a 0-length "secret" input. */
-    if (slen != 0) {
-        psa_key_attributes_t key_attributes = psa_key_attributes_init();
-        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
-        psa_set_key_algorithm(&key_attributes, alg);
-        psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);
+    if (ssl->handshake) {
+        mbedtls_ssl_handshake_free(ssl);
+        mbedtls_free(ssl->handshake);
 
-        status = psa_import_key(&key_attributes, secret, slen, &master_key);
-        if (status != PSA_SUCCESS) {
-            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-        }
-    }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        mbedtls_ssl_transform_free(ssl->transform_negotiate);
+        mbedtls_free(ssl->transform_negotiate);
+#endif
 
-    status = setup_psa_key_derivation(&derivation,
-                                      master_key, alg,
-                                      NULL, 0,
-                                      random, rlen,
-                                      (unsigned char const *) label,
-                                      (size_t) strlen(label),
-                                      NULL, 0,
-                                      dlen);
-    if (status != PSA_SUCCESS) {
-        psa_key_derivation_abort(&derivation);
-        psa_destroy_key(master_key);
-        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        mbedtls_ssl_session_free(ssl->session_negotiate);
+        mbedtls_free(ssl->session_negotiate);
     }
 
-    status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen);
-    if (status != PSA_SUCCESS) {
-        psa_key_derivation_abort(&derivation);
-        psa_destroy_key(master_key);
-        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-    }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    mbedtls_ssl_transform_free(ssl->transform_application);
+    mbedtls_free(ssl->transform_application);
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
-    status = psa_key_derivation_abort(&derivation);
-    if (status != PSA_SUCCESS) {
-        psa_destroy_key(master_key);
-        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    if (ssl->session) {
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
     }
 
-    if (!mbedtls_svc_key_id_is_null(master_key)) {
-        status = psa_destroy_key(master_key);
-    }
-    if (status != PSA_SUCCESS) {
-        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    if (ssl->hostname != NULL) {
+        mbedtls_zeroize_and_free(ssl->hostname, strlen(ssl->hostname));
     }
+#endif
 
-    return 0;
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_free(ssl->cli_id);
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= free"));
+
+    /* Actually clear after last debug message */
+    mbedtls_platform_zeroize(ssl, sizeof(mbedtls_ssl_context));
 }
-#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */
-#else /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_MD_C) &&       \
-    (defined(MBEDTLS_SHA256_C) || \
-    defined(MBEDTLS_SHA384_C))
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_generic(mbedtls_md_type_t md_type,
-                           const unsigned char *secret, size_t slen,
-                           const char *label,
-                           const unsigned char *random, size_t rlen,
-                           unsigned char *dstbuf, size_t dlen)
+/*
+ * Initialize mbedtls_ssl_config
+ */
+void mbedtls_ssl_config_init(mbedtls_ssl_config *conf)
 {
-    size_t nb;
-    size_t i, j, k, md_len;
-    unsigned char *tmp;
-    size_t tmp_len = 0;
-    unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
-    const mbedtls_md_info_t *md_info;
-    mbedtls_md_context_t md_ctx;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    memset(conf, 0, sizeof(mbedtls_ssl_config));
+}
 
-    mbedtls_md_init(&md_ctx);
+/* The selection should be the same as mbedtls_x509_crt_profile_default in
+ * x509_crt.c, plus Montgomery curves for ECDHE. Here, the order matters:
+ * curves with a lower resource usage come first.
+ * See the documentation of mbedtls_ssl_conf_curves() for what we promise
+ * about this list.
+ */
+static const uint16_t ssl_preset_default_groups[] = {
+#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
+    MBEDTLS_SSL_IANA_TLS_GROUP_X25519,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_CURVE448)
+    MBEDTLS_SSL_IANA_TLS_GROUP_X448,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP256R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP384R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP512R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1,
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048,
+    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072,
+    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096,
+    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144,
+    MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192,
+#endif
+    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
+};
 
-    if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) {
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-    }
+static const int ssl_preset_suiteb_ciphersuites[] = {
+    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+    MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+    0
+};
 
-    md_len = mbedtls_md_get_size(md_info);
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
 
-    tmp_len = md_len + strlen(label) + rlen;
-    tmp = mbedtls_calloc(1, tmp_len);
-    if (tmp == NULL) {
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        goto exit;
-    }
+/* NOTICE:
+ *   For ssl_preset_*_sig_algs and ssl_tls12_preset_*_sig_algs, the following
+ *   rules SHOULD be upheld.
+ *   - No duplicate entries.
+ *   - But if there is a good reason, do not change the order of the algorithms.
+ *   - ssl_tls12_preset* is for TLS 1.2 use only.
+ *   - ssl_preset_* is for TLS 1.3 only or hybrid TLS 1.3/1.2 handshakes.
+ */
+static const uint16_t ssl_preset_default_sig_algs[] = {
 
-    nb = strlen(label);
-    memcpy(tmp + md_len, label, nb);
-    memcpy(tmp + md_len + nb, random, rlen);
-    nb += rlen;
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA256) && \
+    defined(PSA_WANT_ECC_SECP_R1_256)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
+    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)
+#endif
 
-    /*
-     * Compute P_<hash>(secret, label + random)[0..dlen]
-     */
-    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
-        goto exit;
-    }
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA384) && \
+    defined(PSA_WANT_ECC_SECP_R1_384)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
+    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
+#endif
 
-    ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
-    if (ret != 0) {
-        goto exit;
-    }
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA512) && \
+    defined(PSA_WANT_ECC_SECP_R1_521)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP521R1_SHA512,
+    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512)
+#endif
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA512)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
+#endif
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA384)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
+#endif
+
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && defined(MBEDTLS_MD_CAN_SHA256)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA512)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA512,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA512 */
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA384)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA384,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA384 */
+
+#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256)
+    MBEDTLS_TLS1_3_SIG_RSA_PKCS1_SHA256,
+#endif /* MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 */
+
+    MBEDTLS_TLS_SIG_NONE
+};
+
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_default_sig_algs[] = {
+
+#if defined(MBEDTLS_MD_CAN_SHA512)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA512),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA512,
+#endif
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA512),
+#endif
+#endif /* MBEDTLS_MD_CAN_SHA512 */
+
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA384,
+#endif
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#endif /* MBEDTLS_MD_CAN_SHA384 */
+
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+    MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
+#endif
+#if defined(MBEDTLS_RSA_C)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_RSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-    for (i = 0; i < dlen; i += md_len) {
-        ret = mbedtls_md_hmac_reset(&md_ctx);
-        if (ret != 0) {
-            goto exit;
-        }
-        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb);
-        if (ret != 0) {
-            goto exit;
-        }
-        ret = mbedtls_md_hmac_finish(&md_ctx, h_i);
-        if (ret != 0) {
-            goto exit;
-        }
+    MBEDTLS_TLS_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-        ret = mbedtls_md_hmac_reset(&md_ctx);
-        if (ret != 0) {
-            goto exit;
-        }
-        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len);
-        if (ret != 0) {
-            goto exit;
-        }
-        ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
-        if (ret != 0) {
-            goto exit;
-        }
+/* NOTICE: see above */
+static const uint16_t ssl_preset_suiteb_sig_algs[] = {
 
-        k = (i + md_len > dlen) ? dlen % md_len : md_len;
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA256) && \
+    defined(MBEDTLS_ECP_HAVE_SECP256R1)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP256R1_SHA256,
+    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256)
+#endif
 
-        for (j = 0; j < k; j++) {
-            dstbuf[i + j]  = h_i[j];
-        }
-    }
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED) && \
+    defined(MBEDTLS_MD_CAN_SHA384) && \
+    defined(MBEDTLS_ECP_HAVE_SECP384R1)
+    MBEDTLS_TLS1_3_SIG_ECDSA_SECP384R1_SHA384,
+    // == MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384)
+#endif
 
-exit:
-    mbedtls_md_free(&md_ctx);
+    MBEDTLS_TLS_SIG_NONE
+};
 
-    if (tmp != NULL) {
-        mbedtls_platform_zeroize(tmp, tmp_len);
-    }
+/* NOTICE: see above */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+static uint16_t ssl_tls12_preset_suiteb_sig_algs[] = {
 
-    mbedtls_platform_zeroize(h_i, sizeof(h_i));
+#if defined(MBEDTLS_MD_CAN_SHA256)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA256),
+#endif
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-    mbedtls_free(tmp);
+#if defined(MBEDTLS_MD_CAN_SHA384)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
+    MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA, MBEDTLS_SSL_HASH_SHA384),
+#endif
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-    return ret;
-}
-#endif /* MBEDTLS_MD_C && ( MBEDTLS_SHA256_C || MBEDTLS_SHA384_C ) */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    MBEDTLS_TLS_SIG_NONE
+};
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_sha256(const unsigned char *secret, size_t slen,
-                          const char *label,
-                          const unsigned char *random, size_t rlen,
-                          unsigned char *dstbuf, size_t dlen)
-{
-    return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen,
-                           label, random, rlen, dstbuf, dlen);
-}
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+static const uint16_t ssl_preset_suiteb_groups[] = {
+#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1,
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
+    MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1,
+#endif
+    MBEDTLS_SSL_IANA_TLS_GROUP_NONE
+};
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/* Function for checking `ssl_preset_*_sig_algs` and `ssl_tls12_preset_*_sig_algs`
+ * to make sure there are no duplicated signature algorithm entries. */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int tls_prf_sha384(const unsigned char *secret, size_t slen,
-                          const char *label,
-                          const unsigned char *random, size_t rlen,
-                          unsigned char *dstbuf, size_t dlen)
+static int ssl_check_no_sig_alg_duplication(const uint16_t *sig_algs)
 {
-    return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen,
-                           label, random, rlen, dstbuf, dlen);
+    size_t i, j;
+    int ret = 0;
+
+    for (i = 0; sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
+        for (j = 0; j < i; j++) {
+            if (sig_algs[i] != sig_algs[j]) {
+                continue;
+            }
+            mbedtls_printf(" entry(%04x,%" MBEDTLS_PRINTF_SIZET
+                           ") is duplicated at %" MBEDTLS_PRINTF_SIZET "\n",
+                           sig_algs[i], j, i);
+            ret = -1;
+        }
+    }
+    return ret;
 }
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
 /*
- * Set appropriate PRF function and other SSL / TLS1.2 functions
- *
- * Inputs:
- * - hash associated with the ciphersuite (only used by TLS 1.2)
- *
- * Outputs:
- * - the tls_prf, calc_verify and calc_finished members of handshake structure
+ * Load default in mbedtls_ssl_config
  */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake,
-                                  mbedtls_md_type_t hash)
+int mbedtls_ssl_config_defaults(mbedtls_ssl_config *conf,
+                                int endpoint, int transport, int preset)
 {
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (hash == MBEDTLS_MD_SHA384) {
-        handshake->tls_prf = tls_prf_sha384;
-        handshake->calc_verify = ssl_calc_verify_tls_sha384;
-        handshake->calc_finished = ssl_calc_finished_tls_sha384;
-    } else
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    {
-        (void) hash;
-        handshake->tls_prf = tls_prf_sha256;
-        handshake->calc_verify = ssl_calc_verify_tls_sha256;
-        handshake->calc_finished = ssl_calc_finished_tls_sha256;
+
+#if defined(MBEDTLS_DEBUG_C) && defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+    if (ssl_check_no_sig_alg_duplication(ssl_preset_suiteb_sig_algs)) {
+        mbedtls_printf("ssl_preset_suiteb_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     }
-#else
-    {
-        (void) handshake;
-        (void) hash;
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+
+    if (ssl_check_no_sig_alg_duplication(ssl_preset_default_sig_algs)) {
+        mbedtls_printf("ssl_preset_default_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     }
-#endif
 
-    return 0;
-}
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_suiteb_sig_algs)) {
+        mbedtls_printf("ssl_tls12_preset_suiteb_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
 
-/*
- * Compute master secret if needed
- *
- * Parameters:
- * [in/out] handshake
- *          [in] resume, premaster, extended_ms, calc_verify, tls_prf
- *               (PSA-PSK) ciphersuite_info, psk_opaque
- *          [out] premaster (cleared)
- * [out] master
- * [in] ssl: optionally used for debugging, EMS and PSA-PSK
- *      debug: conf->f_dbg, conf->p_dbg
- *      EMS: passed to calc_verify (debug + session_negotiate)
- *      PSA-PSA: conf
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake,
-                              unsigned char *master,
-                              const mbedtls_ssl_context *ssl)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    if (ssl_check_no_sig_alg_duplication(ssl_tls12_preset_default_sig_algs)) {
+        mbedtls_printf("ssl_tls12_preset_default_sig_algs has duplicated entries\n");
+        return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+#endif /* MBEDTLS_DEBUG_C && MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-    /* cf. RFC 5246, Section 8.1:
-     * "The master secret is always exactly 48 bytes in length." */
-    size_t const master_secret_len = 48;
+    /* Use the functions here so that they are covered in tests,
+     * but otherwise access member directly for efficiency */
+    mbedtls_ssl_conf_endpoint(conf, endpoint);
+    mbedtls_ssl_conf_transport(conf, transport);
+
+    /*
+     * Things that are common to all presets
+     */
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        conf->authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        mbedtls_ssl_conf_session_tickets(conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED);
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        /* Contrary to TLS 1.2 tickets, TLS 1.3 NewSessionTicket message
+         * handling is disabled by default in Mbed TLS 3.6.x for backward
+         * compatibility with client applications developed using Mbed TLS 3.5
+         * or earlier with the default configuration.
+         *
+         * Up to Mbed TLS 3.5, in the default configuration TLS 1.3 was
+         * disabled, and a Mbed TLS client with the default configuration would
+         * establish a TLS 1.2 connection with a TLS 1.2 and TLS 1.3 capable
+         * server.
+         *
+         * Starting with Mbed TLS 3.6.0, TLS 1.3 is enabled by default, and thus
+         * an Mbed TLS client with the default configuration establishes a
+         * TLS 1.3 connection with a TLS 1.2 and TLS 1.3 capable server. If
+         * following the handshake the TLS 1.3 server sends NewSessionTicket
+         * messages and the Mbed TLS client processes them, this results in
+         * Mbed TLS high level APIs (mbedtls_ssl_read(),
+         * mbedtls_ssl_handshake(), ...) to eventually return an
+         * #MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET non fatal error code
+         * (see the documentation of mbedtls_ssl_read() for more information on
+         * that error code). Applications unaware of that TLS 1.3 specific non
+         * fatal error code are then failing.
+         */
+        mbedtls_ssl_conf_tls13_enable_signal_new_session_tickets(
+            conf, MBEDTLS_SSL_TLS1_3_SIGNAL_NEW_SESSION_TICKETS_DISABLED);
+#endif
+#endif
+    }
+#endif
+
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+    conf->encrypt_then_mac = MBEDTLS_SSL_ETM_ENABLED;
+#endif
 
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    unsigned char session_hash[48];
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+    conf->extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED;
+#endif
 
-    /* The label for the KDF used for key expansion.
-     * This is either "master secret" or "extended master secret"
-     * depending on whether the Extended Master Secret extension
-     * is used. */
-    char const *lbl = "master secret";
+#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && defined(MBEDTLS_SSL_SRV_C)
+    conf->f_cookie_write = ssl_cookie_write_dummy;
+    conf->f_cookie_check = ssl_cookie_check_dummy;
+#endif
 
-    /* The seed for the KDF used for key expansion.
-     * - If the Extended Master Secret extension is not used,
-     *   this is ClientHello.Random + ServerHello.Random
-     *   (see Sect. 8.1 in RFC 5246).
-     * - If the Extended Master Secret extension is used,
-     *   this is the transcript of the handshake so far.
-     *   (see Sect. 4 in RFC 7627). */
-    unsigned char const *seed = handshake->randbytes;
-    size_t seed_len = 64;
+#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
+    conf->anti_replay = MBEDTLS_SSL_ANTI_REPLAY_ENABLED;
+#endif
 
-#if !defined(MBEDTLS_DEBUG_C) &&                    \
-    !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
-    !(defined(MBEDTLS_USE_PSA_CRYPTO) &&            \
-    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))
-    ssl = NULL; /* make sure we don't use it except for those cases */
-    (void) ssl;
+#if defined(MBEDTLS_SSL_SRV_C)
+    conf->cert_req_ca_list = MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED;
+    conf->respect_cli_pref = MBEDTLS_SSL_SRV_CIPHERSUITE_ORDER_SERVER;
 #endif
 
-    if (handshake->resume != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)"));
-        return 0;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    conf->hs_timeout_min = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MIN;
+    conf->hs_timeout_max = MBEDTLS_SSL_DTLS_TIMEOUT_DFL_MAX;
+#endif
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    conf->renego_max_records = MBEDTLS_SSL_RENEGO_MAX_RECORDS_DEFAULT;
+    memset(conf->renego_period,     0x00, 2);
+    memset(conf->renego_period + 2, 0xFF, 6);
+#endif
+
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_SRV_C)
+    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
+        const unsigned char dhm_p[] =
+            MBEDTLS_DHM_RFC3526_MODP_2048_P_BIN;
+        const unsigned char dhm_g[] =
+            MBEDTLS_DHM_RFC3526_MODP_2048_G_BIN;
+
+        if ((ret = mbedtls_ssl_conf_dh_param_bin(conf,
+                                                 dhm_p, sizeof(dhm_p),
+                                                 dhm_g, sizeof(dhm_g))) != 0) {
+            return ret;
+        }
     }
+#endif
 
-#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
-        lbl  = "extended master secret";
-        seed = session_hash;
-        ret = handshake->calc_verify(ssl, session_hash, &seed_len);
-        if (ret != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);
-        }
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-        MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret",
-                              session_hash, seed_len);
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    mbedtls_ssl_conf_early_data(conf, MBEDTLS_SSL_EARLY_DATA_DISABLED);
+#if defined(MBEDTLS_SSL_SRV_C)
+    mbedtls_ssl_conf_max_early_data_size(conf, MBEDTLS_SSL_MAX_EARLY_DATA_SIZE);
+#endif
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SESSION_TICKETS)
+    mbedtls_ssl_conf_new_session_tickets(
+        conf, MBEDTLS_SSL_TLS1_3_DEFAULT_NEW_SESSION_TICKETS);
+#endif
+    /*
+     * Allow all TLS 1.3 key exchange modes by default.
+     */
+    conf->tls13_kex_modes = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
+
+    if (transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+#else
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+#endif
+    } else {
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_3)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+#elif defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        conf->min_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        conf->max_tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+#else
+        return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+#endif
     }
-#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                   \
-    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-    if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) {
-        /* Perform PSK-to-MS expansion in a single step. */
-        psa_status_t status;
-        psa_algorithm_t alg;
-        mbedtls_svc_key_id_t psk;
-        psa_key_derivation_operation_t derivation =
-            PSA_KEY_DERIVATION_OPERATION_INIT;
-        mbedtls_md_type_t hash_alg = handshake->ciphersuite_info->mac;
+    /*
+     * Preset-specific defaults
+     */
+    switch (preset) {
+        /*
+         * NSA Suite B
+         */
+        case MBEDTLS_SSL_PRESET_SUITEB:
 
-        MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion"));
+            conf->ciphersuite_list = ssl_preset_suiteb_ciphersuites;
 
-        psk = mbedtls_ssl_get_opaque_psk(ssl);
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+            conf->cert_profile = &mbedtls_x509_crt_profile_suiteb;
+#endif
 
-        if (hash_alg == MBEDTLS_MD_SHA384) {
-            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
-        } else {
-            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
-        }
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
+                conf->sig_algs = ssl_tls12_preset_suiteb_sig_algs;
+            } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+            conf->sig_algs = ssl_preset_suiteb_sig_algs;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-        size_t other_secret_len = 0;
-        unsigned char *other_secret = NULL;
+#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+            conf->curve_list = NULL;
+#endif
+            conf->group_list = ssl_preset_suiteb_groups;
+            break;
 
-        switch (handshake->ciphersuite_info->key_exchange) {
-            /* Provide other secret.
-             * Other secret is stored in premaster, where first 2 bytes hold the
-             * length of the other key.
-             */
-            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
-                /* For RSA-PSK other key length is always 48 bytes. */
-                other_secret_len = 48;
-                other_secret = handshake->premaster + 2;
-                break;
-            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
-            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
-                other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0);
-                other_secret = handshake->premaster + 2;
-                break;
-            default:
-                break;
-        }
+        /*
+         * Default
+         */
+        default:
 
-        status = setup_psa_key_derivation(&derivation, psk, alg,
-                                          ssl->conf->psk, ssl->conf->psk_len,
-                                          seed, seed_len,
-                                          (unsigned char const *) lbl,
-                                          (size_t) strlen(lbl),
-                                          other_secret, other_secret_len,
-                                          master_secret_len);
-        if (status != PSA_SUCCESS) {
-            psa_key_derivation_abort(&derivation);
-            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-        }
+            conf->ciphersuite_list = mbedtls_ssl_list_ciphersuites();
 
-        status = psa_key_derivation_output_bytes(&derivation,
-                                                 master,
-                                                 master_secret_len);
-        if (status != PSA_SUCCESS) {
-            psa_key_derivation_abort(&derivation);
-            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-        }
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+            conf->cert_profile = &mbedtls_x509_crt_profile_default;
+#endif
 
-        status = psa_key_derivation_abort(&derivation);
-        if (status != PSA_SUCCESS) {
-            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-        }
-    } else
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+            if (mbedtls_ssl_conf_is_tls12_only(conf)) {
+                conf->sig_algs = ssl_tls12_preset_default_sig_algs;
+            } else
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+            conf->sig_algs = ssl_preset_default_sig_algs;
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
+#if defined(MBEDTLS_ECP_C) && !defined(MBEDTLS_DEPRECATED_REMOVED)
+            conf->curve_list = NULL;
 #endif
-    {
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                              \
-        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-        if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
-            psa_status_t status;
-            psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS;
-            psa_key_derivation_operation_t derivation =
-                PSA_KEY_DERIVATION_OPERATION_INIT;
+            conf->group_list = ssl_preset_default_groups;
 
-            MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE"));
+#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_SSL_CLI_C)
+            conf->dhm_min_bitlen = 1024;
+#endif
+    }
 
-            handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE;
+    return 0;
+}
 
-            status = psa_key_derivation_setup(&derivation, alg);
-            if (status != PSA_SUCCESS) {
-                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            }
+/*
+ * Free mbedtls_ssl_config
+ */
+void mbedtls_ssl_config_free(mbedtls_ssl_config *conf)
+{
+    if (conf == NULL) {
+        return;
+    }
 
-            status = psa_key_derivation_set_capacity(&derivation,
-                                                     PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);
-            if (status != PSA_SUCCESS) {
-                psa_key_derivation_abort(&derivation);
-                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            }
+#if defined(MBEDTLS_DHM_C)
+    mbedtls_mpi_free(&conf->dhm_P);
+    mbedtls_mpi_free(&conf->dhm_G);
+#endif
 
-            status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx,
-                                               &derivation);
-            if (status != PSA_SUCCESS) {
-                psa_key_derivation_abort(&derivation);
-                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            }
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED)
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if (!mbedtls_svc_key_id_is_null(conf->psk_opaque)) {
+        conf->psk_opaque = MBEDTLS_SVC_KEY_ID_INIT;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    if (conf->psk != NULL) {
+        mbedtls_zeroize_and_free(conf->psk, conf->psk_len);
+        conf->psk = NULL;
+        conf->psk_len = 0;
+    }
 
-            status = psa_key_derivation_output_bytes(&derivation,
-                                                     handshake->premaster,
-                                                     handshake->pmslen);
-            if (status != PSA_SUCCESS) {
-                psa_key_derivation_abort(&derivation);
-                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            }
+    if (conf->psk_identity != NULL) {
+        mbedtls_zeroize_and_free(conf->psk_identity, conf->psk_identity_len);
+        conf->psk_identity = NULL;
+        conf->psk_identity_len = 0;
+    }
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED */
 
-            status = psa_key_derivation_abort(&derivation);
-            if (status != PSA_SUCCESS) {
-                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
-            }
-        }
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    ssl_key_cert_free(conf->key_cert);
 #endif
-        ret = handshake->tls_prf(handshake->premaster, handshake->pmslen,
-                                 lbl, seed, seed_len,
-                                 master,
-                                 master_secret_len);
-        if (ret != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
-            return ret;
-        }
 
-        MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret",
-                              handshake->premaster,
-                              handshake->pmslen);
+    mbedtls_platform_zeroize(conf, sizeof(mbedtls_ssl_config));
+}
 
-        mbedtls_platform_zeroize(handshake->premaster,
-                                 sizeof(handshake->premaster));
+#if defined(MBEDTLS_PK_C) && \
+    (defined(MBEDTLS_RSA_C) || defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED))
+/*
+ * Convert between MBEDTLS_PK_XXX and SSL_SIG_XXX
+ */
+unsigned char mbedtls_ssl_sig_from_pk(mbedtls_pk_context *pk)
+{
+#if defined(MBEDTLS_RSA_C)
+    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_RSA)) {
+        return MBEDTLS_SSL_SIG_RSA;
     }
-
-    return 0;
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)
+    if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECDSA)) {
+        return MBEDTLS_SSL_SIG_ECDSA;
+    }
+#endif
+    return MBEDTLS_SSL_SIG_ANON;
 }
 
-int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl)
+unsigned char mbedtls_ssl_sig_from_pk_alg(mbedtls_pk_type_t type)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
+    switch (type) {
+        case MBEDTLS_PK_RSA:
+            return MBEDTLS_SSL_SIG_RSA;
+        case MBEDTLS_PK_ECDSA:
+        case MBEDTLS_PK_ECKEY:
+            return MBEDTLS_SSL_SIG_ECDSA;
+        default:
+            return MBEDTLS_SSL_SIG_ANON;
+    }
+}
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys"));
+mbedtls_pk_type_t mbedtls_ssl_pk_alg_from_sig(unsigned char sig)
+{
+    switch (sig) {
+#if defined(MBEDTLS_RSA_C)
+        case MBEDTLS_SSL_SIG_RSA:
+            return MBEDTLS_PK_RSA;
+#endif
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED)
+        case MBEDTLS_SSL_SIG_ECDSA:
+            return MBEDTLS_PK_ECDSA;
+#endif
+        default:
+            return MBEDTLS_PK_NONE;
+    }
+}
+#endif /* MBEDTLS_PK_C &&
+          ( MBEDTLS_RSA_C || MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ANY_ALLOWED_ENABLED ) */
 
-    /* Set PRF, calc_verify and calc_finished function pointers */
-    ret = ssl_set_handshake_prfs(ssl->handshake,
-                                 ciphersuite_info->mac);
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret);
-        return ret;
+/*
+ * Convert from MBEDTLS_SSL_HASH_XXX to MBEDTLS_MD_XXX
+ */
+mbedtls_md_type_t mbedtls_ssl_md_alg_from_hash(unsigned char hash)
+{
+    switch (hash) {
+#if defined(MBEDTLS_MD_CAN_MD5)
+        case MBEDTLS_SSL_HASH_MD5:
+            return MBEDTLS_MD_MD5;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA1)
+        case MBEDTLS_SSL_HASH_SHA1:
+            return MBEDTLS_MD_SHA1;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA224)
+        case MBEDTLS_SSL_HASH_SHA224:
+            return MBEDTLS_MD_SHA224;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+        case MBEDTLS_SSL_HASH_SHA256:
+            return MBEDTLS_MD_SHA256;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA384)
+        case MBEDTLS_SSL_HASH_SHA384:
+            return MBEDTLS_MD_SHA384;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA512)
+        case MBEDTLS_SSL_HASH_SHA512:
+            return MBEDTLS_MD_SHA512;
+#endif
+        default:
+            return MBEDTLS_MD_NONE;
     }
+}
 
-    /* Compute master secret if needed */
-    ret = ssl_compute_master(ssl->handshake,
-                             ssl->session_negotiate->master,
-                             ssl);
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret);
-        return ret;
+/*
+ * Convert from MBEDTLS_MD_XXX to MBEDTLS_SSL_HASH_XXX
+ */
+unsigned char mbedtls_ssl_hash_from_md_alg(int md)
+{
+    switch (md) {
+#if defined(MBEDTLS_MD_CAN_MD5)
+        case MBEDTLS_MD_MD5:
+            return MBEDTLS_SSL_HASH_MD5;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA1)
+        case MBEDTLS_MD_SHA1:
+            return MBEDTLS_SSL_HASH_SHA1;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA224)
+        case MBEDTLS_MD_SHA224:
+            return MBEDTLS_SSL_HASH_SHA224;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+        case MBEDTLS_MD_SHA256:
+            return MBEDTLS_SSL_HASH_SHA256;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA384)
+        case MBEDTLS_MD_SHA384:
+            return MBEDTLS_SSL_HASH_SHA384;
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA512)
+        case MBEDTLS_MD_SHA512:
+            return MBEDTLS_SSL_HASH_SHA512;
+#endif
+        default:
+            return MBEDTLS_SSL_HASH_NONE;
     }
+}
 
-    /* Swap the client and server random values:
-     * - MS derivation wanted client+server (RFC 5246 8.1)
-     * - key derivation wants server+client (RFC 5246 6.3) */
-    {
-        unsigned char tmp[64];
-        memcpy(tmp, ssl->handshake->randbytes, 64);
-        memcpy(ssl->handshake->randbytes, tmp + 32, 32);
-        memcpy(ssl->handshake->randbytes + 32, tmp, 32);
-        mbedtls_platform_zeroize(tmp, sizeof(tmp));
+/*
+ * Check if a curve proposed by the peer is in our list.
+ * Return 0 if we're willing to use it, -1 otherwise.
+ */
+int mbedtls_ssl_check_curve_tls_id(const mbedtls_ssl_context *ssl, uint16_t tls_id)
+{
+    const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
+
+    if (group_list == NULL) {
+        return -1;
     }
 
-    /* Populate transform structure */
-    ret = ssl_tls12_populate_transform(ssl->transform_negotiate,
-                                       ssl->session_negotiate->ciphersuite,
-                                       ssl->session_negotiate->master,
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-                                       ssl->session_negotiate->encrypt_then_mac,
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
-                                       ssl->handshake->tls_prf,
-                                       ssl->handshake->randbytes,
-                                       ssl->tls_version,
-                                       ssl->conf->endpoint,
-                                       ssl);
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret);
-        return ret;
+    for (; *group_list != 0; group_list++) {
+        if (*group_list == tls_id) {
+            return 0;
+        }
     }
 
-    /* We no longer need Server/ClientHello.random values */
-    mbedtls_platform_zeroize(ssl->handshake->randbytes,
-                             sizeof(ssl->handshake->randbytes));
+    return -1;
+}
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys"));
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+/*
+ * Same as mbedtls_ssl_check_curve_tls_id() but with a mbedtls_ecp_group_id.
+ */
+int mbedtls_ssl_check_curve(const mbedtls_ssl_context *ssl, mbedtls_ecp_group_id grp_id)
+{
+    uint16_t tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
 
-    return 0;
+    if (tls_id == 0) {
+        return -1;
+    }
+
+    return mbedtls_ssl_check_curve_tls_id(ssl, tls_id);
 }
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
-int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md)
+static const struct {
+    uint16_t tls_id;
+    mbedtls_ecp_group_id ecp_group_id;
+    psa_ecc_family_t psa_family;
+    uint16_t bits;
+} tls_id_match_table[] =
 {
-    switch (md) {
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA384:
-            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;
-            break;
+#if defined(MBEDTLS_ECP_HAVE_SECP521R1)
+    { 25, MBEDTLS_ECP_DP_SECP521R1, PSA_ECC_FAMILY_SECP_R1, 521 },
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-        case MBEDTLS_SSL_HASH_SHA256:
-            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256;
-            break;
+#if defined(MBEDTLS_ECP_HAVE_BP512R1)
+    { 28, MBEDTLS_ECP_DP_BP512R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 512 },
 #endif
-        default:
-            return -1;
-    }
-#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    (void) ssl;
+#if defined(MBEDTLS_ECP_HAVE_SECP384R1)
+    { 24, MBEDTLS_ECP_DP_SECP384R1, PSA_ECC_FAMILY_SECP_R1, 384 },
 #endif
-    return 0;
-}
+#if defined(MBEDTLS_ECP_HAVE_BP384R1)
+    { 27, MBEDTLS_ECP_DP_BP384R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 384 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP256R1)
+    { 23, MBEDTLS_ECP_DP_SECP256R1, PSA_ECC_FAMILY_SECP_R1, 256 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP256K1)
+    { 22, MBEDTLS_ECP_DP_SECP256K1, PSA_ECC_FAMILY_SECP_K1, 256 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_BP256R1)
+    { 26, MBEDTLS_ECP_DP_BP256R1, PSA_ECC_FAMILY_BRAINPOOL_P_R1, 256 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP224R1)
+    { 21, MBEDTLS_ECP_DP_SECP224R1, PSA_ECC_FAMILY_SECP_R1, 224 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP224K1)
+    { 20, MBEDTLS_ECP_DP_SECP224K1, PSA_ECC_FAMILY_SECP_K1, 224 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP192R1)
+    { 19, MBEDTLS_ECP_DP_SECP192R1, PSA_ECC_FAMILY_SECP_R1, 192 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_SECP192K1)
+    { 18, MBEDTLS_ECP_DP_SECP192K1, PSA_ECC_FAMILY_SECP_K1, 192 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_CURVE25519)
+    { 29, MBEDTLS_ECP_DP_CURVE25519, PSA_ECC_FAMILY_MONTGOMERY, 255 },
+#endif
+#if defined(MBEDTLS_ECP_HAVE_CURVE448)
+    { 30, MBEDTLS_ECP_DP_CURVE448, PSA_ECC_FAMILY_MONTGOMERY, 448 },
+#endif
+    { 0, MBEDTLS_ECP_DP_NONE, 0, 0 },
+};
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,
-                               unsigned char *hash,
-                               size_t *hlen)
+int mbedtls_ssl_get_psa_curve_info_from_tls_id(uint16_t tls_id,
+                                               psa_key_type_t *type,
+                                               size_t *bits)
 {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_status_t status;
-    psa_hash_operation_t sha256_psa = psa_hash_operation_init();
-
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha256"));
-    status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
+        if (tls_id_match_table[i].tls_id == tls_id) {
+            if (type != NULL) {
+                *type = PSA_KEY_TYPE_ECC_KEY_PAIR(tls_id_match_table[i].psa_family);
+            }
+            if (bits != NULL) {
+                *bits = tls_id_match_table[i].bits;
+            }
+            return PSA_SUCCESS;
+        }
     }
 
-    status = psa_hash_finish(&sha256_psa, hash, 32, &hash_size);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    return PSA_ERROR_NOT_SUPPORTED;
+}
+
+mbedtls_ecp_group_id mbedtls_ssl_get_ecp_group_id_from_tls_id(uint16_t tls_id)
+{
+    for (int i = 0; tls_id_match_table[i].tls_id != 0; i++) {
+        if (tls_id_match_table[i].tls_id == tls_id) {
+            return tls_id_match_table[i].ecp_group_id;
+        }
     }
 
-    *hlen = 32;
-    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
+    return MBEDTLS_ECP_DP_NONE;
+}
 
-exit:
-    psa_hash_abort(&sha256_psa);
-    return PSA_TO_MD_ERR(status);
-#else
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_context_t sha256;
+uint16_t mbedtls_ssl_get_tls_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
+{
+    for (int i = 0; tls_id_match_table[i].ecp_group_id != MBEDTLS_ECP_DP_NONE;
+         i++) {
+        if (tls_id_match_table[i].ecp_group_id == grp_id) {
+            return tls_id_match_table[i].tls_id;
+        }
+    }
 
-    mbedtls_md_init(&sha256);
+    return 0;
+}
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha256"));
+#if defined(MBEDTLS_DEBUG_C)
+static const struct {
+    uint16_t tls_id;
+    const char *name;
+} tls_id_curve_name_table[] =
+{
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP521R1, "secp521r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_BP512R1, "brainpoolP512r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP384R1, "secp384r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_BP384R1, "brainpoolP384r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256R1, "secp256r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP256K1, "secp256k1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_BP256R1, "brainpoolP256r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224R1, "secp224r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP224K1, "secp224k1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192R1, "secp192r1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_SECP192K1, "secp192k1" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_X25519, "x25519" },
+    { MBEDTLS_SSL_IANA_TLS_GROUP_X448, "x448" },
+    { 0, NULL },
+};
 
-    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
-    if (ret != 0) {
-        goto exit;
+const char *mbedtls_ssl_get_curve_name_from_tls_id(uint16_t tls_id)
+{
+    for (int i = 0; tls_id_curve_name_table[i].tls_id != 0; i++) {
+        if (tls_id_curve_name_table[i].tls_id == tls_id) {
+            return tls_id_curve_name_table[i].name;
+        }
     }
 
-    ret = mbedtls_md_finish(&sha256, hash);
-    if (ret != 0) {
-        goto exit;
-    }
+    return NULL;
+}
+#endif
 
-    *hlen = 32;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
+                                         const mbedtls_md_type_t md,
+                                         unsigned char *dst,
+                                         size_t dst_len,
+                                         size_t *olen)
+{
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+    psa_hash_operation_t *hash_operation_to_clone;
+    psa_hash_operation_t hash_operation = psa_hash_operation_init();
 
-    MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
+    *olen = 0;
 
-exit:
-    mbedtls_md_free(&sha256);
-    return ret;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-}
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+    switch (md) {
+#if defined(MBEDTLS_MD_CAN_SHA384)
+        case MBEDTLS_MD_SHA384:
+            hash_operation_to_clone = &ssl->handshake->fin_sha384_psa;
+            break;
+#endif
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,
-                               unsigned char *hash,
-                               size_t *hlen)
-{
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_status_t status;
-    psa_hash_operation_t sha384_psa = psa_hash_operation_init();
+#if defined(MBEDTLS_MD_CAN_SHA256)
+        case MBEDTLS_MD_SHA256:
+            hash_operation_to_clone = &ssl->handshake->fin_sha256_psa;
+            break;
+#endif
+
+        default:
+            goto exit;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify sha384"));
-    status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
+    status = psa_hash_clone(hash_operation_to_clone, &hash_operation);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-    status = psa_hash_finish(&sha384_psa, hash, 48, &hash_size);
+    status = psa_hash_finish(&hash_operation, dst, dst_len, olen);
     if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-    *hlen = 48;
-    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
-
 exit:
-    psa_hash_abort(&sha384_psa);
-    return PSA_TO_MD_ERR(status);
-#else
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_context_t sha384;
+#if !defined(MBEDTLS_MD_CAN_SHA384) && \
+    !defined(MBEDTLS_MD_CAN_SHA256)
+    (void) ssl;
+#endif
+    return PSA_TO_MBEDTLS_ERR(status);
+}
+#else /* MBEDTLS_USE_PSA_CRYPTO */
 
-    mbedtls_md_init(&sha384);
+#if defined(MBEDTLS_MD_CAN_SHA384)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_handshake_transcript_sha384(mbedtls_ssl_context *ssl,
+                                               unsigned char *dst,
+                                               size_t dst_len,
+                                               size_t *olen)
+{
+    int ret;
+    mbedtls_md_context_t sha384;
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify sha384"));
+    if (dst_len < 48) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
 
+    mbedtls_md_init(&sha384);
     ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
     if (ret != 0) {
         goto exit;
@@ -6738,2566 +6447,2830 @@ exit:
         goto exit;
     }
 
-    ret = mbedtls_md_finish(&sha384, hash);
-    if (ret != 0) {
+    if ((ret = mbedtls_md_finish(&sha384, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
         goto exit;
     }
 
-    *hlen = 48;
-
-    MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
+    *olen = 48;
 
 exit:
+
     mbedtls_md_free(&sha384);
     return ret;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
 }
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
-    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
-int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex)
+#if defined(MBEDTLS_MD_CAN_SHA256)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_get_handshake_transcript_sha256(mbedtls_ssl_context *ssl,
+                                               unsigned char *dst,
+                                               size_t dst_len,
+                                               size_t *olen)
 {
-    unsigned char *p = ssl->handshake->premaster;
-    unsigned char *end = p + sizeof(ssl->handshake->premaster);
-    const unsigned char *psk = NULL;
-    size_t psk_len = 0;
-    int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len);
-
-    if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) {
-        /*
-         * This should never happen because the existence of a PSK is always
-         * checked before calling this function.
-         *
-         * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with
-         * the shared secret without PSK.
-         */
-        if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-    }
-
-    /*
-     * PMS = struct {
-     *     opaque other_secret<0..2^16-1>;
-     *     opaque psk<0..2^16-1>;
-     * };
-     * with "other_secret" depending on the particular key exchange
-     */
-#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-    if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) {
-        if (end - p < 2) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-
-        MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
-        p += 2;
-
-        if (end < p || (size_t) (end - p) < psk_len) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-
-        memset(p, 0, psk_len);
-        p += psk_len;
-    } else
-#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-    if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
-        /*
-         * other_secret already set by the ClientKeyExchange message,
-         * and is 48 bytes long
-         */
-        if (end - p < 2) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-
-        *p++ = 0;
-        *p++ = 48;
-        p += 48;
-    } else
-#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-    if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t len;
-
-        /* Write length only when we know the actual value */
-        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
-                                           p + 2, end - (p + 2), &len,
-                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
-            return ret;
-        }
-        MBEDTLS_PUT_UINT16_BE(len, p, 0);
-        p += 2 + len;
-
-        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
-    } else
-#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
-#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-    if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-        size_t zlen;
-
-        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen,
-                                            p + 2, end - (p + 2),
-                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret);
-            return ret;
-        }
-
-        MBEDTLS_PUT_UINT16_BE(zlen, p, 0);
-        p += 2 + zlen;
+    int ret;
+    mbedtls_md_context_t sha256;
 
-        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
-                               MBEDTLS_DEBUG_ECDH_Z);
-    } else
-#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
-    {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    if (dst_len < 32) {
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    /* opaque psk<0..2^16-1>; */
-    if (end - p < 2) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-
-    MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
-    p += 2;
-
-    if (end < p || (size_t) (end - p) < psk_len) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    mbedtls_md_init(&sha256);
+    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
+    if (ret != 0) {
+        goto exit;
     }
-
-    memcpy(p, psk, psk_len);
-    p += psk_len;
-
-    ssl->handshake->pmslen = p - ssl->handshake->premaster;
-
-    return 0;
-}
-#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
-
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_write_hello_request(mbedtls_ssl_context *ssl);
-
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl)
-{
-    /* If renegotiation is not enforced, retransmit until we would reach max
-     * timeout if we were using the usual handshake doubling scheme */
-    if (ssl->conf->renego_max_records < 0) {
-        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;
-        unsigned char doublings = 1;
-
-        while (ratio != 0) {
-            ++doublings;
-            ratio >>= 1;
-        }
-
-        if (++ssl->renego_records_seen > doublings) {
-            MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request"));
-            return 0;
-        }
+    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
+    if (ret != 0) {
+        goto exit;
     }
 
-    return ssl_write_hello_request(ssl);
-}
-#endif
-#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
-
-/*
- * Handshake functions
- */
-#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
-/* No certificate support -> dummy functions */
-int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
-{
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
-
-    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
-        ssl->state++;
-        return 0;
+    if ((ret = mbedtls_md_finish(&sha256, dst)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
+        goto exit;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
-    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    *olen = 32;
+
+exit:
+
+    mbedtls_md_free(&sha256);
+    return ret;
 }
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
+int mbedtls_ssl_get_handshake_transcript(mbedtls_ssl_context *ssl,
+                                         const mbedtls_md_type_t md,
+                                         unsigned char *dst,
+                                         size_t dst_len,
+                                         size_t *olen)
 {
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
+    switch (md) {
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
+#if defined(MBEDTLS_MD_CAN_SHA384)
+        case MBEDTLS_MD_SHA384:
+            return ssl_get_handshake_transcript_sha384(ssl, dst, dst_len, olen);
+#endif /* MBEDTLS_MD_CAN_SHA384*/
 
-    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
-        ssl->state++;
-        return 0;
-    }
+#if defined(MBEDTLS_MD_CAN_SHA256)
+        case MBEDTLS_MD_SHA256:
+            return ssl_get_handshake_transcript_sha256(ssl, dst, dst_len, olen);
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 
-    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        default:
+#if !defined(MBEDTLS_MD_CAN_SHA384) && \
+            !defined(MBEDTLS_MD_CAN_SHA256)
+            (void) ssl;
+            (void) dst;
+            (void) dst_len;
+            (void) olen;
+#endif
+            break;
+    }
     return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
 }
 
-#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
-/* Some certificate support -> implement write and parse */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
 
-int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+/* mbedtls_ssl_parse_sig_alg_ext()
+ *
+ * The `extension_data` field of signature algorithm contains  a `SignatureSchemeList`
+ * value (TLS 1.3 RFC8446):
+ *      enum {
+ *         ....
+ *        ecdsa_secp256r1_sha256( 0x0403 ),
+ *        ecdsa_secp384r1_sha384( 0x0503 ),
+ *        ecdsa_secp521r1_sha512( 0x0603 ),
+ *         ....
+ *      } SignatureScheme;
+ *
+ *      struct {
+ *         SignatureScheme supported_signature_algorithms<2..2^16-2>;
+ *      } SignatureSchemeList;
+ *
+ * The `extension_data` field of signature algorithm contains a `SignatureAndHashAlgorithm`
+ * value (TLS 1.2 RFC5246):
+ *      enum {
+ *          none(0), md5(1), sha1(2), sha224(3), sha256(4), sha384(5),
+ *          sha512(6), (255)
+ *      } HashAlgorithm;
+ *
+ *      enum { anonymous(0), rsa(1), dsa(2), ecdsa(3), (255) }
+ *        SignatureAlgorithm;
+ *
+ *      struct {
+ *          HashAlgorithm hash;
+ *          SignatureAlgorithm signature;
+ *      } SignatureAndHashAlgorithm;
+ *
+ *      SignatureAndHashAlgorithm
+ *        supported_signature_algorithms<2..2^16-2>;
+ *
+ * The TLS 1.3 signature algorithm extension was defined to be a compatible
+ * generalization of the TLS 1.2 signature algorithm extension.
+ * `SignatureAndHashAlgorithm` field of TLS 1.2 can be represented by
+ * `SignatureScheme` field of TLS 1.3
+ *
+ */
+int mbedtls_ssl_parse_sig_alg_ext(mbedtls_ssl_context *ssl,
+                                  const unsigned char *buf,
+                                  const unsigned char *end)
 {
-    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-    size_t i, n;
-    const mbedtls_x509_crt *crt;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
+    const unsigned char *p = buf;
+    size_t supported_sig_algs_len = 0;
+    const unsigned char *supported_sig_algs_end;
+    uint16_t sig_alg;
+    uint32_t common_idx = 0;
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    supported_sig_algs_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
 
-    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
-        ssl->state++;
-        return 0;
-    }
+    memset(ssl->handshake->received_sig_algs, 0,
+           sizeof(ssl->handshake->received_sig_algs));
 
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        if (ssl->handshake->client_auth == 0) {
-            MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
-            ssl->state++;
-            return 0;
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, supported_sig_algs_len);
+    supported_sig_algs_end = p + supported_sig_algs_len;
+    while (p < supported_sig_algs_end) {
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, supported_sig_algs_end, 2);
+        sig_alg = MBEDTLS_GET_UINT16_BE(p, 0);
+        p += 2;
+        MBEDTLS_SSL_DEBUG_MSG(4, ("received signature algorithm: 0x%x %s",
+                                  sig_alg,
+                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+        if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+            (!(mbedtls_ssl_sig_alg_is_supported(ssl, sig_alg) &&
+               mbedtls_ssl_sig_alg_is_offered(ssl, sig_alg)))) {
+            continue;
         }
-    }
-#endif /* MBEDTLS_SSL_CLI_C */
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        if (mbedtls_ssl_own_cert(ssl) == NULL) {
-            /* Should never happen because we shouldn't have picked the
-             * ciphersuite if we don't have a certificate. */
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
+
+        MBEDTLS_SSL_DEBUG_MSG(4, ("valid signature algorithm: %s",
+                                  mbedtls_ssl_sig_alg_to_str(sig_alg)));
+
+        if (common_idx + 1 < MBEDTLS_RECEIVED_SIG_ALGS_SIZE) {
+            ssl->handshake->received_sig_algs[common_idx] = sig_alg;
+            common_idx += 1;
         }
     }
-#endif
+    /* Check that we consumed all the message. */
+    if (p != end) {
+        MBEDTLS_SSL_DEBUG_MSG(1,
+                              ("Signature algorithms extension length misaligned"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
 
-    MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl));
+    if (common_idx == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no signature algorithm in common"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
+                                     MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
 
-    /*
-     *     0  .  0    handshake type
-     *     1  .  3    handshake length
-     *     4  .  6    length of all certs
-     *     7  .  9    length of cert. 1
-     *    10  . n-1   peer certificate
-     *     n  . n+2   length of cert. 2
-     *    n+3 . ...   upper level cert, etc.
-     */
-    i = 7;
-    crt = mbedtls_ssl_own_cert(ssl);
+    ssl->handshake->received_sig_algs[common_idx] = MBEDTLS_TLS_SIG_NONE;
+    return 0;
+}
 
-    while (crt != NULL) {
-        n = crt->raw.len;
-        if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET
-                                      " > %" MBEDTLS_PRINTF_SIZET,
-                                      i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
-            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
-        }
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
 
-        ssl->out_msg[i] = MBEDTLS_BYTE_2(n);
-        ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n);
-        ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n);
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
 
-        i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n);
-        i += n; crt = crt->next;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+
+static psa_status_t setup_psa_key_derivation(psa_key_derivation_operation_t *derivation,
+                                             mbedtls_svc_key_id_t key,
+                                             psa_algorithm_t alg,
+                                             const unsigned char *raw_psk, size_t raw_psk_length,
+                                             const unsigned char *seed, size_t seed_length,
+                                             const unsigned char *label, size_t label_length,
+                                             const unsigned char *other_secret,
+                                             size_t other_secret_length,
+                                             size_t capacity)
+{
+    psa_status_t status;
+
+    status = psa_key_derivation_setup(derivation, alg);
+    if (status != PSA_SUCCESS) {
+        return status;
     }
 
-    ssl->out_msg[4]  = MBEDTLS_BYTE_2(i - 7);
-    ssl->out_msg[5]  = MBEDTLS_BYTE_1(i - 7);
-    ssl->out_msg[6]  = MBEDTLS_BYTE_0(i - 7);
+    if (PSA_ALG_IS_TLS12_PRF(alg) || PSA_ALG_IS_TLS12_PSK_TO_MS(alg)) {
+        status = psa_key_derivation_input_bytes(derivation,
+                                                PSA_KEY_DERIVATION_INPUT_SEED,
+                                                seed, seed_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
 
-    ssl->out_msglen  = i;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE;
+        if (other_secret != NULL) {
+            status = psa_key_derivation_input_bytes(derivation,
+                                                    PSA_KEY_DERIVATION_INPUT_OTHER_SECRET,
+                                                    other_secret, other_secret_length);
+            if (status != PSA_SUCCESS) {
+                return status;
+            }
+        }
 
-    ssl->state++;
+        if (mbedtls_svc_key_id_is_null(key)) {
+            status = psa_key_derivation_input_bytes(
+                derivation, PSA_KEY_DERIVATION_INPUT_SECRET,
+                raw_psk, raw_psk_length);
+        } else {
+            status = psa_key_derivation_input_key(
+                derivation, PSA_KEY_DERIVATION_INPUT_SECRET, key);
+        }
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
 
-    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
-        return ret;
+        status = psa_key_derivation_input_bytes(derivation,
+                                                PSA_KEY_DERIVATION_INPUT_LABEL,
+                                                label, label_length);
+        if (status != PSA_SUCCESS) {
+            return status;
+        }
+    } else {
+        return PSA_ERROR_NOT_SUPPORTED;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate"));
+    status = psa_key_derivation_set_capacity(derivation, capacity);
+    if (status != PSA_SUCCESS) {
+        return status;
+    }
 
-    return ret;
+    return PSA_SUCCESS;
 }
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+#if defined(PSA_WANT_ALG_SHA_384) || \
+    defined(PSA_WANT_ALG_SHA_256)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
-                                        unsigned char *crt_buf,
-                                        size_t crt_buf_len)
+static int tls_prf_generic(mbedtls_md_type_t md_type,
+                           const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen)
 {
-    mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;
+    psa_status_t status;
+    psa_algorithm_t alg;
+    mbedtls_svc_key_id_t master_key = MBEDTLS_SVC_KEY_ID_INIT;
+    psa_key_derivation_operation_t derivation =
+        PSA_KEY_DERIVATION_OPERATION_INIT;
 
-    if (peer_crt == NULL) {
-        return -1;
+    if (md_type == MBEDTLS_MD_SHA384) {
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_384);
+    } else {
+        alg = PSA_ALG_TLS12_PRF(PSA_ALG_SHA_256);
     }
 
-    if (peer_crt->raw.len != crt_buf_len) {
-        return -1;
+    /* Normally a "secret" should be long enough to be impossible to
+     * find by brute force, and in particular should not be empty. But
+     * this PRF is also used to derive an IV, in particular in EAP-TLS,
+     * and for this use case it makes sense to have a 0-length "secret".
+     * Since the key API doesn't allow importing a key of length 0,
+     * keep master_key=0, which setup_psa_key_derivation() understands
+     * to mean a 0-length "secret" input. */
+    if (slen != 0) {
+        psa_key_attributes_t key_attributes = psa_key_attributes_init();
+        psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+        psa_set_key_algorithm(&key_attributes, alg);
+        psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);
+
+        status = psa_import_key(&key_attributes, secret, slen, &master_key);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
     }
 
-    return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len);
-}
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
-                                        unsigned char *crt_buf,
-                                        size_t crt_buf_len)
-{
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned char const * const peer_cert_digest =
-        ssl->session->peer_cert_digest;
-    mbedtls_md_type_t const peer_cert_digest_type =
-        ssl->session->peer_cert_digest_type;
-    mbedtls_md_info_t const * const digest_info =
-        mbedtls_md_info_from_type(peer_cert_digest_type);
-    unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
-    size_t digest_len;
+    status = setup_psa_key_derivation(&derivation,
+                                      master_key, alg,
+                                      NULL, 0,
+                                      random, rlen,
+                                      (unsigned char const *) label,
+                                      (size_t) strlen(label),
+                                      NULL, 0,
+                                      dlen);
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(&derivation);
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+    }
 
-    if (peer_cert_digest == NULL || digest_info == NULL) {
-        return -1;
+    status = psa_key_derivation_output_bytes(&derivation, dstbuf, dlen);
+    if (status != PSA_SUCCESS) {
+        psa_key_derivation_abort(&derivation);
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
     }
 
-    digest_len = mbedtls_md_get_size(digest_info);
-    if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) {
-        return -1;
+    status = psa_key_derivation_abort(&derivation);
+    if (status != PSA_SUCCESS) {
+        psa_destroy_key(master_key);
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
     }
 
-    ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest);
-    if (ret != 0) {
-        return -1;
+    if (!mbedtls_svc_key_id_is_null(master_key)) {
+        status = psa_destroy_key(master_key);
+    }
+    if (status != PSA_SUCCESS) {
+        return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
     }
 
-    return memcmp(tmp_digest, peer_cert_digest, digest_len);
+    return 0;
 }
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+#endif /* PSA_WANT_ALG_SHA_256 || PSA_WANT_ALG_SHA_384 */
+#else /* MBEDTLS_USE_PSA_CRYPTO */
 
-/*
- * Once the certificate message is read, parse it into a cert chain and
- * perform basic checks, but leave actual verification to the caller
- */
+#if defined(MBEDTLS_MD_C) &&       \
+    (defined(MBEDTLS_MD_CAN_SHA256) || \
+    defined(MBEDTLS_MD_CAN_SHA384))
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl,
-                                       mbedtls_x509_crt *chain)
+static int tls_prf_generic(mbedtls_md_type_t md_type,
+                           const unsigned char *secret, size_t slen,
+                           const char *label,
+                           const unsigned char *random, size_t rlen,
+                           unsigned char *dstbuf, size_t dlen)
 {
+    size_t nb;
+    size_t i, j, k, md_len;
+    unsigned char *tmp;
+    size_t tmp_len = 0;
+    unsigned char h_i[MBEDTLS_MD_MAX_SIZE];
+    const mbedtls_md_info_t *md_info;
+    mbedtls_md_context_t md_ctx;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-    int crt_cnt = 0;
-#endif
-    size_t i, n;
-    uint8_t alert;
 
-    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
-        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
-    }
+    mbedtls_md_init(&md_ctx);
 
-    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) {
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
-        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    if ((md_info = mbedtls_md_info_from_type(md_type)) == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
-        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    md_len = mbedtls_md_get_size(md_info);
+
+    tmp_len = md_len + strlen(label) + rlen;
+    tmp = mbedtls_calloc(1, tmp_len);
+    if (tmp == NULL) {
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        goto exit;
     }
 
-    i = mbedtls_ssl_hs_hdr_len(ssl);
+    nb = strlen(label);
+    memcpy(tmp + md_len, label, nb);
+    memcpy(tmp + md_len + nb, random, rlen);
+    nb += rlen;
 
     /*
-     * Same message structure as in mbedtls_ssl_write_certificate()
+     * Compute P_<hash>(secret, label + random)[0..dlen]
      */
-    n = (ssl->in_msg[i+1] << 8) | ssl->in_msg[i+2];
-
-    if (ssl->in_msg[i] != 0 ||
-        ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
-        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    if ((ret = mbedtls_md_setup(&md_ctx, md_info, 1)) != 0) {
+        goto exit;
     }
 
-    /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
-    i += 3;
-
-    /* Iterate through and parse the CRTs in the provided chain. */
-    while (i < ssl->in_hslen) {
-        /* Check that there's room for the next CRT's length fields. */
-        if (i + 3 > ssl->in_hslen) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-            mbedtls_ssl_send_alert_message(ssl,
-                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
-            return MBEDTLS_ERR_SSL_DECODE_ERROR;
-        }
-        /* In theory, the CRT can be up to 2**24 Bytes, but we don't support
-         * anything beyond 2**16 ~ 64K. */
-        if (ssl->in_msg[i] != 0) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-            mbedtls_ssl_send_alert_message(ssl,
-                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                           MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
-            return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
-        }
-
-        /* Read length of the next CRT in the chain. */
-        n = ((unsigned int) ssl->in_msg[i + 1] << 8)
-            | (unsigned int) ssl->in_msg[i + 2];
-        i += 3;
+    ret = mbedtls_md_hmac_starts(&md_ctx, secret, slen);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_hmac_update(&md_ctx, tmp + md_len, nb);
+    if (ret != 0) {
+        goto exit;
+    }
+    ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
+    if (ret != 0) {
+        goto exit;
+    }
 
-        if (n < 128 || i + n > ssl->in_hslen) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
-            mbedtls_ssl_send_alert_message(ssl,
-                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
-            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    for (i = 0; i < dlen; i += md_len) {
+        ret = mbedtls_md_hmac_reset(&md_ctx);
+        if (ret != 0) {
+            goto exit;
         }
-
-        /* Check if we're handling the first CRT in the chain. */
-#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
-        if (crt_cnt++ == 0 &&
-            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
-            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
-            /* During client-side renegotiation, check that the server's
-             * end-CRTs hasn't changed compared to the initial handshake,
-             * mitigating the triple handshake attack. On success, reuse
-             * the original end-CRT instead of parsing it again. */
-            MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation"));
-            if (ssl_check_peer_crt_unchanged(ssl,
-                                             &ssl->in_msg[i],
-                                             n) != 0) {
-                MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation"));
-                mbedtls_ssl_send_alert_message(ssl,
-                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                               MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED);
-                return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
-            }
-
-            /* Now we can safely free the original chain. */
-            ssl_clear_peer_cert(ssl->session);
+        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len + nb);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_finish(&md_ctx, h_i);
+        if (ret != 0) {
+            goto exit;
         }
-#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
-
-        /* Parse the next certificate in the chain. */
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-        ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n);
-#else
-        /* If we don't need to store the CRT chain permanently, parse
-         * it in-place from the input buffer instead of making a copy. */
-        ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n);
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-        switch (ret) {
-            case 0: /*ok*/
-            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
-                /* Ignore certificate with an unknown algorithm: maybe a
-                   prior certificate was already trusted. */
-                break;
 
-            case MBEDTLS_ERR_X509_ALLOC_FAILED:
-                alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
-                goto crt_parse_der_failed;
+        ret = mbedtls_md_hmac_reset(&md_ctx);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_update(&md_ctx, tmp, md_len);
+        if (ret != 0) {
+            goto exit;
+        }
+        ret = mbedtls_md_hmac_finish(&md_ctx, tmp);
+        if (ret != 0) {
+            goto exit;
+        }
 
-            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
-                alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-                goto crt_parse_der_failed;
+        k = (i + md_len > dlen) ? dlen % md_len : md_len;
 
-            default:
-                alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
-crt_parse_der_failed:
-                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert);
-                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
-                return ret;
+        for (j = 0; j < k; j++) {
+            dstbuf[i + j]  = h_i[j];
         }
+    }
 
-        i += n;
+exit:
+    mbedtls_md_free(&md_ctx);
+
+    if (tmp != NULL) {
+        mbedtls_platform_zeroize(tmp, tmp_len);
     }
 
-    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain);
-    return 0;
+    mbedtls_platform_zeroize(h_i, sizeof(h_i));
+
+    mbedtls_free(tmp);
+
+    return ret;
 }
+#endif /* MBEDTLS_MD_C && ( MBEDTLS_MD_CAN_SHA256 || MBEDTLS_MD_CAN_SHA384 ) */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_SSL_SRV_C)
+#if defined(MBEDTLS_MD_CAN_SHA256)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl)
+static int tls_prf_sha256(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen)
 {
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        return -1;
-    }
+    return tls_prf_generic(MBEDTLS_MD_SHA256, secret, slen,
+                           label, random, rlen, dstbuf, dlen);
+}
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 
-    if (ssl->in_hslen   == 3 + mbedtls_ssl_hs_hdr_len(ssl) &&
-        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE    &&
-        ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&
-        memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate"));
-        return 0;
-    }
-    return -1;
+#if defined(MBEDTLS_MD_CAN_SHA384)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int tls_prf_sha384(const unsigned char *secret, size_t slen,
+                          const char *label,
+                          const unsigned char *random, size_t rlen,
+                          unsigned char *dstbuf, size_t dlen)
+{
+    return tls_prf_generic(MBEDTLS_MD_SHA384, secret, slen,
+                           label, random, rlen, dstbuf, dlen);
 }
-#endif /* MBEDTLS_SSL_SRV_C */
+#endif /* MBEDTLS_MD_CAN_SHA384*/
 
-/* Check if a certificate message is expected.
- * Return either
- * - SSL_CERTIFICATE_EXPECTED, or
- * - SSL_CERTIFICATE_SKIP
- * indicating whether a Certificate message is expected or not.
+/*
+ * Set appropriate PRF function and other SSL / TLS1.2 functions
+ *
+ * Inputs:
+ * - hash associated with the ciphersuite (only used by TLS 1.2)
+ *
+ * Outputs:
+ * - the tls_prf, calc_verify and calc_finished members of handshake structure
  */
-#define SSL_CERTIFICATE_EXPECTED 0
-#define SSL_CERTIFICATE_SKIP     1
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,
-                                            int authmode)
+static int ssl_set_handshake_prfs(mbedtls_ssl_handshake_params *handshake,
+                                  mbedtls_md_type_t hash)
 {
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-
-    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
-        return SSL_CERTIFICATE_SKIP;
-    }
-
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
-            return SSL_CERTIFICATE_SKIP;
-        }
-
-        if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
-            ssl->session_negotiate->verify_result =
-                MBEDTLS_X509_BADCERT_SKIP_VERIFY;
-            return SSL_CERTIFICATE_SKIP;
-        }
+#if defined(MBEDTLS_MD_CAN_SHA384)
+    if (hash == MBEDTLS_MD_SHA384) {
+        handshake->tls_prf = tls_prf_sha384;
+        handshake->calc_verify = ssl_calc_verify_tls_sha384;
+        handshake->calc_finished = ssl_calc_finished_tls_sha384;
+    } else
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+    {
+        (void) hash;
+        handshake->tls_prf = tls_prf_sha256;
+        handshake->calc_verify = ssl_calc_verify_tls_sha256;
+        handshake->calc_finished = ssl_calc_finished_tls_sha256;
     }
 #else
-    ((void) authmode);
-#endif /* MBEDTLS_SSL_SRV_C */
+    {
+        (void) handshake;
+        (void) hash;
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+#endif
 
-    return SSL_CERTIFICATE_EXPECTED;
+    return 0;
 }
 
+/*
+ * Compute master secret if needed
+ *
+ * Parameters:
+ * [in/out] handshake
+ *          [in] resume, premaster, extended_ms, calc_verify, tls_prf
+ *               (PSA-PSK) ciphersuite_info, psk_opaque
+ *          [out] premaster (cleared)
+ * [out] master
+ * [in] ssl: optionally used for debugging, EMS and PSA-PSK
+ *      debug: conf->f_dbg, conf->p_dbg
+ *      EMS: passed to calc_verify (debug + session_negotiate)
+ *      PSA-PSA: conf
+ */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl,
-                                        int authmode,
-                                        mbedtls_x509_crt *chain,
-                                        void *rs_ctx)
+static int ssl_compute_master(mbedtls_ssl_handshake_params *handshake,
+                              unsigned char *master,
+                              const mbedtls_ssl_context *ssl)
 {
-    int ret = 0;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
-        ssl->handshake->ciphersuite_info;
-    int have_ca_chain = 0;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
-    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
-    void *p_vrfy;
+    /* cf. RFC 5246, Section 8.1:
+     * "The master secret is always exactly 48 bytes in length." */
+    size_t const master_secret_len = 48;
 
-    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    unsigned char session_hash[48];
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
+
+    /* The label for the KDF used for key expansion.
+     * This is either "master secret" or "extended master secret"
+     * depending on whether the Extended Master Secret extension
+     * is used. */
+    char const *lbl = "master secret";
+
+    /* The seed for the KDF used for key expansion.
+     * - If the Extended Master Secret extension is not used,
+     *   this is ClientHello.Random + ServerHello.Random
+     *   (see Sect. 8.1 in RFC 5246).
+     * - If the Extended Master Secret extension is used,
+     *   this is the transcript of the handshake so far.
+     *   (see Sect. 4 in RFC 7627). */
+    unsigned char const *seed = handshake->randbytes;
+    size_t seed_len = 64;
+
+#if !defined(MBEDTLS_DEBUG_C) &&                    \
+    !defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \
+    !(defined(MBEDTLS_USE_PSA_CRYPTO) &&            \
+    defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED))
+    ssl = NULL; /* make sure we don't use it except for those cases */
+    (void) ssl;
+#endif
+
+    if (handshake->resume != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("no premaster (session resumed)"));
         return 0;
     }
 
-    if (ssl->f_vrfy != NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
-        f_vrfy = ssl->f_vrfy;
-        p_vrfy = ssl->p_vrfy;
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
-        f_vrfy = ssl->conf->f_vrfy;
-        p_vrfy = ssl->conf->p_vrfy;
+#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
+    if (handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED) {
+        lbl  = "extended master secret";
+        seed = session_hash;
+        ret = handshake->calc_verify(ssl, session_hash, &seed_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "calc_verify", ret);
+        }
+
+        MBEDTLS_SSL_DEBUG_BUF(3, "session hash for extended master secret",
+                              session_hash, seed_len);
     }
+#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 
-    /*
-     * Main check: verify certificate
-     */
-#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-    if (ssl->conf->f_ca_cb != NULL) {
-        ((void) rs_ctx);
-        have_ca_chain = 1;
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                   \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+    if (mbedtls_ssl_ciphersuite_uses_psk(handshake->ciphersuite_info) == 1) {
+        /* Perform PSK-to-MS expansion in a single step. */
+        psa_status_t status;
+        psa_algorithm_t alg;
+        mbedtls_svc_key_id_t psk;
+        psa_key_derivation_operation_t derivation =
+            PSA_KEY_DERIVATION_OPERATION_INIT;
+        mbedtls_md_type_t hash_alg = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PSK-to-MS expansion"));
+
+        psk = mbedtls_ssl_get_opaque_psk(ssl);
+
+        if (hash_alg == MBEDTLS_MD_SHA384) {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384);
+        } else {
+            alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256);
+        }
+
+        size_t other_secret_len = 0;
+        unsigned char *other_secret = NULL;
+
+        switch (handshake->ciphersuite_info->key_exchange) {
+            /* Provide other secret.
+             * Other secret is stored in premaster, where first 2 bytes hold the
+             * length of the other key.
+             */
+            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+                /* For RSA-PSK other key length is always 48 bytes. */
+                other_secret_len = 48;
+                other_secret = handshake->premaster + 2;
+                break;
+            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+                other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0);
+                other_secret = handshake->premaster + 2;
+                break;
+            default:
+                break;
+        }
 
-        MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
-        ret = mbedtls_x509_crt_verify_with_ca_cb(
-            chain,
-            ssl->conf->f_ca_cb,
-            ssl->conf->p_ca_cb,
-            ssl->conf->cert_profile,
-            ssl->hostname,
-            &ssl->session_negotiate->verify_result,
-            f_vrfy, p_vrfy);
-    } else
-#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
-    {
-        mbedtls_x509_crt *ca_chain;
-        mbedtls_x509_crl *ca_crl;
+        status = setup_psa_key_derivation(&derivation, psk, alg,
+                                          ssl->conf->psk, ssl->conf->psk_len,
+                                          seed, seed_len,
+                                          (unsigned char const *) lbl,
+                                          (size_t) strlen(lbl),
+                                          other_secret, other_secret_len,
+                                          master_secret_len);
+        if (status != PSA_SUCCESS) {
+            psa_key_derivation_abort(&derivation);
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+        }
 
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        if (ssl->handshake->sni_ca_chain != NULL) {
-            ca_chain = ssl->handshake->sni_ca_chain;
-            ca_crl   = ssl->handshake->sni_ca_crl;
-        } else
-#endif
-        {
-            ca_chain = ssl->conf->ca_chain;
-            ca_crl   = ssl->conf->ca_crl;
+        status = psa_key_derivation_output_bytes(&derivation,
+                                                 master,
+                                                 master_secret_len);
+        if (status != PSA_SUCCESS) {
+            psa_key_derivation_abort(&derivation);
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         }
 
-        if (ca_chain != NULL) {
-            have_ca_chain = 1;
+        status = psa_key_derivation_abort(&derivation);
+        if (status != PSA_SUCCESS) {
+            return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         }
+    } else
+#endif
+    {
+#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                              \
+        defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
+        if (handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
+            psa_status_t status;
+            psa_algorithm_t alg = PSA_ALG_TLS12_ECJPAKE_TO_PMS;
+            psa_key_derivation_operation_t derivation =
+                PSA_KEY_DERIVATION_OPERATION_INIT;
 
-        ret = mbedtls_x509_crt_verify_restartable(
-            chain,
-            ca_chain, ca_crl,
-            ssl->conf->cert_profile,
-            ssl->hostname,
-            &ssl->session_negotiate->verify_result,
-            f_vrfy, p_vrfy, rs_ctx);
-    }
+            MBEDTLS_SSL_DEBUG_MSG(2, ("perform PSA-based PMS KDF for ECJPAKE"));
 
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
-    }
+            handshake->pmslen = PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE;
 
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
-        return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
-    }
-#endif
+            status = psa_key_derivation_setup(&derivation, alg);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
 
-    /*
-     * Secondary checks: always done, but change 'ret' only if it was 0
-     */
+            status = psa_key_derivation_set_capacity(&derivation,
+                                                     PSA_TLS12_ECJPAKE_TO_PMS_DATA_SIZE);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
 
-#if defined(MBEDTLS_ECP_C)
-    {
-        const mbedtls_pk_context *pk = &chain->pk;
-
-        /* If certificate uses an EC key, make sure the curve is OK.
-         * This is a public key, so it can't be opaque, so can_do() is a good
-         * enough check to ensure pk_ec() is safe to use here. */
-        if (mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
-            /* and in the unlikely case the above assumption no longer holds
-             * we are making sure that pk_ec() here does not return a NULL
-             */
-            const mbedtls_ecp_keypair *ec = mbedtls_pk_ec(*pk);
-            if (ec == NULL) {
-                MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_pk_ec() returned NULL"));
-                return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+            status = psa_pake_get_implicit_key(&handshake->psa_pake_ctx,
+                                               &derivation);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
             }
 
-            if (mbedtls_ssl_check_curve(ssl, ec->grp.id) != 0) {
-                ssl->session_negotiate->verify_result |=
-                    MBEDTLS_X509_BADCERT_BAD_KEY;
+            status = psa_key_derivation_output_bytes(&derivation,
+                                                     handshake->premaster,
+                                                     handshake->pmslen);
+            if (status != PSA_SUCCESS) {
+                psa_key_derivation_abort(&derivation);
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
+            }
 
-                MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
-                if (ret == 0) {
-                    ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
-                }
+            status = psa_key_derivation_abort(&derivation);
+            if (status != PSA_SUCCESS) {
+                return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
             }
         }
-    }
-#endif /* MBEDTLS_ECP_C */
-
-    if (mbedtls_ssl_check_cert_usage(chain,
-                                     ciphersuite_info,
-                                     !ssl->conf->endpoint,
-                                     &ssl->session_negotiate->verify_result) != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
-        if (ret == 0) {
-            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+#endif
+        ret = handshake->tls_prf(handshake->premaster, handshake->pmslen,
+                                 lbl, seed, seed_len,
+                                 master,
+                                 master_secret_len);
+        if (ret != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
+            return ret;
         }
-    }
-
-    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
-     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
-     * with details encoded in the verification flags. All other kinds
-     * of error codes, including those from the user provided f_vrfy
-     * functions, are treated as fatal and lead to a failure of
-     * ssl_parse_certificate even if verification was optional. */
-    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
-        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
-         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
-        ret = 0;
-    }
 
-    if (have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
-        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
-    }
-
-    if (ret != 0) {
-        uint8_t alert;
-
-        /* The certificate may have been rejected for several reasons.
-           Pick one and send the corresponding alert. Which alert to send
-           may be a subject of debate in some cases. */
-        if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
-            alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
-            alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NS_CERT_TYPE) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
-        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
-            alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
-        } else {
-            alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
-        }
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       alert);
-    }
+        MBEDTLS_SSL_DEBUG_BUF(3, "premaster secret",
+                              handshake->premaster,
+                              handshake->pmslen);
 
-#if defined(MBEDTLS_DEBUG_C)
-    if (ssl->session_negotiate->verify_result != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
-                                  (unsigned int) ssl->session_negotiate->verify_result));
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
+        mbedtls_platform_zeroize(handshake->premaster,
+                                 sizeof(handshake->premaster));
     }
-#endif /* MBEDTLS_DEBUG_C */
 
-    return ret;
+    return 0;
 }
 
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,
-                                        unsigned char *start, size_t len)
+int mbedtls_ssl_derive_keys(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    /* Remember digest of the peer's end-CRT. */
-    ssl->session_negotiate->peer_cert_digest =
-        mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);
-    if (ssl->session_negotiate->peer_cert_digest == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed",
-                                  MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN));
-        mbedtls_ssl_send_alert_message(ssl,
-                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
-
-        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-    }
+    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
 
-    ret = mbedtls_md(mbedtls_md_info_from_type(
-                         MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),
-                     start, len,
-                     ssl->session_negotiate->peer_cert_digest);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive keys"));
 
-    ssl->session_negotiate->peer_cert_digest_type =
-        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
-    ssl->session_negotiate->peer_cert_digest_len =
-        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
+    /* Set PRF, calc_verify and calc_finished function pointers */
+    ret = ssl_set_handshake_prfs(ssl->handshake,
+                                 (mbedtls_md_type_t) ciphersuite_info->mac);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_set_handshake_prfs", ret);
+        return ret;
+    }
 
-    return ret;
-}
+    /* Compute master secret if needed */
+    ret = ssl_compute_master(ssl->handshake,
+                             ssl->session_negotiate->master,
+                             ssl);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_compute_master", ret);
+        return ret;
+    }
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl,
-                                    unsigned char *start, size_t len)
-{
-    unsigned char *end = start + len;
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    /* Swap the client and server random values:
+     * - MS derivation wanted client+server (RFC 5246 8.1)
+     * - key derivation wants server+client (RFC 5246 6.3) */
+    {
+        unsigned char tmp[64];
+        memcpy(tmp, ssl->handshake->randbytes, 64);
+        memcpy(ssl->handshake->randbytes, tmp + 32, 32);
+        memcpy(ssl->handshake->randbytes + 32, tmp, 32);
+        mbedtls_platform_zeroize(tmp, sizeof(tmp));
+    }
 
-    /* Make a copy of the peer's raw public key. */
-    mbedtls_pk_init(&ssl->handshake->peer_pubkey);
-    ret = mbedtls_pk_parse_subpubkey(&start, end,
-                                     &ssl->handshake->peer_pubkey);
+    /* Populate transform structure */
+    ret = ssl_tls12_populate_transform(ssl->transform_negotiate,
+                                       ssl->session_negotiate->ciphersuite,
+                                       ssl->session_negotiate->master,
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                       ssl->session_negotiate->encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                       ssl->handshake->tls_prf,
+                                       ssl->handshake->randbytes,
+                                       ssl->tls_version,
+                                       ssl->conf->endpoint,
+                                       ssl);
     if (ret != 0) {
-        /* We should have parsed the public key before. */
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        MBEDTLS_SSL_DEBUG_RET(1, "ssl_tls12_populate_transform", ret);
+        return ret;
     }
 
+    /* We no longer need Server/ClientHello.random values */
+    mbedtls_platform_zeroize(ssl->handshake->randbytes,
+                             sizeof(ssl->handshake->randbytes));
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= derive keys"));
+
     return 0;
 }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
-int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
+int mbedtls_ssl_set_calc_verify_md(mbedtls_ssl_context *ssl, int md)
 {
-    int ret = 0;
-    int crt_expected;
-#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
-                       ? ssl->handshake->sni_authmode
-                       : ssl->conf->authmode;
-#else
-    const int authmode = ssl->conf->authmode;
+    switch (md) {
+#if defined(MBEDTLS_MD_CAN_SHA384)
+        case MBEDTLS_SSL_HASH_SHA384:
+            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha384;
+            break;
 #endif
-    void *rs_ctx = NULL;
-    mbedtls_x509_crt *chain = NULL;
+#if defined(MBEDTLS_MD_CAN_SHA256)
+        case MBEDTLS_SSL_HASH_SHA256:
+            ssl->handshake->calc_verify = ssl_calc_verify_tls_sha256;
+            break;
+#endif
+        default:
+            return -1;
+    }
+#if !defined(MBEDTLS_MD_CAN_SHA384) && \
+    !defined(MBEDTLS_MD_CAN_SHA256)
+    (void) ssl;
+#endif
+    return 0;
+}
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+static int ssl_calc_verify_tls_psa(const mbedtls_ssl_context *ssl,
+                                   const psa_hash_operation_t *hs_op,
+                                   size_t buffer_size,
+                                   unsigned char *hash,
+                                   size_t *hlen)
+{
+    psa_status_t status;
+    psa_hash_operation_t cloned_op = psa_hash_operation_init();
 
-    crt_expected = ssl_parse_certificate_coordinate(ssl, authmode);
-    if (crt_expected == SSL_CERTIFICATE_SKIP) {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
+#if !defined(MBEDTLS_DEBUG_C)
+    (void) ssl;
+#endif
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> PSA calc verify"));
+    status = psa_hash_clone(hs_op, &cloned_op);
+    if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if (ssl->handshake->ecrs_enabled &&
-        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) {
-        chain = ssl->handshake->ecrs_peer_cert;
-        ssl->handshake->ecrs_peer_cert = NULL;
-        goto crt_verify;
-    }
-#endif
-
-    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
-        /* mbedtls_ssl_read_record may have sent an alert already. We
-           let it decide whether to alert. */
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+    status = psa_hash_finish(&cloned_op, hash, buffer_size, hlen);
+    if (status != PSA_SUCCESS) {
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (ssl_srv_check_client_no_crt_notification(ssl) == 0) {
-        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
-
-        if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) {
-            ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
-        }
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= PSA calc verify"));
 
-        goto exit;
-    }
-#endif /* MBEDTLS_SSL_SRV_C */
+exit:
+    psa_hash_abort(&cloned_op);
+    return mbedtls_md_error_from_psa(status);
+}
+#else
+static int ssl_calc_verify_tls_legacy(const mbedtls_ssl_context *ssl,
+                                      const mbedtls_md_context_t *hs_ctx,
+                                      unsigned char *hash,
+                                      size_t *hlen)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t cloned_ctx;
 
-    /* Clear existing peer CRT structure in case we tried to
-     * reuse a session but it failed, and allocate a new one. */
-    ssl_clear_peer_cert(ssl->session_negotiate);
+    mbedtls_md_init(&cloned_ctx);
 
-    chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
-    if (chain == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed",
-                                  sizeof(mbedtls_x509_crt)));
-        mbedtls_ssl_send_alert_message(ssl,
-                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+#if !defined(MBEDTLS_DEBUG_C)
+    (void) ssl;
+#endif
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc verify"));
 
-        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
+    ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0);
+    if (ret != 0) {
         goto exit;
     }
-    mbedtls_x509_crt_init(chain);
-
-    ret = ssl_parse_certificate_chain(ssl, chain);
+    ret = mbedtls_md_clone(&cloned_ctx, hs_ctx);
     if (ret != 0) {
         goto exit;
     }
 
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if (ssl->handshake->ecrs_enabled) {
-        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
-    }
-
-crt_verify:
-    if (ssl->handshake->ecrs_enabled) {
-        rs_ctx = &ssl->handshake->ecrs_ctx;
-    }
-#endif
-
-    ret = ssl_parse_certificate_verify(ssl, authmode,
-                                       chain, rs_ctx);
+    ret = mbedtls_md_finish(&cloned_ctx, hash);
     if (ret != 0) {
         goto exit;
     }
 
-#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    {
-        unsigned char *crt_start, *pk_start;
-        size_t crt_len, pk_len;
+    *hlen = mbedtls_md_get_size(mbedtls_md_info_from_ctx(hs_ctx));
 
-        /* We parse the CRT chain without copying, so
-         * these pointers point into the input buffer,
-         * and are hence still valid after freeing the
-         * CRT chain. */
+    MBEDTLS_SSL_DEBUG_BUF(3, "calculated verify result", hash, *hlen);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc verify"));
 
-        crt_start = chain->raw.p;
-        crt_len   = chain->raw.len;
+exit:
+    mbedtls_md_free(&cloned_ctx);
+    return ret;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-        pk_start = chain->pk_raw.p;
-        pk_len   = chain->pk_raw.len;
+#if defined(MBEDTLS_MD_CAN_SHA256)
+int ssl_calc_verify_tls_sha256(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha256_psa, 32,
+                                   hash, hlen);
+#else
+    return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha256,
+                                      hash, hlen);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_MD_CAN_SHA256 */
 
-        /* Free the CRT structures before computing
-         * digest and copying the peer's public key. */
-        mbedtls_x509_crt_free(chain);
-        mbedtls_free(chain);
-        chain = NULL;
+#if defined(MBEDTLS_MD_CAN_SHA384)
+int ssl_calc_verify_tls_sha384(const mbedtls_ssl_context *ssl,
+                               unsigned char *hash,
+                               size_t *hlen)
+{
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    return ssl_calc_verify_tls_psa(ssl, &ssl->handshake->fin_sha384_psa, 48,
+                                   hash, hlen);
+#else
+    return ssl_calc_verify_tls_legacy(ssl, &ssl->handshake->fin_sha384,
+                                      hash, hlen);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
+#endif /* MBEDTLS_MD_CAN_SHA384 */
 
-        ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len);
-        if (ret != 0) {
-            goto exit;
-        }
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
+int mbedtls_ssl_psk_derive_premaster(mbedtls_ssl_context *ssl, mbedtls_key_exchange_type_t key_ex)
+{
+    unsigned char *p = ssl->handshake->premaster;
+    unsigned char *end = p + sizeof(ssl->handshake->premaster);
+    const unsigned char *psk = NULL;
+    size_t psk_len = 0;
+    int psk_ret = mbedtls_ssl_get_psk(ssl, &psk, &psk_len);
 
-        ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len);
-        if (ret != 0) {
-            goto exit;
+    if (psk_ret == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) {
+        /*
+         * This should never happen because the existence of a PSK is always
+         * checked before calling this function.
+         *
+         * The exception is opaque DHE-PSK. For DHE-PSK fill premaster with
+         * the shared secret without PSK.
+         */
+        if (key_ex != MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
     }
-#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    /* Pass ownership to session structure. */
-    ssl->session_negotiate->peer_cert = chain;
-    chain = NULL;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate"));
-
-exit:
 
-    if (ret == 0) {
-        ssl->state++;
-    }
+    /*
+     * PMS = struct {
+     *     opaque other_secret<0..2^16-1>;
+     *     opaque psk<0..2^16-1>;
+     * };
+     * with "other_secret" depending on the particular key exchange
+     */
+#if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_PSK) {
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
-    if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
-        ssl->handshake->ecrs_peer_cert = chain;
-        chain = NULL;
-    }
-#endif
+        MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
+        p += 2;
 
-    if (chain != NULL) {
-        mbedtls_x509_crt_free(chain);
-        mbedtls_free(chain);
-    }
+        if (end < p || (size_t) (end - p) < psk_len) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-    return ret;
-}
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+        memset(p, 0, psk_len);
+        p += psk_len;
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+        /*
+         * other_secret already set by the ClientKeyExchange message,
+         * and is 48 bytes long
+         */
+        if (end - p < 2) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
 
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static int ssl_calc_finished_tls_sha256(
-    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
-{
-    int len = 12;
-    const char *sender;
-    unsigned char padbuf[32];
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_hash_operation_t sha256_psa = PSA_HASH_OPERATION_INIT;
-    psa_status_t status;
-#else
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_context_t sha256;
-#endif
+        *p++ = 0;
+        *p++ = 48;
+        p += 48;
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_DHE_PSK) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t len;
 
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if (!session) {
-        session = ssl->session;
-    }
+        /* Write length only when we know the actual value */
+        if ((ret = mbedtls_dhm_calc_secret(&ssl->handshake->dhm_ctx,
+                                           p + 2, (size_t) (end - (p + 2)), &len,
+                                           ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_dhm_calc_secret", ret);
+            return ret;
+        }
+        MBEDTLS_PUT_UINT16_BE(len, p, 0);
+        p += 2 + len;
 
-    sender = (from == MBEDTLS_SSL_IS_CLIENT)
-             ? "client finished"
-             : "server finished";
+        MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+    if (key_ex == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK) {
+        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+        size_t zlen;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    sha256_psa = psa_hash_operation_init();
+        if ((ret = mbedtls_ecdh_calc_secret(&ssl->handshake->ecdh_ctx, &zlen,
+                                            p + 2, (size_t) (end - (p + 2)),
+                                            ssl->conf->f_rng, ssl->conf->p_rng)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_calc_secret", ret);
+            return ret;
+        }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha256"));
+        MBEDTLS_PUT_UINT16_BE(zlen, p, 0);
+        p += 2 + zlen;
 
-    status = psa_hash_clone(&ssl->handshake->fin_sha256_psa, &sha256_psa);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+        MBEDTLS_SSL_DEBUG_ECDH(3, &ssl->handshake->ecdh_ctx,
+                               MBEDTLS_DEBUG_ECDH_Z);
+    } else
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    status = psa_hash_finish(&sha256_psa, padbuf, sizeof(padbuf), &hash_size);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    /* opaque psk<0..2^16-1>; */
+    if (end - p < 2) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 32);
-#else
-
-    mbedtls_md_init(&sha256);
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha256"));
+    MBEDTLS_PUT_UINT16_BE(psk_len, p, 0);
+    p += 2;
 
-    ret = mbedtls_md_setup(&sha256, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 0);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_clone(&sha256, &ssl->handshake->fin_sha256);
-    if (ret != 0) {
-        goto exit;
+    if (end < p || (size_t) (end - p) < psk_len) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
 
-    /*
-     * TLSv1.2:
-     *   hash = PRF( master, finished_label,
-     *               Hash( handshake ) )[0.11]
-     */
+    memcpy(p, psk, psk_len);
+    p += psk_len;
 
-    ret = mbedtls_md_finish(&sha256, padbuf);
-    if (ret != 0) {
-        goto exit;
-    }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    ssl->handshake->pmslen = (size_t) (p - ssl->handshake->premaster);
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha256 output", padbuf, 32);
+    return 0;
+}
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
 
-    ssl->handshake->tls_prf(session->master, 48, sender,
-                            padbuf, 32, buf, len);
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_RENEGOTIATION)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_write_hello_request(mbedtls_ssl_context *ssl);
 
-    MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len);
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+int mbedtls_ssl_resend_hello_request(mbedtls_ssl_context *ssl)
+{
+    /* If renegotiation is not enforced, retransmit until we would reach max
+     * timeout if we were using the usual handshake doubling scheme */
+    if (ssl->conf->renego_max_records < 0) {
+        uint32_t ratio = ssl->conf->hs_timeout_max / ssl->conf->hs_timeout_min + 1;
+        unsigned char doublings = 1;
 
-    mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
+        while (ratio != 0) {
+            ++doublings;
+            ratio >>= 1;
+        }
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+        if (++ssl->renego_records_seen > doublings) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("no longer retransmitting hello request"));
+            return 0;
+        }
+    }
 
-exit:
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&sha256_psa);
-    return PSA_TO_MD_ERR(status);
-#else
-    mbedtls_md_free(&sha256);
-    return ret;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    return ssl_write_hello_request(ssl);
 }
-#endif /* MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
-
+#endif
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_RENEGOTIATION */
 
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-static int ssl_calc_finished_tls_sha384(
-    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
+/*
+ * Handshake functions
+ */
+#if !defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+/* No certificate support -> dummy functions */
+int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
 {
-    int len = 12;
-    const char *sender;
-    unsigned char padbuf[48];
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t hash_size;
-    psa_hash_operation_t sha384_psa = PSA_HASH_OPERATION_INIT;
-    psa_status_t status;
-#else
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    mbedtls_md_context_t sha384;
-#endif
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
 
-    mbedtls_ssl_session *session = ssl->session_negotiate;
-    if (!session) {
-        session = ssl->session;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+        ssl->state++;
+        return 0;
     }
 
-    sender = (from == MBEDTLS_SSL_IS_CLIENT)
-                ? "client finished"
-                : "server finished";
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    sha384_psa = psa_hash_operation_init();
+int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls sha384"));
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
 
-    status = psa_hash_clone(&ssl->handshake->fin_sha384_psa, &sha384_psa);
-    if (status != PSA_SUCCESS) {
-        goto exit;
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
+        ssl->state++;
+        return 0;
     }
 
-    status = psa_hash_finish(&sha384_psa, padbuf, sizeof(padbuf), &hash_size);
-    if (status != PSA_SUCCESS) {
-        goto exit;
-    }
-    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, 48);
-#else
-    mbedtls_md_init(&sha384);
+    MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+    return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+}
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc  finished tls sha384"));
+#else /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+/* Some certificate support -> implement write and parse */
 
-    ret = mbedtls_md_setup(&sha384, mbedtls_md_info_from_type(MBEDTLS_MD_SHA384), 0);
-    if (ret != 0) {
-        goto exit;
-    }
-    ret = mbedtls_md_clone(&sha384, &ssl->handshake->fin_sha384);
-    if (ret != 0) {
-        goto exit;
-    }
+int mbedtls_ssl_write_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
+    size_t i, n;
+    const mbedtls_x509_crt *crt;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
 
-    /*
-     * TLSv1.2:
-     *   hash = PRF( master, finished_label,
-     *               Hash( handshake ) )[0.11]
-     */
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
 
-    ret = mbedtls_md_finish(&sha384, padbuf);
-    if (ret != 0) {
-        goto exit;
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+        ssl->state++;
+        return 0;
+    }
+
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        if (ssl->handshake->client_auth == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write certificate"));
+            ssl->state++;
+            return 0;
+        }
+    }
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (mbedtls_ssl_own_cert(ssl) == NULL) {
+            /* Should never happen because we shouldn't have picked the
+             * ciphersuite if we don't have a certificate. */
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        }
     }
 #endif
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "finished sha384 output", padbuf, 48);
+    MBEDTLS_SSL_DEBUG_CRT(3, "own certificate", mbedtls_ssl_own_cert(ssl));
 
-    ssl->handshake->tls_prf(session->master, 48, sender,
-                            padbuf, 48, buf, len);
+    /*
+     *     0  .  0    handshake type
+     *     1  .  3    handshake length
+     *     4  .  6    length of all certs
+     *     7  .  9    length of cert. 1
+     *    10  . n-1   peer certificate
+     *     n  . n+2   length of cert. 2
+     *    n+3 . ...   upper level cert, etc.
+     */
+    i = 7;
+    crt = mbedtls_ssl_own_cert(ssl);
 
-    MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len);
+    while (crt != NULL) {
+        n = crt->raw.len;
+        if (n > MBEDTLS_SSL_OUT_CONTENT_LEN - 3 - i) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("certificate too large, %" MBEDTLS_PRINTF_SIZET
+                                      " > %" MBEDTLS_PRINTF_SIZET,
+                                      i + 3 + n, (size_t) MBEDTLS_SSL_OUT_CONTENT_LEN));
+            return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+        }
 
-    mbedtls_platform_zeroize(padbuf, sizeof(padbuf));
+        ssl->out_msg[i] = MBEDTLS_BYTE_2(n);
+        ssl->out_msg[i + 1] = MBEDTLS_BYTE_1(n);
+        ssl->out_msg[i + 2] = MBEDTLS_BYTE_0(n);
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc  finished"));
+        i += 3; memcpy(ssl->out_msg + i, crt->raw.p, n);
+        i += n; crt = crt->next;
+    }
 
-exit:
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_hash_abort(&sha384_psa);
-    return PSA_TO_MD_ERR(status);
-#else
-    mbedtls_md_free(&sha384);
-    return ret;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-}
-#endif /* MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA*/
+    ssl->out_msg[4]  = MBEDTLS_BYTE_2(i - 7);
+    ssl->out_msg[5]  = MBEDTLS_BYTE_1(i - 7);
+    ssl->out_msg[6]  = MBEDTLS_BYTE_0(i - 7);
 
-void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl)
-{
-    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free"));
+    ssl->out_msglen  = i;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE;
 
-    /*
-     * Free our handshake params
-     */
-    mbedtls_ssl_handshake_free(ssl);
-    mbedtls_free(ssl->handshake);
-    ssl->handshake = NULL;
+    ssl->state++;
 
-    /*
-     * Free the previous transform and switch in the current one
-     */
-    if (ssl->transform) {
-        mbedtls_ssl_transform_free(ssl->transform);
-        mbedtls_free(ssl->transform);
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
     }
-    ssl->transform = ssl->transform_negotiate;
-    ssl->transform_negotiate = NULL;
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free"));
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write certificate"));
+
+    return ret;
 }
 
-void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl)
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
+                                        unsigned char *crt_buf,
+                                        size_t crt_buf_len)
 {
-    int resume = ssl->handshake->resume;
+    mbedtls_x509_crt const * const peer_crt = ssl->session->peer_cert;
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup"));
+    if (peer_crt == NULL) {
+        return -1;
+    }
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
-        ssl->renego_status =  MBEDTLS_SSL_RENEGOTIATION_DONE;
-        ssl->renego_records_seen = 0;
+    if (peer_crt->raw.len != crt_buf_len) {
+        return -1;
     }
-#endif
 
-    /*
-     * Free the previous session and switch in the current one
-     */
-    if (ssl->session) {
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-        /* RFC 7366 3.1: keep the EtM state */
-        ssl->session_negotiate->encrypt_then_mac =
-            ssl->session->encrypt_then_mac;
-#endif
+    return memcmp(peer_crt->raw.p, crt_buf, peer_crt->raw.len);
+}
+#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_check_peer_crt_unchanged(mbedtls_ssl_context *ssl,
+                                        unsigned char *crt_buf,
+                                        size_t crt_buf_len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned char const * const peer_cert_digest =
+        ssl->session->peer_cert_digest;
+    mbedtls_md_type_t const peer_cert_digest_type =
+        ssl->session->peer_cert_digest_type;
+    mbedtls_md_info_t const * const digest_info =
+        mbedtls_md_info_from_type(peer_cert_digest_type);
+    unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
+    size_t digest_len;
 
-        mbedtls_ssl_session_free(ssl->session);
-        mbedtls_free(ssl->session);
+    if (peer_cert_digest == NULL || digest_info == NULL) {
+        return -1;
     }
-    ssl->session = ssl->session_negotiate;
-    ssl->session_negotiate = NULL;
 
-    /*
-     * Add cache entry
-     */
-    if (ssl->conf->f_set_cache != NULL &&
-        ssl->session->id_len != 0 &&
-        resume == 0) {
-        if (ssl->conf->f_set_cache(ssl->conf->p_cache,
-                                   ssl->session->id,
-                                   ssl->session->id_len,
-                                   ssl->session) != 0) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session"));
-        }
+    digest_len = mbedtls_md_get_size(digest_info);
+    if (digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN) {
+        return -1;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        ssl->handshake->flight != NULL) {
-        /* Cancel handshake timer */
-        mbedtls_ssl_set_timer(ssl, 0);
-
-        /* Keep last flight around in case we need to resend it:
-         * we need the handshake and transform structures for that */
-        MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform"));
-    } else
-#endif
-    mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);
-
-    ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
+    ret = mbedtls_md(digest_info, crt_buf, crt_buf_len, tmp_digest);
+    if (ret != 0) {
+        return -1;
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup"));
+    return memcmp(tmp_digest, peer_cert_digest, digest_len);
 }
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
 
-int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl)
+/*
+ * Once the certificate message is read, parse it into a cert chain and
+ * perform basic checks, but leave actual verification to the caller
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_chain(mbedtls_ssl_context *ssl,
+                                       mbedtls_x509_crt *chain)
 {
-    int ret, hash_len;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+    int crt_cnt = 0;
+#endif
+    size_t i, n;
+    uint8_t alert;
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished"));
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
 
-    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate);
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_CERTIFICATE) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
 
-    ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    if (ssl->in_hslen < mbedtls_ssl_hs_hdr_len(ssl) + 3 + 3) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
+    i = mbedtls_ssl_hs_hdr_len(ssl);
+
     /*
-     * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
-     * may define some other value. Currently (early 2016), no defined
-     * ciphersuite does this (and this is unlikely to change as activity has
-     * moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
+     * Same message structure as in mbedtls_ssl_write_certificate()
      */
-    hash_len = 12;
+    n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1);
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ssl->verify_data_len = hash_len;
-    memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len);
-#endif
+    if (ssl->in_msg[i] != 0 ||
+        ssl->in_hslen != n + 3 + mbedtls_ssl_hs_hdr_len(ssl)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
 
-    ssl->out_msglen  = 4 + hash_len;
-    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
-    ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;
+    /* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
+    i += 3;
 
-    /*
-     * In case of session resuming, invert the client and server
-     * ChangeCipherSpec messages order.
-     */
-    if (ssl->handshake->resume != 0) {
-#if defined(MBEDTLS_SSL_CLI_C)
-        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+    /* Iterate through and parse the CRTs in the provided chain. */
+    while (i < ssl->in_hslen) {
+        /* Check that there's room for the next CRT's length fields. */
+        if (i + 3 > ssl->in_hslen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
+        /* In theory, the CRT can be up to 2**24 Bytes, but we don't support
+         * anything beyond 2**16 ~ 64K. */
+        if (ssl->in_msg[i] != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT);
+            return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
         }
-#endif
-    } else {
-        ssl->state++;
-    }
 
-    /*
-     * Switch to our negotiated transform and session parameters for outbound
-     * data.
-     */
-    MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data"));
+        /* Read length of the next CRT in the chain. */
+        n = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i + 1);
+        i += 3;
+
+        if (n < 128 || i + n > ssl->in_hslen) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate message"));
+            mbedtls_ssl_send_alert_message(ssl,
+                                           MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                           MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+            return MBEDTLS_ERR_SSL_DECODE_ERROR;
+        }
+
+        /* Check if we're handling the first CRT in the chain. */
+#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
+        if (crt_cnt++ == 0 &&
+            ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
+            ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+            /* During client-side renegotiation, check that the server's
+             * end-CRTs hasn't changed compared to the initial handshake,
+             * mitigating the triple handshake attack. On success, reuse
+             * the original end-CRT instead of parsing it again. */
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Check that peer CRT hasn't changed during renegotiation"));
+            if (ssl_check_peer_crt_unchanged(ssl,
+                                             &ssl->in_msg[i],
+                                             n) != 0) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("new server cert during renegotiation"));
+                mbedtls_ssl_send_alert_message(ssl,
+                                               MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                               MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED);
+                return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+            }
+
+            /* Now we can safely free the original chain. */
+            ssl_clear_peer_cert(ssl->session);
+        }
+#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
+
+        /* Parse the next certificate in the chain. */
+#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+        ret = mbedtls_x509_crt_parse_der(chain, ssl->in_msg + i, n);
+#else
+        /* If we don't need to store the CRT chain permanently, parse
+         * it in-place from the input buffer instead of making a copy. */
+        ret = mbedtls_x509_crt_parse_der_nocopy(chain, ssl->in_msg + i, n);
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+        switch (ret) {
+            case 0: /*ok*/
+            case MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + MBEDTLS_ERR_OID_NOT_FOUND:
+                /* Ignore certificate with an unknown algorithm: maybe a
+                   prior certificate was already trusted. */
+                break;
+
+            case MBEDTLS_ERR_X509_ALLOC_FAILED:
+                alert = MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR;
+                goto crt_parse_der_failed;
+
+            case MBEDTLS_ERR_X509_UNKNOWN_VERSION:
+                alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+                goto crt_parse_der_failed;
+
+            default:
+                alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+crt_parse_der_failed:
+                mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, alert);
+                MBEDTLS_SSL_DEBUG_RET(1, " mbedtls_x509_crt_parse_der", ret);
+                return ret;
+        }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        unsigned char i;
+        i += n;
+    }
 
-        /* Remember current epoch settings for resending */
-        ssl->handshake->alt_transform_out = ssl->transform_out;
-        memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,
-               sizeof(ssl->handshake->alt_out_ctr));
+    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", chain);
+    return 0;
+}
 
-        /* Set sequence_number to zero */
-        memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2);
+#if defined(MBEDTLS_SSL_SRV_C)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_srv_check_client_no_crt_notification(mbedtls_ssl_context *ssl)
+{
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        return -1;
+    }
 
+    if (ssl->in_hslen   == 3 + mbedtls_ssl_hs_hdr_len(ssl) &&
+        ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE    &&
+        ssl->in_msg[0]  == MBEDTLS_SSL_HS_CERTIFICATE   &&
+        memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl), "\0\0\0", 3) == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("peer has no certificate"));
+        return 0;
+    }
+    return -1;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
 
-        /* Increment epoch */
-        for (i = 2; i > 0; i--) {
-            if (++ssl->cur_out_ctr[i - 1] != 0) {
-                break;
-            }
+/* Check if a certificate message is expected.
+ * Return either
+ * - SSL_CERTIFICATE_EXPECTED, or
+ * - SSL_CERTIFICATE_SKIP
+ * indicating whether a Certificate message is expected or not.
+ */
+#define SSL_CERTIFICATE_EXPECTED 0
+#define SSL_CERTIFICATE_SKIP     1
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_parse_certificate_coordinate(mbedtls_ssl_context *ssl,
+                                            int authmode)
+{
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        ssl->handshake->ciphersuite_info;
+
+    if (!mbedtls_ssl_ciphersuite_uses_srv_cert(ciphersuite_info)) {
+        return SSL_CERTIFICATE_SKIP;
+    }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+        if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK) {
+            return SSL_CERTIFICATE_SKIP;
         }
 
-        /* The loop goes to its end iff the counter is wrapping */
-        if (i == 0) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap"));
-            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
+        if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+            ssl->session_negotiate->verify_result =
+                MBEDTLS_X509_BADCERT_SKIP_VERIFY;
+            return SSL_CERTIFICATE_SKIP;
         }
-    } else
-#endif /* MBEDTLS_SSL_PROTO_DTLS */
-    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));
+    }
+#else
+    ((void) authmode);
+#endif /* MBEDTLS_SSL_SRV_C */
 
-    ssl->transform_out = ssl->transform_negotiate;
-    ssl->session_out = ssl->session_negotiate;
+    return SSL_CERTIFICATE_EXPECTED;
+}
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        mbedtls_ssl_send_flight_completed(ssl);
-    }
-#endif
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_remember_peer_crt_digest(mbedtls_ssl_context *ssl,
+                                        unsigned char *start, size_t len)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    /* Remember digest of the peer's end-CRT. */
+    ssl->session_negotiate->peer_cert_digest =
+        mbedtls_calloc(1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN);
+    if (ssl->session_negotiate->peer_cert_digest == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%d bytes) failed",
+                                  MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN));
+        mbedtls_ssl_send_alert_message(ssl,
+                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
 
-    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
-        return ret;
+        return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
-        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
-        return ret;
-    }
-#endif
+    ret = mbedtls_md(mbedtls_md_info_from_type(
+                         MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE),
+                     start, len,
+                     ssl->session_negotiate->peer_cert_digest);
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished"));
+    ssl->session_negotiate->peer_cert_digest_type =
+        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
+    ssl->session_negotiate->peer_cert_digest_len =
+        MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
 
-    return 0;
+    return ret;
 }
 
-#define SSL_MAX_HASH_LEN 12
-
-int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_remember_peer_pubkey(mbedtls_ssl_context *ssl,
+                                    unsigned char *start, size_t len)
 {
+    unsigned char *end = start + len;
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    unsigned int hash_len = 12;
-    unsigned char buf[SSL_MAX_HASH_LEN];
-
-    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished"));
 
-    ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);
+    /* Make a copy of the peer's raw public key. */
+    mbedtls_pk_init(&ssl->handshake->peer_pubkey);
+    ret = mbedtls_pk_parse_subpubkey(&start, end,
+                                     &ssl->handshake->peer_pubkey);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+        /* We should have parsed the public key before. */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    return 0;
+}
+#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+
+int mbedtls_ssl_parse_certificate(mbedtls_ssl_context *ssl)
+{
+    int ret = 0;
+    int crt_expected;
+    /* Authmode: precedence order is SNI if used else configuration */
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+                       ? ssl->handshake->sni_authmode
+                       : ssl->conf->authmode;
+#else
+    const int authmode = ssl->conf->authmode;
+#endif
+    void *rs_ctx = NULL;
+    mbedtls_x509_crt *chain = NULL;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate"));
+
+    crt_expected = ssl_parse_certificate_coordinate(ssl, authmode);
+    if (crt_expected == SSL_CERTIFICATE_SKIP) {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip parse certificate"));
+        goto exit;
+    }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled &&
+        ssl->handshake->ecrs_state == ssl_ecrs_crt_verify) {
+        chain = ssl->handshake->ecrs_peer_cert;
+        ssl->handshake->ecrs_peer_cert = NULL;
+        goto crt_verify;
     }
+#endif
 
     if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        /* mbedtls_ssl_read_record may have sent an alert already. We
+           let it decide whether to alert. */
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
         goto exit;
     }
 
-    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
-        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (ssl_srv_check_client_no_crt_notification(ssl) == 0) {
+        ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
+
+        if (authmode != MBEDTLS_SSL_VERIFY_OPTIONAL) {
+            ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
+        }
+
         goto exit;
     }
+#endif /* MBEDTLS_SSL_SRV_C */
 
-    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) {
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
-        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    /* Clear existing peer CRT structure in case we tried to
+     * reuse a session but it failed, and allocate a new one. */
+    ssl_clear_peer_cert(ssl->session_negotiate);
+
+    chain = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+    if (chain == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("alloc(%" MBEDTLS_PRINTF_SIZET " bytes) failed",
+                                  sizeof(mbedtls_x509_crt)));
+        mbedtls_ssl_send_alert_message(ssl,
+                                       MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+
+        ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
         goto exit;
     }
+    mbedtls_x509_crt_init(chain);
 
-    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
-        ret = MBEDTLS_ERR_SSL_DECODE_ERROR;
+    ret = ssl_parse_certificate_chain(ssl, chain);
+    if (ret != 0) {
         goto exit;
     }
 
-    if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl),
-                          buf, hash_len) != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);
-        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-        goto exit;
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ssl->handshake->ecrs_enabled) {
+        ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
     }
 
-#if defined(MBEDTLS_SSL_RENEGOTIATION)
-    ssl->verify_data_len = hash_len;
-    memcpy(ssl->peer_verify_data, buf, hash_len);
+crt_verify:
+    if (ssl->handshake->ecrs_enabled) {
+        rs_ctx = &ssl->handshake->ecrs_ctx;
+    }
 #endif
 
-    if (ssl->handshake->resume != 0) {
-#if defined(MBEDTLS_SSL_CLI_C)
-        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
-        }
-#endif
-#if defined(MBEDTLS_SSL_SRV_C)
-        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+    ret = mbedtls_ssl_verify_certificate(ssl, authmode, chain,
+                                         ssl->handshake->ciphersuite_info,
+                                         rs_ctx);
+    if (ret != 0) {
+        goto exit;
+    }
+
+#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
+    {
+        unsigned char *crt_start, *pk_start;
+        size_t crt_len, pk_len;
+
+        /* We parse the CRT chain without copying, so
+         * these pointers point into the input buffer,
+         * and are hence still valid after freeing the
+         * CRT chain. */
+
+        crt_start = chain->raw.p;
+        crt_len   = chain->raw.len;
+
+        pk_start = chain->pk_raw.p;
+        pk_len   = chain->pk_raw.len;
+
+        /* Free the CRT structures before computing
+         * digest and copying the peer's public key. */
+        mbedtls_x509_crt_free(chain);
+        mbedtls_free(chain);
+        chain = NULL;
+
+        ret = ssl_remember_peer_crt_digest(ssl, crt_start, crt_len);
+        if (ret != 0) {
+            goto exit;
         }
-#endif
-    } else {
-        ssl->state++;
-    }
 
-#if defined(MBEDTLS_SSL_PROTO_DTLS)
-    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-        mbedtls_ssl_recv_flight_completed(ssl);
+        ret = ssl_remember_peer_pubkey(ssl, pk_start, pk_len);
+        if (ret != 0) {
+            goto exit;
+        }
     }
-#endif
+#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
+    /* Pass ownership to session structure. */
+    ssl->session_negotiate->peer_cert = chain;
+    chain = NULL;
+#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 
-    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished"));
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate"));
 
 exit:
-    mbedtls_platform_zeroize(buf, hash_len);
-    return ret;
-}
 
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-/*
- * Helper to get TLS 1.2 PRF from ciphersuite
- * (Duplicates bits of logic from ssl_set_handshake_prfs().)
- */
-static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id)
-{
-    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
-        mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
-        return tls_prf_sha384;
-    } else
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    {
-        if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) {
-            return tls_prf_sha256;
-        }
+    if (ret == 0) {
+        ssl->state++;
+    }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) {
+        ssl->handshake->ecrs_peer_cert = chain;
+        chain = NULL;
     }
-#endif
-#if !defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA) && \
-    !defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    (void) ciphersuite_info;
 #endif
 
-    return NULL;
-}
-#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
+    if (chain != NULL) {
+        mbedtls_x509_crt_free(chain);
+        mbedtls_free(chain);
+    }
 
-static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf)
-{
-    ((void) tls_prf);
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (tls_prf == tls_prf_sha384) {
-        return MBEDTLS_SSL_TLS_PRF_SHA384;
-    } else
-#endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
-    if (tls_prf == tls_prf_sha256) {
-        return MBEDTLS_SSL_TLS_PRF_SHA256;
-    } else
-#endif
-    return MBEDTLS_SSL_TLS_PRF_NONE;
+    return ret;
 }
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
-/*
- * Populate a transform structure with session keys and all the other
- * necessary information.
- *
- * Parameters:
- * - [in/out]: transform: structure to populate
- *      [in] must be just initialised with mbedtls_ssl_transform_init()
- *      [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()
- * - [in] ciphersuite
- * - [in] master
- * - [in] encrypt_then_mac
- * - [in] tls_prf: pointer to PRF to use for key derivation
- * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
- * - [in] tls_version: TLS version
- * - [in] endpoint: client or server
- * - [in] ssl: used for:
- *        - ssl->conf->{f,p}_export_keys
- *      [in] optionally used for:
- *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
- */
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,
-                                        int ciphersuite,
-                                        const unsigned char master[48],
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-                                        int encrypt_then_mac,
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
-                                        ssl_tls_prf_t tls_prf,
-                                        const unsigned char randbytes[64],
-                                        mbedtls_ssl_protocol_version tls_version,
-                                        unsigned endpoint,
-                                        const mbedtls_ssl_context *ssl)
+static int ssl_calc_finished_tls_generic(mbedtls_ssl_context *ssl, void *ctx,
+                                         unsigned char *padbuf, size_t hlen,
+                                         unsigned char *buf, int from)
 {
-    int ret = 0;
-    unsigned char keyblk[256];
-    unsigned char *key1;
-    unsigned char *key2;
-    unsigned char *mac_enc;
-    unsigned char *mac_dec;
-    size_t mac_key_len = 0;
-    size_t iv_copy_len;
-    size_t keylen;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-    mbedtls_ssl_mode_t ssl_mode;
-#if !defined(MBEDTLS_USE_PSA_CRYPTO)
-    const mbedtls_cipher_info_t *cipher_info;
-    const mbedtls_md_info_t *md_info;
-#endif /* !MBEDTLS_USE_PSA_CRYPTO */
-
+    unsigned int len = 12;
+    const char *sender;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_key_type_t key_type;
-    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
-    psa_algorithm_t alg;
-    psa_algorithm_t mac_alg = 0;
-    size_t key_bits;
-    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-#endif
-
-#if !defined(MBEDTLS_DEBUG_C) && \
-    !defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    if (ssl->f_export_keys == NULL) {
-        ssl = NULL; /* make sure we don't use it except for these cases */
-        (void) ssl;
-    }
-#endif
-
-    /*
-     * Some data just needs copying into the structure
-     */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-    transform->encrypt_then_mac = encrypt_then_mac;
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
-    transform->tls_version = tls_version;
-
-#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-    memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes));
+    psa_status_t status;
+    psa_hash_operation_t *hs_op = ctx;
+    psa_hash_operation_t cloned_op = PSA_HASH_OPERATION_INIT;
+    size_t hash_size;
+#else
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    mbedtls_md_context_t *hs_ctx = ctx;
+    mbedtls_md_context_t cloned_ctx;
+    mbedtls_md_init(&cloned_ctx);
 #endif
 
-#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-        /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform
-         * generation separate. This should never happen. */
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-    }
-#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
-
-    /*
-     * Get various info structures
-     */
-    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
-    if (ciphersuite_info == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found",
-                                  ciphersuite));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    mbedtls_ssl_session *session = ssl->session_negotiate;
+    if (!session) {
+        session = ssl->session;
     }
 
-    ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite(
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-        encrypt_then_mac,
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
-        ciphersuite_info);
-
-    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
-        transform->taglen =
-            ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
-    }
+    sender = (from == MBEDTLS_SSL_IS_CLIENT)
+             ? "client finished"
+             : "server finished";
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher,
-                                            transform->taglen,
-                                            &alg,
-                                            &key_type,
-                                            &key_bits)) != PSA_SUCCESS) {
-        ret = PSA_TO_MBEDTLS_ERR(status);
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret);
-        goto end;
-    }
-#else
-    cipher_info = mbedtls_cipher_info_from_type(ciphersuite_info->cipher);
-    if (cipher_info == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found",
-                                  ciphersuite_info->cipher));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc PSA finished tls"));
+
+    status = psa_hash_clone(hs_op, &cloned_op);
+    if (status != PSA_SUCCESS) {
+        goto exit;
     }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    mac_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
-    if (mac_alg == 0) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_hash_info_psa_from_md for %u not found",
-                                  (unsigned) ciphersuite_info->mac));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    status = psa_hash_finish(&cloned_op, padbuf, hlen, &hash_size);
+    if (status != PSA_SUCCESS) {
+        goto exit;
     }
+    MBEDTLS_SSL_DEBUG_BUF(3, "PSA calculated padbuf", padbuf, hlen);
 #else
-    md_info = mbedtls_md_info_from_type(ciphersuite_info->mac);
-    if (md_info == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found",
-                                  (unsigned) ciphersuite_info->mac));
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    /* Copy own and peer's CID if the use of the CID
-     * extension has been negotiated. */
-    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform"));
-
-        transform->in_cid_len = ssl->own_cid_len;
-        memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len);
-        MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid,
-                              transform->in_cid_len);
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> calc finished tls"));
 
-        transform->out_cid_len = ssl->handshake->peer_cid_len;
-        memcpy(transform->out_cid, ssl->handshake->peer_cid,
-               ssl->handshake->peer_cid_len);
-        MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid,
-                              transform->out_cid_len);
+    ret = mbedtls_md_setup(&cloned_ctx, mbedtls_md_info_from_ctx(hs_ctx), 0);
+    if (ret != 0) {
+        goto exit;
     }
-#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
-
-    /*
-     * Compute key block using the PRF
-     */
-    ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256);
+    ret = mbedtls_md_clone(&cloned_ctx, hs_ctx);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
-        return ret;
+        goto exit;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s",
-                              mbedtls_ssl_get_ciphersuite_name(ciphersuite)));
-    MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48);
-    MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64);
-    MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256);
-
-    /*
-     * Determine the appropriate key, IV and MAC length.
-     */
-
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    keylen = PSA_BITS_TO_BYTES(key_bits);
-#else
-    keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
-#endif
+    ret = mbedtls_md_finish(&cloned_ctx, padbuf);
+    if (ret != 0) {
+        goto exit;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_GCM_C) ||                           \
-    defined(MBEDTLS_CCM_C) ||                           \
-    defined(MBEDTLS_CHACHAPOLY_C)
-    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
-        size_t explicit_ivlen;
+    MBEDTLS_SSL_DEBUG_BUF(4, "finished output", padbuf, hlen);
 
-        transform->maclen = 0;
-        mac_key_len = 0;
+    /*
+     * TLSv1.2:
+     *   hash = PRF( master, finished_label,
+     *               Hash( handshake ) )[0.11]
+     */
+    ssl->handshake->tls_prf(session->master, 48, sender,
+                            padbuf, hlen, buf, len);
 
-        /* All modes haves 96-bit IVs, but the length of the static parts vary
-         * with mode and version:
-         * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes
-         *   (to be concatenated with a dynamically chosen IV of 8 Bytes)
-         * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's
-         *   a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record
-         *   sequence number).
-         */
-        transform->ivlen = 12;
+    MBEDTLS_SSL_DEBUG_BUF(3, "calc finished result", buf, len);
 
-        int is_chachapoly = 0;
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20);
-#else
-        is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info)
-                         == MBEDTLS_MODE_CHACHAPOLY);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    mbedtls_platform_zeroize(padbuf, hlen);
 
-        if (is_chachapoly) {
-            transform->fixed_ivlen = 12;
-        } else {
-            transform->fixed_ivlen = 4;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= calc finished"));
 
-        /* Minimum length of encrypted record */
-        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
-        transform->minlen = explicit_ivlen + transform->taglen;
-    } else
-#endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||
-        ssl_mode == MBEDTLS_SSL_MODE_CBC ||
-        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+exit:
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-        size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
+    psa_hash_abort(&cloned_op);
+    return mbedtls_md_error_from_psa(status);
 #else
-        size_t block_size = cipher_info->block_size;
+    mbedtls_md_free(&cloned_ctx);
+    return ret;
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
+}
 
+#if defined(MBEDTLS_MD_CAN_SHA256)
+static int ssl_calc_finished_tls_sha256(
+    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
+{
+    unsigned char padbuf[32];
+    return ssl_calc_finished_tls_generic(ssl,
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-        /* Get MAC length */
-        mac_key_len = PSA_HASH_LENGTH(mac_alg);
+                                         &ssl->handshake->fin_sha256_psa,
 #else
-        /* Initialize HMAC contexts */
-        if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 ||
-            (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
-            goto end;
-        }
+                                         &ssl->handshake->fin_sha256,
+#endif
+                                         padbuf, sizeof(padbuf),
+                                         buf, from);
+}
+#endif /* MBEDTLS_MD_CAN_SHA256*/
 
-        /* Get MAC length */
-        mac_key_len = mbedtls_md_get_size(md_info);
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-        transform->maclen = mac_key_len;
 
-        /* IV length */
+#if defined(MBEDTLS_MD_CAN_SHA384)
+static int ssl_calc_finished_tls_sha384(
+    mbedtls_ssl_context *ssl, unsigned char *buf, int from)
+{
+    unsigned char padbuf[48];
+    return ssl_calc_finished_tls_generic(ssl,
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-        transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg);
+                                         &ssl->handshake->fin_sha384_psa,
 #else
-        transform->ivlen = cipher_info->iv_size;
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
-
-        /* Minimum length */
-        if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
-            transform->minlen = transform->maclen;
-        } else {
-            /*
-             * GenericBlockCipher:
-             * 1. if EtM is in use: one block plus MAC
-             *    otherwise: * first multiple of blocklen greater than maclen
-             * 2. IV
-             */
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-            if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
-                transform->minlen = transform->maclen
-                                    + block_size;
-            } else
+                                         &ssl->handshake->fin_sha384,
 #endif
-            {
-                transform->minlen = transform->maclen
-                                    + block_size
-                                    - transform->maclen % block_size;
-            }
-
-            if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
-                transform->minlen += transform->ivlen;
-            } else {
-                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
-                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-                goto end;
-            }
-        }
-    } else
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
-    {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
-        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-    }
+                                         padbuf, sizeof(padbuf),
+                                         buf, from);
+}
+#endif /* MBEDTLS_MD_CAN_SHA384*/
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u",
-                              (unsigned) keylen,
-                              (unsigned) transform->minlen,
-                              (unsigned) transform->ivlen,
-                              (unsigned) transform->maclen));
+void mbedtls_ssl_handshake_wrapup_free_hs_transform(mbedtls_ssl_context *ssl)
+{
+    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup: final free"));
 
     /*
-     * Finally setup the cipher contexts, IVs and MAC secrets.
+     * Free our handshake params
      */
-#if defined(MBEDTLS_SSL_CLI_C)
-    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        key1 = keyblk + mac_key_len * 2;
-        key2 = keyblk + mac_key_len * 2 + keylen;
-
-        mac_enc = keyblk;
-        mac_dec = keyblk + mac_key_len;
-
-        iv_copy_len = (transform->fixed_ivlen) ?
-                      transform->fixed_ivlen : transform->ivlen;
-        memcpy(transform->iv_enc, key2 + keylen,  iv_copy_len);
-        memcpy(transform->iv_dec, key2 + keylen + iv_copy_len,
-               iv_copy_len);
-    } else
-#endif /* MBEDTLS_SSL_CLI_C */
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
-        key1 = keyblk + mac_key_len * 2 + keylen;
-        key2 = keyblk + mac_key_len * 2;
-
-        mac_enc = keyblk + mac_key_len;
-        mac_dec = keyblk;
-
-        iv_copy_len = (transform->fixed_ivlen) ?
-                      transform->fixed_ivlen : transform->ivlen;
-        memcpy(transform->iv_dec, key1 + keylen,  iv_copy_len);
-        memcpy(transform->iv_enc, key1 + keylen + iv_copy_len,
-               iv_copy_len);
-    } else
-#endif /* MBEDTLS_SSL_SRV_C */
-    {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
-        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        goto end;
-    }
+    mbedtls_ssl_handshake_free(ssl);
+    mbedtls_free(ssl->handshake);
+    ssl->handshake = NULL;
 
-    if (ssl != NULL && ssl->f_export_keys != NULL) {
-        ssl->f_export_keys(ssl->p_export_keys,
-                           MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,
-                           master, 48,
-                           randbytes + 32,
-                           randbytes,
-                           tls_prf_get_type(tls_prf));
+    /*
+     * Free the previous transform and switch in the current one
+     */
+    if (ssl->transform) {
+        mbedtls_ssl_transform_free(ssl->transform);
+        mbedtls_free(ssl->transform);
     }
+    ssl->transform = ssl->transform_negotiate;
+    ssl->transform_negotiate = NULL;
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-    transform->psa_alg = alg;
-
-    if (alg != MBEDTLS_SSL_NULL_CIPHER) {
-        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
-        psa_set_key_algorithm(&attributes, alg);
-        psa_set_key_type(&attributes, key_type);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup: final free"));
+}
 
-        if ((status = psa_import_key(&attributes,
-                                     key1,
-                                     PSA_BITS_TO_BYTES(key_bits),
-                                     &transform->psa_key_enc)) != PSA_SUCCESS) {
-            MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status);
-            ret = PSA_TO_MBEDTLS_ERR(status);
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
-            goto end;
-        }
+void mbedtls_ssl_handshake_wrapup(mbedtls_ssl_context *ssl)
+{
+    int resume = ssl->handshake->resume;
 
-        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("=> handshake wrapup"));
 
-        if ((status = psa_import_key(&attributes,
-                                     key2,
-                                     PSA_BITS_TO_BYTES(key_bits),
-                                     &transform->psa_key_dec)) != PSA_SUCCESS) {
-            ret = PSA_TO_MBEDTLS_ERR(status);
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
-            goto end;
-        }
-    }
-#else
-    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,
-                                    cipher_info)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
-        goto end;
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
+        ssl->renego_status =  MBEDTLS_SSL_RENEGOTIATION_DONE;
+        ssl->renego_records_seen = 0;
     }
+#endif
 
-    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,
-                                    cipher_info)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
-        goto end;
+    /*
+     * Free the previous session and switch in the current one
+     */
+    if (ssl->session) {
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+        /* RFC 7366 3.1: keep the EtM state */
+        ssl->session_negotiate->encrypt_then_mac =
+            ssl->session->encrypt_then_mac;
+#endif
+
+        mbedtls_ssl_session_free(ssl->session);
+        mbedtls_free(ssl->session);
     }
+    ssl->session = ssl->session_negotiate;
+    ssl->session_negotiate = NULL;
 
-    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1,
-                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
-                                     MBEDTLS_ENCRYPT)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
-        goto end;
+    /*
+     * Add cache entry
+     */
+    if (ssl->conf->f_set_cache != NULL &&
+        ssl->session->id_len != 0 &&
+        resume == 0) {
+        if (ssl->conf->f_set_cache(ssl->conf->p_cache,
+                                   ssl->session->id,
+                                   ssl->session->id_len,
+                                   ssl->session) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("cache did not store session"));
+        }
     }
 
-    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2,
-                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
-                                     MBEDTLS_DECRYPT)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
-        goto end;
-    }
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        ssl->handshake->flight != NULL) {
+        /* Cancel handshake timer */
+        mbedtls_ssl_set_timer(ssl, 0);
 
-#if defined(MBEDTLS_CIPHER_MODE_CBC)
-    if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) {
-        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc,
-                                                   MBEDTLS_PADDING_NONE)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
-            goto end;
-        }
+        /* Keep last flight around in case we need to resend it:
+         * we need the handshake and transform structures for that */
+        MBEDTLS_SSL_DEBUG_MSG(3, ("skip freeing handshake and transform"));
+    } else
+#endif
+    mbedtls_ssl_handshake_wrapup_free_hs_transform(ssl);
 
-        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec,
-                                                   MBEDTLS_PADDING_NONE)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
-            goto end;
-        }
-    }
-#endif /* MBEDTLS_CIPHER_MODE_CBC */
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    ssl->state = MBEDTLS_SSL_HANDSHAKE_OVER;
 
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
-    /* For HMAC-based ciphersuites, initialize the HMAC transforms.
-       For AEAD-based ciphersuites, there is nothing to do here. */
-    if (mac_key_len != 0) {
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-        transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg);
+    MBEDTLS_SSL_DEBUG_MSG(3, ("<= handshake wrapup"));
+}
 
-        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
-        psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg));
-        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
+int mbedtls_ssl_write_finished(mbedtls_ssl_context *ssl)
+{
+    int ret;
+    unsigned int hash_len;
 
-        if ((status = psa_import_key(&attributes,
-                                     mac_enc, mac_key_len,
-                                     &transform->psa_mac_enc)) != PSA_SUCCESS) {
-            ret = PSA_TO_MBEDTLS_ERR(status);
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
-            goto end;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> write finished"));
 
-        if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) ||
-            ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING)
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
-             && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED)
+    mbedtls_ssl_update_out_pointers(ssl, ssl->transform_negotiate);
+
+    ret = ssl->handshake->calc_finished(ssl, ssl->out_msg + 4, ssl->conf->endpoint);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
+
+    /*
+     * RFC 5246 7.4.9 (Page 63) says 12 is the default length and ciphersuites
+     * may define some other value. Currently (early 2016), no defined
+     * ciphersuite does this (and this is unlikely to change as activity has
+     * moved to TLS 1.3 now) so we can keep the hardcoded 12 here.
+     */
+    hash_len = 12;
+
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy(ssl->own_verify_data, ssl->out_msg + 4, hash_len);
 #endif
-            )) {
-            /* mbedtls_ct_hmac() requires the key to be exportable */
-            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT |
-                                    PSA_KEY_USAGE_VERIFY_HASH);
-        } else {
-            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
-        }
 
-        if ((status = psa_import_key(&attributes,
-                                     mac_dec, mac_key_len,
-                                     &transform->psa_mac_dec)) != PSA_SUCCESS) {
-            ret = PSA_TO_MBEDTLS_ERR(status);
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
-            goto end;
-        }
-#else
-        ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len);
-        if (ret != 0) {
-            goto end;
+    ssl->out_msglen  = 4 + hash_len;
+    ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
+    ssl->out_msg[0]  = MBEDTLS_SSL_HS_FINISHED;
+
+    /*
+     * In case of session resuming, invert the client and server
+     * ChangeCipherSpec messages order.
+     */
+    if (ssl->handshake->resume != 0) {
+#if defined(MBEDTLS_SSL_CLI_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
         }
-        ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len);
-        if (ret != 0) {
-            goto end;
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
         }
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+#endif
+    } else {
+        ssl->state++;
     }
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
-
-    ((void) mac_dec);
-    ((void) mac_enc);
-
-end:
-    mbedtls_platform_zeroize(keyblk, sizeof(keyblk));
-    return ret;
-}
 
-#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
-    defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_psa_ecjpake_read_round(
-    psa_pake_operation_t *pake_ctx,
-    const unsigned char *buf,
-    size_t len, mbedtls_ecjpake_rounds_t round)
-{
-    psa_status_t status;
-    size_t input_offset = 0;
     /*
-     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
-     * At round two perform a single cycle
+     * Switch to our negotiated transform and session parameters for outbound
+     * data.
      */
-    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
+    MBEDTLS_SSL_DEBUG_MSG(3, ("switching to new transform spec for outbound data"));
 
-    for (; remaining_steps > 0; remaining_steps--) {
-        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
-             step <= PSA_PAKE_STEP_ZK_PROOF;
-             ++step) {
-            /* Length is stored at the first byte */
-            size_t length = buf[input_offset];
-            input_offset += 1;
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        unsigned char i;
 
-            if (input_offset + length > len) {
-                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-            }
+        /* Remember current epoch settings for resending */
+        ssl->handshake->alt_transform_out = ssl->transform_out;
+        memcpy(ssl->handshake->alt_out_ctr, ssl->cur_out_ctr,
+               sizeof(ssl->handshake->alt_out_ctr));
 
-            status = psa_pake_input(pake_ctx, step,
-                                    buf + input_offset, length);
-            if (status != PSA_SUCCESS) {
-                return PSA_TO_MBEDTLS_ERR(status);
-            }
+        /* Set sequence_number to zero */
+        memset(&ssl->cur_out_ctr[2], 0, sizeof(ssl->cur_out_ctr) - 2);
 
-            input_offset += length;
-        }
-    }
 
-    if (input_offset != len) {
-        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-    }
+        /* Increment epoch */
+        for (i = 2; i > 0; i--) {
+            if (++ssl->cur_out_ctr[i - 1] != 0) {
+                break;
+            }
+        }
 
-    return 0;
-}
+        /* The loop goes to its end iff the counter is wrapping */
+        if (i == 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("DTLS epoch would wrap"));
+            return MBEDTLS_ERR_SSL_COUNTER_WRAPPING;
+        }
+    } else
+#endif /* MBEDTLS_SSL_PROTO_DTLS */
+    memset(ssl->cur_out_ctr, 0, sizeof(ssl->cur_out_ctr));
 
-int mbedtls_psa_ecjpake_write_round(
-    psa_pake_operation_t *pake_ctx,
-    unsigned char *buf,
-    size_t len, size_t *olen,
-    mbedtls_ecjpake_rounds_t round)
-{
-    psa_status_t status;
-    size_t output_offset = 0;
-    size_t output_len;
-    /*
-     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
-     * At round two perform a single cycle
-     */
-    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
+    ssl->transform_out = ssl->transform_negotiate;
+    ssl->session_out = ssl->session_negotiate;
 
-    for (; remaining_steps > 0; remaining_steps--) {
-        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
-             step <= PSA_PAKE_STEP_ZK_PROOF;
-             ++step) {
-            /*
-             * For each step, prepend 1 byte with the length of the data as
-             * given by psa_pake_output().
-             */
-            status = psa_pake_output(pake_ctx, step,
-                                     buf + output_offset + 1,
-                                     len - output_offset - 1,
-                                     &output_len);
-            if (status != PSA_SUCCESS) {
-                return PSA_TO_MBEDTLS_ERR(status);
-            }
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_send_flight_completed(ssl);
+    }
+#endif
 
-            *(buf + output_offset) = (uint8_t) output_len;
+    if ((ret = mbedtls_ssl_write_handshake_msg(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_write_handshake_msg", ret);
+        return ret;
+    }
 
-            output_offset += output_len + 1;
-        }
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM &&
+        (ret = mbedtls_ssl_flight_transmit(ssl)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_flight_transmit", ret);
+        return ret;
     }
+#endif
 
-    *olen = output_offset;
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= write finished"));
 
     return 0;
 }
-#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO)
-int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
-                                           unsigned char *hash, size_t *hashlen,
-                                           unsigned char *data, size_t data_len,
-                                           mbedtls_md_type_t md_alg)
+#define SSL_MAX_HASH_LEN 12
+
+int mbedtls_ssl_parse_finished(mbedtls_ssl_context *ssl)
 {
-    psa_status_t status;
-    psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
-    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    unsigned int hash_len = 12;
+    unsigned char buf[SSL_MAX_HASH_LEN];
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished"));
+
+    ret = ssl->handshake->calc_finished(ssl, buf, ssl->conf->endpoint ^ 1);
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "calc_finished", ret);
+    }
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange"));
+    if ((ret = mbedtls_ssl_read_record(ssl, 1)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        goto exit;
+    }
 
-    if ((status = psa_hash_setup(&hash_operation,
-                                 hash_alg)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_setup", status);
+    if (ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
         goto exit;
     }
 
-    if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes,
-                                  64)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
+    if (ssl->in_msg[0] != MBEDTLS_SSL_HS_FINISHED) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE);
+        ret = MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
         goto exit;
     }
 
-    if ((status = psa_hash_update(&hash_operation,
-                                  data, data_len)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
+    if (ssl->in_hslen  != mbedtls_ssl_hs_hdr_len(ssl) + hash_len) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
+        ret = MBEDTLS_ERR_SSL_DECODE_ERROR;
         goto exit;
     }
 
-    if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE,
-                                  hashlen)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_finish", status);
+    if (mbedtls_ct_memcmp(ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl),
+                          buf, hash_len) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad finished message"));
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR);
+        ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         goto exit;
     }
 
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+    ssl->verify_data_len = hash_len;
+    memcpy(ssl->peer_verify_data, buf, hash_len);
+#endif
+
+    if (ssl->handshake->resume != 0) {
+#if defined(MBEDTLS_SSL_CLI_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
+            ssl->state = MBEDTLS_SSL_CLIENT_CHANGE_CIPHER_SPEC;
+        }
+#endif
+#if defined(MBEDTLS_SSL_SRV_C)
+        if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
+            ssl->state = MBEDTLS_SSL_HANDSHAKE_WRAPUP;
+        }
+#endif
+    } else {
+        ssl->state++;
+    }
+
+#if defined(MBEDTLS_SSL_PROTO_DTLS)
+    if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+        mbedtls_ssl_recv_flight_completed(ssl);
+    }
+#endif
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse finished"));
+
 exit:
-    if (status != PSA_SUCCESS) {
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
-        switch (status) {
-            case PSA_ERROR_NOT_SUPPORTED:
-                return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
-            case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */
-            case PSA_ERROR_BUFFER_TOO_SMALL:
-                return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
-            case PSA_ERROR_INSUFFICIENT_MEMORY:
-                return MBEDTLS_ERR_MD_ALLOC_FAILED;
-            default:
-                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
+    mbedtls_platform_zeroize(buf, hash_len);
+    return ret;
+}
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+/*
+ * Helper to get TLS 1.2 PRF from ciphersuite
+ * (Duplicates bits of logic from ssl_set_handshake_prfs().)
+ */
+static tls_prf_fn ssl_tls12prf_from_cs(int ciphersuite_id)
+{
+    const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
+        mbedtls_ssl_ciphersuite_from_id(ciphersuite_id);
+#if defined(MBEDTLS_MD_CAN_SHA384)
+    if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA384) {
+        return tls_prf_sha384;
+    } else
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+    {
+        if (ciphersuite_info != NULL && ciphersuite_info->mac == MBEDTLS_MD_SHA256) {
+            return tls_prf_sha256;
         }
     }
-    return 0;
+#endif
+#if !defined(MBEDTLS_MD_CAN_SHA384) && \
+    !defined(MBEDTLS_MD_CAN_SHA256)
+    (void) ciphersuite_info;
+#endif
+
+    return NULL;
 }
+#endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 
-#else
+static mbedtls_tls_prf_types tls_prf_get_type(mbedtls_ssl_tls_prf_cb *tls_prf)
+{
+    ((void) tls_prf);
+#if defined(MBEDTLS_MD_CAN_SHA384)
+    if (tls_prf == tls_prf_sha384) {
+        return MBEDTLS_SSL_TLS_PRF_SHA384;
+    } else
+#endif
+#if defined(MBEDTLS_MD_CAN_SHA256)
+    if (tls_prf == tls_prf_sha256) {
+        return MBEDTLS_SSL_TLS_PRF_SHA256;
+    } else
+#endif
+    return MBEDTLS_SSL_TLS_PRF_NONE;
+}
 
-int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
-                                           unsigned char *hash, size_t *hashlen,
-                                           unsigned char *data, size_t data_len,
-                                           mbedtls_md_type_t md_alg)
+/*
+ * Populate a transform structure with session keys and all the other
+ * necessary information.
+ *
+ * Parameters:
+ * - [in/out]: transform: structure to populate
+ *      [in] must be just initialised with mbedtls_ssl_transform_init()
+ *      [out] fully populated, ready for use by mbedtls_ssl_{en,de}crypt_buf()
+ * - [in] ciphersuite
+ * - [in] master
+ * - [in] encrypt_then_mac
+ * - [in] tls_prf: pointer to PRF to use for key derivation
+ * - [in] randbytes: buffer holding ServerHello.random + ClientHello.random
+ * - [in] tls_version: TLS version
+ * - [in] endpoint: client or server
+ * - [in] ssl: used for:
+ *        - ssl->conf->{f,p}_export_keys
+ *      [in] optionally used for:
+ *        - MBEDTLS_DEBUG_C: ssl->conf->{f,p}_dbg
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls12_populate_transform(mbedtls_ssl_transform *transform,
+                                        int ciphersuite,
+                                        const unsigned char master[48],
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+                                        int encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+                                        ssl_tls_prf_t tls_prf,
+                                        const unsigned char randbytes[64],
+                                        mbedtls_ssl_protocol_version tls_version,
+                                        unsigned endpoint,
+                                        const mbedtls_ssl_context *ssl)
 {
     int ret = 0;
-    mbedtls_md_context_t ctx;
-    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
-    *hashlen = mbedtls_md_get_size(md_info);
+    unsigned char keyblk[256];
+    unsigned char *key1;
+    unsigned char *key2;
+    unsigned char *mac_enc;
+    unsigned char *mac_dec;
+    size_t mac_key_len = 0;
+    size_t iv_copy_len;
+    size_t keylen;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    mbedtls_ssl_mode_t ssl_mode;
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+    const mbedtls_cipher_info_t *cipher_info;
+    const mbedtls_md_info_t *md_info;
+#endif /* !MBEDTLS_USE_PSA_CRYPTO */
 
-    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform mbedtls-based computation of digest of ServerKeyExchange"));
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    psa_key_type_t key_type;
+    psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
+    psa_algorithm_t alg;
+    psa_algorithm_t mac_alg = 0;
+    size_t key_bits;
+    psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
+#endif
 
-    mbedtls_md_init(&ctx);
+    /*
+     * Some data just needs copying into the structure
+     */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+    transform->encrypt_then_mac = encrypt_then_mac;
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+    transform->tls_version = tls_version;
+
+#if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
+    memcpy(transform->randbytes, randbytes, sizeof(transform->randbytes));
+#endif
+
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
+        /* At the moment, we keep TLS <= 1.2 and TLS 1.3 transform
+         * generation separate. This should never happen. */
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 
     /*
-     * digitally-signed struct {
-     *     opaque client_random[32];
-     *     opaque server_random[32];
-     *     ServerDHParams params;
-     * };
+     * Get various info structures
      */
-    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
-        goto exit;
+    ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
+    if (ciphersuite_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("ciphersuite info for %d not found",
+                                  ciphersuite));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    if ((ret = mbedtls_md_starts(&ctx)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_starts", ret);
-        goto exit;
+
+    ssl_mode = mbedtls_ssl_get_mode_from_ciphersuite(
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+        encrypt_then_mac,
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM */
+        ciphersuite_info);
+
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
+        transform->taglen =
+            ciphersuite_info->flags & MBEDTLS_CIPHERSUITE_SHORT_TAG ? 8 : 16;
     }
-    if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
-        goto exit;
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher,
+                                            transform->taglen,
+                                            &alg,
+                                            &key_type,
+                                            &key_bits)) != PSA_SUCCESS) {
+        ret = PSA_TO_MBEDTLS_ERR(status);
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", ret);
+        goto end;
     }
-    if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
-        goto exit;
+#else
+    cipher_info = mbedtls_cipher_info_from_type((mbedtls_cipher_type_t) ciphersuite_info->cipher);
+    if (cipher_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("cipher info for %u not found",
+                                  ciphersuite_info->cipher));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    mac_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
+    if (mac_alg == 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md_psa_alg_from_type for %u not found",
+                                  (unsigned) ciphersuite_info->mac));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
-    if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
-        goto exit;
+#else
+    md_info = mbedtls_md_info_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
+    if (md_info == NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("mbedtls_md info for %u not found",
+                                  (unsigned) ciphersuite_info->mac));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-exit:
-    mbedtls_md_free(&ctx);
+#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
+    /* Copy own and peer's CID if the use of the CID
+     * extension has been negotiated. */
+    if (ssl->handshake->cid_in_use == MBEDTLS_SSL_CID_ENABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Copy CIDs into SSL transform"));
+
+        transform->in_cid_len = ssl->own_cid_len;
+        memcpy(transform->in_cid, ssl->own_cid, ssl->own_cid_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Incoming CID", transform->in_cid,
+                              transform->in_cid_len);
+
+        transform->out_cid_len = ssl->handshake->peer_cid_len;
+        memcpy(transform->out_cid, ssl->handshake->peer_cid,
+               ssl->handshake->peer_cid_len);
+        MBEDTLS_SSL_DEBUG_BUF(3, "Outgoing CID", transform->out_cid,
+                              transform->out_cid_len);
+    }
+#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 
+    /*
+     * Compute key block using the PRF
+     */
+    ret = tls_prf(master, 48, "key expansion", randbytes, 64, keyblk, 256);
     if (ret != 0) {
-        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
-                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        MBEDTLS_SSL_DEBUG_RET(1, "prf", ret);
+        return ret;
     }
 
-    return ret;
-}
-#endif /* MBEDTLS_USE_PSA_CRYPTO */
+    MBEDTLS_SSL_DEBUG_MSG(3, ("ciphersuite = %s",
+                              mbedtls_ssl_get_ciphersuite_name(ciphersuite)));
+    MBEDTLS_SSL_DEBUG_BUF(3, "master secret", master, 48);
+    MBEDTLS_SSL_DEBUG_BUF(4, "random bytes", randbytes, 64);
+    MBEDTLS_SSL_DEBUG_BUF(4, "key block", keyblk, 256);
 
-#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
+    /*
+     * Determine the appropriate key, IV and MAC length.
+     */
 
-/* Find the preferred hash for a given signature algorithm. */
-unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
-    mbedtls_ssl_context *ssl,
-    unsigned int sig_alg)
-{
-    unsigned int i;
-    uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    keylen = PSA_BITS_TO_BYTES(key_bits);
+#else
+    keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
+#endif
 
-    if (sig_alg == MBEDTLS_SSL_SIG_ANON) {
-        return MBEDTLS_SSL_HASH_NONE;
-    }
+#if defined(MBEDTLS_SSL_HAVE_AEAD)
+    if (ssl_mode == MBEDTLS_SSL_MODE_AEAD) {
+        size_t explicit_ivlen;
 
-    for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
-        unsigned int hash_alg_received =
-            MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(
-                received_sig_algs[i]);
-        unsigned int sig_alg_received =
-            MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(
-                received_sig_algs[i]);
+        transform->maclen = 0;
+        mac_key_len = 0;
 
-        if (sig_alg == sig_alg_received) {
+        /* All modes haves 96-bit IVs, but the length of the static parts vary
+         * with mode and version:
+         * - For GCM and CCM in TLS 1.2, there's a static IV of 4 Bytes
+         *   (to be concatenated with a dynamically chosen IV of 8 Bytes)
+         * - For ChaChaPoly in TLS 1.2, and all modes in TLS 1.3, there's
+         *   a static IV of 12 Bytes (to be XOR'ed with the 8 Byte record
+         *   sequence number).
+         */
+        transform->ivlen = 12;
+
+        int is_chachapoly = 0;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-            if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) {
-                psa_algorithm_t psa_hash_alg =
-                    mbedtls_hash_info_psa_from_md(hash_alg_received);
+        is_chachapoly = (key_type == PSA_KEY_TYPE_CHACHA20);
+#else
+        is_chachapoly = (mbedtls_cipher_info_get_mode(cipher_info)
+                         == MBEDTLS_MODE_CHACHAPOLY);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-                if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA &&
-                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
-                                           PSA_ALG_ECDSA(psa_hash_alg),
-                                           PSA_KEY_USAGE_SIGN_HASH)) {
-                    continue;
-                }
+        if (is_chachapoly) {
+            transform->fixed_ivlen = 12;
+        } else {
+            transform->fixed_ivlen = 4;
+        }
 
-                if (sig_alg_received == MBEDTLS_SSL_SIG_RSA &&
-                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
-                                           PSA_ALG_RSA_PKCS1V15_SIGN(
-                                               psa_hash_alg),
-                                           PSA_KEY_USAGE_SIGN_HASH)) {
-                    continue;
-                }
-            }
+        /* Minimum length of encrypted record */
+        explicit_ivlen = transform->ivlen - transform->fixed_ivlen;
+        transform->minlen = explicit_ivlen + transform->taglen;
+    } else
+#endif /* MBEDTLS_SSL_HAVE_AEAD */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    if (ssl_mode == MBEDTLS_SSL_MODE_STREAM ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC ||
+        ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        size_t block_size = PSA_BLOCK_CIPHER_BLOCK_LENGTH(key_type);
+#else
+        size_t block_size = mbedtls_cipher_info_get_block_size(cipher_info);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-            return hash_alg_received;
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        /* Get MAC length */
+        mac_key_len = PSA_HASH_LENGTH(mac_alg);
+#else
+        /* Initialize HMAC contexts */
+        if ((ret = mbedtls_md_setup(&transform->md_ctx_enc, md_info, 1)) != 0 ||
+            (ret = mbedtls_md_setup(&transform->md_ctx_dec, md_info, 1)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
+            goto end;
         }
-    }
-
-    return MBEDTLS_SSL_HASH_NONE;
-}
 
-#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+        /* Get MAC length */
+        mac_key_len = mbedtls_md_get_size(md_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+        transform->maclen = mac_key_len;
 
-/* Serialization of TLS 1.2 sessions:
- *
- * struct {
- *    uint64 start_time;
- *    uint8 ciphersuite[2];           // defined by the standard
- *    uint8 session_id_len;           // at most 32
- *    opaque session_id[32];
- *    opaque master[48];              // fixed length in the standard
- *    uint32 verify_result;
- *    opaque peer_cert<0..2^24-1>;    // length 0 means no peer cert
- *    opaque ticket<0..2^24-1>;       // length 0 means no ticket
- *    uint32 ticket_lifetime;
- *    uint8 mfl_code;                 // up to 255 according to standard
- *    uint8 encrypt_then_mac;         // 0 or 1
- * } serialized_session_tls12;
- *
- */
-static size_t ssl_tls12_session_save(const mbedtls_ssl_session *session,
-                                     unsigned char *buf,
-                                     size_t buf_len)
-{
-    unsigned char *p = buf;
-    size_t used = 0;
+        /* IV length */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        transform->ivlen = PSA_CIPHER_IV_LENGTH(key_type, alg);
+#else
+        transform->ivlen = mbedtls_cipher_info_get_iv_size(cipher_info);
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#if defined(MBEDTLS_HAVE_TIME)
-    uint64_t start;
+        /* Minimum length */
+        if (ssl_mode == MBEDTLS_SSL_MODE_STREAM) {
+            transform->minlen = transform->maclen;
+        } else {
+            /*
+             * GenericBlockCipher:
+             * 1. if EtM is in use: one block plus MAC
+             *    otherwise: * first multiple of blocklen greater than maclen
+             * 2. IV
+             */
+#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
+            if (ssl_mode == MBEDTLS_SSL_MODE_CBC_ETM) {
+                transform->minlen = transform->maclen
+                                    + block_size;
+            } else
 #endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+            {
+                transform->minlen = transform->maclen
+                                    + block_size
+                                    - transform->maclen % block_size;
+            }
+
+            if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2) {
+                transform->minlen += transform->ivlen;
+            } else {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+                ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+                goto end;
+            }
+        }
+    } else
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("keylen: %u, minlen: %u, ivlen: %u, maclen: %u",
+                              (unsigned) keylen,
+                              (unsigned) transform->minlen,
+                              (unsigned) transform->ivlen,
+                              (unsigned) transform->maclen));
 
     /*
-     * Time
+     * Finally setup the cipher contexts, IVs and MAC secrets.
      */
-#if defined(MBEDTLS_HAVE_TIME)
-    used += 8;
+#if defined(MBEDTLS_SSL_CLI_C)
+    if (endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        key1 = keyblk + mac_key_len * 2;
+        key2 = keyblk + mac_key_len * 2 + keylen;
 
-    if (used <= buf_len) {
-        start = (uint64_t) session->start;
+        mac_enc = keyblk;
+        mac_dec = keyblk + mac_key_len;
+
+        iv_copy_len = (transform->fixed_ivlen) ?
+                      transform->fixed_ivlen : transform->ivlen;
+        memcpy(transform->iv_enc, key2 + keylen,  iv_copy_len);
+        memcpy(transform->iv_dec, key2 + keylen + iv_copy_len,
+               iv_copy_len);
+    } else
+#endif /* MBEDTLS_SSL_CLI_C */
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (endpoint == MBEDTLS_SSL_IS_SERVER) {
+        key1 = keyblk + mac_key_len * 2 + keylen;
+        key2 = keyblk + mac_key_len * 2;
+
+        mac_enc = keyblk + mac_key_len;
+        mac_dec = keyblk;
+
+        iv_copy_len = (transform->fixed_ivlen) ?
+                      transform->fixed_ivlen : transform->ivlen;
+        memcpy(transform->iv_dec, key1 + keylen,  iv_copy_len);
+        memcpy(transform->iv_enc, key1 + keylen + iv_copy_len,
+               iv_copy_len);
+    } else
+#endif /* MBEDTLS_SSL_SRV_C */
+    {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto end;
+    }
 
-        MBEDTLS_PUT_UINT64_BE(start, p, 0);
-        p += 8;
+    if (ssl->f_export_keys != NULL) {
+        ssl->f_export_keys(ssl->p_export_keys,
+                           MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET,
+                           master, 48,
+                           randbytes + 32,
+                           randbytes,
+                           tls_prf_get_type(tls_prf));
     }
-#endif /* MBEDTLS_HAVE_TIME */
 
-    /*
-     * Basic mandatory fields
-     */
-    used += 2   /* ciphersuite */
-            + 1 /* id_len */
-            + sizeof(session->id)
-            + sizeof(session->master)
-            + 4; /* verify_result */
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    transform->psa_alg = alg;
 
-    if (used <= buf_len) {
-        MBEDTLS_PUT_UINT16_BE(session->ciphersuite, p, 0);
-        p += 2;
+    if (alg != MBEDTLS_SSL_NULL_CIPHER) {
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT);
+        psa_set_key_algorithm(&attributes, alg);
+        psa_set_key_type(&attributes, key_type);
 
-        *p++ = MBEDTLS_BYTE_0(session->id_len);
-        memcpy(p, session->id, 32);
-        p += 32;
+        if ((status = psa_import_key(&attributes,
+                                     key1,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_enc)) != PSA_SUCCESS) {
+            MBEDTLS_SSL_DEBUG_RET(3, "psa_import_key", (int) status);
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
+            goto end;
+        }
 
-        memcpy(p, session->master, 48);
-        p += 48;
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_DECRYPT);
 
-        MBEDTLS_PUT_UINT32_BE(session->verify_result, p, 0);
-        p += 4;
+        if ((status = psa_import_key(&attributes,
+                                     key2,
+                                     PSA_BITS_TO_BYTES(key_bits),
+                                     &transform->psa_key_dec)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", ret);
+            goto end;
+        }
     }
-
-    /*
-     * Peer's end-entity certificate
-     */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    if (session->peer_cert == NULL) {
-        cert_len = 0;
-    } else {
-        cert_len = session->peer_cert->raw.len;
+#else
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_enc,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        goto end;
     }
 
-    used += 3 + cert_len;
+    if ((ret = mbedtls_cipher_setup(&transform->cipher_ctx_dec,
+                                    cipher_info)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setup", ret);
+        goto end;
+    }
 
-    if (used <= buf_len) {
-        *p++ = MBEDTLS_BYTE_2(cert_len);
-        *p++ = MBEDTLS_BYTE_1(cert_len);
-        *p++ = MBEDTLS_BYTE_0(cert_len);
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc, key1,
+                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
+                                     MBEDTLS_ENCRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        goto end;
+    }
 
-        if (session->peer_cert != NULL) {
-            memcpy(p, session->peer_cert->raw.p, cert_len);
-            p += cert_len;
-        }
+    if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec, key2,
+                                     (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
+                                     MBEDTLS_DECRYPT)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
+        goto end;
     }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    if (session->peer_cert_digest != NULL) {
-        used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
-        if (used <= buf_len) {
-            *p++ = (unsigned char) session->peer_cert_digest_type;
-            *p++ = (unsigned char) session->peer_cert_digest_len;
-            memcpy(p, session->peer_cert_digest,
-                   session->peer_cert_digest_len);
-            p += session->peer_cert_digest_len;
+
+#if defined(MBEDTLS_CIPHER_MODE_CBC)
+    if (mbedtls_cipher_info_get_mode(cipher_info) == MBEDTLS_MODE_CBC) {
+        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_enc,
+                                                   MBEDTLS_PADDING_NONE)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
+            goto end;
         }
-    } else {
-        used += 2;
-        if (used <= buf_len) {
-            *p++ = (unsigned char) MBEDTLS_MD_NONE;
-            *p++ = 0;
+
+        if ((ret = mbedtls_cipher_set_padding_mode(&transform->cipher_ctx_dec,
+                                                   MBEDTLS_PADDING_NONE)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_set_padding_mode", ret);
+            goto end;
         }
     }
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#endif /* MBEDTLS_CIPHER_MODE_CBC */
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    /*
-     * Session ticket if any, plus associated data
-     */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    used += 3 + session->ticket_len + 4; /* len + ticket + lifetime */
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
+    /* For HMAC-based ciphersuites, initialize the HMAC transforms.
+       For AEAD-based ciphersuites, there is nothing to do here. */
+    if (mac_key_len != 0) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+        transform->psa_mac_alg = PSA_ALG_HMAC(mac_alg);
 
-    if (used <= buf_len) {
-        *p++ = MBEDTLS_BYTE_2(session->ticket_len);
-        *p++ = MBEDTLS_BYTE_1(session->ticket_len);
-        *p++ = MBEDTLS_BYTE_0(session->ticket_len);
+        psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE);
+        psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(mac_alg));
+        psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
 
-        if (session->ticket != NULL) {
-            memcpy(p, session->ticket, session->ticket_len);
-            p += session->ticket_len;
+        if ((status = psa_import_key(&attributes,
+                                     mac_enc, mac_key_len,
+                                     &transform->psa_mac_enc)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
+            goto end;
         }
 
-        MBEDTLS_PUT_UINT32_BE(session->ticket_lifetime, p, 0);
-        p += 4;
-    }
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
-
-    /*
-     * Misc extension-related info
-     */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    used += 1;
-
-    if (used <= buf_len) {
-        *p++ = session->mfl_code;
-    }
+        if ((transform->psa_alg == MBEDTLS_SSL_NULL_CIPHER) ||
+            ((transform->psa_alg == PSA_ALG_CBC_NO_PADDING)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_CBC_ETM)
+             && (transform->encrypt_then_mac == MBEDTLS_SSL_ETM_DISABLED)
 #endif
+            )) {
+            /* mbedtls_ct_hmac() requires the key to be exportable */
+            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_EXPORT |
+                                    PSA_KEY_USAGE_VERIFY_HASH);
+        } else {
+            psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_HASH);
+        }
 
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    used += 1;
-
-    if (used <= buf_len) {
-        *p++ = MBEDTLS_BYTE_0(session->encrypt_then_mac);
+        if ((status = psa_import_key(&attributes,
+                                     mac_dec, mac_key_len,
+                                     &transform->psa_mac_dec)) != PSA_SUCCESS) {
+            ret = PSA_TO_MBEDTLS_ERR(status);
+            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_mac_key", ret);
+            goto end;
+        }
+#else
+        ret = mbedtls_md_hmac_starts(&transform->md_ctx_enc, mac_enc, mac_key_len);
+        if (ret != 0) {
+            goto end;
+        }
+        ret = mbedtls_md_hmac_starts(&transform->md_ctx_dec, mac_dec, mac_key_len);
+        if (ret != 0) {
+            goto end;
+        }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
     }
-#endif
+#endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
 
-    return used;
+    ((void) mac_dec);
+    ((void) mac_enc);
+
+end:
+    mbedtls_platform_zeroize(keyblk, sizeof(keyblk));
+    return ret;
 }
 
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls12_session_load(mbedtls_ssl_session *session,
-                                  const unsigned char *buf,
-                                  size_t len)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \
+    defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_psa_ecjpake_read_round(
+    psa_pake_operation_t *pake_ctx,
+    const unsigned char *buf,
+    size_t len, mbedtls_ecjpake_rounds_t round)
 {
-#if defined(MBEDTLS_HAVE_TIME)
-    uint64_t start;
-#endif
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    size_t cert_len;
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-
-    const unsigned char *p = buf;
-    const unsigned char * const end = buf + len;
-
+    psa_status_t status;
+    size_t input_offset = 0;
     /*
-     * Time
+     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
+     * At round two perform a single cycle
      */
-#if defined(MBEDTLS_HAVE_TIME)
-    if (8 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
-
-    start = ((uint64_t) p[0] << 56) |
-            ((uint64_t) p[1] << 48) |
-            ((uint64_t) p[2] << 40) |
-            ((uint64_t) p[3] << 32) |
-            ((uint64_t) p[4] << 24) |
-            ((uint64_t) p[5] << 16) |
-            ((uint64_t) p[6] <<  8) |
-            ((uint64_t) p[7]);
-    p += 8;
-
-    session->start = (time_t) start;
-#endif /* MBEDTLS_HAVE_TIME */
+    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
 
-    /*
-     * Basic mandatory fields
-     */
-    if (2 + 1 + 32 + 48 + 4 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+    for (; remaining_steps > 0; remaining_steps--) {
+        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
+             step <= PSA_PAKE_STEP_ZK_PROOF;
+             ++step) {
+            /* Length is stored at the first byte */
+            size_t length = buf[input_offset];
+            input_offset += 1;
 
-    session->ciphersuite = (p[0] << 8) | p[1];
-    p += 2;
+            if (input_offset + length > len) {
+                return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+            }
 
-    session->id_len = *p++;
-    memcpy(session->id, p, 32);
-    p += 32;
+            status = psa_pake_input(pake_ctx, step,
+                                    buf + input_offset, length);
+            if (status != PSA_SUCCESS) {
+                return PSA_TO_MBEDTLS_ERR(status);
+            }
 
-    memcpy(session->master, p, 48);
-    p += 48;
+            input_offset += length;
+        }
+    }
 
-    session->verify_result = ((uint32_t) p[0] << 24) |
-                             ((uint32_t) p[1] << 16) |
-                             ((uint32_t) p[2] <<  8) |
-                             ((uint32_t) p[3]);
-    p += 4;
+    if (input_offset != len) {
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
 
-    /* Immediately clear invalid pointer values that have been read, in case
-     * we exit early before we replaced them with valid ones. */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    session->peer_cert = NULL;
-#else
-    session->peer_cert_digest = NULL;
-#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    session->ticket = NULL;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+    return 0;
+}
 
+int mbedtls_psa_ecjpake_write_round(
+    psa_pake_operation_t *pake_ctx,
+    unsigned char *buf,
+    size_t len, size_t *olen,
+    mbedtls_ecjpake_rounds_t round)
+{
+    psa_status_t status;
+    size_t output_offset = 0;
+    size_t output_len;
     /*
-     * Peer certificate
+     * At round one repeat the KEY_SHARE, ZK_PUBLIC & ZF_PROOF twice
+     * At round two perform a single cycle
      */
-#if defined(MBEDTLS_X509_CRT_PARSE_C)
-#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    /* Deserialize CRT from the end of the ticket. */
-    if (3 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+    unsigned int remaining_steps = (round == MBEDTLS_ECJPAKE_ROUND_ONE) ? 2 : 1;
 
-    cert_len = (p[0] << 16) | (p[1] << 8) | p[2];
-    p += 3;
+    for (; remaining_steps > 0; remaining_steps--) {
+        for (psa_pake_step_t step = PSA_PAKE_STEP_KEY_SHARE;
+             step <= PSA_PAKE_STEP_ZK_PROOF;
+             ++step) {
+            /*
+             * For each step, prepend 1 byte with the length of the data as
+             * given by psa_pake_output().
+             */
+            status = psa_pake_output(pake_ctx, step,
+                                     buf + output_offset + 1,
+                                     len - output_offset - 1,
+                                     &output_len);
+            if (status != PSA_SUCCESS) {
+                return PSA_TO_MBEDTLS_ERR(status);
+            }
 
-    if (cert_len != 0) {
-        int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+            *(buf + output_offset) = (uint8_t) output_len;
 
-        if (cert_len > (size_t) (end - p)) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+            output_offset += output_len + 1;
         }
+    }
 
-        session->peer_cert = mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
+    *olen = output_offset;
 
-        if (session->peer_cert == NULL) {
-            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        }
+    return 0;
+}
+#endif //MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO
 
-        mbedtls_x509_crt_init(session->peer_cert);
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
+                                           unsigned char *hash, size_t *hashlen,
+                                           unsigned char *data, size_t data_len,
+                                           mbedtls_md_type_t md_alg)
+{
+    psa_status_t status;
+    psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
+    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(md_alg);
 
-        if ((ret = mbedtls_x509_crt_parse_der(session->peer_cert,
-                                              p, cert_len)) != 0) {
-            mbedtls_x509_crt_free(session->peer_cert);
-            mbedtls_free(session->peer_cert);
-            session->peer_cert = NULL;
-            return ret;
-        }
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform PSA-based computation of digest of ServerKeyExchange"));
 
-        p += cert_len;
+    if ((status = psa_hash_setup(&hash_operation,
+                                 hash_alg)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_setup", status);
+        goto exit;
     }
-#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-    /* Deserialize CRT digest from the end of the ticket. */
-    if (2 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+
+    if ((status = psa_hash_update(&hash_operation, ssl->handshake->randbytes,
+                                  64)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
+        goto exit;
     }
 
-    session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
-    session->peer_cert_digest_len  = (size_t) *p++;
+    if ((status = psa_hash_update(&hash_operation,
+                                  data, data_len)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_update", status);
+        goto exit;
+    }
 
-    if (session->peer_cert_digest_len != 0) {
-        const mbedtls_md_info_t *md_info =
-            mbedtls_md_info_from_type(session->peer_cert_digest_type);
-        if (md_info == NULL) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
-        if (session->peer_cert_digest_len != mbedtls_md_get_size(md_info)) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    if ((status = psa_hash_finish(&hash_operation, hash, PSA_HASH_MAX_SIZE,
+                                  hashlen)) != PSA_SUCCESS) {
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_hash_finish", status);
+        goto exit;
+    }
 
-        if (session->peer_cert_digest_len > (size_t) (end - p)) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+exit:
+    if (status != PSA_SUCCESS) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+        switch (status) {
+            case PSA_ERROR_NOT_SUPPORTED:
+                return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE;
+            case PSA_ERROR_BAD_STATE: /* Intentional fallthrough */
+            case PSA_ERROR_BUFFER_TOO_SMALL:
+                return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
+            case PSA_ERROR_INSUFFICIENT_MEMORY:
+                return MBEDTLS_ERR_MD_ALLOC_FAILED;
+            default:
+                return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
         }
+    }
+    return 0;
+}
 
-        session->peer_cert_digest =
-            mbedtls_calloc(1, session->peer_cert_digest_len);
-        if (session->peer_cert_digest == NULL) {
-            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        }
+#else
 
-        memcpy(session->peer_cert_digest, p,
-               session->peer_cert_digest_len);
-        p += session->peer_cert_digest_len;
-    }
-#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
-#endif /* MBEDTLS_X509_CRT_PARSE_C */
+int mbedtls_ssl_get_key_exchange_md_tls1_2(mbedtls_ssl_context *ssl,
+                                           unsigned char *hash, size_t *hashlen,
+                                           unsigned char *data, size_t data_len,
+                                           mbedtls_md_type_t md_alg)
+{
+    int ret = 0;
+    mbedtls_md_context_t ctx;
+    const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
+    *hashlen = mbedtls_md_get_size(md_info);
+
+    MBEDTLS_SSL_DEBUG_MSG(3, ("Perform mbedtls-based computation of digest of ServerKeyExchange"));
+
+    mbedtls_md_init(&ctx);
 
     /*
-     * Session ticket and associated data
+     * digitally-signed struct {
+     *     opaque client_random[32];
+     *     opaque server_random[32];
+     *     ServerDHParams params;
+     * };
      */
-#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
-    if (3 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    if ((ret = mbedtls_md_setup(&ctx, md_info, 0)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_setup", ret);
+        goto exit;
+    }
+    if ((ret = mbedtls_md_starts(&ctx)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_starts", ret);
+        goto exit;
+    }
+    if ((ret = mbedtls_md_update(&ctx, ssl->handshake->randbytes, 64)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
+        goto exit;
+    }
+    if ((ret = mbedtls_md_update(&ctx, data, data_len)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_update", ret);
+        goto exit;
+    }
+    if ((ret = mbedtls_md_finish(&ctx, hash)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_md_finish", ret);
+        goto exit;
     }
 
-    session->ticket_len = (p[0] << 16) | (p[1] << 8) | p[2];
-    p += 3;
+exit:
+    mbedtls_md_free(&ctx);
 
-    if (session->ticket_len != 0) {
-        if (session->ticket_len > (size_t) (end - p)) {
-            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-        }
+    if (ret != 0) {
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR);
+    }
 
-        session->ticket = mbedtls_calloc(1, session->ticket_len);
-        if (session->ticket == NULL) {
-            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
-        }
+    return ret;
+}
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-        memcpy(session->ticket, p, session->ticket_len);
-        p += session->ticket_len;
-    }
+#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED)
 
-    if (4 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+/* Find the preferred hash for a given signature algorithm. */
+unsigned int mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+    mbedtls_ssl_context *ssl,
+    unsigned int sig_alg)
+{
+    unsigned int i;
+    uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;
+
+    if (sig_alg == MBEDTLS_SSL_SIG_ANON) {
+        return MBEDTLS_SSL_HASH_NONE;
     }
 
-    session->ticket_lifetime = ((uint32_t) p[0] << 24) |
-                               ((uint32_t) p[1] << 16) |
-                               ((uint32_t) p[2] <<  8) |
-                               ((uint32_t) p[3]);
-    p += 4;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
+    for (i = 0; received_sig_algs[i] != MBEDTLS_TLS_SIG_NONE; i++) {
+        unsigned int hash_alg_received =
+            MBEDTLS_SSL_TLS12_HASH_ALG_FROM_SIG_AND_HASH_ALG(
+                received_sig_algs[i]);
+        unsigned int sig_alg_received =
+            MBEDTLS_SSL_TLS12_SIG_ALG_FROM_SIG_AND_HASH_ALG(
+                received_sig_algs[i]);
 
-    /*
-     * Misc extension-related info
-     */
-#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    if (1 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+        mbedtls_md_type_t md_alg =
+            mbedtls_ssl_md_alg_from_hash((unsigned char) hash_alg_received);
+        if (md_alg == MBEDTLS_MD_NONE) {
+            continue;
+        }
 
-    session->mfl_code = *p++;
-#endif
+        if (sig_alg == sig_alg_received) {
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+            if (ssl->handshake->key_cert && ssl->handshake->key_cert->key) {
+                psa_algorithm_t psa_hash_alg =
+                    mbedtls_md_psa_alg_from_type(md_alg);
 
-#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    if (1 > (size_t) (end - p)) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
-    }
+                if (sig_alg_received == MBEDTLS_SSL_SIG_ECDSA &&
+                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
+                                           PSA_ALG_ECDSA(psa_hash_alg),
+                                           PSA_KEY_USAGE_SIGN_HASH)) {
+                    continue;
+                }
 
-    session->encrypt_then_mac = *p++;
-#endif
+                if (sig_alg_received == MBEDTLS_SSL_SIG_RSA &&
+                    !mbedtls_pk_can_do_ext(ssl->handshake->key_cert->key,
+                                           PSA_ALG_RSA_PKCS1V15_SIGN(
+                                               psa_hash_alg),
+                                           PSA_KEY_USAGE_SIGN_HASH)) {
+                    continue;
+                }
+            }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-    /* Done, should have consumed entire buffer */
-    if (p != end) {
-        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+            return hash_alg_received;
+        }
     }
 
-    return 0;
+    return MBEDTLS_SSL_HASH_NONE;
 }
+
+#endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
+
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 
 int mbedtls_ssl_validate_ciphersuite(
@@ -9429,7 +9402,7 @@ int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,
     }
 
     /* Length of supported_signature_algorithms */
-    supported_sig_alg_len = p - supported_sig_alg;
+    supported_sig_alg_len = (size_t) (p - supported_sig_alg);
     if (supported_sig_alg_len == 0) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("No signature algorithms defined."));
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
@@ -9439,7 +9412,7 @@ int mbedtls_ssl_write_sig_alg_ext(mbedtls_ssl_context *ssl, unsigned char *buf,
     MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len + 2, buf, 2);
     MBEDTLS_PUT_UINT16_BE(supported_sig_alg_len, buf, 4);
 
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
 
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
     mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_SIG_ALG);
@@ -9668,9 +9641,8 @@ int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
     /* Now it's clear that we will overwrite the old hostname,
      * so we can free it safely */
     if (session->hostname != NULL) {
-        mbedtls_platform_zeroize(session->hostname,
+        mbedtls_zeroize_and_free(session->hostname,
                                  strlen(session->hostname));
-        mbedtls_free(session->hostname);
     }
 
     /* Passing NULL as hostname shall clear the old one */
@@ -9692,4 +9664,306 @@ int mbedtls_ssl_session_set_hostname(mbedtls_ssl_session *session,
           MBEDTLS_SSL_SERVER_NAME_INDICATION &&
           MBEDTLS_SSL_CLI_C */
 
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_EARLY_DATA) && \
+    defined(MBEDTLS_SSL_ALPN)
+int mbedtls_ssl_session_set_ticket_alpn(mbedtls_ssl_session *session,
+                                        const char *alpn)
+{
+    size_t alpn_len = 0;
+
+    if (alpn != NULL) {
+        alpn_len = strlen(alpn);
+
+        if (alpn_len > MBEDTLS_SSL_MAX_ALPN_NAME_LEN) {
+            return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+        }
+    }
+
+    if (session->ticket_alpn != NULL) {
+        mbedtls_zeroize_and_free(session->ticket_alpn,
+                                 strlen(session->ticket_alpn));
+        session->ticket_alpn = NULL;
+    }
+
+    if (alpn != NULL) {
+        session->ticket_alpn = mbedtls_calloc(alpn_len + 1, 1);
+        if (session->ticket_alpn == NULL) {
+            return MBEDTLS_ERR_SSL_ALLOC_FAILED;
+        }
+        memcpy(session->ticket_alpn, alpn, alpn_len);
+    }
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_EARLY_DATA && MBEDTLS_SSL_ALPN */
+
+/*
+ * The following functions are used by 1.2 and 1.3, client and server.
+ */
+#if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED)
+int mbedtls_ssl_check_cert_usage(const mbedtls_x509_crt *cert,
+                                 const mbedtls_ssl_ciphersuite_t *ciphersuite,
+                                 int recv_endpoint,
+                                 mbedtls_ssl_protocol_version tls_version,
+                                 uint32_t *flags)
+{
+    int ret = 0;
+    unsigned int usage = 0;
+    const char *ext_oid;
+    size_t ext_len;
+
+    /*
+     * keyUsage
+     */
+
+    /* Note: don't guard this with MBEDTLS_SSL_CLI_C because the server wants
+     * to check what a compliant client will think while choosing which cert
+     * to send to the client. */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
+    if (tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+        recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        /* TLS 1.2 server part of the key exchange */
+        switch (ciphersuite->key_exchange) {
+            case MBEDTLS_KEY_EXCHANGE_RSA:
+            case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
+                usage = MBEDTLS_X509_KU_KEY_ENCIPHERMENT;
+                break;
+
+            case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
+            case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
+            case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
+                usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
+                break;
+
+            case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
+            case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
+                usage = MBEDTLS_X509_KU_KEY_AGREEMENT;
+                break;
+
+            /* Don't use default: we want warnings when adding new values */
+            case MBEDTLS_KEY_EXCHANGE_NONE:
+            case MBEDTLS_KEY_EXCHANGE_PSK:
+            case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
+            case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
+            case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
+                usage = 0;
+        }
+    } else
+#endif
+    {
+        /* This is either TLS 1.3 authentication, which always uses signatures,
+         * or 1.2 client auth: rsa_sign and mbedtls_ecdsa_sign are the only
+         * options we implement, both using signatures. */
+        (void) tls_version;
+        (void) ciphersuite;
+        usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE;
+    }
+
+    if (mbedtls_x509_crt_check_key_usage(cert, usage) != 0) {
+        *flags |= MBEDTLS_X509_BADCERT_KEY_USAGE;
+        ret = -1;
+    }
+
+    /*
+     * extKeyUsage
+     */
+
+    if (recv_endpoint == MBEDTLS_SSL_IS_CLIENT) {
+        ext_oid = MBEDTLS_OID_SERVER_AUTH;
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
+    } else {
+        ext_oid = MBEDTLS_OID_CLIENT_AUTH;
+        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
+    }
+
+    if (mbedtls_x509_crt_check_extended_key_usage(cert, ext_oid, ext_len) != 0) {
+        *flags |= MBEDTLS_X509_BADCERT_EXT_KEY_USAGE;
+        ret = -1;
+    }
+
+    return ret;
+}
+
+int mbedtls_ssl_verify_certificate(mbedtls_ssl_context *ssl,
+                                   int authmode,
+                                   mbedtls_x509_crt *chain,
+                                   const mbedtls_ssl_ciphersuite_t *ciphersuite_info,
+                                   void *rs_ctx)
+{
+    if (authmode == MBEDTLS_SSL_VERIFY_NONE) {
+        return 0;
+    }
+
+    /*
+     * Primary check: use the appropriate X.509 verification function
+     */
+    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+    void *p_vrfy;
+    if (ssl->f_vrfy != NULL) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Use context-specific verification callback"));
+        f_vrfy = ssl->f_vrfy;
+        p_vrfy = ssl->p_vrfy;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Use configuration-specific verification callback"));
+        f_vrfy = ssl->conf->f_vrfy;
+        p_vrfy = ssl->conf->p_vrfy;
+    }
+
+    int ret = 0;
+    int have_ca_chain_or_callback = 0;
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    if (ssl->conf->f_ca_cb != NULL) {
+        ((void) rs_ctx);
+        have_ca_chain_or_callback = 1;
+
+        MBEDTLS_SSL_DEBUG_MSG(3, ("use CA callback for X.509 CRT verification"));
+        ret = mbedtls_x509_crt_verify_with_ca_cb(
+            chain,
+            ssl->conf->f_ca_cb,
+            ssl->conf->p_ca_cb,
+            ssl->conf->cert_profile,
+            ssl->hostname,
+            &ssl->session_negotiate->verify_result,
+            f_vrfy, p_vrfy);
+    } else
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
+    {
+        mbedtls_x509_crt *ca_chain;
+        mbedtls_x509_crl *ca_crl;
+#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+        if (ssl->handshake->sni_ca_chain != NULL) {
+            ca_chain = ssl->handshake->sni_ca_chain;
+            ca_crl   = ssl->handshake->sni_ca_crl;
+        } else
+#endif
+        {
+            ca_chain = ssl->conf->ca_chain;
+            ca_crl   = ssl->conf->ca_crl;
+        }
+
+        if (ca_chain != NULL) {
+            have_ca_chain_or_callback = 1;
+        }
+
+        ret = mbedtls_x509_crt_verify_restartable(
+            chain,
+            ca_chain, ca_crl,
+            ssl->conf->cert_profile,
+            ssl->hostname,
+            &ssl->session_negotiate->verify_result,
+            f_vrfy, p_vrfy, rs_ctx);
+    }
+
+    if (ret != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
+    }
+
+#if defined(MBEDTLS_SSL_ECP_RESTARTABLE_ENABLED)
+    if (ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
+        return MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS;
+    }
+#endif
+
+    /*
+     * Secondary checks: always done, but change 'ret' only if it was 0
+     */
+
+    /* With TLS 1.2 and ECC certs, check that the curve used by the
+     * certificate is on our list of acceptable curves.
+     *
+     * With TLS 1.3 this is not needed because the curve is part of the
+     * signature algorithm (eg ecdsa_secp256r1_sha256) which is checked when
+     * we validate the signature made with the key associated to this cert.
+     */
+#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \
+    defined(MBEDTLS_PK_HAVE_ECC_KEYS)
+    if (ssl->tls_version == MBEDTLS_SSL_VERSION_TLS1_2 &&
+        mbedtls_pk_can_do(&chain->pk, MBEDTLS_PK_ECKEY)) {
+        if (mbedtls_ssl_check_curve(ssl, mbedtls_pk_get_ec_group_id(&chain->pk)) != 0) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (EC key curve)"));
+            ssl->session_negotiate->verify_result |= MBEDTLS_X509_BADCERT_BAD_KEY;
+            if (ret == 0) {
+                ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+            }
+        }
+    }
+#endif /* MBEDTLS_SSL_PROTO_TLS1_2 && MBEDTLS_PK_HAVE_ECC_KEYS */
+
+    /* Check X.509 usage extensions (keyUsage, extKeyUsage) */
+    if (mbedtls_ssl_check_cert_usage(chain,
+                                     ciphersuite_info,
+                                     ssl->conf->endpoint,
+                                     ssl->tls_version,
+                                     &ssl->session_negotiate->verify_result) != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
+        if (ret == 0) {
+            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
+        }
+    }
+
+    /* With authmode optional, we want to keep going if the certificate was
+     * unacceptable, but still fail on other errors (out of memory etc),
+     * including fatal errors from the f_vrfy callback.
+     *
+     * The only acceptable errors are:
+     * - MBEDTLS_ERR_X509_CERT_VERIFY_FAILED: cert rejected by primary check;
+     * - MBEDTLS_ERR_SSL_BAD_CERTIFICATE: cert rejected by secondary checks.
+     * Anything else is a fatal error. */
+    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
+        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
+         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
+        ret = 0;
+    }
+
+    /* Return a specific error as this is a user error: inconsistent
+     * configuration - can't verify without trust anchors. */
+    if (have_ca_chain_or_callback == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
+        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
+    }
+
+    if (ret != 0) {
+        uint8_t alert;
+
+        /* The certificate may have been rejected for several reasons.
+           Pick one and send the corresponding alert. Which alert to send
+           may be a subject of debate in some cases. */
+        if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_OTHER) {
+            alert = MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
+            alert = MBEDTLS_SSL_ALERT_MSG_BAD_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_KEY_USAGE) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXT_KEY_USAGE) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_PK) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_BAD_KEY) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED;
+        } else if (ssl->session_negotiate->verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
+            alert = MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA;
+        } else {
+            alert = MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN;
+        }
+        mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
+                                       alert);
+    }
+
+#if defined(MBEDTLS_DEBUG_C)
+    if (ssl->session_negotiate->verify_result != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
+                                  (unsigned int) ssl->session_negotiate->verify_result));
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
+    }
+#endif /* MBEDTLS_DEBUG_C */
+
+    return ret;
+}
+#endif /* MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED */
+
 #endif /* MBEDTLS_SSL_TLS_C */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c b/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c
index 890e9a906e48671f4e4f15319ac2fd659ed31ac2..9b2da5a39d34dfde3a5d6d07a03c7bed08382c0c 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls12_client.c
@@ -2,19 +2,7 @@
  *  TLS client-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -26,16 +14,24 @@
 #include "mbedtls/ssl.h"
 #include "ssl_client.h"
 #include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/constant_time.h"
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
 #include "psa/crypto.h"
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
 #include <string.h>
@@ -50,8 +46,6 @@
 #include "mbedtls/platform_util.h"
 #endif
 
-#include "hash_info.h"
-
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
@@ -93,7 +87,8 @@ static int ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
 }
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -124,7 +119,8 @@ static int ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
 
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -368,7 +364,8 @@ static int ssl_write_session_ticket_ext(mbedtls_ssl_context *ssl,
 
     *olen = 0;
 
-    if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {
+    if (mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==
+        MBEDTLS_SSL_SESSION_TICKETS_DISABLED) {
         return 0;
     }
 
@@ -541,7 +538,8 @@ int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,
     p += ext_len;
 #endif
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     if (uses_ec) {
         if ((ret = ssl_write_supported_point_formats_ext(ssl, p, end,
@@ -610,7 +608,7 @@ int mbedtls_ssl_tls12_write_client_hello_exts(mbedtls_ssl_context *ssl,
     p += ext_len;
 #endif
 
-    *out_len = p - buf;
+    *out_len = (size_t) (p - buf);
 
     return 0;
 }
@@ -790,7 +788,8 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
                                         const unsigned char *buf,
                                         size_t len)
 {
-    if (ssl->conf->session_tickets == MBEDTLS_SSL_SESSION_TICKETS_DISABLED ||
+    if ((mbedtls_ssl_conf_get_session_tickets(ssl->conf) ==
+         MBEDTLS_SSL_SESSION_TICKETS_DISABLED) ||
         len != 0) {
         MBEDTLS_SSL_DEBUG_MSG(1,
                               ("non-matching session ticket extension"));
@@ -809,7 +808,8 @@ static int ssl_parse_session_ticket_ext(mbedtls_ssl_context *ssl,
 }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl,
@@ -831,11 +831,10 @@ static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl,
     while (list_size > 0) {
         if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
             p[0] == MBEDTLS_ECP_PF_COMPRESSED) {
-#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
-            (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C))
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \
+            defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)
             ssl->handshake->ecdh_ctx.point_format = p[0];
-#endif /* !MBEDTLS_USE_PSA_CRYPTO &&
-          ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */
 #if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
             defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
             mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,
@@ -854,7 +853,8 @@ static int ssl_parse_supported_point_formats_ext(mbedtls_ssl_context *ssl,
                                    MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE);
     return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -943,7 +943,7 @@ static int ssl_parse_alpn_ext(mbedtls_ssl_context *ssl,
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    list_len = (buf[0] << 8) | buf[1];
+    list_len = MBEDTLS_GET_UINT16_BE(buf, 0);
     if (list_len != len - 2) {
         mbedtls_ssl_send_alert_message(ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
@@ -1267,8 +1267,10 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
     buf += mbedtls_ssl_hs_hdr_len(ssl);
 
     MBEDTLS_SSL_DEBUG_BUF(3, "server hello, version", buf, 2);
-    ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport);
+    ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
+                                                                               ssl->conf->transport);
     ssl->session_negotiate->tls_version = ssl->tls_version;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     if (ssl->tls_version < ssl->conf->min_tls_version ||
         ssl->tls_version > ssl->conf->max_tls_version) {
@@ -1305,8 +1307,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
     }
 
     if (ssl->in_hslen > mbedtls_ssl_hs_hdr_len(ssl) + 39 + n) {
-        ext_len = ((buf[38 + n] <<  8)
-                   | (buf[39 + n]));
+        ext_len = MBEDTLS_GET_UINT16_BE(buf, 38 + n);
 
         if ((ext_len > 0 && ext_len < 4) ||
             ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 40 + n + ext_len) {
@@ -1327,7 +1328,7 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
     }
 
     /* ciphersuite (used later) */
-    i = (buf[35 + n] << 8) | buf[36 + n];
+    i = (int) MBEDTLS_GET_UINT16_BE(buf, n + 35);
 
     /*
      * Read and check compression
@@ -1448,10 +1449,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
                            ext_len));
 
     while (ext_len) {
-        unsigned int ext_id   = ((ext[0] <<  8)
-                                 | (ext[1]));
-        unsigned int ext_size = ((ext[2] <<  8)
-                                 | (ext[3]));
+        unsigned int ext_id   = MBEDTLS_GET_UINT16_BE(ext, 0);
+        unsigned int ext_size = MBEDTLS_GET_UINT16_BE(ext, 2);
 
         if (ext_size + 4 > ext_len) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("bad server hello message"));
@@ -1538,7 +1537,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
                 break;
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+                defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
                 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
             case MBEDTLS_TLS_EXT_SUPPORTED_POINT_FORMATS:
                 MBEDTLS_SSL_DEBUG_MSG(3,
@@ -1550,7 +1550,8 @@ static int ssl_parse_server_hello(mbedtls_ssl_context *ssl)
                 }
 
                 break;
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1714,9 +1715,9 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
                                         unsigned char *end)
 {
     uint16_t tls_id;
-    uint8_t ecpoint_len;
+    size_t ecpoint_len;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    psa_ecc_family_t ec_psa_family = 0;
+    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
     size_t ec_bits = 0;
 
     /*
@@ -1740,9 +1741,8 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
     }
 
     /* Next two bytes are the namedcurve value */
-    tls_id = *(*p)++;
-    tls_id <<= 8;
-    tls_id |= *(*p)++;
+    tls_id = MBEDTLS_GET_UINT16_BE(*p, 0);
+    *p += 2;
 
     /* Check it's a curve we offered */
     if (mbedtls_ssl_check_curve_tls_id(ssl, tls_id) != 0) {
@@ -1753,12 +1753,12 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
     }
 
     /* Convert EC's TLS ID to PSA key type. */
-    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ec_psa_family,
+    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,
                                                    &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
-    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
-    handshake->ecdh_bits = ec_bits;
+    handshake->xxdh_psa_type = key_type;
+    handshake->xxdh_psa_bits = ec_bits;
 
     /* Keep a copy of the peer's public key */
     ecpoint_len = *(*p)++;
@@ -1766,12 +1766,12 @@ static int ssl_parse_server_ecdh_params(mbedtls_ssl_context *ssl,
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) {
+    if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) {
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
 
-    memcpy(handshake->ecdh_psa_peerkey, *p, ecpoint_len);
-    handshake->ecdh_psa_peerkey_len = ecpoint_len;
+    memcpy(handshake->xxdh_psa_peerkey, *p, ecpoint_len);
+    handshake->xxdh_psa_peerkey_len = ecpoint_len;
     *p += ecpoint_len;
 
     return 0;
@@ -1882,7 +1882,7 @@ static int ssl_parse_server_psk_hint(mbedtls_ssl_context *ssl,
                               ("bad server key exchange message (psk_identity_hint length)"));
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
-    len = (*p)[0] << 8 | (*p)[1];
+    len = MBEDTLS_GET_UINT16_BE(*p, 0);
     *p += 2;
 
     if (end - (*p) < len) {
@@ -1988,7 +1988,6 @@ MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    const mbedtls_ecp_keypair *peer_key;
     mbedtls_pk_context *peer_pk;
 
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
@@ -2009,45 +2008,53 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
     }
 
-    peer_key = mbedtls_pk_ec(*peer_pk);
+#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    const mbedtls_ecp_keypair *peer_key = mbedtls_pk_ec_ro(*peer_pk);
+#endif /* !defined(MBEDTLS_PK_USE_PSA_EC_DATA) */
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    size_t olen = 0;
     uint16_t tls_id = 0;
-    psa_ecc_family_t ecc_family;
+    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
+    mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(peer_pk);
 
-    if (mbedtls_ssl_check_curve(ssl, peer_key->grp.id) != 0) {
+    if (mbedtls_ssl_check_curve(ssl, grp_id) != 0) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)"));
         return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
     }
 
-    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(peer_key->grp.id);
+    tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
     if (tls_id == 0) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("ECC group %u not suported",
-                                  peer_key->grp.id));
+                                  grp_id));
         return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
     }
 
     /* If the above conversion to TLS ID was fine, then also this one will be,
        so there is no need to check the return value here */
-    mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family,
-                                               &ssl->handshake->ecdh_bits);
+    mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,
+                                               &ssl->handshake->xxdh_psa_bits);
 
-    ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family);
+    ssl->handshake->xxdh_psa_type = key_type;
 
     /* Store peer's public key in psa format. */
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    memcpy(ssl->handshake->xxdh_psa_peerkey, peer_pk->pub_raw, peer_pk->pub_raw_len);
+    ssl->handshake->xxdh_psa_peerkey_len = peer_pk->pub_raw_len;
+    ret = 0;
+#else /* MBEDTLS_PK_USE_PSA_EC_DATA */
+    size_t olen = 0;
     ret = mbedtls_ecp_point_write_binary(&peer_key->grp, &peer_key->Q,
                                          MBEDTLS_ECP_PF_UNCOMPRESSED, &olen,
-                                         ssl->handshake->ecdh_psa_peerkey,
-                                         MBEDTLS_PSA_MAX_EC_PUBKEY_LENGTH);
+                                         ssl->handshake->xxdh_psa_peerkey,
+                                         sizeof(ssl->handshake->xxdh_psa_peerkey));
 
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecp_point_write_binary"), ret);
         return ret;
     }
-
-    ssl->handshake->ecdh_psa_peerkey_len = olen;
-#else
+    ssl->handshake->xxdh_psa_peerkey_len = olen;
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
+#else /* MBEDTLS_USE_PSA_CRYPTO */
     if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx, peer_key,
                                        MBEDTLS_ECDH_THEIRS)) != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret);
@@ -2058,7 +2065,7 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
         MBEDTLS_SSL_DEBUG_MSG(1, ("bad server certificate (ECDH curve)"));
         return MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
     }
-#endif
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
     /* We don't need the peer's public key anymore. Free it,
      * so that more RAM is available for upcoming expensive
@@ -2166,7 +2173,7 @@ start_processing:
 #endif
     p   = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
     end = ssl->in_msg + ssl->in_hslen;
-    MBEDTLS_SSL_DEBUG_BUF(3,   "server key exchange", p, end - p);
+    MBEDTLS_SSL_DEBUG_BUF(3,   "server key exchange", p, (size_t) (end - p));
 
 #if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
     if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
@@ -2286,12 +2293,12 @@ start_processing:
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
     if (mbedtls_ssl_ciphersuite_uses_server_signature(ciphersuite_info)) {
         size_t sig_len, hashlen;
-        unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+        unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 
         mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE;
         mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
         unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
-        size_t params_len = p - params;
+        size_t params_len = (size_t) (p - params);
         void *rs_ctx = NULL;
         uint16_t sig_alg;
 
@@ -2349,7 +2356,7 @@ start_processing:
                 MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
-        sig_len = (p[0] << 8) | p[1];
+        sig_len = MBEDTLS_GET_UINT16_BE(p, 0);
         p += 2;
 
         if (p != end - sig_len) {
@@ -2403,7 +2410,7 @@ start_processing:
             mbedtls_pk_rsassa_pss_options rsassa_pss_options;
             rsassa_pss_options.mgf1_hash_id = md_alg;
             rsassa_pss_options.expected_salt_len =
-                mbedtls_hash_info_get_size(md_alg);
+                mbedtls_md_get_size_from_type(md_alg);
             if (rsassa_pss_options.expected_salt_len == 0) {
                 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
             }
@@ -2577,8 +2584,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)
     }
 
     /* supported_signature_algorithms */
-    sig_alg_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] <<  8)
-                   | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n]));
+    sig_alg_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n);
 
     /*
      * The furthest access in buf is in the loop few lines below:
@@ -2613,8 +2619,7 @@ static int ssl_parse_certificate_request(mbedtls_ssl_context *ssl)
     n += 2 + sig_alg_len;
 
     /* certificate_authorities */
-    dn_len = ((buf[mbedtls_ssl_hs_hdr_len(ssl) + 1 + n] <<  8)
-              | (buf[mbedtls_ssl_hs_hdr_len(ssl) + 2 + n]));
+    dn_len = MBEDTLS_GET_UINT16_BE(buf, mbedtls_ssl_hs_hdr_len(ssl) + 1 + n);
 
     n += dn_len;
     if (ssl->in_hslen != mbedtls_ssl_hs_hdr_len(ssl) + 3 + n) {
@@ -2775,12 +2780,12 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
         key_attributes = psa_key_attributes_init();
         psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
         psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
-        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
-        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);
 
         /* Generate ECDH private key. */
         status = psa_generate_key(&key_attributes,
-                                  &handshake->ecdh_psa_privkey);
+                                  &handshake->xxdh_psa_privkey);
         if (status != PSA_SUCCESS) {
             return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         }
@@ -2793,12 +2798,12 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
         size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
         size_t own_pubkey_len;
 
-        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+        status = psa_export_public_key(handshake->xxdh_psa_privkey,
                                        own_pubkey, own_pubkey_max_len,
                                        &own_pubkey_len);
         if (status != PSA_SUCCESS) {
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
         }
 
@@ -2809,15 +2814,15 @@ static int ssl_write_client_key_exchange(mbedtls_ssl_context *ssl)
 
         /* Compute ECDH shared secret. */
         status = psa_raw_key_agreement(PSA_ALG_ECDH,
-                                       handshake->ecdh_psa_privkey,
-                                       handshake->ecdh_psa_peerkey,
-                                       handshake->ecdh_psa_peerkey_len,
+                                       handshake->xxdh_psa_privkey,
+                                       handshake->xxdh_psa_peerkey,
+                                       handshake->xxdh_psa_peerkey_len,
                                        ssl->handshake->premaster,
                                        sizeof(ssl->handshake->premaster),
                                        &ssl->handshake->pmslen);
 
-        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
-        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);
+        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 
         if (status != PSA_SUCCESS || destruction_status != PSA_SUCCESS) {
             return MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
@@ -2947,12 +2952,12 @@ ecdh_calc_secret:
         key_attributes = psa_key_attributes_init();
         psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
         psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
-        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
-        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);
 
         /* Generate ECDH private key. */
         status = psa_generate_key(&key_attributes,
-                                  &handshake->ecdh_psa_privkey);
+                                  &handshake->xxdh_psa_privkey);
         if (status != PSA_SUCCESS) {
             return PSA_TO_MBEDTLS_ERR(status);
         }
@@ -2965,12 +2970,12 @@ ecdh_calc_secret:
         size_t own_pubkey_max_len = (size_t) (end - own_pubkey);
         size_t own_pubkey_len = 0;
 
-        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+        status = psa_export_public_key(handshake->xxdh_psa_privkey,
                                        own_pubkey, own_pubkey_max_len,
                                        &own_pubkey_len);
         if (status != PSA_SUCCESS) {
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return PSA_TO_MBEDTLS_ERR(status);
         }
 
@@ -2992,15 +2997,15 @@ ecdh_calc_secret:
 
         /* Perform ECDH computation after the uint16 reserved for the length */
         status = psa_raw_key_agreement(PSA_ALG_ECDH,
-                                       handshake->ecdh_psa_privkey,
-                                       handshake->ecdh_psa_peerkey,
-                                       handshake->ecdh_psa_peerkey_len,
+                                       handshake->xxdh_psa_privkey,
+                                       handshake->xxdh_psa_peerkey,
+                                       handshake->xxdh_psa_peerkey_len,
                                        pms + zlen_size,
                                        pms_end - (pms + zlen_size),
                                        &zlen);
 
-        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
-        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);
+        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 
         if (status != PSA_SUCCESS) {
             return PSA_TO_MBEDTLS_ERR(status);
@@ -3128,7 +3133,8 @@ ecdh_calc_secret:
 
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
         if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
-                                                    ciphersuite_info->key_exchange)) != 0) {
+                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->
+                                                    key_exchange)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1,
                                   "mbedtls_ssl_psk_derive_premaster", ret);
             return ret;
@@ -3243,9 +3249,9 @@ static int ssl_write_certificate_verify(mbedtls_ssl_context *ssl)
     size_t hashlen;
     void *rs_ctx = NULL;
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf);
+    size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);
 #else
-    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf);
+    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);
 #endif
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
@@ -3412,10 +3418,9 @@ static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl)
 
     msg = ssl->in_msg + mbedtls_ssl_hs_hdr_len(ssl);
 
-    lifetime = (((uint32_t) msg[0]) << 24) | (msg[1] << 16) |
-               (msg[2] << 8) | (msg[3]);
+    lifetime = MBEDTLS_GET_UINT32_BE(msg, 0);
 
-    ticket_len = (msg[4] << 8) | (msg[5]);
+    ticket_len = MBEDTLS_GET_UINT16_BE(msg, 4);
 
     if (ticket_len + 6 + mbedtls_ssl_hs_hdr_len(ssl) != ssl->in_hslen) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("bad new session ticket message"));
@@ -3439,16 +3444,14 @@ static int ssl_parse_new_session_ticket(mbedtls_ssl_context *ssl)
     }
 
     if (ssl->session != NULL && ssl->session->ticket != NULL) {
-        mbedtls_platform_zeroize(ssl->session->ticket,
+        mbedtls_zeroize_and_free(ssl->session->ticket,
                                  ssl->session->ticket_len);
-        mbedtls_free(ssl->session->ticket);
         ssl->session->ticket = NULL;
         ssl->session->ticket_len = 0;
     }
 
-    mbedtls_platform_zeroize(ssl->session_negotiate->ticket,
+    mbedtls_zeroize_and_free(ssl->session_negotiate->ticket,
                              ssl->session_negotiate->ticket_len);
-    mbedtls_free(ssl->session_negotiate->ticket);
     ssl->session_negotiate->ticket = NULL;
     ssl->session_negotiate->ticket_len = 0;
 
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c b/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c
index 631331d8217c815eb4817bc23d0bb36741c029bd..03722ac33cbeaff86464d11e58189579c3fd7af9 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls12_server.c
@@ -2,19 +2,7 @@
  *  TLS server-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -25,19 +13,27 @@
 
 #include "mbedtls/ssl.h"
 #include "ssl_misc.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform_util.h"
 #include "constant_time_internal.h"
 #include "mbedtls/constant_time.h"
-#include "hash_info.h"
 
 #include <string.h>
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDHE_ENABLED)
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
+#endif
 #endif
 
 #if defined(MBEDTLS_ECP_C)
@@ -140,7 +136,8 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,
     return 0;
 }
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 /*
  * Function for parsing a supported groups (TLS 1.3) or supported elliptic
@@ -179,7 +176,6 @@ static int ssl_parse_renegotiation_info(mbedtls_ssl_context *ssl,
  * generalization of the TLS 1.2 supported elliptic curves extension. They both
  * share the same extension identifier.
  *
- * DHE groups are not supported yet.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
@@ -196,7 +192,7 @@ static int ssl_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
                                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
-    list_size = ((buf[0] << 8) | (buf[1]));
+    list_size = MBEDTLS_GET_UINT16_BE(buf, 0);
     if (list_size + 2 != len ||
         list_size % 2 != 0) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
@@ -266,11 +262,10 @@ static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl,
     while (list_size > 0) {
         if (p[0] == MBEDTLS_ECP_PF_UNCOMPRESSED ||
             p[0] == MBEDTLS_ECP_PF_COMPRESSED) {
-#if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
-            (defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C))
+#if !defined(MBEDTLS_USE_PSA_CRYPTO) && \
+            defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED)
             ssl->handshake->ecdh_ctx.point_format = p[0];
-#endif /* !MBEDTLS_USE_PSA_CRYPTO &&
-          ( MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ) */
+#endif /* !MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED */
 #if !defined(MBEDTLS_USE_PSA_CRYPTO) &&                             \
             defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
             mbedtls_ecjpake_set_point_format(&ssl->handshake->ecjpake_ctx,
@@ -286,7 +281,8 @@ static int ssl_parse_supported_point_formats(mbedtls_ssl_context *ssl,
 
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -662,13 +658,13 @@ static int ssl_parse_use_srtp_ext(mbedtls_ssl_context *ssl,
 /*
  * Return 0 if the given key uses one of the acceptable curves, -1 otherwise
  */
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_check_key_curve(mbedtls_pk_context *pk,
                                uint16_t *curves_tls_id)
 {
     uint16_t *curr_tls_id = curves_tls_id;
-    mbedtls_ecp_group_id grp_id = mbedtls_pk_ec(*pk)->grp.id;
+    mbedtls_ecp_group_id grp_id = mbedtls_pk_get_ec_group_id(pk);
     mbedtls_ecp_group_id curr_grp_id;
 
     while (*curr_tls_id != 0) {
@@ -681,7 +677,7 @@ static int ssl_check_key_curve(mbedtls_pk_context *pk,
 
     return -1;
 }
-#endif /* MBEDTLS_ECDSA_C */
+#endif /* MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED */
 
 /*
  * Try picking a certificate for this ciphersuite,
@@ -760,13 +756,15 @@ static int ssl_pick_cert(mbedtls_ssl_context *ssl,
          * and decrypting with the same RSA key.
          */
         if (mbedtls_ssl_check_cert_usage(cur->cert, ciphersuite_info,
-                                         MBEDTLS_SSL_IS_SERVER, &flags) != 0) {
+                                         MBEDTLS_SSL_IS_CLIENT,
+                                         MBEDTLS_SSL_VERSION_TLS1_2,
+                                         &flags) != 0) {
             MBEDTLS_SSL_DEBUG_MSG(3, ("certificate mismatch: "
                                       "(extended) key usage extension"));
             continue;
         }
 
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
         if (pk_alg == MBEDTLS_PK_ECDSA &&
             ssl_check_key_curve(&cur->cert->pk,
                                 ssl->handshake->curves_tls_id) != 0) {
@@ -830,7 +828,8 @@ static int ssl_ciphersuite_match(mbedtls_ssl_context *ssl, int suite_id,
 #endif
 
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
     if (mbedtls_ssl_ciphersuite_uses_ec(suite_info) &&
         (ssl->handshake->curves_tls_id == NULL ||
          ssl->handshake->curves_tls_id[0] == 0)) {
@@ -922,12 +921,15 @@ read_record_header:
      * If renegotiating, then the input was read with mbedtls_ssl_read_record(),
      * otherwise read it ourselves manually in order to support SSLv2
      * ClientHello, which doesn't use the same record layer format.
+     * Otherwise in a scenario of TLS 1.3/TLS 1.2 version negotiation, the
+     * ClientHello has been already fully fetched by the TLS 1.3 code and the
+     * flag ssl->keep_current_message is raised.
      */
     renegotiating = 0;
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     renegotiating = (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE);
 #endif
-    if (!renegotiating) {
+    if (!renegotiating && !ssl->keep_current_message) {
         if ((ret = mbedtls_ssl_fetch_input(ssl, 5)) != 0) {
             /* No alert on a read error. */
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
@@ -957,7 +959,7 @@ read_record_header:
     }
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, message len.: %d",
-                              (ssl->in_len[0] << 8) | ssl->in_len[1]));
+                              MBEDTLS_GET_UINT16_BE(ssl->in_len, 0)));
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("client hello, protocol version: [%d:%d]",
                               buf[1], buf[2]));
@@ -993,7 +995,7 @@ read_record_header:
     }
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 
-    msg_len = (ssl->in_len[0] << 8) | ssl->in_len[1];
+    msg_len = MBEDTLS_GET_UINT16_BE(ssl->in_len, 0);
 
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
     if (ssl->renego_status != MBEDTLS_SSL_INITIAL_HANDSHAKE) {
@@ -1002,24 +1004,28 @@ read_record_header:
     } else
 #endif
     {
-        if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
-            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
-        }
+        if (ssl->keep_current_message) {
+            ssl->keep_current_message = 0;
+        } else {
+            if (msg_len > MBEDTLS_SSL_IN_CONTENT_LEN) {
+                MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+                return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+            }
 
-        if ((ret = mbedtls_ssl_fetch_input(ssl,
-                                           mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) {
-            MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
-            return ret;
-        }
+            if ((ret = mbedtls_ssl_fetch_input(ssl,
+                                               mbedtls_ssl_in_hdr_len(ssl) + msg_len)) != 0) {
+                MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_fetch_input", ret);
+                return ret;
+            }
 
-        /* Done reading this record, get ready for the next one */
+            /* Done reading this record, get ready for the next one */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-        if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
-            ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl);
-        } else
+            if (ssl->conf->transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM) {
+                ssl->next_record_offset = msg_len + mbedtls_ssl_in_hdr_len(ssl);
+            } else
 #endif
-        ssl->in_left = 0;
+            ssl->in_left = 0;
+        }
     }
 
     buf = ssl->in_msg;
@@ -1083,9 +1089,7 @@ read_record_header:
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
         if (ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS) {
             /* This couldn't be done in ssl_prepare_handshake_record() */
-            unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) |
-                                       ssl->in_msg[5];
-
+            unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);
             if (cli_msg_seq != ssl->handshake->in_msg_seq) {
                 MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message_seq: "
                                           "%u (expected %u)", cli_msg_seq,
@@ -1097,8 +1101,7 @@ read_record_header:
         } else
 #endif
         {
-            unsigned int cli_msg_seq = (ssl->in_msg[4] << 8) |
-                                       ssl->in_msg[5];
+            unsigned int cli_msg_seq = (unsigned int) MBEDTLS_GET_UINT16_BE(ssl->in_msg, 4);
             ssl->handshake->out_msg_seq = cli_msg_seq;
             ssl->handshake->in_msg_seq  = cli_msg_seq + 1;
         }
@@ -1127,11 +1130,11 @@ read_record_header:
     msg_len -= mbedtls_ssl_hs_hdr_len(ssl);
 
     /*
-     * ClientHello layer:
+     * ClientHello layout:
      *     0  .   1   protocol version
      *     2  .  33   random bytes (starting with 4 bytes of Unix time)
-     *    34  .  35   session id length (1 byte)
-     *    35  . 34+x  session id
+     *    34  .  34   session id length (1 byte)
+     *    35  . 34+x  session id, where x = session id length from byte 34
      *   35+x . 35+x  DTLS only: cookie length (1 byte)
      *   36+x .  ..   DTLS only: cookie
      *    ..  .  ..   ciphersuite list length (2 bytes)
@@ -1157,8 +1160,10 @@ read_record_header:
      */
     MBEDTLS_SSL_DEBUG_BUF(3, "client hello, version", buf, 2);
 
-    ssl->tls_version = mbedtls_ssl_read_version(buf, ssl->conf->transport);
+    ssl->tls_version = (mbedtls_ssl_protocol_version) mbedtls_ssl_read_version(buf,
+                                                                               ssl->conf->transport);
     ssl->session_negotiate->tls_version = ssl->tls_version;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     if (ssl->tls_version != MBEDTLS_SSL_VERSION_TLS1_2) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("server only supports TLS 1.2"));
@@ -1249,8 +1254,7 @@ read_record_header:
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
     ciph_offset = 35 + sess_len;
 
-    ciph_len = (buf[ciph_offset + 0] << 8)
-               | (buf[ciph_offset + 1]);
+    ciph_len = MBEDTLS_GET_UINT16_BE(buf, ciph_offset);
 
     if (ciph_len < 2 ||
         ciph_len + 2 + ciph_offset + 1 > msg_len || /* 1 for comp. alg. len */
@@ -1298,8 +1302,7 @@ read_record_header:
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
 
-        ext_len = (buf[ext_offset + 0] << 8)
-                  | (buf[ext_offset + 1]);
+        ext_len = MBEDTLS_GET_UINT16_BE(buf, ext_offset);
 
         if (msg_len != ext_offset + 2 + ext_len) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
@@ -1323,8 +1326,8 @@ read_record_header:
                                            MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR);
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
-        ext_id   = ((ext[0] <<  8) | (ext[1]));
-        ext_size = ((ext[2] <<  8) | (ext[3]));
+        ext_id   = MBEDTLS_GET_UINT16_BE(ext, 0);
+        ext_size = MBEDTLS_GET_UINT16_BE(ext, 2);
 
         if (ext_size + 4 > ext_len) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
@@ -1369,7 +1372,8 @@ read_record_header:
                 break;
 #endif /* MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+                defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
                 defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
             case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found supported elliptic curves extension"));
@@ -1389,7 +1393,8 @@ read_record_header:
                     return ret;
                 }
                 break;
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C ||
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED || \
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
           MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
@@ -1499,7 +1504,7 @@ read_record_header:
     if (!sig_hash_alg_ext_present) {
         uint16_t *received_sig_algs = ssl->handshake->received_sig_algs;
         const uint16_t default_sig_algs[] = {
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
             MBEDTLS_SSL_TLS12_SIG_AND_HASH_ALG(MBEDTLS_SSL_SIG_ECDSA,
                                                MBEDTLS_SSL_HASH_SHA1),
 #endif
@@ -1854,7 +1859,7 @@ static void ssl_write_renegotiation_ext(mbedtls_ssl_context *ssl,
         *p++ = 0x00;
     }
 
-    *olen = p - buf;
+    *olen = (size_t) (p - buf);
 }
 
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
@@ -1883,7 +1888,8 @@ static void ssl_write_max_fragment_length_ext(mbedtls_ssl_context *ssl,
 }
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
                                                   unsigned char *buf,
@@ -1911,7 +1917,9 @@ static void ssl_write_supported_point_formats_ext(mbedtls_ssl_context *ssl,
 
     *olen = 6;
 }
-#endif /* MBEDTLS_ECDH_C || MBEDTLS_ECDSA_C || MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
+#endif /* MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED ||
+          MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
 static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
@@ -1943,7 +1951,7 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     ret = mbedtls_psa_ecjpake_write_round(&ssl->handshake->psa_pake_ctx,
-                                          p + 2, end - p - 2, &kkpp_len,
+                                          p + 2, (size_t) (end - p - 2), &kkpp_len,
                                           MBEDTLS_ECJPAKE_ROUND_ONE);
     if (ret != 0) {
         psa_destroy_key(ssl->handshake->psa_pake_password);
@@ -1953,7 +1961,7 @@ static void ssl_write_ecjpake_kkpp_ext(mbedtls_ssl_context *ssl,
     }
 #else
     ret = mbedtls_ecjpake_write_round_one(&ssl->handshake->ecjpake_ctx,
-                                          p + 2, end - p - 2, &kkpp_len,
+                                          p + 2, (size_t) (end - p - 2), &kkpp_len,
                                           ssl->conf->f_rng, ssl->conf->p_rng);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_write_round_one", ret);
@@ -2074,7 +2082,7 @@ static int ssl_write_hello_verify_request(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_BUF(3, "cookie sent", cookie_len_byte + 1, *cookie_len_byte);
 
-    ssl->out_msglen  = p - ssl->out_msg;
+    ssl->out_msglen  = (size_t) (p - ssl->out_msg);
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST;
 
@@ -2172,11 +2180,6 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
     }
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
-
     /*
      *     0  .   0   handshake type
      *     1  .   3   handshake length
@@ -2208,11 +2211,37 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
     p += 4;
 #endif /* MBEDTLS_HAVE_TIME */
 
-    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 28)) != 0) {
+    if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 20)) != 0) {
         return ret;
     }
+    p += 20;
 
-    p += 28;
+#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
+    /*
+     * RFC 8446
+     * TLS 1.3 has a downgrade protection mechanism embedded in the server's
+     * random value. TLS 1.3 servers which negotiate TLS 1.2 or below in
+     * response to a ClientHello MUST set the last 8 bytes of their Random
+     * value specially in their ServerHello.
+     */
+    if (mbedtls_ssl_conf_is_tls13_enabled(ssl->conf)) {
+        static const unsigned char magic_tls12_downgrade_string[] =
+        { 'D', 'O', 'W', 'N', 'G', 'R', 'D', 1 };
+
+        MBEDTLS_STATIC_ASSERT(
+            sizeof(magic_tls12_downgrade_string) == 8,
+            "magic_tls12_downgrade_string does not have the expected size");
+
+        memcpy(p, magic_tls12_downgrade_string,
+               sizeof(magic_tls12_downgrade_string));
+    } else
+#endif
+    {
+        if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, p, 8)) != 0) {
+            return ret;
+        }
+    }
+    p += 8;
 
     memcpy(ssl->handshake->randbytes + 32, buf + 6, 32);
 
@@ -2314,7 +2343,8 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
     ext_len += olen;
 #endif
 
-#if defined(MBEDTLS_ECDH_C) || defined(MBEDTLS_ECDSA_C) || \
+#if defined(MBEDTLS_KEY_EXCHANGE_SOME_ECDH_OR_ECDHE_1_2_ENABLED) || \
+    defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
     const mbedtls_ssl_ciphersuite_t *suite =
         mbedtls_ssl_ciphersuite_from_id(ssl->session_negotiate->ciphersuite);
@@ -2352,7 +2382,7 @@ static int ssl_write_server_hello(mbedtls_ssl_context *ssl)
         p += 2 + ext_len;
     }
 
-    ssl->out_msglen  = p - buf;
+    ssl->out_msglen  = (size_t) (p - buf);
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_SERVER_HELLO;
 
@@ -2438,7 +2468,7 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
 #if defined(MBEDTLS_RSA_C)
     p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_RSA_SIGN;
 #endif
-#if defined(MBEDTLS_ECDSA_C)
+#if defined(MBEDTLS_KEY_EXCHANGE_ECDSA_CERT_REQ_ALLOWED_ENABLED)
     p[1 + ct_len++] = MBEDTLS_SSL_CERT_TYPE_ECDSA_SIGN;
 #endif
 
@@ -2536,12 +2566,12 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
 
             MBEDTLS_SSL_DEBUG_BUF(3, "requested DN", p - dn_size, dn_size);
 
-            total_dn_size += 2 + dn_size;
+            total_dn_size += (unsigned short) (2 + dn_size);
             crt = crt->next;
         }
     }
 
-    ssl->out_msglen  = p - buf;
+    ssl->out_msglen  = (size_t) (p - buf);
     ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
     ssl->out_msg[0]  = MBEDTLS_SSL_HS_CERTIFICATE_REQUEST;
     MBEDTLS_PUT_UINT16_BE(total_dn_size, ssl->out_msg, 4 + ct_len + sa_len);
@@ -2554,22 +2584,25 @@ static int ssl_write_certificate_request(mbedtls_ssl_context *ssl)
 }
 #endif /* MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED */
 
-#if defined(MBEDTLS_USE_PSA_CRYPTO) &&                      \
-    (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
+#if (defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
     defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED))
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
-    unsigned char buf[
-        PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
+    mbedtls_pk_context *pk;
+    mbedtls_pk_type_t pk_type;
     psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
-    uint16_t tls_id = 0;
-    psa_ecc_family_t ecc_family;
+    unsigned char buf[PSA_KEY_EXPORT_ECC_KEY_PAIR_MAX_SIZE(PSA_VENDOR_ECC_MAX_CURVE_BITS)];
     size_t key_len;
-    mbedtls_pk_context *pk;
+#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+    uint16_t tls_id = 0;
+    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
+    mbedtls_ecp_group_id grp_id;
     mbedtls_ecp_keypair *key;
+#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */
 
     pk = mbedtls_ssl_own_key(ssl);
 
@@ -2577,41 +2610,82 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
     }
 
-    switch (mbedtls_pk_get_type(pk)) {
+    pk_type = mbedtls_pk_get_type(pk);
+
+    switch (pk_type) {
         case MBEDTLS_PK_OPAQUE:
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+        case MBEDTLS_PK_ECKEY:
+        case MBEDTLS_PK_ECKEY_DH:
+        case MBEDTLS_PK_ECDSA:
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
             if (!mbedtls_pk_can_do(pk, MBEDTLS_PK_ECKEY)) {
                 return MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
             }
 
-            ssl->handshake->ecdh_psa_privkey =
-                *((mbedtls_svc_key_id_t *) pk->pk_ctx);
-
-            /* Key should not be destroyed in the TLS library */
-            ssl->handshake->ecdh_psa_privkey_is_external = 1;
-
-            status = psa_get_key_attributes(ssl->handshake->ecdh_psa_privkey,
-                                            &key_attributes);
+            /* Get the attributes of the key previously parsed by PK module in
+             * order to extract its type and length (in bits). */
+            status = psa_get_key_attributes(pk->priv_id, &key_attributes);
             if (status != PSA_SUCCESS) {
-                ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-                return PSA_TO_MBEDTLS_ERR(status);
+                ret = PSA_TO_MBEDTLS_ERR(status);
+                goto exit;
             }
+            ssl->handshake->xxdh_psa_type = psa_get_key_type(&key_attributes);
+            ssl->handshake->xxdh_psa_bits = psa_get_key_bits(&key_attributes);
+
+#if defined(MBEDTLS_PK_USE_PSA_EC_DATA)
+            if (pk_type != MBEDTLS_PK_OPAQUE) {
+                /* PK_ECKEY[_DH] and PK_ECDSA instead as parsed from the PK
+                 * module and only have ECDSA capabilities. Since we need
+                 * them for ECDH later, we export and then re-import them with
+                 * proper flags and algorithm. Of course We also set key's type
+                 * and bits that we just got above. */
+                key_attributes = psa_key_attributes_init();
+                psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
+                psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
+                psa_set_key_type(&key_attributes,
+                                 PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));
+                psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);
+
+                status = psa_export_key(pk->priv_id, buf, sizeof(buf), &key_len);
+                if (status != PSA_SUCCESS) {
+                    ret = PSA_TO_MBEDTLS_ERR(status);
+                    goto exit;
+                }
+                status = psa_import_key(&key_attributes, buf, key_len,
+                                        &ssl->handshake->xxdh_psa_privkey);
+                if (status != PSA_SUCCESS) {
+                    ret = PSA_TO_MBEDTLS_ERR(status);
+                    goto exit;
+                }
 
-            ssl->handshake->ecdh_psa_type = psa_get_key_type(&key_attributes);
-            ssl->handshake->ecdh_bits = psa_get_key_bits(&key_attributes);
+                /* Set this key as owned by the TLS library: it will be its duty
+                 * to clear it exit. */
+                ssl->handshake->xxdh_psa_privkey_is_external = 0;
 
-            psa_reset_key_attributes(&key_attributes);
+                ret = 0;
+                break;
+            }
+#endif /* MBEDTLS_PK_USE_PSA_EC_DATA */
 
+            /* Opaque key is created by the user (externally from Mbed TLS)
+             * so we assume it already has the right algorithm and flags
+             * set. Just copy its ID as reference. */
+            ssl->handshake->xxdh_psa_privkey = pk->priv_id;
+            ssl->handshake->xxdh_psa_privkey_is_external = 1;
             ret = 0;
             break;
+
+#if !defined(MBEDTLS_PK_USE_PSA_EC_DATA)
         case MBEDTLS_PK_ECKEY:
         case MBEDTLS_PK_ECKEY_DH:
         case MBEDTLS_PK_ECDSA:
-            key = mbedtls_pk_ec(*pk);
-            if (key == NULL) {
+            key = mbedtls_pk_ec_rw(*pk);
+            grp_id = mbedtls_pk_get_ec_group_id(pk);
+            if (grp_id == MBEDTLS_ECP_DP_NONE) {
                 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
             }
-
-            tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(key->grp.id);
+            tls_id = mbedtls_ssl_get_tls_id_from_ecp_group_id(grp_id);
             if (tls_id == 0) {
                 /* This elliptic curve is not supported */
                 return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
@@ -2619,44 +2693,47 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
 
             /* If the above conversion to TLS ID was fine, then also this one will
                be, so there is no need to check the return value here */
-            mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &ecc_family,
-                                                       &ssl->handshake->ecdh_bits);
+            mbedtls_ssl_get_psa_curve_info_from_tls_id(tls_id, &key_type,
+                                                       &ssl->handshake->xxdh_psa_bits);
 
-            ssl->handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ecc_family);
+            ssl->handshake->xxdh_psa_type = key_type;
 
             key_attributes = psa_key_attributes_init();
             psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
             psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
             psa_set_key_type(&key_attributes,
-                             PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->ecdh_psa_type));
-            psa_set_key_bits(&key_attributes, ssl->handshake->ecdh_bits);
+                             PSA_KEY_TYPE_ECC_KEY_PAIR(ssl->handshake->xxdh_psa_type));
+            psa_set_key_bits(&key_attributes, ssl->handshake->xxdh_psa_bits);
 
-            key_len = PSA_BITS_TO_BYTES(key->grp.pbits);
-            ret = mbedtls_ecp_write_key(key, buf, key_len);
+            ret = mbedtls_ecp_write_key_ext(key, &key_len, buf, sizeof(buf));
             if (ret != 0) {
-                goto cleanup;
+                mbedtls_platform_zeroize(buf, sizeof(buf));
+                break;
             }
 
             status = psa_import_key(&key_attributes, buf, key_len,
-                                    &ssl->handshake->ecdh_psa_privkey);
+                                    &ssl->handshake->xxdh_psa_privkey);
             if (status != PSA_SUCCESS) {
                 ret = PSA_TO_MBEDTLS_ERR(status);
-                goto cleanup;
+                mbedtls_platform_zeroize(buf, sizeof(buf));
+                break;
             }
 
+            mbedtls_platform_zeroize(buf, sizeof(buf));
             ret = 0;
             break;
+#endif /* !MBEDTLS_PK_USE_PSA_EC_DATA */
         default:
             ret = MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH;
     }
 
-cleanup:
+exit:
+    psa_reset_key_attributes(&key_attributes);
     mbedtls_platform_zeroize(buf, sizeof(buf));
 
     return ret;
 }
-#elif defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
-    defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
+#else /* MBEDTLS_USE_PSA_CRYPTO */
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
 {
@@ -2674,7 +2751,7 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
     }
 
     if ((ret = mbedtls_ecdh_get_params(&ssl->handshake->ecdh_ctx,
-                                       mbedtls_pk_ec(*mbedtls_ssl_own_key(ssl)),
+                                       mbedtls_pk_ec_ro(*mbedtls_ssl_own_key(ssl)),
                                        MBEDTLS_ECDH_OURS)) != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ecdh_get_params"), ret);
         return ret;
@@ -2682,6 +2759,7 @@ static int ssl_get_ecdh_params_from_cert(mbedtls_ssl_context *ssl)
 
     return 0;
 }
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
           MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 
@@ -2734,9 +2812,9 @@ static int ssl_prepare_server_key_exchange(mbedtls_ssl_context *ssl,
 
 #if defined(MBEDTLS_KEY_EXCHANGE_WITH_SERVER_SIGNATURE_ENABLED)
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    size_t out_buf_len = ssl->out_buf_len - (ssl->out_msg - ssl->out_buf);
+    size_t out_buf_len = ssl->out_buf_len - (size_t) (ssl->out_msg - ssl->out_buf);
 #else
-    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (ssl->out_msg - ssl->out_buf);
+    size_t out_buf_len = MBEDTLS_SSL_OUT_BUFFER_LEN - (size_t) (ssl->out_msg - ssl->out_buf);
 #endif
 #endif
 
@@ -2923,26 +3001,26 @@ curve_matching_done:
         const size_t header_size = 4; // curve_type(1), namedcurve(2),
                                       // data length(1)
         const size_t data_length_size = 1;
-        psa_ecc_family_t ec_psa_family = 0;
+        psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
         size_t ec_bits = 0;
 
         MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
 
         /* Convert EC's TLS ID to PSA key type. */
         if (mbedtls_ssl_get_psa_curve_info_from_tls_id(*curr_tls_id,
-                                                       &ec_psa_family,
+                                                       &key_type,
                                                        &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
             MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid ecc group parse."));
             return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
         }
-        handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
-        handshake->ecdh_bits = ec_bits;
+        handshake->xxdh_psa_type = key_type;
+        handshake->xxdh_psa_bits = ec_bits;
 
         key_attributes = psa_key_attributes_init();
         psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
         psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
-        psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
-        psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+        psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);
+        psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);
 
         /*
          * ECParameters curve_params
@@ -2959,7 +3037,7 @@ curve_matching_done:
 
         /* Generate ECDH private key. */
         status = psa_generate_key(&key_attributes,
-                                  &handshake->ecdh_psa_privkey);
+                                  &handshake->xxdh_psa_privkey);
         if (status != PSA_SUCCESS) {
             ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
@@ -2981,14 +3059,14 @@ curve_matching_done:
         size_t own_pubkey_max_len = (size_t) (MBEDTLS_SSL_OUT_CONTENT_LEN
                                               - (own_pubkey - ssl->out_msg));
 
-        status = psa_export_public_key(handshake->ecdh_psa_privkey,
+        status = psa_export_public_key(handshake->xxdh_psa_privkey,
                                        own_pubkey, own_pubkey_max_len,
                                        &len);
         if (status != PSA_SUCCESS) {
             ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
-            (void) psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            (void) psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return ret;
         }
 
@@ -3041,9 +3119,9 @@ curve_matching_done:
             return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
 
-        size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
+        size_t dig_signed_len = (size_t) (ssl->out_msg + ssl->out_msglen - dig_signed);
         size_t hashlen = 0;
-        unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+        unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -3056,8 +3134,8 @@ curve_matching_done:
         mbedtls_pk_type_t sig_alg =
             mbedtls_ssl_get_ciphersuite_sig_pk_alg(ciphersuite_info);
 
-        unsigned int sig_hash =
-            mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
+        unsigned char sig_hash =
+            (unsigned char) mbedtls_ssl_tls12_get_preferred_hash_for_sig_alg(
                 ssl, mbedtls_ssl_sig_from_pk_alg(sig_alg));
 
         mbedtls_md_type_t md_alg = mbedtls_ssl_md_alg_from_hash(sig_hash);
@@ -3315,7 +3393,7 @@ static int ssl_parse_client_dh_public(mbedtls_ssl_context *ssl, unsigned char **
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    n = ((*p)[0] << 8) | (*p)[1];
+    n = MBEDTLS_GET_UINT16_BE(*p, 0);
     *p += 2;
 
     if (*p + n > end) {
@@ -3454,9 +3532,8 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
     unsigned char *pms = ssl->handshake->premaster + pms_offset;
     unsigned char ver[2];
     unsigned char fake_pms[48], peer_pms[48];
-    unsigned char mask;
-    size_t i, peer_pmslen;
-    unsigned int diff;
+    size_t peer_pmslen;
+    mbedtls_ct_condition_t diff;
 
     /* In case of a failure in decryption, the decryption may write less than
      * 2 bytes of output, but we always read the first two bytes. It doesn't
@@ -3485,13 +3562,10 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
     /* Avoid data-dependent branches while checking for invalid
      * padding, to protect against timing-based Bleichenbacher-type
      * attacks. */
-    diff  = (unsigned int) ret;
-    diff |= peer_pmslen ^ 48;
-    diff |= peer_pms[0] ^ ver[0];
-    diff |= peer_pms[1] ^ ver[1];
-
-    /* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
-    mask = mbedtls_ct_uint_mask(diff);
+    diff = mbedtls_ct_bool(ret);
+    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pmslen, 48));
+    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[0], ver[0]));
+    diff = mbedtls_ct_bool_or(diff, mbedtls_ct_uint_ne(peer_pms[1], ver[1]));
 
     /*
      * Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
@@ -3510,7 +3584,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
     }
 
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-    if (diff != 0) {
+    if (diff != MBEDTLS_CT_FALSE) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("bad client key exchange message"));
     }
 #endif
@@ -3524,9 +3598,7 @@ static int ssl_parse_encrypted_pms(mbedtls_ssl_context *ssl,
 
     /* Set pms to either the true or the fake PMS, without
      * data-dependent branches. */
-    for (i = 0; i < ssl->handshake->pmslen; i++) {
-        pms[i] = (mask & fake_pms[i]) | ((~mask) & peer_pms[i]);
-    }
+    mbedtls_ct_memcpy_if(diff, pms, fake_pms, peer_pms, ssl->handshake->pmslen);
 
     return 0;
 }
@@ -3554,7 +3626,7 @@ static int ssl_parse_client_psk_identity(mbedtls_ssl_context *ssl, unsigned char
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    n = ((*p)[0] << 8) | (*p)[1];
+    n = MBEDTLS_GET_UINT16_BE(*p, 0);
     *p += 2;
 
     if (n == 0 || n > end - *p) {
@@ -3667,43 +3739,53 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
         psa_status_t status = PSA_ERROR_GENERIC_ERROR;
         mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
-        MBEDTLS_SSL_DEBUG_MSG(1, ("Read the peer's public key."));
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Read the peer's public key."));
 
         /*
          * We must have at least two bytes (1 for length, at least 1 for data)
          */
         if (buf_len < 2) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length"));
-            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid buffer length: %" MBEDTLS_PRINTF_SIZET,
+                                      buf_len));
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         }
 
         if (data_len < 1 || data_len > buf_len) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length"));
-            return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid data length: %" MBEDTLS_PRINTF_SIZET
+                                      " > %" MBEDTLS_PRINTF_SIZET,
+                                      data_len, buf_len));
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         }
 
         /* Store peer's ECDH public key. */
-        memcpy(handshake->ecdh_psa_peerkey, p, data_len);
-        handshake->ecdh_psa_peerkey_len = data_len;
+        if (data_len > sizeof(handshake->xxdh_psa_peerkey)) {
+            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %" MBEDTLS_PRINTF_SIZET
+                                      " > %" MBEDTLS_PRINTF_SIZET,
+                                      data_len,
+                                      sizeof(handshake->xxdh_psa_peerkey)));
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+        }
+        memcpy(handshake->xxdh_psa_peerkey, p, data_len);
+        handshake->xxdh_psa_peerkey_len = data_len;
 
         /* Compute ECDH shared secret. */
         status = psa_raw_key_agreement(
-            PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
-            handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
+            PSA_ALG_ECDH, handshake->xxdh_psa_privkey,
+            handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len,
             handshake->premaster, sizeof(handshake->premaster),
             &handshake->pmslen);
         if (status != PSA_SUCCESS) {
             ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_raw_key_agreement", ret);
-            if (handshake->ecdh_psa_privkey_is_external == 0) {
-                (void) psa_destroy_key(handshake->ecdh_psa_privkey);
+            if (handshake->xxdh_psa_privkey_is_external == 0) {
+                (void) psa_destroy_key(handshake->xxdh_psa_privkey);
             }
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return ret;
         }
 
-        if (handshake->ecdh_psa_privkey_is_external == 0) {
-            status = psa_destroy_key(handshake->ecdh_psa_privkey);
+        if (handshake->xxdh_psa_privkey_is_external == 0) {
+            status = psa_destroy_key(handshake->xxdh_psa_privkey);
 
             if (status != PSA_SUCCESS) {
                 ret = PSA_TO_MBEDTLS_ERR(status);
@@ -3711,10 +3793,10 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
                 return ret;
             }
         }
-        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 #else
         if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,
-                                            p, end - p)) != 0) {
+                                            p, (size_t) (end - p))) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret);
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
@@ -3753,7 +3835,8 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
 
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
         if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
-                                                    ciphersuite_info->key_exchange)) != 0) {
+                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->
+                                                    key_exchange)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
             return ret;
         }
@@ -3785,7 +3868,8 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
 
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
         if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
-                                                    ciphersuite_info->key_exchange)) != 0) {
+                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->
+                                                    key_exchange)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
             return ret;
         }
@@ -3826,7 +3910,8 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
         MBEDTLS_SSL_DEBUG_MPI(3, "DHM: K ", &ssl->handshake->dhm_ctx.K);
 #else
         if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
-                                                    ciphersuite_info->key_exchange)) != 0) {
+                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->
+                                                    key_exchange)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
             return ret;
         }
@@ -3838,39 +3923,48 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
         psa_status_t destruction_status = PSA_ERROR_CORRUPTION_DETECTED;
-        uint8_t ecpoint_len;
+        size_t ecpoint_len;
 
         mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
         if ((ret = ssl_parse_client_psk_identity(ssl, &p, end)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, ("ssl_parse_client_psk_identity"), ret);
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return ret;
         }
 
         /* Keep a copy of the peer's public key */
         if (p >= end) {
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
 
         ecpoint_len = *(p++);
         if ((size_t) (end - p) < ecpoint_len) {
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
 
-        if (ecpoint_len > sizeof(handshake->ecdh_psa_peerkey)) {
-            psa_destroy_key(handshake->ecdh_psa_privkey);
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        /* When FFDH is enabled, the array handshake->xxdh_psa_peer_key size takes into account
+           the sizes of the FFDH keys which are at least 2048 bits.
+           The size of the array is thus greater than 256 bytes which is greater than any
+           possible value of ecpoint_len (type uint8_t) and the check below can be skipped.*/
+#if !defined(PSA_WANT_ALG_FFDH)
+        if (ecpoint_len > sizeof(handshake->xxdh_psa_peerkey)) {
+            psa_destroy_key(handshake->xxdh_psa_privkey);
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
             return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         }
+#else
+        MBEDTLS_STATIC_ASSERT(sizeof(handshake->xxdh_psa_peerkey) >= UINT8_MAX,
+                              "peer key buffer too small");
+#endif
 
-        memcpy(handshake->ecdh_psa_peerkey, p, ecpoint_len);
-        handshake->ecdh_psa_peerkey_len = ecpoint_len;
+        memcpy(handshake->xxdh_psa_peerkey, p, ecpoint_len);
+        handshake->xxdh_psa_peerkey_len = ecpoint_len;
         p += ecpoint_len;
 
         /* As RFC 5489 section 2, the premaster secret is formed as follows:
@@ -3888,15 +3982,15 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
 
         /* Compute ECDH shared secret. */
         status = psa_raw_key_agreement(PSA_ALG_ECDH,
-                                       handshake->ecdh_psa_privkey,
-                                       handshake->ecdh_psa_peerkey,
-                                       handshake->ecdh_psa_peerkey_len,
+                                       handshake->xxdh_psa_privkey,
+                                       handshake->xxdh_psa_peerkey,
+                                       handshake->xxdh_psa_peerkey_len,
                                        psm + zlen_size,
                                        psm_end - (psm + zlen_size),
                                        &zlen);
 
-        destruction_status = psa_destroy_key(handshake->ecdh_psa_privkey);
-        handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        destruction_status = psa_destroy_key(handshake->xxdh_psa_privkey);
+        handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
 
         if (status != PSA_SUCCESS) {
             return PSA_TO_MBEDTLS_ERR(status);
@@ -3915,7 +4009,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
         }
 
         if ((ret = mbedtls_ecdh_read_public(&ssl->handshake->ecdh_ctx,
-                                            p, end - p)) != 0) {
+                                            p, (size_t) (end - p))) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecdh_read_public", ret);
             return MBEDTLS_ERR_SSL_DECODE_ERROR;
         }
@@ -3924,7 +4018,8 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
                                MBEDTLS_DEBUG_ECDH_QP);
 
         if ((ret = mbedtls_ssl_psk_derive_premaster(ssl,
-                                                    ciphersuite_info->key_exchange)) != 0) {
+                                                    (mbedtls_key_exchange_type_t) ciphersuite_info->
+                                                    key_exchange)) != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_psk_derive_premaster", ret);
             return ret;
         }
@@ -3943,7 +4038,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
     if (ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
         if ((ret = mbedtls_psa_ecjpake_read_round(
-                 &ssl->handshake->psa_pake_ctx, p, end - p,
+                 &ssl->handshake->psa_pake_ctx, p, (size_t) (end - p),
                  MBEDTLS_ECJPAKE_ROUND_TWO)) != 0) {
             psa_destroy_key(ssl->handshake->psa_pake_password);
             psa_pake_abort(&ssl->handshake->psa_pake_ctx);
@@ -3953,7 +4048,7 @@ static int ssl_parse_client_key_exchange(mbedtls_ssl_context *ssl)
         }
 #else
         ret = mbedtls_ecjpake_read_round_two(&ssl->handshake->ecjpake_ctx,
-                                             p, end - p);
+                                             p, (size_t) (end - p));
         if (ret != 0) {
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ecjpake_read_round_two", ret);
             return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
@@ -4127,7 +4222,7 @@ static int ssl_parse_certificate_verify(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    sig_len = (ssl->in_msg[i] << 8) | ssl->in_msg[i+1];
+    sig_len = MBEDTLS_GET_UINT16_BE(ssl->in_msg, i);
     i += 2;
 
     if (i + sig_len != ssl->in_hslen) {
@@ -4188,6 +4283,9 @@ static int ssl_write_new_session_ticket(mbedtls_ssl_context *ssl)
      * 10 .  9+n ticket content
      */
 
+#if defined(MBEDTLS_HAVE_TIME)
+    ssl->session_negotiate->ticket_creation_time = mbedtls_ms_time();
+#endif
     if ((ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
                                          ssl->session_negotiate,
                                          ssl->out_msg + 10,
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c
index a7fecedfdaa9e68765069c92cdb5a44b680f930f..b63b5e63c5b41f3e1030192ee474255f19b85afe 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_client.c
@@ -2,21 +2,7 @@
  *  TLS 1.3 client-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS ( https://tls.mbed.org )
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -25,7 +11,7 @@
 
 #include <string.h>
 
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
 
@@ -33,10 +19,19 @@
 #include "ssl_client.h"
 #include "ssl_tls13_keys.h"
 #include "ssl_debug_helpers.h"
+#include "mbedtls/psa_util.h"
 
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
+#endif
 
 /* Write extensions */
 
@@ -117,7 +112,8 @@ static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,
     }
 
     if (&buf[2] != end) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("supported_versions ext data length incorrect"));
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("supported_versions ext data length incorrect"));
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
                                      MBEDTLS_ERR_SSL_DECODE_ERROR);
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
@@ -184,23 +180,24 @@ static int ssl_tls13_reset_key_share(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-#if defined(MBEDTLS_ECDH_C)
-    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) ||
+        mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {
         int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
         psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
         /* Destroy generated private key. */
-        status = psa_destroy_key(ssl->handshake->ecdh_psa_privkey);
+        status = psa_destroy_key(ssl->handshake->xxdh_psa_privkey);
         if (status != PSA_SUCCESS) {
             ret = PSA_TO_MBEDTLS_ERR(status);
             MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
             return ret;
         }
 
-        ssl->handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+        ssl->handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
         return 0;
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
     if (0 /* other KEMs? */) {
         /* Do something */
     }
@@ -219,7 +216,7 @@ static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl,
     int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
 
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
     const uint16_t *group_list = mbedtls_ssl_get_groups(ssl);
     /* Pick first available ECDHE group compatible with TLS 1.3 */
     if (group_list == NULL) {
@@ -227,22 +224,25 @@ static int ssl_tls13_get_default_group_id(mbedtls_ssl_context *ssl,
     }
 
     for (; *group_list != 0; group_list++) {
-        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list,
-                                                        NULL, NULL) == PSA_SUCCESS) &&
+#if defined(PSA_WANT_ALG_ECDH)
+        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(
+                 *group_list, NULL, NULL) == PSA_SUCCESS) &&
             mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) {
             *group_id = *group_list;
             return 0;
         }
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+        if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {
+            *group_id = *group_list;
+            return 0;
+        }
+#endif
     }
 #else
     ((void) ssl);
     ((void) group_id);
-#endif /* MBEDTLS_ECDH_C */
-
-    /*
-     * Add DHE named groups here.
-     * Pick first available DHE group compatible with TLS 1.3
-     */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
 
     return ret;
 }
@@ -287,7 +287,7 @@ static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
     /* HRR could already have requested something else. */
     group_id = ssl->handshake->offered_group_id;
     if (!mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) &&
-        !mbedtls_ssl_tls13_named_group_is_dhe(group_id)) {
+        !mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_get_default_group_id(ssl,
                                                             &group_id));
     }
@@ -301,8 +301,9 @@ static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
      * only one key share entry is allowed.
      */
     client_shares = p;
-#if defined(MBEDTLS_ECDH_C)
-    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id)) {
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group_id) ||
+        mbedtls_ssl_tls13_named_group_is_ffdh(group_id)) {
         /* Pointer to group */
         unsigned char *group = p;
         /* Length of key_exchange */
@@ -314,7 +315,7 @@ static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
          */
         MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
         p += 4;
-        ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+        ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(
             ssl, group_id, p, end, &key_exchange_len);
         p += key_exchange_len;
         if (ret != 0) {
@@ -326,7 +327,7 @@ static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
         /* Write key_exchange_length */
         MBEDTLS_PUT_UINT16_BE(key_exchange_len, group, 2);
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
     if (0 /* other KEMs? */) {
         /* Do something */
     } else {
@@ -352,7 +353,8 @@ static int ssl_tls13_write_key_share_ext(mbedtls_ssl_context *ssl,
     /* Output the total length of key_share extension. */
     *out_len = p - buf;
 
-    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, key_share extension", buf, *out_len);
+    MBEDTLS_SSL_DEBUG_BUF(
+        3, "client hello, key_share extension", buf, *out_len);
 
     mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_KEY_SHARE);
 
@@ -375,7 +377,7 @@ static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl,
                                              const unsigned char *buf,
                                              const unsigned char *end)
 {
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
     const unsigned char *p = buf;
     int selected_group;
     int found = 0;
@@ -402,15 +404,22 @@ static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl,
      * then the client MUST abort the handshake with an "illegal_parameter" alert.
      */
     for (; *group_list != 0; group_list++) {
-        if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(*group_list,
-                                                        NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) ||
-            *group_list != selected_group) {
-            continue;
+#if defined(PSA_WANT_ALG_ECDH)
+        if (mbedtls_ssl_tls13_named_group_is_ecdhe(*group_list)) {
+            if ((mbedtls_ssl_get_psa_curve_info_from_tls_id(
+                     *group_list, NULL, NULL) == PSA_ERROR_NOT_SUPPORTED) ||
+                *group_list != selected_group) {
+                found = 1;
+                break;
+            }
         }
-
-        /* We found a match */
-        found = 1;
-        break;
+#endif /* PSA_WANT_ALG_ECDH */
+#if defined(PSA_WANT_ALG_FFDH)
+        if (mbedtls_ssl_tls13_named_group_is_ffdh(*group_list)) {
+            found = 1;
+            break;
+        }
+#endif /* PSA_WANT_ALG_FFDH */
     }
 
     /* Client MUST verify that the selected_group field does not
@@ -432,12 +441,12 @@ static int ssl_tls13_parse_hrr_key_share_ext(mbedtls_ssl_context *ssl,
     ssl->handshake->offered_group_id = selected_group;
 
     return 0;
-#else
+#else /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
     (void) ssl;
     (void) buf;
     (void) end;
     return MBEDTLS_ERR_SSL_BAD_CONFIG;
-#endif
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
 }
 
 /*
@@ -472,31 +481,25 @@ static int ssl_tls13_parse_key_share_ext(mbedtls_ssl_context *ssl,
     /* Check that the chosen group matches the one we offered. */
     offered_group = ssl->handshake->offered_group_id;
     if (offered_group != group) {
-        MBEDTLS_SSL_DEBUG_MSG(1,
-                              ("Invalid server key share, our group %u, their group %u",
-                               (unsigned) offered_group, (unsigned) group));
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Invalid server key share, our group %u, their group %u",
+                (unsigned) offered_group, (unsigned) group));
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
 
-#if defined(MBEDTLS_ECDH_C)
-    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) {
-        if (mbedtls_ssl_get_psa_curve_info_from_tls_id(group, NULL, NULL)
-            == PSA_ERROR_NOT_SUPPORTED) {
-            MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid TLS curve group id"));
-            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
-        }
-
-        MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH curve: %s",
-                                  mbedtls_ssl_get_curve_name_from_tls_id(group)));
-
-        ret = mbedtls_ssl_tls13_read_public_ecdhe_share(ssl, p, end - p);
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) ||
+        mbedtls_ssl_tls13_named_group_is_ffdh(group)) {
+        MBEDTLS_SSL_DEBUG_MSG(2,
+                              ("DHE group name: %s", mbedtls_ssl_named_group_to_str(group)));
+        ret = mbedtls_ssl_tls13_read_public_xxdhe_share(ssl, p, end - p);
         if (ret != 0) {
             return ret;
         }
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
     if (0 /* other KEMs? */) {
         /* Do something */
     } else {
@@ -618,7 +621,7 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
     /* Skip writing extension if no PSK key exchange mode
      * is enabled in the config.
      */
-    if (!mbedtls_ssl_conf_tls13_some_psk_enabled(ssl)) {
+    if (!mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl)) {
         MBEDTLS_SSL_DEBUG_MSG(3, ("skip psk_key_exchange_modes extension"));
         return 0;
     }
@@ -637,14 +640,14 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
      */
     p += 5;
 
-    if (mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl)) {
+    if (mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl)) {
         *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_ECDHE;
         ke_modes_len++;
 
         MBEDTLS_SSL_DEBUG_MSG(4, ("Adding PSK-ECDHE key exchange mode"));
     }
 
-    if (mbedtls_ssl_conf_tls13_psk_enabled(ssl)) {
+    if (mbedtls_ssl_conf_tls13_is_psk_enabled(ssl)) {
         *p++ = MBEDTLS_SSL_TLS1_3_PSK_MODE_PURE;
         ke_modes_len++;
 
@@ -663,26 +666,26 @@ static int ssl_tls13_write_psk_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
     return 0;
 }
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static psa_algorithm_t ssl_tls13_get_ciphersuite_hash_alg(int ciphersuite)
 {
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info = NULL;
     ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(ciphersuite);
 
     if (ciphersuite_info != NULL) {
-        return mbedtls_psa_translate_md(ciphersuite_info->mac);
+        return mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
     }
 
     return PSA_ALG_NONE;
 }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 static int ssl_tls13_has_configured_ticket(mbedtls_ssl_context *ssl)
 {
     mbedtls_ssl_session *session = ssl->session_negotiate;
     return ssl->handshake->resume &&
            session != NULL && session->ticket != NULL &&
-           mbedtls_ssl_conf_tls13_check_kex_modes(
-        ssl, mbedtls_ssl_session_get_ticket_flags(
+           mbedtls_ssl_conf_tls13_is_kex_mode_enabled(
+        ssl, mbedtls_ssl_tls13_session_get_ticket_flags(
             session, MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL));
 }
 
@@ -692,10 +695,8 @@ static int ssl_tls13_early_data_has_valid_ticket(mbedtls_ssl_context *ssl)
     mbedtls_ssl_session *session = ssl->session_negotiate;
     return ssl->handshake->resume &&
            session->tls_version == MBEDTLS_SSL_VERSION_TLS1_3 &&
-           (session->ticket_flags &
-            MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA) &&
-           mbedtls_ssl_tls13_cipher_suite_is_offered(
-        ssl, session->ciphersuite);
+           mbedtls_ssl_tls13_session_ticket_allow_early_data(session) &&
+           mbedtls_ssl_tls13_cipher_suite_is_offered(ssl, session->ciphersuite);
 }
 #endif
 
@@ -847,7 +848,7 @@ static int ssl_tls13_write_binder(mbedtls_ssl_context *ssl,
 
     /* Get current state of handshake transcript. */
     ret = mbedtls_ssl_get_handshake_transcript(
-        ssl, mbedtls_hash_info_md_from_psa(hash_alg),
+        ssl, mbedtls_md_type_from_psa_alg(hash_alg),
         transcript, sizeof(transcript), &transcript_len);
     if (ret != 0) {
         return ret;
@@ -928,28 +929,14 @@ int mbedtls_ssl_tls13_write_identities_of_pre_shared_key_ext(
     if (ssl_tls13_ticket_get_identity(
             ssl, &hash_alg, &identity, &identity_len) == 0) {
 #if defined(MBEDTLS_HAVE_TIME)
-        mbedtls_time_t now = mbedtls_time(NULL);
+        mbedtls_ms_time_t now = mbedtls_ms_time();
         mbedtls_ssl_session *session = ssl->session_negotiate;
+        /* The ticket age has been checked to be smaller than the
+         * `ticket_lifetime` in ssl_prepare_client_hello() which is smaller than
+         * 7 days (enforced in ssl_tls13_parse_new_session_ticket()) . Thus the
+         * cast to `uint32_t` of the ticket age is safe. */
         uint32_t obfuscated_ticket_age =
-            (uint32_t) (now - session->ticket_received);
-
-        /*
-         * The ticket timestamp is in seconds but the ticket age is in
-         * milliseconds. If the ticket was received at the end of a second and
-         * re-used here just at the beginning of the next second, the computed
-         * age `now - session->ticket_received` is equal to 1s thus 1000 ms
-         * while the actual age could be just a few milliseconds or tens of
-         * milliseconds. If the server has more accurate ticket timestamps
-         * (typically timestamps in milliseconds), as part of the processing of
-         * the ClientHello, it may compute a ticket lifetime smaller than the
-         * one computed here and potentially reject the ticket. To avoid that,
-         * remove one second to the ticket age if possible.
-         */
-        if (obfuscated_ticket_age > 0) {
-            obfuscated_ticket_age -= 1;
-        }
-
-        obfuscated_ticket_age *= 1000;
+            (uint32_t) (now - session->ticket_reception_time);
         obfuscated_ticket_age += session->ticket_age_add;
 
         ret = ssl_tls13_write_identity(ssl, p, end,
@@ -1123,7 +1110,7 @@ static int ssl_tls13_parse_server_pre_shared_key_ext(mbedtls_ssl_context *ssl,
         return ret;
     }
 
-    if (mbedtls_psa_translate_md(ssl->handshake->ciphersuite_info->mac)
+    if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac)
         != hash_alg) {
         MBEDTLS_SSL_DEBUG_MSG(
             1, ("Invalid ciphersuite for external psk."));
@@ -1154,6 +1141,11 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
 
     *out_len = 0;
 
+    ret = mbedtls_ssl_tls13_crypto_init(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
     /* Write supported_versions extension
      *
      * Supported Versions Extension is mandatory with TLS 1.3.
@@ -1173,8 +1165,17 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
     }
     p += ext_len;
 
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    ret = mbedtls_ssl_tls13_write_record_size_limit_ext(
+        ssl, p, end, &ext_len);
+    if (ret != 0) {
+        return ret;
+    }
+    p += ext_len;
+#endif
+
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
-    if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+    if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {
         ret = ssl_tls13_write_key_share_ext(ssl, p, end, &ext_len);
         if (ret != 0) {
             return ret;
@@ -1184,23 +1185,29 @@ int mbedtls_ssl_tls13_write_client_hello_exts(mbedtls_ssl_context *ssl,
 #endif
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
-        ssl_tls13_early_data_has_valid_ticket(ssl) &&
-        ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
-        ret = mbedtls_ssl_tls13_write_early_data_ext(ssl, p, end, &ext_len);
-        if (ret != 0) {
-            return ret;
-        }
-        p += ext_len;
+    /* In the first ClientHello, write the early data indication extension if
+     * necessary and update the early data state.
+     * If an HRR has been received and thus we are currently writing the
+     * second ClientHello, the second ClientHello must not contain an early
+     * data extension and the early data state must stay as it is:
+     * MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT or
+     * MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED.
+     */
+    if (!ssl->handshake->hello_retry_request_flag) {
+        if (mbedtls_ssl_conf_tls13_is_some_psk_enabled(ssl) &&
+            ssl_tls13_early_data_has_valid_ticket(ssl) &&
+            ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED) {
+            ret = mbedtls_ssl_tls13_write_early_data_ext(
+                ssl, 0, p, end, &ext_len);
+            if (ret != 0) {
+                return ret;
+            }
+            p += ext_len;
 
-        /* Initializes the status to `rejected`. It will be updated to
-         * `accepted` if the EncryptedExtension message contain an early data
-         * indication extension.
-         */
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("<= skip write early_data extension"));
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT;
+            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT;
+        } else {
+            ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT;
+        }
     }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
@@ -1237,11 +1244,7 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)
     size_t psk_len;
     const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
 
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
-#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
-        mbedtls_ssl_handshake_set_state(
-            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);
-#endif
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_IND_SENT) {
         MBEDTLS_SSL_DEBUG_MSG(
             1, ("Set hs psk for early data when writing the first psk"));
 
@@ -1296,6 +1299,16 @@ int mbedtls_ssl_tls13_finalize_client_hello(mbedtls_ssl_context *ssl)
             return ret;
         }
 
+#if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO);
+#else
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Switch to early data keys for outbound traffic"));
+        mbedtls_ssl_set_outbound_transform(
+            ssl, ssl->handshake->transform_earlydata);
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
+#endif
     }
 #endif /* MBEDTLS_SSL_EARLY_DATA */
     return 0;
@@ -1324,8 +1337,8 @@ static int ssl_tls13_is_supported_versions_ext_present(
 {
     const unsigned char *p = buf;
     size_t legacy_session_id_echo_len;
-    size_t extensions_len;
-    const unsigned char *extensions_end;
+    const unsigned char *supported_versions_data;
+    const unsigned char *supported_versions_data_end;
 
     /*
      * Check there is enough data to access the legacy_session_id_echo vector
@@ -1347,45 +1360,9 @@ static int ssl_tls13_is_supported_versions_ext_present(
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_echo_len + 4);
     p += legacy_session_id_echo_len + 4;
 
-    /* Case of no extension */
-    if (p == end) {
-        return 0;
-    }
-
-    /* ...
-     * Extension extensions<6..2^16-1>;
-     * ...
-     * struct {
-     *      ExtensionType extension_type; (2 bytes)
-     *      opaque extension_data<0..2^16-1>;
-     * } Extension;
-     */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
-    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
-    p += 2;
-
-    /* Check extensions do not go beyond the buffer of data. */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
-    extensions_end = p + extensions_len;
-
-    while (p < extensions_end) {
-        unsigned int extension_type;
-        size_t extension_data_len;
-
-        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
-        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
-        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
-        p += 4;
-
-        if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {
-            return 1;
-        }
-
-        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
-        p += extension_data_len;
-    }
-
-    return 0;
+    return mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+        ssl, p, end,
+        &supported_versions_data, &supported_versions_data_end);
 }
 
 /* Returns a negative value on failure, and otherwise
@@ -1446,8 +1423,8 @@ static int ssl_server_hello_is_hrr(mbedtls_ssl_context *ssl,
      * } ServerHello;
      *
      */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end,
-                                 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic));
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(
+        buf, end, 2 + sizeof(mbedtls_ssl_tls13_hello_retry_request_magic));
 
     if (memcmp(buf + 2, mbedtls_ssl_tls13_hello_retry_request_magic,
                sizeof(mbedtls_ssl_tls13_hello_retry_request_magic)) == 0) {
@@ -1491,13 +1468,20 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
             return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
         }
 
+        /*
+         * Version 1.2 of the protocol has been negotiated, set the
+         * ssl->keep_current_message flag for the ServerHello to be kept and
+         * parsed as a TLS 1.2 ServerHello. We also change ssl->tls_version to
+         * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step()
+         * will dispatch to the TLS 1.2 state machine.
+         */
         ssl->keep_current_message = 1;
         ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
-        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                                MBEDTLS_SSL_HS_SERVER_HELLO,
-                                                                buf, (size_t) (end - buf)));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                                 ssl, MBEDTLS_SSL_HS_SERVER_HELLO,
+                                 buf, (size_t) (end - buf)));
 
-        if (mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+        if (mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {
             ret = ssl_tls13_reset_key_share(ssl);
             if (ret != 0) {
                 return ret;
@@ -1507,10 +1491,8 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
         return SSL_SERVER_HELLO_TLS1_2;
     }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
     ssl->session_negotiate->tls_version = ssl->tls_version;
-#endif /* MBEDTLS_SSL_SESSION_TICKETS */
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
 
     handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
 
@@ -1521,15 +1503,16 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
             break;
         case SSL_SERVER_HELLO_HRR:
             MBEDTLS_SSL_DEBUG_MSG(2, ("received HelloRetryRequest message"));
-            /* If a client receives a second
-             * HelloRetryRequest in the same connection (i.e., where the ClientHello
-             * was itself in response to a HelloRetryRequest), it MUST abort the
-             * handshake with an "unexpected_message" alert.
+            /* If a client receives a second HelloRetryRequest in the same
+             * connection (i.e., where the ClientHello was itself in response
+             * to a HelloRetryRequest), it MUST abort the handshake with an
+             * "unexpected_message" alert.
              */
-            if (handshake->hello_retry_request_count > 0) {
+            if (handshake->hello_retry_request_flag) {
                 MBEDTLS_SSL_DEBUG_MSG(1, ("Multiple HRRs received"));
-                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
-                                             MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                    MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
                 return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
             }
             /*
@@ -1538,7 +1521,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
              * in the ClientHello.
              * In a PSK only key exchange that what we expect.
              */
-            if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+            if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {
                 MBEDTLS_SSL_DEBUG_MSG(1,
                                       ("Unexpected HRR in pure PSK key exchange."));
                 MBEDTLS_SSL_PEND_FATAL_ALERT(
@@ -1547,7 +1530,7 @@ static int ssl_tls13_preprocess_server_hello(mbedtls_ssl_context *ssl,
                 return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
             }
 
-            handshake->hello_retry_request_count++;
+            handshake->hello_retry_request_flag = 1;
 
             break;
     }
@@ -1702,7 +1685,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,
      * proposed in the HRR, we abort the handshake and send an
      * "illegal_parameter" alert.
      */
-    else if ((!is_hrr) && (handshake->hello_retry_request_count > 0) &&
+    else if ((!is_hrr) && handshake->hello_retry_request_flag &&
              (cipher_suite != ssl->session_negotiate->ciphersuite)) {
         fatal_alert = MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER;
     }
@@ -1721,7 +1704,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,
                               cipher_suite, ciphersuite_info->name));
 
 #if defined(MBEDTLS_HAVE_TIME)
-    ssl->session_negotiate->start = time(NULL);
+    ssl->session_negotiate->start = mbedtls_time(NULL);
 #endif /* MBEDTLS_HAVE_TIME */
 
     /* ...
@@ -1815,7 +1798,7 @@ static int ssl_tls13_parse_server_hello(mbedtls_ssl_context *ssl,
 
             case MBEDTLS_TLS_EXT_KEY_SHARE:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found key_shares extension"));
-                if (!mbedtls_ssl_conf_tls13_some_ephemeral_enabled(ssl)) {
+                if (!mbedtls_ssl_conf_tls13_is_some_ephemeral_enabled(ssl)) {
                     fatal_alert = MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT;
                     goto cleanup;
                 }
@@ -1890,20 +1873,25 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
      *    exchange mode is EPHEMERAL-only.
      */
     switch (handshake->received_extensions &
-            (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) {
+            (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) |
+             MBEDTLS_SSL_EXT_MASK(KEY_SHARE))) {
         /* Only the pre_shared_key extension was received */
         case MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY):
-            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+            handshake->key_exchange_mode =
+                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
             break;
 
         /* Only the key_share extension was received */
         case MBEDTLS_SSL_EXT_MASK(KEY_SHARE):
-            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+            handshake->key_exchange_mode =
+                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
             break;
 
         /* Both the pre_shared_key and key_share extensions were received */
-        case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) | MBEDTLS_SSL_EXT_MASK(KEY_SHARE)):
-            handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        case (MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY) |
+              MBEDTLS_SSL_EXT_MASK(KEY_SHARE)):
+            handshake->key_exchange_mode =
+                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
             break;
 
         /* Neither pre_shared_key nor key_share extension was received */
@@ -1912,49 +1900,19 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
             ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
             goto cleanup;
     }
-#if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA) &&
-        (handshake->selected_identity != 0 ||
-         handshake->ciphersuite_info->id !=
-         ssl->session_negotiate->ciphersuite)) {
-        /* RFC8446 4.2.11
-         * If the server supplies an "early_data" extension, the
-         * client MUST verify that the server's selected_identity
-         * is 0. If any other value is returned, the client MUST
-         * abort the handshake with an "illegal_parameter" alert.
-         *
-         * RFC 8446 4.2.10
-         * In order to accept early data, the server MUST have accepted a PSK
-         * cipher suite and selected the first key offered in the client's
-         * "pre_shared_key" extension. In addition, it MUST verify that the
-         * following values are the same as those associated with the
-         * selected PSK:
-         * - The TLS version number
-         * - The selected cipher suite
-         * - The selected ALPN [RFC7301] protocol, if any
-         *
-         * We check here that when early data is involved the server
-         * selected the cipher suite associated to the pre-shared key
-         * as it must have.
-         */
-        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
-                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
-        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
-    }
-#endif
 
-    if (!mbedtls_ssl_conf_tls13_check_kex_modes(
+    if (!mbedtls_ssl_conf_tls13_is_kex_mode_enabled(
             ssl, handshake->key_exchange_mode)) {
         ret = MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-        MBEDTLS_SSL_DEBUG_MSG(2,
-                              ("Key exchange mode(%s) is not supported.",
-                               ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
+        MBEDTLS_SSL_DEBUG_MSG(
+            2, ("Key exchange mode(%s) is not supported.",
+                ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
         goto cleanup;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(3,
-                          ("Selected key exchange mode: %s",
-                           ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
+    MBEDTLS_SSL_DEBUG_MSG(
+        3, ("Selected key exchange mode: %s",
+            ssl_tls13_get_kex_mode_str(handshake->key_exchange_mode)));
 
     /* Start the TLS 1.3 key scheduling if not already done.
      *
@@ -1966,7 +1924,7 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
      * cases we compute it here.
      */
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_SENT ||
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT ||
         handshake->key_exchange_mode ==
         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL)
 #endif
@@ -1989,7 +1947,6 @@ static int ssl_tls13_postprocess_server_hello(mbedtls_ssl_context *ssl)
 
     mbedtls_ssl_set_inbound_transform(ssl, handshake->transform_handshake);
     MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic"));
-    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
     ssl->session_in = ssl->session_negotiate;
 
 cleanup:
@@ -2021,6 +1978,13 @@ static int ssl_tls13_postprocess_hrr(mbedtls_ssl_context *ssl)
     }
 
     ssl->session_negotiate->ciphersuite = ssl->handshake->ciphersuite_info->id;
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->early_data_state != MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
+    }
+#endif
+
     return 0;
 }
 
@@ -2038,9 +2002,8 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> %s", __func__));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
-                                                               MBEDTLS_SSL_HS_SERVER_HELLO,
-                                                               &buf, &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len));
 
     ret = ssl_tls13_preprocess_server_hello(ssl, buf, buf + buf_len);
     if (ret < 0) {
@@ -2061,9 +2024,8 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)
         MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_reset_transcript_for_hrr(ssl));
     }
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_SERVER_HELLO, buf,
-                                                            buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, buf, buf_len));
 
     if (is_hrr) {
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_hrr(ssl));
@@ -2072,8 +2034,8 @@ static int ssl_tls13_process_server_hello(mbedtls_ssl_context *ssl)
          * immediately before its second flight. This may either be before
          * its second ClientHello or before its encrypted handshake flight.
          */
-        mbedtls_ssl_handshake_set_state(ssl,
-                                        MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO);
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO);
 #else
         mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
 #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
@@ -2153,7 +2115,8 @@ static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl,
             case MBEDTLS_TLS_EXT_ALPN:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found alpn extension"));
 
-                if ((ret = ssl_tls13_parse_alpn_ext(ssl, p, (size_t) extension_data_len)) != 0) {
+                if ((ret = ssl_tls13_parse_alpn_ext(
+                         ssl, p, (size_t) extension_data_len)) != 0) {
                     return ret;
                 }
 
@@ -2177,12 +2140,13 @@ static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl,
             case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension"));
 
-                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, p + extension_data_len);
-
-                /* TODO: Return unconditionally here until we handle the record size limit correctly.
-                 *            Once handled correctly, only return in case of errors. */
-                return ret;
-
+                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(
+                    ssl, p, p + extension_data_len);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret);
+                    return ret;
+                }
                 break;
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
@@ -2196,6 +2160,17 @@ static int ssl_tls13_parse_encrypted_extensions(mbedtls_ssl_context *ssl,
         p += extension_data_len;
     }
 
+    if ((handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) &&
+        (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(MAX_FRAGMENT_LENGTH))) {
+        MBEDTLS_SSL_DEBUG_MSG(3,
+                              (
+                                  "Record size limit extension cannot be used with max fragment length extension"));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+            MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
     MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
                            handshake->received_extensions);
 
@@ -2216,27 +2191,80 @@ static int ssl_tls13_process_encrypted_extensions(mbedtls_ssl_context *ssl)
     int ret;
     unsigned char *buf;
     size_t buf_len;
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse encrypted extensions"));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
-                                                               MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
-                                                               &buf, &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                             &buf, &buf_len));
 
     /* Process the message contents */
     MBEDTLS_SSL_PROC_CHK(
         ssl_tls13_parse_encrypted_extensions(ssl, buf, buf + buf_len));
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->handshake->received_extensions &
-        MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
-        ssl->early_data_status = MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+        /* RFC8446 4.2.11
+         * If the server supplies an "early_data" extension, the
+         * client MUST verify that the server's selected_identity
+         * is 0. If any other value is returned, the client MUST
+         * abort the handshake with an "illegal_parameter" alert.
+         *
+         * RFC 8446 4.2.10
+         * In order to accept early data, the server MUST have accepted a PSK
+         * cipher suite and selected the first key offered in the client's
+         * "pre_shared_key" extension. In addition, it MUST verify that the
+         * following values are the same as those associated with the
+         * selected PSK:
+         * - The TLS version number
+         * - The selected cipher suite
+         * - The selected ALPN [RFC7301] protocol, if any
+         *
+         * The server has sent an early data extension in its Encrypted
+         * Extension message thus accepted to receive early data. We
+         * check here that the additional constraints on the handshake
+         * parameters, when early data are exchanged, are met,
+         * namely:
+         * - a PSK has been selected for the handshake
+         * - the selected PSK for the handshake was the first one proposed
+         *   by the client.
+         * - the selected ciphersuite for the handshake is the ciphersuite
+         *   associated with the selected PSK.
+         */
+        if ((!mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) ||
+            handshake->selected_identity != 0 ||
+            handshake->ciphersuite_info->id !=
+            ssl->session_negotiate->ciphersuite) {
+
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
+                MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+            return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+        }
+
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED;
+    } else if (ssl->early_data_state !=
+               MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED;
     }
 #endif
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
-                                                            buf, buf_len));
+    /*
+     * In case the client has proposed a PSK associated with a ticket,
+     * `ssl->session_negotiate->ciphersuite` still contains at this point the
+     * identifier of the ciphersuite associated with the ticket. This is that
+     * way because, if an exchange of early data is agreed upon, we need
+     * it to check that the ciphersuite selected for the handshake is the
+     * ticket ciphersuite (see above). This information is not needed
+     * anymore thus we can now set it to the identifier of the ciphersuite
+     * used in this session under negotiation.
+     */
+    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                             buf, buf_len));
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
     if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
@@ -2256,6 +2284,7 @@ cleanup:
 
 }
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
 /*
  * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
  *
@@ -2294,6 +2323,32 @@ cleanup:
     return ret;
 }
 
+int mbedtls_ssl_get_early_data_status(mbedtls_ssl_context *ssl)
+{
+    if ((ssl->conf->endpoint != MBEDTLS_SSL_IS_CLIENT) ||
+        (!mbedtls_ssl_is_handshake_over(ssl))) {
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
+    }
+
+    switch (ssl->early_data_state) {
+        case MBEDTLS_SSL_EARLY_DATA_STATE_NO_IND_SENT:
+            return MBEDTLS_SSL_EARLY_DATA_STATUS_NOT_INDICATED;
+            break;
+
+        case MBEDTLS_SSL_EARLY_DATA_STATE_REJECTED:
+            return MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED;
+            break;
+
+        case MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED:
+            return MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED;
+            break;
+
+        default:
+            return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
 /*
  * STATE HANDLING: CertificateRequest
@@ -2472,16 +2527,16 @@ static int ssl_tls13_process_certificate_request(mbedtls_ssl_context *ssl)
         unsigned char *buf;
         size_t buf_len;
 
-        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
-                                                                   MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
-                                                                   &buf, &buf_len));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                 &buf, &buf_len));
 
-        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(ssl,
-                                                                 buf, buf + buf_len));
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_request(
+                                 ssl, buf, buf + buf_len));
 
-        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                                MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
-                                                                buf, buf_len));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                 buf, buf_len));
     } else if (ret == SSL_CERTIFICATE_REQUEST_SKIP) {
         ret = 0;
     } else {
@@ -2555,10 +2610,9 @@ static int ssl_tls13_process_server_finished(mbedtls_ssl_context *ssl)
     }
 
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_ACCEPTED) {
+    if (ssl->early_data_state == MBEDTLS_SSL_EARLY_DATA_STATE_ACCEPTED) {
+        ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_SERVER_FINISHED_RECEIVED;
         mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
-    } else if (ssl->early_data_status == MBEDTLS_SSL_EARLY_DATA_STATUS_REJECTED) {
-        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
     } else
 #endif /* MBEDTLS_SSL_EARLY_DATA */
     {
@@ -2643,8 +2697,8 @@ static int ssl_tls13_write_client_finished(mbedtls_ssl_context *ssl)
 
     ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1,
-                              "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret);
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_tls13_compute_resumption_master_secret ", ret);
         return ret;
     }
 
@@ -2678,6 +2732,37 @@ static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/* From RFC 8446 section 4.2.10
+ *
+ * struct {
+ *     select (Handshake.msg_type) {
+ *         case new_session_ticket:   uint32 max_early_data_size;
+ *         ...
+ *     };
+ * } EarlyDataIndication;
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_new_session_ticket_early_data_ext(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *buf,
+    const unsigned char *end)
+{
+    mbedtls_ssl_session *session = ssl->session;
+
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(buf, end, 4);
+
+    session->max_early_data_size = MBEDTLS_GET_UINT32_BE(buf, 0);
+    mbedtls_ssl_tls13_session_set_ticket_flags(
+        session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+    MBEDTLS_SSL_DEBUG_MSG(
+        3, ("received max_early_data_size: %u",
+            (unsigned int) session->max_early_data_size));
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl,
                                                    const unsigned char *buf,
@@ -2711,15 +2796,12 @@ static int ssl_tls13_parse_new_session_ticket_exts(mbedtls_ssl_context *ssl,
         switch (extension_type) {
 #if defined(MBEDTLS_SSL_EARLY_DATA)
             case MBEDTLS_TLS_EXT_EARLY_DATA:
-                if (extension_data_len != 4) {
-                    MBEDTLS_SSL_PEND_FATAL_ALERT(
-                        MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
-                        MBEDTLS_ERR_SSL_DECODE_ERROR);
-                    return MBEDTLS_ERR_SSL_DECODE_ERROR;
-                }
-                if (ssl->session != NULL) {
-                    ssl->session->ticket_flags |=
-                        MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA;
+                ret = ssl_tls13_parse_new_session_ticket_early_data_ext(
+                    ssl, p, p + extension_data_len);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "ssl_tls13_parse_new_session_ticket_early_data_ext",
+                        ret);
                 }
                 break;
 #endif /* MBEDTLS_SSL_EARLY_DATA */
@@ -2779,6 +2861,11 @@ static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,
     MBEDTLS_SSL_DEBUG_MSG(3,
                           ("ticket_lifetime: %u",
                            (unsigned int) session->ticket_lifetime));
+    if (session->ticket_lifetime >
+        MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime exceeds 7 days."));
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
 
     session->ticket_age_add = MBEDTLS_GET_UINT32_BE(p, 4);
     MBEDTLS_SSL_DEBUG_MSG(3,
@@ -2817,7 +2904,7 @@ static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,
     session->ticket_len = ticket_len;
 
     /* Clear all flags in ticket_flags */
-    mbedtls_ssl_session_clear_ticket_flags(
+    mbedtls_ssl_tls13_session_clear_ticket_flags(
         session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
 
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
@@ -2835,12 +2922,17 @@ static int ssl_tls13_parse_new_session_ticket(mbedtls_ssl_context *ssl,
         return ret;
     }
 
-    /* session has been updated, allow export */
-    session->exported = 0;
-
     return 0;
 }
 
+/* Non negative return values for ssl_tls13_postprocess_new_session_ticket().
+ * - POSTPROCESS_NEW_SESSION_TICKET_SIGNAL, all good, we have to signal the
+ *   application that a valid ticket has been received.
+ * - POSTPROCESS_NEW_SESSION_TICKET_DISCARD, no fatal error, we keep the
+ *   connection alive but we do not signal the ticket to the application.
+ */
+#define POSTPROCESS_NEW_SESSION_TICKET_SIGNAL 0
+#define POSTPROCESS_NEW_SESSION_TICKET_DISCARD 1
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
                                                     unsigned char *ticket_nonce,
@@ -2852,9 +2944,13 @@ static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
     psa_algorithm_t psa_hash_alg;
     int hash_length;
 
+    if (session->ticket_lifetime == 0) {
+        return POSTPROCESS_NEW_SESSION_TICKET_DISCARD;
+    }
+
 #if defined(MBEDTLS_HAVE_TIME)
     /* Store ticket creation time */
-    session->ticket_received = mbedtls_time(NULL);
+    session->ticket_reception_time = mbedtls_ms_time();
 #endif
 
     ciphersuite_info = mbedtls_ssl_ciphersuite_from_id(session->ciphersuite);
@@ -2863,7 +2959,7 @@ static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac);
+    psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
     hash_length = PSA_HASH_LENGTH(psa_hash_alg);
     if (hash_length == -1 ||
         (size_t) hash_length > sizeof(session->resumption_key)) {
@@ -2904,11 +3000,11 @@ static int ssl_tls13_postprocess_new_session_ticket(mbedtls_ssl_context *ssl,
                           session->resumption_key_len);
 
     /* Set ticket_flags depends on the selected key exchange modes */
-    mbedtls_ssl_session_set_ticket_flags(
+    mbedtls_ssl_tls13_session_set_ticket_flags(
         session, ssl->conf->tls13_kex_modes);
     MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
 
-    return 0;
+    return POSTPROCESS_NEW_SESSION_TICKET_SIGNAL;
 }
 
 /*
@@ -2929,12 +3025,37 @@ static int ssl_tls13_process_new_session_ticket(mbedtls_ssl_context *ssl)
                              ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
                              &buf, &buf_len));
 
+    /*
+     * We are about to update (maybe only partially) ticket data thus block
+     * any session export for the time being.
+     */
+    ssl->session->exported = 1;
+
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_new_session_ticket(
                              ssl, buf, buf + buf_len,
                              &ticket_nonce, &ticket_nonce_len));
 
-    MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_new_session_ticket(
-                             ssl, ticket_nonce, ticket_nonce_len));
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_postprocess_new_session_ticket(
+                                 ssl, ticket_nonce, ticket_nonce_len));
+
+    switch (ret) {
+        case POSTPROCESS_NEW_SESSION_TICKET_SIGNAL:
+            /*
+             * All good, we have received a new valid ticket, session data can
+             * be exported now and we signal the ticket to the application.
+             */
+            ssl->session->exported = 0;
+            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
+            break;
+
+        case POSTPROCESS_NEW_SESSION_TICKET_DISCARD:
+            ret = 0;
+            MBEDTLS_SSL_DEBUG_MSG(2, ("Discard new session ticket"));
+            break;
+
+        default:
+            ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
 
     mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
 
@@ -2984,9 +3105,11 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
             ret = ssl_tls13_process_server_finished(ssl);
             break;
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
         case MBEDTLS_SSL_END_OF_EARLY_DATA:
             ret = ssl_tls13_write_end_of_early_data(ssl);
             break;
+#endif
 
         case MBEDTLS_SSL_CLIENT_CERTIFICATE:
             ret = ssl_tls13_write_client_certificate(ssl);
@@ -3016,40 +3139,39 @@ int mbedtls_ssl_tls13_handshake_client_step(mbedtls_ssl_context *ssl)
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
         case MBEDTLS_SSL_CLIENT_CCS_BEFORE_2ND_CLIENT_HELLO:
             ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
-            if (ret == 0) {
-                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
+            if (ret != 0) {
+                break;
             }
+            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_HELLO);
             break;
 
         case MBEDTLS_SSL_CLIENT_CCS_AFTER_SERVER_FINISHED:
             ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
-            if (ret == 0) {
-                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+            if (ret != 0) {
+                break;
             }
+            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
             break;
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
         case MBEDTLS_SSL_CLIENT_CCS_AFTER_CLIENT_HELLO:
             ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
             if (ret == 0) {
                 mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
 
-#if defined(MBEDTLS_SSL_EARLY_DATA)
                 MBEDTLS_SSL_DEBUG_MSG(
                     1, ("Switch to early data keys for outbound traffic"));
                 mbedtls_ssl_set_outbound_transform(
                     ssl, ssl->handshake->transform_earlydata);
-#endif
+                ssl->early_data_state = MBEDTLS_SSL_EARLY_DATA_STATE_CAN_WRITE;
             }
             break;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
         case MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET:
             ret = ssl_tls13_process_new_session_ticket(ssl);
-            if (ret != 0) {
-                break;
-            }
-            ret = MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET;
             break;
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c
index 669a90a9bbb2dbf5d717be7995d46fb65ae827a3..b6d09788ba05f48e4a3b4718b36dac49587d746b 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_generic.c
@@ -2,19 +2,7 @@
  *  TLS 1.3 functionality shared between client and server
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -24,7 +12,7 @@
 #include <string.h>
 
 #include "mbedtls/error.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform.h"
 #include "mbedtls/constant_time.h"
@@ -37,11 +25,27 @@
 #include "ssl_debug_helpers.h"
 
 #include "psa/crypto.h"
-#include "mbedtls/psa_util.h"
+#include "psa_util_internal.h"
+
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+int mbedtls_ssl_tls13_crypto_init(mbedtls_ssl_context *ssl)
+{
+    psa_status_t status = psa_crypto_init();
+    if (status != PSA_SUCCESS) {
+        (void) ssl; // unused when debugging is disabled
+        MBEDTLS_SSL_DEBUG_RET(1, "psa_crypto_init", status);
+    }
+    return PSA_TO_MBEDTLS_ERR(status);
+}
 
 const uint8_t mbedtls_ssl_tls13_hello_retry_request_magic[
     MBEDTLS_SERVER_HELLO_RANDOM_LEN] =
@@ -86,6 +90,61 @@ cleanup:
     return ret;
 }
 
+int mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *buf, const unsigned char *end,
+    const unsigned char **supported_versions_data,
+    const unsigned char **supported_versions_data_end)
+{
+    const unsigned char *p = buf;
+    size_t extensions_len;
+    const unsigned char *extensions_end;
+
+    *supported_versions_data = NULL;
+    *supported_versions_data_end = NULL;
+
+    /* Case of no extension */
+    if (p == end) {
+        return 0;
+    }
+
+    /* ...
+     * Extension extensions<x..2^16-1>;
+     * ...
+     * struct {
+     *      ExtensionType extension_type; (2 bytes)
+     *      opaque extension_data<0..2^16-1>;
+     * } Extension;
+     */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 2);
+    extensions_len = MBEDTLS_GET_UINT16_BE(p, 0);
+    p += 2;
+
+    /* Check extensions do not go beyond the buffer of data. */
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, extensions_len);
+    extensions_end = p + extensions_len;
+
+    while (p < extensions_end) {
+        unsigned int extension_type;
+        size_t extension_data_len;
+
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, 4);
+        extension_type = MBEDTLS_GET_UINT16_BE(p, 0);
+        extension_data_len = MBEDTLS_GET_UINT16_BE(p, 2);
+        p += 4;
+        MBEDTLS_SSL_CHK_BUF_READ_PTR(p, extensions_end, extension_data_len);
+
+        if (extension_type == MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS) {
+            *supported_versions_data = p;
+            *supported_versions_data_end = p + extension_data_len;
+            return 1;
+        }
+        p += extension_data_len;
+    }
+
+    return 0;
+}
+
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
 /*
  * STATE HANDLING: Read CertificateVerify
@@ -142,10 +201,12 @@ static void ssl_tls13_create_verify_structure(const unsigned char *transcript_ha
     idx = 64;
 
     if (from == MBEDTLS_SSL_IS_CLIENT) {
-        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(client_cv));
+        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.client_cv,
+               MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv));
         idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(client_cv);
     } else { /* from == MBEDTLS_SSL_IS_SERVER */
-        memcpy(verify_buffer + idx, MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(server_cv));
+        memcpy(verify_buffer + idx, mbedtls_ssl_tls13_labels.server_cv,
+               MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv));
         idx += MBEDTLS_SSL_TLS1_3_LBL_LEN(server_cv);
     }
 
@@ -192,15 +253,17 @@ static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl,
 
     /* RFC 8446 section 4.4.3
      *
-     * If the CertificateVerify message is sent by a server, the signature algorithm
-     * MUST be one offered in the client's "signature_algorithms" extension unless
-     * no valid certificate chain can be produced without unsupported algorithms
+     * If the CertificateVerify message is sent by a server, the signature
+     * algorithm MUST be one offered in the client's "signature_algorithms"
+     * extension unless no valid certificate chain can be produced without
+     * unsupported algorithms
      *
      * RFC 8446 section 4.4.2.2
      *
      * If the client cannot construct an acceptable chain using the provided
-     * certificates and decides to abort the handshake, then it MUST abort the handshake
-     * with an appropriate certificate-related alert (by default, "unsupported_certificate").
+     * certificates and decides to abort the handshake, then it MUST abort the
+     * handshake with an appropriate certificate-related alert
+     * (by default, "unsupported_certificate").
      *
      * Check if algorithm is an offered signature algorithm.
      */
@@ -217,7 +280,7 @@ static int ssl_tls13_parse_certificate_verify(mbedtls_ssl_context *ssl,
         goto error;
     }
 
-    hash_alg = mbedtls_hash_info_psa_from_md(md_alg);
+    hash_alg = mbedtls_md_psa_alg_from_type(md_alg);
     if (hash_alg == 0) {
         goto error;
     }
@@ -295,17 +358,18 @@ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse certificate verify"));
 
     MBEDTLS_SSL_PROC_CHK(
-        mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
-                                              MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len));
+        mbedtls_ssl_tls13_fetch_handshake_msg(
+            ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf, &buf_len));
 
     /* Need to calculate the hash of the transcript first
      * before reading the message since otherwise it gets
      * included in the transcript
      */
-    ret = mbedtls_ssl_get_handshake_transcript(ssl,
-                                               ssl->handshake->ciphersuite_info->mac,
-                                               transcript, sizeof(transcript),
-                                               &transcript_len);
+    ret = mbedtls_ssl_get_handshake_transcript(
+        ssl,
+        (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac,
+        transcript, sizeof(transcript),
+        &transcript_len);
     if (ret != 0) {
         MBEDTLS_SSL_PEND_FATAL_ALERT(
             MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR,
@@ -325,13 +389,13 @@ int mbedtls_ssl_tls13_process_certificate_verify(mbedtls_ssl_context *ssl)
                                       MBEDTLS_SSL_IS_CLIENT);
 
     /* Process the message contents */
-    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify(ssl, buf,
-                                                            buf + buf_len, verify_buffer,
-                                                            verify_buffer_len));
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_certificate_verify(
+                             ssl, buf, buf + buf_len,
+                             verify_buffer, verify_buffer_len));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
-                                                            buf, buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
+                             buf, buf_len));
 
 cleanup:
 
@@ -416,6 +480,7 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
         mbedtls_free(ssl->session_negotiate->peer_cert);
     }
 
+    /* This is used by ssl_tls13_validate_certificate() */
     if (certificate_list_len == 0) {
         ssl->session_negotiate->peer_cert = NULL;
         ret = 0;
@@ -545,7 +610,8 @@ exit:
         return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
 
-    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate", ssl->session_negotiate->peer_cert);
+    MBEDTLS_SSL_DEBUG_CRT(3, "peer certificate",
+                          ssl->session_negotiate->peer_cert);
 
     return ret;
 }
@@ -570,25 +636,13 @@ int mbedtls_ssl_tls13_parse_certificate(mbedtls_ssl_context *ssl,
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
 {
-    int ret = 0;
-    int authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
-    mbedtls_x509_crt *ca_chain;
-    mbedtls_x509_crl *ca_crl;
-    const char *ext_oid;
-    size_t ext_len;
-    uint32_t verify_result = 0;
-
-    /* If SNI was used, overwrite authentication mode
-     * from the configuration. */
-#if defined(MBEDTLS_SSL_SRV_C)
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER) {
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-        if (ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET) {
-            authmode = ssl->handshake->sni_authmode;
-        } else
-#endif
-        authmode = ssl->conf->authmode;
-    }
+    /* Authmode: precedence order is SNI if used else configuration */
+#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
+    const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
+                       ? ssl->handshake->sni_authmode
+                       : ssl->conf->authmode;
+#else
+    const int authmode = ssl->conf->authmode;
 #endif
 
     /*
@@ -611,14 +665,20 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
             if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL) {
                 return 0;
             } else {
-                MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
-                                             MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE);
+                MBEDTLS_SSL_PEND_FATAL_ALERT(
+                    MBEDTLS_SSL_ALERT_MSG_NO_CERT,
+                    MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE);
                 return MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
             }
         }
 #endif /* MBEDTLS_SSL_SRV_C */
 
 #if defined(MBEDTLS_SSL_CLI_C)
+        /* Regardless of authmode, the server is not allowed to send an empty
+         * certificate chain. (Last paragraph before 4.4.2.1 in RFC 8446: "The
+         * server's certificate_list MUST always be non-empty.") With authmode
+         * optional/none, we continue the handshake if we can't validate the
+         * server's cert, but we still break it if no certificate was sent. */
         if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
             MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_NO_CERT,
                                          MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE);
@@ -627,109 +687,9 @@ static int ssl_tls13_validate_certificate(mbedtls_ssl_context *ssl)
 #endif /* MBEDTLS_SSL_CLI_C */
     }
 
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if (ssl->handshake->sni_ca_chain != NULL) {
-        ca_chain = ssl->handshake->sni_ca_chain;
-        ca_crl = ssl->handshake->sni_ca_crl;
-    } else
-#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
-    {
-        ca_chain = ssl->conf->ca_chain;
-        ca_crl = ssl->conf->ca_crl;
-    }
-
-    /*
-     * Main check: verify certificate
-     */
-    ret = mbedtls_x509_crt_verify_with_profile(
-        ssl->session_negotiate->peer_cert,
-        ca_chain, ca_crl,
-        ssl->conf->cert_profile,
-        ssl->hostname,
-        &verify_result,
-        ssl->conf->f_vrfy, ssl->conf->p_vrfy);
-
-    if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1, "x509_verify_cert", ret);
-    }
-
-    /*
-     * Secondary checks: always done, but change 'ret' only if it was 0
-     */
-    if (ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT) {
-        ext_oid = MBEDTLS_OID_SERVER_AUTH;
-        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_SERVER_AUTH);
-    } else {
-        ext_oid = MBEDTLS_OID_CLIENT_AUTH;
-        ext_len = MBEDTLS_OID_SIZE(MBEDTLS_OID_CLIENT_AUTH);
-    }
-
-    if ((mbedtls_x509_crt_check_key_usage(
-             ssl->session_negotiate->peer_cert,
-             MBEDTLS_X509_KU_DIGITAL_SIGNATURE) != 0) ||
-        (mbedtls_x509_crt_check_extended_key_usage(
-             ssl->session_negotiate->peer_cert,
-             ext_oid, ext_len) != 0)) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad certificate (usage extensions)"));
-        if (ret == 0) {
-            ret = MBEDTLS_ERR_SSL_BAD_CERTIFICATE;
-        }
-    }
-
-    /* mbedtls_x509_crt_verify_with_profile is supposed to report a
-     * verification failure through MBEDTLS_ERR_X509_CERT_VERIFY_FAILED,
-     * with details encoded in the verification flags. All other kinds
-     * of error codes, including those from the user provided f_vrfy
-     * functions, are treated as fatal and lead to a failure of
-     * mbedtls_ssl_tls13_parse_certificate even if verification was optional.
-     */
-    if (authmode == MBEDTLS_SSL_VERIFY_OPTIONAL &&
-        (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ||
-         ret == MBEDTLS_ERR_SSL_BAD_CERTIFICATE)) {
-        ret = 0;
-    }
-
-    if (ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("got no CA chain"));
-        ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED;
-    }
-
-    if (ret != 0) {
-        /* The certificate may have been rejected for several reasons.
-           Pick one and send the corresponding alert. Which alert to send
-           may be a subject of debate in some cases. */
-        if (verify_result & MBEDTLS_X509_BADCERT_OTHER) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED, ret);
-        } else if (verify_result & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_BAD_CERT, ret);
-        } else if (verify_result & (MBEDTLS_X509_BADCERT_KEY_USAGE |
-                                    MBEDTLS_X509_BADCERT_EXT_KEY_USAGE |
-                                    MBEDTLS_X509_BADCERT_NS_CERT_TYPE |
-                                    MBEDTLS_X509_BADCERT_BAD_PK |
-                                    MBEDTLS_X509_BADCERT_BAD_KEY)) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_CERT, ret);
-        } else if (verify_result & MBEDTLS_X509_BADCERT_EXPIRED) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_EXPIRED, ret);
-        } else if (verify_result & MBEDTLS_X509_BADCERT_REVOKED) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_REVOKED, ret);
-        } else if (verify_result & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA, ret);
-        } else {
-            MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN, ret);
-        }
-    }
-
-#if defined(MBEDTLS_DEBUG_C)
-    if (verify_result != 0) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("! Certificate verification flags %08x",
-                                  (unsigned int) verify_result));
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("Certificate verification flags clear"));
-    }
-#endif /* MBEDTLS_DEBUG_C */
-
-    ssl->session_negotiate->verify_result = verify_result;
-    return ret;
+    return mbedtls_ssl_verify_certificate(ssl, authmode,
+                                          ssl->session_negotiate->peer_cert,
+                                          NULL, NULL);
 }
 #else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -760,11 +720,12 @@ int mbedtls_ssl_tls13_process_certificate(mbedtls_ssl_context *ssl)
     /* Validate the certificate chain and set the verification results. */
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_validate_certificate(ssl));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
-                                                            buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, buf_len));
 
 cleanup:
+#else /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
+    (void) ssl;
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= parse certificate"));
@@ -868,18 +829,16 @@ int mbedtls_ssl_tls13_write_certificate(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate"));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                         MBEDTLS_SSL_HS_CERTIFICATE, &buf,
-                                                         &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, &buf, &buf_len));
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_body(ssl,
                                                           buf,
                                                           buf + buf_len,
                                                           &msg_len));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_CERTIFICATE, buf,
-                                                            msg_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE, buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -895,7 +854,7 @@ cleanup:
 int mbedtls_ssl_tls13_check_sig_alg_cert_key_match(uint16_t sig_alg,
                                                    mbedtls_pk_context *key)
 {
-    mbedtls_pk_type_t pk_type = mbedtls_ssl_sig_from_pk(key);
+    mbedtls_pk_type_t pk_type = (mbedtls_pk_type_t) mbedtls_ssl_sig_from_pk(key);
     size_t key_size = mbedtls_pk_get_bitlen(key);
 
     switch (pk_type) {
@@ -962,11 +921,9 @@ static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl,
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    ret = mbedtls_ssl_get_handshake_transcript(ssl,
-                                               ssl->handshake->ciphersuite_info->mac,
-                                               handshake_hash,
-                                               sizeof(handshake_hash),
-                                               &handshake_hash_len);
+    ret = mbedtls_ssl_get_handshake_transcript(
+        ssl, (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac,
+        handshake_hash, sizeof(handshake_hash), &handshake_hash_len);
     if (ret != 0) {
         return ret;
     }
@@ -1016,7 +973,7 @@ static int ssl_tls13_write_certificate_verify_body(mbedtls_ssl_context *ssl,
         }
 
         /* Hash verify buffer with indicated hash function */
-        psa_algorithm = mbedtls_hash_info_psa_from_md(md_alg);
+        psa_algorithm = mbedtls_md_psa_alg_from_type(md_alg);
         status = psa_hash_compute(psa_algorithm,
                                   verify_buffer,
                                   verify_buffer_len,
@@ -1073,16 +1030,16 @@ int mbedtls_ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write certificate verify"));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                         MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, &buf,
-                                                         &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
+                             &buf, &buf_len));
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_verify_body(
                              ssl, buf, buf + buf_len, &msg_len));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_CERTIFICATE_VERIFY, buf,
-                                                            msg_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_CERTIFICATE_VERIFY,
+                             buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -1108,13 +1065,13 @@ static int ssl_tls13_preprocess_finished_message(mbedtls_ssl_context *ssl)
 {
     int ret;
 
-    ret = mbedtls_ssl_tls13_calculate_verify_data(ssl,
-                                                  ssl->handshake->state_local.finished_in.digest,
-                                                  sizeof(ssl->handshake->state_local.finished_in.
-                                                         digest),
-                                                  &ssl->handshake->state_local.finished_in.digest_len,
-                                                  ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ?
-                                                  MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT);
+    ret = mbedtls_ssl_tls13_calculate_verify_data(
+        ssl,
+        ssl->handshake->state_local.finished_in.digest,
+        sizeof(ssl->handshake->state_local.finished_in.digest),
+        &ssl->handshake->state_local.finished_in.digest_len,
+        ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT ?
+        MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_calculate_verify_data", ret);
         return ret;
@@ -1173,17 +1130,17 @@ int mbedtls_ssl_tls13_process_finished_message(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> parse finished message"));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(ssl,
-                                                               MBEDTLS_SSL_HS_FINISHED,
-                                                               &buf, &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_FINISHED, &buf, &buf_len));
 
     /* Preprocessing step: Compute handshake digest */
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_preprocess_finished_message(ssl));
 
-    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(ssl, buf, buf + buf_len));
+    MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_finished_message(
+                             ssl, buf, buf + buf_len));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(ssl,
-                                                            MBEDTLS_SSL_HS_FINISHED, buf, buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                             ssl, MBEDTLS_SSL_HS_FINISHED, buf, buf_len));
 
 cleanup:
 
@@ -1321,6 +1278,12 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write change cipher spec"));
 
+    /* Only one CCS to send. */
+    if (ssl->handshake->ccs_sent) {
+        ret = 0;
+        goto cleanup;
+    }
+
     /* Write CCS message */
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_change_cipher_spec_body(
                              ssl, ssl->out_msg,
@@ -1332,6 +1295,8 @@ int mbedtls_ssl_tls13_write_change_cipher_spec(mbedtls_ssl_context *ssl)
     /* Dispatch message */
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_write_record(ssl, 0));
 
+    ssl->handshake->ccs_sent = 1;
+
 cleanup:
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= write change cipher spec"));
@@ -1344,7 +1309,7 @@ cleanup:
  *
  * struct {
  *   select ( Handshake.msg_type ) {
- *     ...
+ *     case new_session_ticket:   uint32 max_early_data_size;
  *     case client_hello:         Empty;
  *     case encrypted_extensions: Empty;
  *   };
@@ -1352,25 +1317,92 @@ cleanup:
  */
 #if defined(MBEDTLS_SSL_EARLY_DATA)
 int mbedtls_ssl_tls13_write_early_data_ext(mbedtls_ssl_context *ssl,
+                                           int in_new_session_ticket,
                                            unsigned char *buf,
                                            const unsigned char *end,
                                            size_t *out_len)
 {
     unsigned char *p = buf;
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    const size_t needed = in_new_session_ticket ? 8 : 4;
+#else
+    const size_t needed = 4;
+    ((void) in_new_session_ticket);
+#endif
+
     *out_len = 0;
-    ((void) ssl);
 
-    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4);
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, needed);
 
     MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_EARLY_DATA, p, 0);
-    MBEDTLS_PUT_UINT16_BE(0, p, 2);
+    MBEDTLS_PUT_UINT16_BE(needed - 4, p, 2);
+
+#if defined(MBEDTLS_SSL_SRV_C)
+    if (in_new_session_ticket) {
+        MBEDTLS_PUT_UINT32_BE(ssl->conf->max_early_data_size, p, 4);
+        MBEDTLS_SSL_DEBUG_MSG(
+            4, ("Sent max_early_data_size=%u",
+                (unsigned int) ssl->conf->max_early_data_size));
+    }
+#endif
 
-    *out_len = 4;
+    *out_len = needed;
 
     mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_EARLY_DATA);
 
     return 0;
 }
+
+#if defined(MBEDTLS_SSL_SRV_C)
+int mbedtls_ssl_tls13_check_early_data_len(mbedtls_ssl_context *ssl,
+                                           size_t early_data_len)
+{
+    /*
+     * This function should be called only while an handshake is in progress
+     * and thus a session under negotiation. Add a sanity check to detect a
+     * misuse.
+     */
+    if (ssl->session_negotiate == NULL) {
+        return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+    }
+
+    /* RFC 8446 section 4.6.1
+     *
+     * A server receiving more than max_early_data_size bytes of 0-RTT data
+     * SHOULD terminate the connection with an "unexpected_message" alert.
+     * Note that if it is still possible to send early_data_len bytes of early
+     * data, it means that early_data_len is smaller than max_early_data_size
+     * (type uint32_t) and can fit in an uint32_t. We use this further
+     * down.
+     */
+    if (early_data_len >
+        (ssl->session_negotiate->max_early_data_size -
+         ssl->total_early_data_size)) {
+
+        MBEDTLS_SSL_DEBUG_MSG(
+            2, ("EarlyData: Too much early data received, "
+                "%lu + %" MBEDTLS_PRINTF_SIZET " > %lu",
+                (unsigned long) ssl->total_early_data_size,
+                early_data_len,
+                (unsigned long) ssl->session_negotiate->max_early_data_size));
+
+        MBEDTLS_SSL_PEND_FATAL_ALERT(
+            MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+            MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+        return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+    }
+
+    /*
+     * early_data_len has been checked to be less than max_early_data_size
+     * that is uint32_t. Its cast to an uint32_t below is thus safe. We need
+     * the cast to appease some compilers.
+     */
+    ssl->total_early_data_size += (uint32_t) early_data_len;
+
+    return 0;
+}
+#endif /* MBEDTLS_SSL_SRV_C */
 #endif /* MBEDTLS_SSL_EARLY_DATA */
 
 /* Reset SSL context and update hash for handling HRR.
@@ -1394,7 +1426,7 @@ int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(3, ("Reset SSL session for HRR"));
 
-    ret = mbedtls_ssl_get_handshake_transcript(ssl, ciphersuite_info->mac,
+    ret = mbedtls_ssl_get_handshake_transcript(ssl, (mbedtls_md_type_t) ciphersuite_info->mac,
                                                hash_transcript + 4,
                                                PSA_HASH_MAX_SIZE,
                                                &hash_len);
@@ -1428,9 +1460,9 @@ int mbedtls_ssl_reset_transcript_for_hrr(mbedtls_ssl_context *ssl)
     return ret;
 }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
 
-int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
+int mbedtls_ssl_tls13_read_public_xxdhe_share(mbedtls_ssl_context *ssl,
                                               const unsigned char *buf,
                                               size_t buf_len)
 {
@@ -1446,14 +1478,61 @@ int mbedtls_ssl_tls13_read_public_ecdhe_share(mbedtls_ssl_context *ssl,
     /* Check if key size is consistent with given buffer length. */
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, peerkey_len);
 
-    /* Store peer's ECDH public key. */
-    memcpy(handshake->ecdh_psa_peerkey, p, peerkey_len);
-    handshake->ecdh_psa_peerkey_len = peerkey_len;
+    /* Store peer's ECDH/FFDH public key. */
+    if (peerkey_len > sizeof(handshake->xxdh_psa_peerkey)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid public key length: %u > %" MBEDTLS_PRINTF_SIZET,
+                                  (unsigned) peerkey_len,
+                                  sizeof(handshake->xxdh_psa_peerkey)));
+        return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    }
+    memcpy(handshake->xxdh_psa_peerkey, p, peerkey_len);
+    handshake->xxdh_psa_peerkey_len = peerkey_len;
 
     return 0;
 }
 
-int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+#if defined(PSA_WANT_ALG_FFDH)
+static psa_status_t  mbedtls_ssl_get_psa_ffdh_info_from_tls_id(
+    uint16_t tls_id, size_t *bits, psa_key_type_t *key_type)
+{
+    switch (tls_id) {
+#if defined(PSA_WANT_DH_RFC7919_2048)
+        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE2048:
+            *bits = 2048;
+            *key_type = PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
+            return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_2048 */
+#if defined(PSA_WANT_DH_RFC7919_3072)
+        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE3072:
+            *bits = 3072;
+            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
+            return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_3072 */
+#if defined(PSA_WANT_DH_RFC7919_4096)
+        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE4096:
+            *bits = 4096;
+            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
+            return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_4096 */
+#if defined(PSA_WANT_DH_RFC7919_6144)
+        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE6144:
+            *bits = 6144;
+            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
+            return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_6144 */
+#if defined(PSA_WANT_DH_RFC7919_8192)
+        case MBEDTLS_SSL_IANA_TLS_GROUP_FFDHE8192:
+            *bits = 8192;
+            *key_type =  PSA_KEY_TYPE_DH_KEY_PAIR(PSA_DH_FAMILY_RFC7919);
+            return PSA_SUCCESS;
+#endif /* PSA_WANT_DH_RFC7919_8192 */
+        default:
+            return PSA_ERROR_NOT_SUPPORTED;
+    }
+}
+#endif /* PSA_WANT_ALG_FFDH */
+
+int mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(
     mbedtls_ssl_context *ssl,
     uint16_t named_group,
     unsigned char *buf,
@@ -1465,29 +1544,47 @@ int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
     psa_key_attributes_t key_attributes;
     size_t own_pubkey_len;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    psa_ecc_family_t ec_psa_family = 0;
-    size_t ec_bits = 0;
+    size_t bits = 0;
+    psa_key_type_t key_type = PSA_KEY_TYPE_NONE;
+    psa_algorithm_t alg = PSA_ALG_NONE;
+    size_t buf_size = (size_t) (end - buf);
 
-    MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH computation."));
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Perform PSA-based ECDH/FFDH computation."));
 
     /* Convert EC's TLS ID to PSA key type. */
-    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(named_group,
-                                                   &ec_psa_family,
-                                                   &ec_bits) == PSA_ERROR_NOT_SUPPORTED) {
+#if defined(PSA_WANT_ALG_ECDH)
+    if (mbedtls_ssl_get_psa_curve_info_from_tls_id(
+            named_group, &key_type, &bits) == PSA_SUCCESS) {
+        alg = PSA_ALG_ECDH;
+    }
+#endif
+#if defined(PSA_WANT_ALG_FFDH)
+    if (mbedtls_ssl_get_psa_ffdh_info_from_tls_id(named_group, &bits,
+                                                  &key_type) == PSA_SUCCESS) {
+        alg = PSA_ALG_FFDH;
+    }
+#endif
+
+    if (key_type == PSA_KEY_TYPE_NONE) {
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
-    handshake->ecdh_psa_type = PSA_KEY_TYPE_ECC_KEY_PAIR(ec_psa_family);
-    ssl->handshake->ecdh_bits = ec_bits;
+
+    if (buf_size < PSA_BITS_TO_BYTES(bits)) {
+        return MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL;
+    }
+
+    handshake->xxdh_psa_type = key_type;
+    ssl->handshake->xxdh_psa_bits = bits;
 
     key_attributes = psa_key_attributes_init();
     psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
-    psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
-    psa_set_key_type(&key_attributes, handshake->ecdh_psa_type);
-    psa_set_key_bits(&key_attributes, handshake->ecdh_bits);
+    psa_set_key_algorithm(&key_attributes, alg);
+    psa_set_key_type(&key_attributes, handshake->xxdh_psa_type);
+    psa_set_key_bits(&key_attributes, handshake->xxdh_psa_bits);
 
-    /* Generate ECDH private key. */
+    /* Generate ECDH/FFDH private key. */
     status = psa_generate_key(&key_attributes,
-                              &handshake->ecdh_psa_privkey);
+                              &handshake->xxdh_psa_privkey);
     if (status != PSA_SUCCESS) {
         ret = PSA_TO_MBEDTLS_ERR(status);
         MBEDTLS_SSL_DEBUG_RET(1, "psa_generate_key", ret);
@@ -1495,22 +1592,22 @@ int mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
 
     }
 
-    /* Export the public part of the ECDH private key from PSA. */
-    status = psa_export_public_key(handshake->ecdh_psa_privkey,
-                                   buf, (size_t) (end - buf),
+    /* Export the public part of the ECDH/FFDH private key from PSA. */
+    status = psa_export_public_key(handshake->xxdh_psa_privkey,
+                                   buf, buf_size,
                                    &own_pubkey_len);
+
     if (status != PSA_SUCCESS) {
         ret = PSA_TO_MBEDTLS_ERR(status);
         MBEDTLS_SSL_DEBUG_RET(1, "psa_export_public_key", ret);
         return ret;
-
     }
 
     *out_len = own_pubkey_len;
 
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
 
 /* RFC 8446 section 4.2
  *
@@ -1568,6 +1665,7 @@ int mbedtls_ssl_tls13_check_received_extension(
 }
 
 #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+
 /* RFC 8449, section 4:
  *
  * The ExtensionData of the "record_size_limit" extension is
@@ -1583,7 +1681,8 @@ int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
     uint16_t record_size_limit;
     const size_t extension_data_len = end - buf;
 
-    if (extension_data_len != MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) {
+    if (extension_data_len !=
+        MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH) {
         MBEDTLS_SSL_DEBUG_MSG(2,
                               ("record_size_limit extension has invalid length: %"
                                MBEDTLS_PRINTF_SIZET " Bytes",
@@ -1600,28 +1699,56 @@ int mbedtls_ssl_tls13_parse_record_size_limit_ext(mbedtls_ssl_context *ssl,
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("RecordSizeLimit: %u Bytes", record_size_limit));
 
-    /* RFC 8449, section 4
+    /* RFC 8449, section 4:
      *
      * Endpoints MUST NOT send a "record_size_limit" extension with a value
      * smaller than 64.  An endpoint MUST treat receipt of a smaller value
      * as a fatal error and generate an "illegal_parameter" alert.
      */
     if (record_size_limit < MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("Invalid record size limit : %u Bytes",
+                                  record_size_limit));
         MBEDTLS_SSL_PEND_FATAL_ALERT(
             MBEDTLS_SSL_ALERT_MSG_ILLEGAL_PARAMETER,
             MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
         return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(2,
-                          (
-                              "record_size_limit extension is still in development. Aborting handshake."));
+    ssl->session_negotiate->record_size_limit = record_size_limit;
 
-    MBEDTLS_SSL_PEND_FATAL_ALERT(
-        MBEDTLS_SSL_ALERT_MSG_UNSUPPORTED_EXT,
-        MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION);
-    return MBEDTLS_ERR_SSL_UNSUPPORTED_EXTENSION;
+    return 0;
 }
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+int mbedtls_ssl_tls13_write_record_size_limit_ext(mbedtls_ssl_context *ssl,
+                                                  unsigned char *buf,
+                                                  const unsigned char *end,
+                                                  size_t *out_len)
+{
+    unsigned char *p = buf;
+    *out_len = 0;
+
+    MBEDTLS_STATIC_ASSERT(MBEDTLS_SSL_IN_CONTENT_LEN >= MBEDTLS_SSL_RECORD_SIZE_LIMIT_MIN,
+                          "MBEDTLS_SSL_IN_CONTENT_LEN is less than the "
+                          "minimum record size limit");
+
+    MBEDTLS_SSL_CHK_BUF_PTR(p, end, 6);
+
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT, p, 0);
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_RECORD_SIZE_LIMIT_EXTENSION_DATA_LENGTH,
+                          p, 2);
+    MBEDTLS_PUT_UINT16_BE(MBEDTLS_SSL_IN_CONTENT_LEN, p, 4);
+
+    *out_len = 6;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("Sent RecordSizeLimit: %d Bytes",
+                              MBEDTLS_SSL_IN_CONTENT_LEN));
+
+    mbedtls_ssl_tls13_set_hs_sent_ext_mask(ssl, MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT);
+
+    return 0;
+}
+
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 
 #endif /* MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_PROTO_TLS1_3 */
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h b/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h
index 3fb79a95da158b35a81a4124c82f424e00b84342..b4506f71c7ef16d5b1606497eb1694e41d72141a 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_invasive.h
@@ -1,18 +1,6 @@
 /*
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #ifndef MBEDTLS_SSL_TLS13_INVASIVE_H
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
index 6edce50bc8cfb01b234e9e124d5c073db3afcefb..739414ea2fe819b18440dff1547a40975d383006 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.c
@@ -2,19 +2,7 @@
  *  TLS 1.3 key schedule
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 ( the "License" ); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -25,7 +13,7 @@
 #include <string.h>
 
 #include "mbedtls/hkdf.h"
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
 
@@ -34,10 +22,17 @@
 #include "ssl_tls13_invasive.h"
 
 #include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
 
-#define PSA_TO_MBEDTLS_ERR(status) PSA_TO_MBEDTLS_ERR_LIST(status,   \
-                                                           psa_to_ssl_errors,             \
-                                                           psa_generic_status_to_mbedtls)
+/* Define a local translating function to save code size by not using too many
+ * arguments in each translating place. */
+static int local_err_translation(psa_status_t status)
+{
+    return psa_status_to_mbedtls(status, psa_to_ssl_errors,
+                                 ARRAY_LENGTH(psa_to_ssl_errors),
+                                 psa_generic_status_to_mbedtls);
+}
+#define PSA_TO_MBEDTLS_ERR(status) local_err_translation(status)
 
 #define MBEDTLS_SSL_TLS1_3_LABEL(name, string)       \
     .name = string,
@@ -455,25 +450,27 @@ int mbedtls_ssl_tls13_derive_early_secrets(
      */
 
     /* Create client_early_traffic_secret */
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          early_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->client_early_traffic_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        early_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_e_traffic),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->client_early_traffic_secret,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
 
     /* Create early exporter */
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          early_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->early_exporter_master_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        early_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(e_exp_master),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->early_exporter_master_secret,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
@@ -515,13 +512,14 @@ int mbedtls_ssl_tls13_derive_handshake_secrets(
      * Derive-Secret( ., "c hs traffic", ClientHello...ServerHello )
      */
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          handshake_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->client_handshake_traffic_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        handshake_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_hs_traffic),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->client_handshake_traffic_secret,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
@@ -531,13 +529,14 @@ int mbedtls_ssl_tls13_derive_handshake_secrets(
      * Derive-Secret( ., "s hs traffic", ClientHello...ServerHello )
      */
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          handshake_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->server_handshake_traffic_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        handshake_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_hs_traffic),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->server_handshake_traffic_secret,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
@@ -578,35 +577,38 @@ int mbedtls_ssl_tls13_derive_application_secrets(
      *
      */
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          application_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->client_application_traffic_secret_N,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        application_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(c_ap_traffic),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->client_application_traffic_secret_N,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          application_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->server_application_traffic_secret_N,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        application_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(s_ap_traffic),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->server_application_traffic_secret_N,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          application_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->exporter_master_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        application_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(exp_master),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->exporter_master_secret,
+        hash_len);
     if (ret != 0) {
         return ret;
     }
@@ -633,13 +635,14 @@ int mbedtls_ssl_tls13_derive_resumption_master_secret(
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                          application_secret, hash_len,
-                                          MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master),
-                                          transcript, transcript_len,
-                                          MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
-                                          derived->resumption_master_secret,
-                                          hash_len);
+    ret = mbedtls_ssl_tls13_derive_secret(
+        hash_alg,
+        application_secret, hash_len,
+        MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_master),
+        transcript, transcript_len,
+        MBEDTLS_SSL_TLS1_3_CONTEXT_HASHED,
+        derived->resumption_master_secret,
+        hash_len);
 
     if (ret != 0) {
         return ret;
@@ -669,23 +672,25 @@ static int ssl_tls13_key_schedule_stage_application(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md(
-        handshake->ciphersuite_info->mac);
+    psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type(
+        (mbedtls_md_type_t) handshake->ciphersuite_info->mac);
 
     /*
      * Compute MasterSecret
      */
-    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,
-                                          handshake->tls13_master_secrets.handshake,
-                                          NULL, 0,
-                                          handshake->tls13_master_secrets.app);
+    ret = mbedtls_ssl_tls13_evolve_secret(
+        hash_alg,
+        handshake->tls13_master_secrets.handshake,
+        NULL, 0,
+        handshake->tls13_master_secrets.app);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
         return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "Master secret",
-                          handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg));
+    MBEDTLS_SSL_DEBUG_BUF(
+        4, "Master secret",
+        handshake->tls13_master_secrets.app, PSA_HASH_LENGTH(hash_alg));
 
     return 0;
 }
@@ -780,10 +785,10 @@ int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,
     mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets =
         &ssl->handshake->tls13_hs_secrets;
 
-    mbedtls_md_type_t const md_type = ssl->handshake->ciphersuite_info->mac;
+    mbedtls_md_type_t const md_type = (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac;
 
-    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(
-        ssl->handshake->ciphersuite_info->mac);
+    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(
+        (mbedtls_md_type_t) ssl->handshake->ciphersuite_info->mac);
     size_t const hash_len = PSA_HASH_LENGTH(hash_alg);
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> mbedtls_ssl_tls13_calculate_verify_data"));
@@ -810,7 +815,8 @@ int mbedtls_ssl_tls13_calculate_verify_data(mbedtls_ssl_context *ssl,
     }
     MBEDTLS_SSL_DEBUG_BUF(4, "handshake hash", transcript, transcript_len);
 
-    ret = ssl_tls13_calc_finished_core(hash_alg, base_key, transcript, dst, actual_len);
+    ret = ssl_tls13_calc_finished_core(hash_alg, base_key,
+                                       transcript, dst, actual_len);
     if (ret != 0) {
         goto exit;
     }
@@ -873,18 +879,20 @@ int mbedtls_ssl_tls13_create_psk_binder(mbedtls_ssl_context *ssl,
                           early_secret, hash_len);
 
     if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
-        ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                              early_secret, hash_len,
-                                              MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder),
-                                              NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
-                                              binder_key, hash_len);
+        ret = mbedtls_ssl_tls13_derive_secret(
+            hash_alg,
+            early_secret, hash_len,
+            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(res_binder),
+            NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+            binder_key, hash_len);
         MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'res binder'"));
     } else {
-        ret = mbedtls_ssl_tls13_derive_secret(hash_alg,
-                                              early_secret, hash_len,
-                                              MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder),
-                                              NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
-                                              binder_key, hash_len);
+        ret = mbedtls_ssl_tls13_derive_secret(
+            hash_alg,
+            early_secret, hash_len,
+            MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN(ext_binder),
+            NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
+            binder_key, hash_len);
         MBEDTLS_SSL_DEBUG_MSG(4, ("Derive Early Secret with 'ext binder'"));
     }
 
@@ -913,11 +921,11 @@ exit:
     return ret;
 }
 
-int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
-                                         int endpoint,
-                                         int ciphersuite,
-                                         mbedtls_ssl_key_set const *traffic_keys,
-                                         mbedtls_ssl_context *ssl /* DEBUG ONLY */)
+int mbedtls_ssl_tls13_populate_transform(
+    mbedtls_ssl_transform *transform,
+    int endpoint, int ciphersuite,
+    mbedtls_ssl_key_set const *traffic_keys,
+    mbedtls_ssl_context *ssl /* DEBUG ONLY */)
 {
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     int ret;
@@ -999,14 +1007,14 @@ int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
 
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_enc,
-                                     key_enc, cipher_info->key_bitlen,
+                                     key_enc, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
                                      MBEDTLS_ENCRYPT)) != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
         return ret;
     }
 
     if ((ret = mbedtls_cipher_setkey(&transform->cipher_ctx_dec,
-                                     key_dec, cipher_info->key_bitlen,
+                                     key_dec, (int) mbedtls_cipher_info_get_key_bitlen(cipher_info),
                                      MBEDTLS_DECRYPT)) != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_cipher_setkey", ret);
         return ret;
@@ -1039,12 +1047,13 @@ int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
     /*
      * Setup psa keys and alg
      */
-    if ((status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher,
+    if ((status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher,
                                             transform->taglen,
                                             &alg,
                                             &key_type,
                                             &key_bits)) != PSA_SUCCESS) {
-        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status));
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_cipher_to_psa", PSA_TO_MBEDTLS_ERR(status));
         return PSA_TO_MBEDTLS_ERR(status);
     }
 
@@ -1059,7 +1068,8 @@ int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
                                      key_enc,
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_enc)) != PSA_SUCCESS) {
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
             return PSA_TO_MBEDTLS_ERR(status);
         }
 
@@ -1069,7 +1079,8 @@ int mbedtls_ssl_tls13_populate_transform(mbedtls_ssl_transform *transform,
                                      key_dec,
                                      PSA_BITS_TO_BYTES(key_bits),
                                      &transform->psa_key_dec)) != PSA_SUCCESS) {
-            MBEDTLS_SSL_DEBUG_RET(1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "psa_import_key", PSA_TO_MBEDTLS_ERR(status));
             return PSA_TO_MBEDTLS_ERR(status);
         }
     }
@@ -1095,7 +1106,7 @@ static int ssl_tls13_get_cipher_key_info(
         taglen = 16;
     }
 
-    status = mbedtls_ssl_cipher_to_psa(ciphersuite_info->cipher, taglen,
+    status = mbedtls_ssl_cipher_to_psa((mbedtls_cipher_type_t) ciphersuite_info->cipher, taglen,
                                        &alg, &key_type, &key_bits);
     if (status != PSA_SUCCESS) {
         return PSA_TO_MBEDTLS_ERR(status);
@@ -1129,12 +1140,13 @@ static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl,
     size_t hash_len;
     unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
     size_t transcript_len;
-    size_t key_len;
-    size_t iv_len;
+    size_t key_len = 0;
+    size_t iv_len = 0;
     mbedtls_ssl_tls13_early_secrets tls13_early_secrets;
 
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        handshake->ciphersuite_info;
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_early_key"));
 
@@ -1144,9 +1156,9 @@ static int ssl_tls13_generate_early_key(mbedtls_ssl_context *ssl,
         goto cleanup;
     }
 
-    md_type = ciphersuite_info->mac;
+    md_type = (mbedtls_md_type_t) ciphersuite_info->mac;
 
-    hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
+    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
     hash_len = PSA_HASH_LENGTH(hash_alg);
 
     ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
@@ -1274,7 +1286,7 @@ int mbedtls_ssl_tls13_key_schedule_stage_early(mbedtls_ssl_context *ssl)
         return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
     }
 
-    hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac);
+    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac);
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
     if (mbedtls_ssl_tls13_key_exchange_mode_with_psk(ssl)) {
         ret = mbedtls_ssl_tls13_export_handshake_psk(ssl, &psk, &psk_len);
@@ -1329,12 +1341,14 @@ static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,
     size_t hash_len;
     unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
     size_t transcript_len;
-    size_t key_len;
-    size_t iv_len;
+    size_t key_len = 0;
+    size_t iv_len = 0;
 
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    const mbedtls_ssl_ciphersuite_t *ciphersuite_info = handshake->ciphersuite_info;
-    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets = &handshake->tls13_hs_secrets;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
+        handshake->ciphersuite_info;
+    mbedtls_ssl_tls13_handshake_secrets *tls13_hs_secrets =
+        &handshake->tls13_hs_secrets;
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_generate_handshake_keys"));
 
@@ -1344,9 +1358,9 @@ static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,
         return ret;
     }
 
-    md_type = ciphersuite_info->mac;
+    md_type = (mbedtls_md_type_t) ciphersuite_info->mac;
 
-    hash_alg = mbedtls_hash_info_psa_from_md(ciphersuite_info->mac);
+    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
     hash_len = PSA_HASH_LENGTH(hash_alg);
 
     ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
@@ -1360,9 +1374,9 @@ static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,
         return ret;
     }
 
-    ret = mbedtls_ssl_tls13_derive_handshake_secrets(hash_alg,
-                                                     handshake->tls13_master_secrets.handshake,
-                                                     transcript, transcript_len, tls13_hs_secrets);
+    ret = mbedtls_ssl_tls13_derive_handshake_secrets(
+        hash_alg, handshake->tls13_master_secrets.handshake,
+        transcript, transcript_len, tls13_hs_secrets);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_derive_handshake_secrets",
                               ret);
@@ -1380,27 +1394,30 @@ static int ssl_tls13_generate_handshake_keys(mbedtls_ssl_context *ssl,
      * Export client handshake traffic secret
      */
     if (ssl->f_export_keys != NULL) {
-        ssl->f_export_keys(ssl->p_export_keys,
-                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
-                           tls13_hs_secrets->client_handshake_traffic_secret,
-                           hash_len,
-                           handshake->randbytes,
-                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
-                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
-
-        ssl->f_export_keys(ssl->p_export_keys,
-                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET,
-                           tls13_hs_secrets->server_handshake_traffic_secret,
-                           hash_len,
-                           handshake->randbytes,
-                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
-                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
-    }
-
-    ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg,
-                                              tls13_hs_secrets->client_handshake_traffic_secret,
-                                              tls13_hs_secrets->server_handshake_traffic_secret,
-                                              hash_len, key_len, iv_len, traffic_keys);
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_HANDSHAKE_TRAFFIC_SECRET,
+            tls13_hs_secrets->client_handshake_traffic_secret,
+            hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
+
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_HANDSHAKE_TRAFFIC_SECRET,
+            tls13_hs_secrets->server_handshake_traffic_secret,
+            hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: FIX! */);
+    }
+
+    ret = mbedtls_ssl_tls13_make_traffic_keys(
+        hash_alg,
+        tls13_hs_secrets->client_handshake_traffic_secret,
+        tls13_hs_secrets->server_handshake_traffic_secret,
+        hash_len, key_len, iv_len, traffic_keys);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret);
         goto exit;
@@ -1450,8 +1467,8 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
-    psa_algorithm_t const hash_alg = mbedtls_hash_info_psa_from_md(
-        handshake->ciphersuite_info->mac);
+    psa_algorithm_t const hash_alg = mbedtls_md_psa_alg_from_type(
+        (mbedtls_md_type_t) handshake->ciphersuite_info->mac);
     unsigned char *shared_secret = NULL;
     size_t shared_secret_len = 0;
 
@@ -1462,13 +1479,18 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
      * are derived in the handshake secret derivation stage.
      */
     if (mbedtls_ssl_tls13_key_exchange_mode_with_ephemeral(ssl)) {
-        if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id)) {
-#if defined(MBEDTLS_ECDH_C)
+        if (mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ||
+            mbedtls_ssl_tls13_named_group_is_ffdh(handshake->offered_group_id)) {
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
+            psa_algorithm_t alg =
+                mbedtls_ssl_tls13_named_group_is_ecdhe(handshake->offered_group_id) ?
+                PSA_ALG_ECDH : PSA_ALG_FFDH;
+
             /* Compute ECDH shared secret. */
             psa_status_t status = PSA_ERROR_GENERIC_ERROR;
             psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
 
-            status = psa_get_key_attributes(handshake->ecdh_psa_privkey,
+            status = psa_get_key_attributes(handshake->xxdh_psa_privkey,
                                             &key_attributes);
             if (status != PSA_SUCCESS) {
                 ret = PSA_TO_MBEDTLS_ERR(status);
@@ -1482,8 +1504,8 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
             }
 
             status = psa_raw_key_agreement(
-                PSA_ALG_ECDH, handshake->ecdh_psa_privkey,
-                handshake->ecdh_psa_peerkey, handshake->ecdh_psa_peerkey_len,
+                alg, handshake->xxdh_psa_privkey,
+                handshake->xxdh_psa_peerkey, handshake->xxdh_psa_peerkey_len,
                 shared_secret, shared_secret_len, &shared_secret_len);
             if (status != PSA_SUCCESS) {
                 ret = PSA_TO_MBEDTLS_ERR(status);
@@ -1491,15 +1513,15 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
                 goto cleanup;
             }
 
-            status = psa_destroy_key(handshake->ecdh_psa_privkey);
+            status = psa_destroy_key(handshake->xxdh_psa_privkey);
             if (status != PSA_SUCCESS) {
                 ret = PSA_TO_MBEDTLS_ERR(status);
                 MBEDTLS_SSL_DEBUG_RET(1, "psa_destroy_key", ret);
                 goto cleanup;
             }
 
-            handshake->ecdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
-#endif /* MBEDTLS_ECDH_C */
+            handshake->xxdh_psa_privkey = MBEDTLS_SVC_KEY_ID_INIT;
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
         } else {
             MBEDTLS_SSL_DEBUG_MSG(1, ("Group not supported."));
             return MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
@@ -1510,10 +1532,10 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
     /*
      * Compute the Handshake Secret
      */
-    ret = mbedtls_ssl_tls13_evolve_secret(hash_alg,
-                                          handshake->tls13_master_secrets.early,
-                                          shared_secret, shared_secret_len,
-                                          handshake->tls13_master_secrets.handshake);
+    ret = mbedtls_ssl_tls13_evolve_secret(
+        hash_alg, handshake->tls13_master_secrets.early,
+        shared_secret, shared_secret_len,
+        handshake->tls13_master_secrets.handshake);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_evolve_secret", ret);
         goto cleanup;
@@ -1525,8 +1547,7 @@ static int ssl_tls13_key_schedule_stage_handshake(mbedtls_ssl_context *ssl)
 
 cleanup:
     if (shared_secret != NULL) {
-        mbedtls_platform_zeroize(shared_secret, shared_secret_len);
-        mbedtls_free(shared_secret);
+        mbedtls_zeroize_and_free(shared_secret, shared_secret_len);
     }
 
     return ret;
@@ -1571,7 +1592,7 @@ static int ssl_tls13_generate_application_keys(
     size_t hash_len;
 
     /* Variables relating to the cipher for the chosen ciphersuite. */
-    size_t key_len, iv_len;
+    size_t key_len = 0, iv_len = 0;
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> derive application traffic keys"));
 
@@ -1584,9 +1605,9 @@ static int ssl_tls13_generate_application_keys(
         goto cleanup;
     }
 
-    md_type = handshake->ciphersuite_info->mac;
+    md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;
 
-    hash_alg = mbedtls_hash_info_psa_from_md(handshake->ciphersuite_info->mac);
+    hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) handshake->ciphersuite_info->mac);
     hash_len = PSA_HASH_LENGTH(hash_alg);
 
     /* Compute current handshake transcript. It's the caller's responsibility
@@ -1601,22 +1622,22 @@ static int ssl_tls13_generate_application_keys(
 
     /* Compute application secrets from master secret and transcript hash. */
 
-    ret = mbedtls_ssl_tls13_derive_application_secrets(hash_alg,
-                                                       handshake->tls13_master_secrets.app,
-                                                       transcript, transcript_len,
-                                                       app_secrets);
+    ret = mbedtls_ssl_tls13_derive_application_secrets(
+        hash_alg, handshake->tls13_master_secrets.app,
+        transcript, transcript_len, app_secrets);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1,
-                              "mbedtls_ssl_tls13_derive_application_secrets", ret);
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_tls13_derive_application_secrets", ret);
         goto cleanup;
     }
 
     /* Derive first epoch of IV + Key for application traffic. */
 
-    ret = mbedtls_ssl_tls13_make_traffic_keys(hash_alg,
-                                              app_secrets->client_application_traffic_secret_N,
-                                              app_secrets->server_application_traffic_secret_N,
-                                              hash_len, key_len, iv_len, traffic_keys);
+    ret = mbedtls_ssl_tls13_make_traffic_keys(
+        hash_alg,
+        app_secrets->client_application_traffic_secret_N,
+        app_secrets->server_application_traffic_secret_N,
+        hash_len, key_len, iv_len, traffic_keys);
     if (ret != 0) {
         MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_tls13_make_traffic_keys", ret);
         goto cleanup;
@@ -1634,21 +1655,23 @@ static int ssl_tls13_generate_application_keys(
      * Export client/server application traffic secret 0
      */
     if (ssl->f_export_keys != NULL) {
-        ssl->f_export_keys(ssl->p_export_keys,
-                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET,
-                           app_secrets->client_application_traffic_secret_N, hash_len,
-                           handshake->randbytes,
-                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
-                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
-                                                       a new constant for TLS 1.3! */);
-
-        ssl->f_export_keys(ssl->p_export_keys,
-                           MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET,
-                           app_secrets->server_application_traffic_secret_N, hash_len,
-                           handshake->randbytes,
-                           handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
-                           MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
-                                                       a new constant for TLS 1.3! */);
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_CLIENT_APPLICATION_TRAFFIC_SECRET,
+            app_secrets->client_application_traffic_secret_N, hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
+                                        a new constant for TLS 1.3! */);
+
+        ssl->f_export_keys(
+            ssl->p_export_keys,
+            MBEDTLS_SSL_KEY_EXPORT_TLS1_3_SERVER_APPLICATION_TRAFFIC_SECRET,
+            app_secrets->server_application_traffic_secret_N, hash_len,
+            handshake->randbytes,
+            handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN,
+            MBEDTLS_SSL_TLS_PRF_NONE /* TODO: this should be replaced by
+                                        a new constant for TLS 1.3! */);
     }
 
     MBEDTLS_SSL_DEBUG_BUF(4, "client application_write_key:",
@@ -1729,10 +1752,10 @@ int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl)
     unsigned char transcript[MBEDTLS_TLS1_3_MD_MAX_SIZE];
     size_t transcript_len;
 
-    MBEDTLS_SSL_DEBUG_MSG(2,
-                          ("=> mbedtls_ssl_tls13_compute_resumption_master_secret"));
+    MBEDTLS_SSL_DEBUG_MSG(
+        2, ("=> mbedtls_ssl_tls13_compute_resumption_master_secret"));
 
-    md_type = handshake->ciphersuite_info->mac;
+    md_type = (mbedtls_md_type_t) handshake->ciphersuite_info->mac;
 
     ret = mbedtls_ssl_get_handshake_transcript(ssl, md_type,
                                                transcript, sizeof(transcript),
@@ -1742,7 +1765,7 @@ int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl)
     }
 
     ret = mbedtls_ssl_tls13_derive_resumption_master_secret(
-        mbedtls_psa_translate_md(md_type),
+        mbedtls_md_psa_alg_from_type(md_type),
         handshake->tls13_master_secrets.app,
         transcript, transcript_len,
         &ssl->session_negotiate->app_secrets);
@@ -1754,12 +1777,13 @@ int mbedtls_ssl_tls13_compute_resumption_master_secret(mbedtls_ssl_context *ssl)
     mbedtls_platform_zeroize(&handshake->tls13_master_secrets,
                              sizeof(handshake->tls13_master_secrets));
 
-    MBEDTLS_SSL_DEBUG_BUF(4, "Resumption master secret",
-                          ssl->session_negotiate->app_secrets.resumption_master_secret,
-                          PSA_HASH_LENGTH(mbedtls_psa_translate_md(md_type)));
+    MBEDTLS_SSL_DEBUG_BUF(
+        4, "Resumption master secret",
+        ssl->session_negotiate->app_secrets.resumption_master_secret,
+        PSA_HASH_LENGTH(mbedtls_md_psa_alg_from_type(md_type)));
 
-    MBEDTLS_SSL_DEBUG_MSG(2,
-                          ("<= mbedtls_ssl_tls13_compute_resumption_master_secret"));
+    MBEDTLS_SSL_DEBUG_MSG(
+        2, ("<= mbedtls_ssl_tls13_compute_resumption_master_secret"));
     return 0;
 }
 
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
index 21e9b4d734e28f49a35b6c48a0d3ee8fcf361051..d3a4c6c9926de74fe9023797d25986e80aca9102 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_keys.h
@@ -2,19 +2,7 @@
  *  TLS 1.3 key schedule
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 ( the "License" ); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 #if !defined(MBEDTLS_SSL_TLS1_3_KEYS_H)
 #define MBEDTLS_SSL_TLS1_3_KEYS_H
diff --git a/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c b/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c
index b5a0c9e52aa729ea1a756214c71946ac15bdd16a..693edc7b0bccc1ec95f10bc46359f9c1f9119987 100644
--- a/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c
+++ b/lib/libmbedtls/mbedtls/library/ssl_tls13_server.c
@@ -2,29 +2,19 @@
  *  TLS 1.3 server-side functions
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
 #if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_PROTO_TLS1_3)
 
-#include "mbedtls/debug.h"
+#include "debug_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/platform.h"
 #include "mbedtls/constant_time.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/psa_util.h"
 
 #include "ssl_misc.h"
 #include "ssl_tls13_keys.h"
@@ -49,6 +39,64 @@ static const mbedtls_ssl_ciphersuite_t *ssl_tls13_validate_peer_ciphersuite(
     return ciphersuite_info;
 }
 
+static void ssl_tls13_select_ciphersuite(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *cipher_suites,
+    const unsigned char *cipher_suites_end,
+    int psk_ciphersuite_id,
+    psa_algorithm_t psk_hash_alg,
+    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
+{
+    *selected_ciphersuite_info = NULL;
+
+    /*
+     * In a compliant ClientHello the byte-length of the list of ciphersuites
+     * is even and this function relies on this fact. This should have been
+     * checked in the main ClientHello parsing function. Double check here.
+     */
+    if ((cipher_suites_end - cipher_suites) & 1) {
+        return;
+    }
+
+    for (const unsigned char *p = cipher_suites;
+         p < cipher_suites_end; p += 2) {
+        /*
+         * "cipher_suites_end - p is even" is an invariant of the loop. As
+         * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and it
+         * is thus safe to read two bytes.
+         */
+        uint16_t id = MBEDTLS_GET_UINT16_BE(p, 0);
+
+        const mbedtls_ssl_ciphersuite_t *info =
+            ssl_tls13_validate_peer_ciphersuite(ssl, id);
+        if (info == NULL) {
+            continue;
+        }
+
+        /*
+         * If a valid PSK ciphersuite identifier has been passed in, we want
+         * an exact match.
+         */
+        if (psk_ciphersuite_id != 0) {
+            if (id != psk_ciphersuite_id) {
+                continue;
+            }
+        } else if (psk_hash_alg != PSA_ALG_NONE) {
+            if (mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) info->mac) !=
+                psk_hash_alg) {
+                continue;
+            }
+        }
+
+        *selected_ciphersuite_info = info;
+        return;
+    }
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite, psk_ciphersuite_id=%x, psk_hash_alg=%lx",
+                              (unsigned) psk_ciphersuite_id,
+                              (unsigned long) psk_hash_alg));
+}
+
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
 /* From RFC 8446:
  *
@@ -100,11 +148,37 @@ static int ssl_tls13_parse_key_exchange_modes_ext(mbedtls_ssl_context *ssl,
     return 0;
 }
 
-#define SSL_TLS1_3_OFFERED_PSK_NOT_MATCH   1
-#define SSL_TLS1_3_OFFERED_PSK_MATCH       0
+/*
+ * Non-error return values of
+ * ssl_tls13_offered_psks_check_identity_match_ticket() and
+ * ssl_tls13_offered_psks_check_identity_match(). They are positive to
+ * not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_PSK_IDENTITY_MATCH) in case of success as it may be propagated
+ * up by the callers of this function as a generic success condition.
+ *
+ * The return value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE means
+ * that the pre-shared-key identity matches that of a ticket or an externally-
+ * provisioned pre-shared-key. We have thus been able to retrieve the
+ * attributes of the pre-shared-key but at least one of them does not meet
+ * some criteria and the pre-shared-key cannot be used. For example, a ticket
+ * is expired or its version is not TLS 1.3. Note eventually that the return
+ * value SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE does not have
+ * anything to do with binder check. A binder check is done only when a
+ * suitable pre-shared-key has been selected and only for that selected
+ * pre-shared-key: if the binder check fails, we fail the handshake and we do
+ * not try to find another pre-shared-key for which the binder check would
+ * succeed as recommended by the specification.
+ */
+#define SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH 2
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE 1
+#define SSL_TLS1_3_PSK_IDENTITY_MATCH 0
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl);
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl);
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_offered_psks_check_identity_match_ticket(
     mbedtls_ssl_context *ssl,
@@ -116,9 +190,10 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket(
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *ticket_buffer;
 #if defined(MBEDTLS_HAVE_TIME)
-    mbedtls_time_t now;
-    uint64_t age_in_s;
-    int64_t age_diff_in_ms;
+    mbedtls_ms_time_t now;
+    mbedtls_ms_time_t server_age;
+    uint32_t client_age;
+    mbedtls_ms_time_t age_diff;
 #endif
 
     ((void) obfuscated_ticket_age);
@@ -127,7 +202,7 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket(
 
     /* Ticket parser is not configured, Skip */
     if (ssl->conf->f_ticket_parse == NULL || identity_len == 0) {
-        return 0;
+        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     /* We create a copy of the encrypted ticket since the ticket parsing
@@ -137,63 +212,63 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket(
      */
     ticket_buffer = mbedtls_calloc(1, identity_len);
     if (ticket_buffer == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("buffer too small"));
         return MBEDTLS_ERR_SSL_ALLOC_FAILED;
     }
     memcpy(ticket_buffer, identity, identity_len);
 
-    if ((ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
-                                         session,
-                                         ticket_buffer, identity_len)) != 0) {
-        if (ret == MBEDTLS_ERR_SSL_INVALID_MAC) {
-            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
-        } else if (ret == MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) {
+    ret = ssl->conf->f_ticket_parse(ssl->conf->p_ticket,
+                                    session,
+                                    ticket_buffer, identity_len);
+    switch (ret) {
+        case 0:
+            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+            break;
+
+        case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED:
             MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is expired"));
-        } else {
+            ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
+            break;
+
+        case MBEDTLS_ERR_SSL_INVALID_MAC:
+            MBEDTLS_SSL_DEBUG_MSG(3, ("ticket is not authentic"));
+            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
+            break;
+
+        default:
             MBEDTLS_SSL_DEBUG_RET(1, "ticket_parse", ret);
-        }
+            ret = SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     /* We delete the temporary buffer */
     mbedtls_free(ticket_buffer);
 
-    if (ret != 0) {
+    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         goto exit;
     }
 
-    /* RFC 8446 section 4.2.9
-     *
-     * Servers SHOULD NOT send NewSessionTicket with tickets that are not
-     * compatible with the advertised modes; however, if a server does so,
-     * the impact will just be that the client's attempts at resumption fail.
-     *
-     * We regard the ticket with incompatible key exchange modes as not match.
+    /*
+     * The identity matches that of a ticket. Now check that it has suitable
+     * attributes and bet it will not be the case.
      */
-    ret = MBEDTLS_ERR_ERROR_GENERIC_ERROR;
-    MBEDTLS_SSL_PRINT_TICKET_FLAGS(4,
-                                   session->ticket_flags);
-    if (mbedtls_ssl_tls13_check_kex_modes(
-            ssl,
-            mbedtls_ssl_session_get_ticket_flags(
-                session,
-                MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL))) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable key exchange mode"));
+    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
+
+    if (session->tls_version != MBEDTLS_SSL_VERSION_TLS1_3) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Ticket TLS version is not 1.3."));
         goto exit;
     }
 
-    ret = MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED;
 #if defined(MBEDTLS_HAVE_TIME)
-    now = mbedtls_time(NULL);
+    now = mbedtls_ms_time();
 
-    if (now < session->start) {
+    if (now < session->ticket_creation_time) {
         MBEDTLS_SSL_DEBUG_MSG(
-            3, ("Invalid ticket start time ( now=%" MBEDTLS_PRINTF_LONGLONG
-                ", start=%" MBEDTLS_PRINTF_LONGLONG " )",
-                (long long) now, (long long) session->start));
+            3, ("Invalid ticket creation time ( now = %" MBEDTLS_PRINTF_MS_TIME
+                ", creation_time = %" MBEDTLS_PRINTF_MS_TIME " )",
+                now, session->ticket_creation_time));
         goto exit;
     }
 
-    age_in_s = (uint64_t) (now - session->start);
+    server_age = now - session->ticket_creation_time;
 
     /* RFC 8446 section 4.6.1
      *
@@ -204,12 +279,11 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket(
      * Clients MUST NOT attempt to use tickets which have ages greater than
      * the "ticket_lifetime" value which was provided with the ticket.
      *
-     * For time being, the age MUST be less than 604800 seconds (7 days).
      */
-    if (age_in_s > 604800) {
+    if (server_age > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME * 1000) {
         MBEDTLS_SSL_DEBUG_MSG(
-            3, ("Ticket age exceeds limitation ticket_age=%lu",
-                (long unsigned int) age_in_s));
+            3, ("Ticket age exceeds limitation ticket_age = %" MBEDTLS_PRINTF_MS_TIME,
+                server_age));
         goto exit;
     }
 
@@ -220,27 +294,30 @@ static int ssl_tls13_offered_psks_check_identity_match_ticket(
      * ticket_age_add from PskIdentity.obfuscated_ticket_age modulo 2^32) is
      * within a small tolerance of the time since the ticket was issued.
      *
-     * NOTE: When `now == session->start`, `age_diff_in_ms` may be negative
-     *       as the age units are different on the server (s) and in the
-     *       client (ms) side. Add a -1000 ms tolerance window to take this
-     *       into account.
+     * NOTE: The typical accuracy of an RTC crystal is ±100 to ±20 parts per
+     *       million (360 to 72 milliseconds per hour). Default tolerance
+     *       window is 6s, thus in the worst case clients and servers must
+     *       sync up their system time every 6000/360/2~=8 hours.
      */
-    age_diff_in_ms = age_in_s * 1000;
-    age_diff_in_ms -= (obfuscated_ticket_age - session->ticket_age_add);
-    if (age_diff_in_ms <= -1000 ||
-        age_diff_in_ms > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) {
+    client_age = obfuscated_ticket_age - session->ticket_age_add;
+    age_diff = server_age - (mbedtls_ms_time_t) client_age;
+    if (age_diff < -MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE ||
+        age_diff > MBEDTLS_SSL_TLS1_3_TICKET_AGE_TOLERANCE) {
         MBEDTLS_SSL_DEBUG_MSG(
-            3, ("Ticket age outside tolerance window ( diff=%d )",
-                (int) age_diff_in_ms));
+            3, ("Ticket age outside tolerance window ( diff = %"
+                MBEDTLS_PRINTF_MS_TIME ")",
+                age_diff));
         goto exit;
     }
-
-    ret = 0;
-
 #endif /* MBEDTLS_HAVE_TIME */
 
+    /*
+     * All good, we have found a suitable ticket.
+     */
+    ret = SSL_TLS1_3_PSK_IDENTITY_MATCH;
+
 exit:
-    if (ret != 0) {
+    if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         mbedtls_ssl_session_free(session);
     }
 
@@ -265,13 +342,11 @@ static int ssl_tls13_offered_psks_check_identity_match(
     *psk_type = MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL;
 
     MBEDTLS_SSL_DEBUG_BUF(4, "identity", identity, identity_len);
-    ssl->handshake->resume = 0;
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    if (ssl_tls13_offered_psks_check_identity_match_ticket(
-            ssl, identity, identity_len, obfuscated_ticket_age,
-            session) == SSL_TLS1_3_OFFERED_PSK_MATCH) {
-        ssl->handshake->resume = 1;
+    ret = ssl_tls13_offered_psks_check_identity_match_ticket(
+        ssl, identity, identity_len, obfuscated_ticket_age, session);
+    if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH) {
         *psk_type = MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION;
         ret = mbedtls_ssl_set_hs_psk(ssl,
                                      session->resumption_key,
@@ -286,7 +361,9 @@ static int ssl_tls13_offered_psks_check_identity_match(
                               session->resumption_key_len);
         MBEDTLS_SSL_DEBUG_MSG(4, ("ticket: obfuscated_ticket_age: %u",
                                   (unsigned) obfuscated_ticket_age));
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH;
+    } else if (ret == SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE) {
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH_BUT_PSK_NOT_USABLE;
     }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
@@ -294,9 +371,9 @@ static int ssl_tls13_offered_psks_check_identity_match(
     if (ssl->conf->f_psk != NULL) {
         if (ssl->conf->f_psk(
                 ssl->conf->p_psk, ssl, identity, identity_len) == 0) {
-            return SSL_TLS1_3_OFFERED_PSK_MATCH;
+            return SSL_TLS1_3_PSK_IDENTITY_MATCH;
         }
-        return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
     }
 
     MBEDTLS_SSL_DEBUG_BUF(5, "identity", identity, identity_len);
@@ -310,18 +387,25 @@ static int ssl_tls13_offered_psks_check_identity_match(
             MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_set_hs_psk", ret);
             return ret;
         }
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+        return SSL_TLS1_3_PSK_IDENTITY_MATCH;
     }
 
-    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
+    return SSL_TLS1_3_PSK_IDENTITY_DOES_NOT_MATCH;
 }
 
+/*
+ * Non-error return values of ssl_tls13_offered_psks_check_binder_match().
+ * They are positive to not collide with error codes that are negative. Zero
+ * (SSL_TLS1_3_BINDER_MATCH) in case of success as it may be propagated up
+ * by the callers of this function as a generic success condition.
+ */
+#define SSL_TLS1_3_BINDER_DOES_NOT_MATCH 1
+#define SSL_TLS1_3_BINDER_MATCH 0
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_offered_psks_check_binder_match(mbedtls_ssl_context *ssl,
-                                                     const unsigned char *binder,
-                                                     size_t binder_len,
-                                                     int psk_type,
-                                                     psa_algorithm_t psk_hash_alg)
+static int ssl_tls13_offered_psks_check_binder_match(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *binder, size_t binder_len,
+    int psk_type, psa_algorithm_t psk_hash_alg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -331,9 +415,13 @@ static int ssl_tls13_offered_psks_check_binder_match(mbedtls_ssl_context *ssl,
     size_t psk_len;
     unsigned char server_computed_binder[PSA_HASH_MAX_SIZE];
 
+    if (binder_len != PSA_HASH_LENGTH(psk_hash_alg)) {
+        return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;
+    }
+
     /* Get current state of handshake transcript. */
     ret = mbedtls_ssl_get_handshake_transcript(
-        ssl, mbedtls_hash_info_md_from_psa(psk_hash_alg),
+        ssl, mbedtls_md_type_from_psa_alg(psk_hash_alg),
         transcript, sizeof(transcript), &transcript_len);
     if (ret != 0) {
         return ret;
@@ -360,99 +448,18 @@ static int ssl_tls13_offered_psks_check_binder_match(mbedtls_ssl_context *ssl,
                           server_computed_binder, transcript_len);
     MBEDTLS_SSL_DEBUG_BUF(3, "psk binder ( received ): ", binder, binder_len);
 
-    if (mbedtls_ct_memcmp(server_computed_binder, binder, binder_len) == 0) {
-        return SSL_TLS1_3_OFFERED_PSK_MATCH;
+    if (mbedtls_ct_memcmp(server_computed_binder,
+                          binder,
+                          PSA_HASH_LENGTH(psk_hash_alg)) == 0) {
+        return SSL_TLS1_3_BINDER_MATCH;
     }
 
     mbedtls_platform_zeroize(server_computed_binder,
                              sizeof(server_computed_binder));
-    return SSL_TLS1_3_OFFERED_PSK_NOT_MATCH;
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_psk(
-    mbedtls_ssl_context *ssl,
-    const unsigned char *cipher_suites,
-    const unsigned char *cipher_suites_end,
-    uint16_t *selected_ciphersuite,
-    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
-    psa_algorithm_t psk_hash_alg = PSA_ALG_SHA_256;
-
-    *selected_ciphersuite = 0;
-    *selected_ciphersuite_info = NULL;
-
-    /* RFC 8446, page 55.
-     *
-     * For externally established PSKs, the Hash algorithm MUST be set when the
-     * PSK is established or default to SHA-256 if no such algorithm is defined.
-     *
-     */
-
-    /*
-     * Search for a matching ciphersuite
-     */
-    for (const unsigned char *p = cipher_suites;
-         p < cipher_suites_end; p += 2) {
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
-        cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
-                                                               cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
-        }
-
-        /* MAC of selected ciphersuite MUST be same with PSK binder if exist.
-         * Otherwise, client should reject.
-         */
-        if (psk_hash_alg == mbedtls_psa_translate_md(ciphersuite_info->mac)) {
-            *selected_ciphersuite = cipher_suite;
-            *selected_ciphersuite_info = ciphersuite_info;
-            return 0;
-        }
-    }
-    MBEDTLS_SSL_DEBUG_MSG(2, ("No matched ciphersuite"));
-    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
+    return SSL_TLS1_3_BINDER_DOES_NOT_MATCH;
 }
 
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_select_ciphersuite_for_resumption(
-    mbedtls_ssl_context *ssl,
-    const unsigned char *cipher_suites,
-    const unsigned char *cipher_suites_end,
-    mbedtls_ssl_session *session,
-    uint16_t *selected_ciphersuite,
-    const mbedtls_ssl_ciphersuite_t **selected_ciphersuite_info)
-{
-
-    *selected_ciphersuite = 0;
-    *selected_ciphersuite_info = NULL;
-    for (const unsigned char *p = cipher_suites; p < cipher_suites_end; p += 2) {
-        uint16_t cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-
-        if (cipher_suite != session->ciphersuite) {
-            continue;
-        }
-
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(ssl,
-                                                               cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
-        }
-
-        *selected_ciphersuite = cipher_suite;
-        *selected_ciphersuite_info = ciphersuite_info;
-
-        return 0;
-    }
-
-    return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
-}
-
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
                                          const mbedtls_ssl_session *src)
@@ -465,10 +472,28 @@ static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
     }
     memcpy(dst->resumption_key, src->resumption_key, src->resumption_key_len);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    dst->max_early_data_size = src->max_early_data_size;
+
+#if defined(MBEDTLS_SSL_ALPN)
+    int ret = mbedtls_ssl_session_set_ticket_alpn(dst, src->ticket_alpn);
+    if (ret != 0) {
+        return ret;
+    }
+#endif /* MBEDTLS_SSL_ALPN */
+#endif /* MBEDTLS_SSL_EARLY_DATA*/
+
     return 0;
 }
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 
+struct psk_attributes {
+    int type;
+    int key_exchange_mode;
+    const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+};
+#define PSK_ATTRIBUTES_INIT { 0, 0, NULL }
+
 /* Parser for pre_shared_key extension in client hello
  *    struct {
  *        opaque identity<1..2^16-1>;
@@ -490,11 +515,13 @@ static int ssl_tls13_session_copy_ticket(mbedtls_ssl_session *dst,
  *    } PreSharedKeyExtension;
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
-                                              const unsigned char *pre_shared_key_ext,
-                                              const unsigned char *pre_shared_key_ext_end,
-                                              const unsigned char *ciphersuites,
-                                              const unsigned char *ciphersuites_end)
+static int ssl_tls13_parse_pre_shared_key_ext(
+    mbedtls_ssl_context *ssl,
+    const unsigned char *pre_shared_key_ext,
+    const unsigned char *pre_shared_key_ext_end,
+    const unsigned char *ciphersuites,
+    const unsigned char *ciphersuites_end,
+    struct psk_attributes *psk)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *identities = pre_shared_key_ext;
@@ -545,13 +572,12 @@ static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
         uint32_t obfuscated_ticket_age;
         const unsigned char *binder;
         size_t binder_len;
-        int psk_type;
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+        int psk_ciphersuite_id;
+        psa_algorithm_t psk_hash_alg;
+        int allowed_key_exchange_modes;
+
         mbedtls_ssl_session session;
         mbedtls_ssl_session_init(&session);
-#endif
 
         MBEDTLS_SSL_CHK_BUF_READ_PTR(p_identity_len, identities_end, 2 + 1 + 4);
         identity_len = MBEDTLS_GET_UINT16_BE(p_identity_len, 0);
@@ -573,47 +599,74 @@ static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
 
         ret = ssl_tls13_offered_psks_check_identity_match(
             ssl, identity, identity_len, obfuscated_ticket_age,
-            &psk_type, &session);
-        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            &psk->type, &session);
+        if (ret != SSL_TLS1_3_PSK_IDENTITY_MATCH) {
             continue;
         }
 
         MBEDTLS_SSL_DEBUG_MSG(4, ("found matched identity"));
-        switch (psk_type) {
+
+        switch (psk->type) {
             case MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL:
-                ret = ssl_tls13_select_ciphersuite_for_psk(
-                    ssl, ciphersuites, ciphersuites_end,
-                    &cipher_suite, &ciphersuite_info);
+                psk_ciphersuite_id = 0;
+                psk_hash_alg = PSA_ALG_SHA_256;
+                allowed_key_exchange_modes =
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
                 break;
-            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-                ret = ssl_tls13_select_ciphersuite_for_resumption(
-                    ssl, ciphersuites, ciphersuites_end, &session,
-                    &cipher_suite, &ciphersuite_info);
-                if (ret != 0) {
-                    mbedtls_ssl_session_free(&session);
-                }
-#else
-                ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
-#endif
+            case MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION:
+                psk_ciphersuite_id = session.ciphersuite;
+                psk_hash_alg = PSA_ALG_NONE;
+                ssl->session_negotiate->ticket_flags = session.ticket_flags;
+                allowed_key_exchange_modes =
+                    session.ticket_flags &
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL;
                 break;
+#endif
             default:
                 return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
         }
-        if (ret != 0) {
-            /* See below, no cipher_suite available, abort handshake */
+
+        psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
+
+        if ((allowed_key_exchange_modes &
+             MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL) &&
+            ssl_tls13_key_exchange_is_psk_ephemeral_available(ssl)) {
+            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        } else if ((allowed_key_exchange_modes &
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) &&
+                   ssl_tls13_key_exchange_is_psk_available(ssl)) {
+            psk->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+        }
+
+        if (psk->key_exchange_mode == MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("No suitable PSK key exchange mode"));
+            continue;
+        }
+
+        ssl_tls13_select_ciphersuite(ssl, ciphersuites, ciphersuites_end,
+                                     psk_ciphersuite_id, psk_hash_alg,
+                                     &psk->ciphersuite_info);
+
+        if (psk->ciphersuite_info == NULL) {
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
+            mbedtls_ssl_session_free(&session);
+#endif
+            /*
+             * We consider finding a ciphersuite suitable for the PSK as part
+             * of the validation of its binder. Thus if we do not find one, we
+             * abort the handshake with a decrypt_error alert.
+             */
             MBEDTLS_SSL_PEND_FATAL_ALERT(
                 MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
                 MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
-            MBEDTLS_SSL_DEBUG_RET(
-                2, "ssl_tls13_select_ciphersuite", ret);
-            return ret;
+            return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
         }
 
         ret = ssl_tls13_offered_psks_check_binder_match(
-            ssl, binder, binder_len, psk_type,
-            mbedtls_psa_translate_md(ciphersuite_info->mac));
-        if (ret != SSL_TLS1_3_OFFERED_PSK_MATCH) {
+            ssl, binder, binder_len, psk->type,
+            mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) psk->ciphersuite_info->mac));
+        if (ret != SSL_TLS1_3_BINDER_MATCH) {
             /* For security reasons, the handshake should be aborted when we
              * fail to validate a binder value. See RFC 8446 section 4.2.11.2
              * and appendix E.6. */
@@ -621,8 +674,8 @@ static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
             mbedtls_ssl_session_free(&session);
 #endif
             MBEDTLS_SSL_DEBUG_MSG(3, ("Invalid binder."));
-            MBEDTLS_SSL_DEBUG_RET(1,
-                                  "ssl_tls13_offered_psks_check_binder_match", ret);
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "ssl_tls13_offered_psks_check_binder_match", ret);
             MBEDTLS_SSL_PEND_FATAL_ALERT(
                 MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR,
                 MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
@@ -631,13 +684,8 @@ static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
 
         matched_identity = identity_id;
 
-        /* Update handshake parameters */
-        ssl->handshake->ciphersuite_info = ciphersuite_info;
-        ssl->session_negotiate->ciphersuite = cipher_suite;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("overwrite ciphersuite: %04x - %s",
-                                  cipher_suite, ciphersuite_info->name));
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-        if (psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+        if (psk->type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
             ret = ssl_tls13_session_copy_ticket(ssl->session_negotiate,
                                                 &session);
             mbedtls_ssl_session_free(&session);
@@ -656,15 +704,14 @@ static int ssl_tls13_parse_pre_shared_key_ext(mbedtls_ssl_context *ssl,
     }
 
     /* Update the handshake transcript with the binder list. */
-    ret = ssl->handshake->update_checksum(ssl,
-                                          identities_end,
-                                          (size_t) (binders_end - identities_end));
+    ret = ssl->handshake->update_checksum(
+        ssl, identities_end, (size_t) (binders_end - identities_end));
     if (0 != ret) {
         MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
         return ret;
     }
     if (matched_identity == -1) {
-        MBEDTLS_SSL_DEBUG_MSG(3, ("No matched PSK or ticket."));
+        MBEDTLS_SSL_DEBUG_MSG(3, ("No usable PSK or ticket."));
         return MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY;
     }
 
@@ -738,7 +785,7 @@ static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,
     size_t versions_len;
     const unsigned char *versions_end;
     uint16_t tls_version;
-    int tls13_supported = 0;
+    int found_supported_version = 0;
 
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, 1);
     versions_len = p[0];
@@ -751,28 +798,33 @@ static int ssl_tls13_parse_supported_versions_ext(mbedtls_ssl_context *ssl,
         tls_version = mbedtls_ssl_read_version(p, ssl->conf->transport);
         p += 2;
 
-        /* In this implementation we only support TLS 1.3 and DTLS 1.3. */
-        if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3) {
-            tls13_supported = 1;
+        if (MBEDTLS_SSL_VERSION_TLS1_3 == tls_version) {
+            found_supported_version = 1;
+            break;
+        }
+
+        if ((MBEDTLS_SSL_VERSION_TLS1_2 == tls_version) &&
+            mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) {
+            found_supported_version = 1;
             break;
         }
     }
 
-    if (!tls13_supported) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("TLS 1.3 is not supported by the client"));
+    if (!found_supported_version) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("No supported version found."));
 
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
                                      MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);
         return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version. Supported is [%04x]",
+    MBEDTLS_SSL_DEBUG_MSG(1, ("Negotiated version: [%04x]",
                               (unsigned int) tls_version));
 
-    return 0;
+    return (int) tls_version;
 }
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
 /*
  *
  * From RFC 8446:
@@ -828,20 +880,21 @@ static int ssl_tls13_parse_supported_groups_ext(mbedtls_ssl_context *ssl,
     return 0;
 
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH */
 
 #define SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH 1
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
 /*
  *  ssl_tls13_parse_key_shares_ext() verifies whether the information in the
- *  extension is correct and stores the first acceptable key share and its associated group.
+ *  extension is correct and stores the first acceptable key share and its
+ *  associated group.
  *
  *  Possible return values are:
  *  - 0: Successful processing of the client provided key share extension.
- *  - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by the client
- *    does not match a group supported by the server. A HelloRetryRequest will
- *    be needed.
+ *  - SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH: The key shares provided by
+ *    the client does not match a group supported by the server. A
+ *    HelloRetryRequest will be needed.
  *  - A negative value for fatal errors.
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
@@ -905,13 +958,14 @@ static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl,
         }
 
         /*
-         * For now, we only support ECDHE groups.
+         * ECDHE and FFDHE groups are supported
          */
-        if (mbedtls_ssl_tls13_named_group_is_ecdhe(group)) {
-            MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH group: %s (%04x)",
+        if (mbedtls_ssl_tls13_named_group_is_ecdhe(group) ||
+            mbedtls_ssl_tls13_named_group_is_ffdh(group)) {
+            MBEDTLS_SSL_DEBUG_MSG(2, ("ECDH/FFDH group: %s (%04x)",
                                       mbedtls_ssl_named_group_to_str(group),
                                       group));
-            ret = mbedtls_ssl_tls13_read_public_ecdhe_share(
+            ret = mbedtls_ssl_tls13_read_public_xxdhe_share(
                 ssl, key_exchange - 2, key_exchange_len + 2);
             if (ret != 0) {
                 return ret;
@@ -933,7 +987,7 @@ static int ssl_tls13_parse_key_shares_ext(mbedtls_ssl_context *ssl,
     }
     return 0;
 }
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_client_hello_has_exts(mbedtls_ssl_context *ssl,
@@ -982,24 +1036,13 @@ static int ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(
 }
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */
 
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_check_ephemeral_key_exchange(mbedtls_ssl_context *ssl)
-{
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
-    return mbedtls_ssl_conf_tls13_ephemeral_enabled(ssl) &&
-           ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl);
-#else
-    ((void) ssl);
-    return 0;
-#endif
-}
-
-MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_check_psk_key_exchange(mbedtls_ssl_context *ssl)
+static int ssl_tls13_key_exchange_is_psk_available(mbedtls_ssl_context *ssl)
 {
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
-    return mbedtls_ssl_conf_tls13_psk_enabled(ssl) &&
-           mbedtls_ssl_tls13_psk_enabled(ssl) &&
+    return mbedtls_ssl_conf_tls13_is_psk_enabled(ssl) &&
+           mbedtls_ssl_tls13_is_psk_supported(ssl) &&
            ssl_tls13_client_hello_has_exts_for_psk_key_exchange(ssl);
 #else
     ((void) ssl);
@@ -1008,62 +1051,29 @@ static int ssl_tls13_check_psk_key_exchange(mbedtls_ssl_context *ssl)
 }
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_check_psk_ephemeral_key_exchange(mbedtls_ssl_context *ssl)
+static int ssl_tls13_key_exchange_is_psk_ephemeral_available(mbedtls_ssl_context *ssl)
 {
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-    return mbedtls_ssl_conf_tls13_psk_ephemeral_enabled(ssl) &&
-           mbedtls_ssl_tls13_psk_ephemeral_enabled(ssl) &&
+    return mbedtls_ssl_conf_tls13_is_psk_ephemeral_enabled(ssl) &&
+           mbedtls_ssl_tls13_is_psk_ephemeral_supported(ssl) &&
            ssl_tls13_client_hello_has_exts_for_psk_ephemeral_key_exchange(ssl);
 #else
     ((void) ssl);
     return 0;
 #endif
 }
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
 
-static int ssl_tls13_determine_key_exchange_mode(mbedtls_ssl_context *ssl)
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_key_exchange_is_ephemeral_available(mbedtls_ssl_context *ssl)
 {
-    /*
-     * Determine the key exchange algorithm to use.
-     * There are three types of key exchanges supported in TLS 1.3:
-     * - (EC)DH with ECDSA,
-     * - (EC)DH with PSK,
-     * - plain PSK.
-     *
-     * The PSK-based key exchanges may additionally be used with 0-RTT.
-     *
-     * Our built-in order of preference is
-     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
-     *  2 ) Certificate Mode ( ephemeral )
-     *  3 ) Plain PSK Mode ( psk )
-     */
-
-    ssl->handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_NONE;
-
-    if (ssl_tls13_check_psk_ephemeral_key_exchange(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
-    } else
-    if (ssl_tls13_check_ephemeral_key_exchange(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
-    } else
-    if (ssl_tls13_check_psk_key_exchange(ssl)) {
-        ssl->handshake->key_exchange_mode =
-            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(
-            1,
-            ("ClientHello message misses mandatory extensions."));
-        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
-                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
-        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
-    }
-
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
+    return mbedtls_ssl_conf_tls13_is_ephemeral_enabled(ssl) &&
+           ssl_tls13_client_hello_has_exts_for_ephemeral_key_exchange(ssl);
+#else
+    ((void) ssl);
     return 0;
-
+#endif
 }
 
 #if defined(MBEDTLS_X509_CRT_PARSE_C) && \
@@ -1233,6 +1243,7 @@ static int ssl_tls13_pick_key_cert(mbedtls_ssl_context *ssl)
 
 #define SSL_CLIENT_HELLO_OK           0
 #define SSL_CLIENT_HELLO_HRR_REQUIRED 1
+#define SSL_CLIENT_HELLO_TLS1_2       2
 
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
@@ -1241,16 +1252,23 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     const unsigned char *p = buf;
+    const unsigned char *random;
     size_t legacy_session_id_len;
+    const unsigned char *legacy_session_id;
     size_t cipher_suites_len;
+    const unsigned char *cipher_suites;
     const unsigned char *cipher_suites_end;
     size_t extensions_len;
     const unsigned char *extensions_end;
+    const unsigned char *supported_versions_data;
+    const unsigned char *supported_versions_data_end;
     mbedtls_ssl_handshake_params *handshake = ssl->handshake;
     int hrr_required = 0;
+    int no_usable_share_for_key_agreement = 0;
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
-    const unsigned char *cipher_suites;
+    int got_psk = 0;
+    struct psk_attributes psk = PSK_ATTRIBUTES_INIT;
     const unsigned char *pre_shared_key_ext = NULL;
     const unsigned char *pre_shared_key_ext_end = NULL;
 #endif
@@ -1291,55 +1309,38 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
     }
     p += 2;
 
-    /*
-     * Only support TLS 1.3 currently, temporarily set the version.
-     */
-    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    /* Store minor version for later use with ticket serialization. */
-    ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
-    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
-#endif
-
     /* ...
      * Random random;
      * ...
      * with Random defined as:
      * opaque Random[32];
      */
-    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes",
-                          p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
-
-    memcpy(&handshake->randbytes[0], p, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    random = p;
     p += MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
 
     /* ...
      * opaque legacy_session_id<0..32>;
      * ...
      */
-    legacy_session_id_len = p[0];
-    p++;
+    legacy_session_id_len = *(p++);
+    legacy_session_id = p;
 
-    if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
-        return MBEDTLS_ERR_SSL_DECODE_ERROR;
-    }
-
-    ssl->session_negotiate->id_len = legacy_session_id_len;
-    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id",
-                          p, legacy_session_id_len);
     /*
      * Check we have enough data for the legacy session identifier
      * and the ciphersuite list length.
      */
     MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, legacy_session_id_len + 2);
-
-    memcpy(&ssl->session_negotiate->id[0], p, legacy_session_id_len);
     p += legacy_session_id_len;
 
+    /* ...
+     * CipherSuite cipher_suites<2..2^16-2>;
+     * ...
+     * with CipherSuite defined as:
+     * uint8 CipherSuite[2];
+     */
     cipher_suites_len = MBEDTLS_GET_UINT16_BE(p, 0);
     p += 2;
+    cipher_suites = p;
 
     /*
      * The length of the ciphersuite list has to be even.
@@ -1354,57 +1355,107 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
      * compression methods and the length of the extensions.
      *
      * cipher_suites                cipher_suites_len bytes
-     * legacy_compression_methods                   2 bytes
-     * extensions_len                               2 bytes
+     * legacy_compression_methods length            1 byte
      */
-    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 2 + 2);
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p, end, cipher_suites_len + 1);
+    p += cipher_suites_len;
+    cipher_suites_end = p;
 
-    /* ...
-     * CipherSuite cipher_suites<2..2^16-2>;
-     * ...
-     * with CipherSuite defined as:
-     * uint8 CipherSuite[2];
+    /* Check if we have enough data for legacy_compression_methods
+     * and the length of the extensions (2 bytes).
      */
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
-    cipher_suites = p;
-#endif
-    cipher_suites_end = p + cipher_suites_len;
-    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, ciphersuitelist",
-                          p, cipher_suites_len);
+    MBEDTLS_SSL_CHK_BUF_READ_PTR(p + 1, end, p[0] + 2);
 
     /*
-     * Search for a matching ciphersuite
+     * Search for the supported versions extension and parse it to determine
+     * if the client supports TLS 1.3.
      */
-    for (; p < cipher_suites_end; p += 2) {
-        uint16_t cipher_suite;
-        const mbedtls_ssl_ciphersuite_t *ciphersuite_info;
+    ret = mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts(
+        ssl, p + 1 + p[0], end,
+        &supported_versions_data, &supported_versions_data_end);
+    if (ret < 0) {
+        MBEDTLS_SSL_DEBUG_RET(1,
+                              ("mbedtls_ssl_tls13_is_supported_versions_ext_present_in_exts"), ret);
+        return ret;
+    }
+
+    if (ret == 0) {
+        return SSL_CLIENT_HELLO_TLS1_2;
+    }
+
+    if (ret == 1) {
+        ret = ssl_tls13_parse_supported_versions_ext(ssl,
+                                                     supported_versions_data,
+                                                     supported_versions_data_end);
+        if (ret < 0) {
+            MBEDTLS_SSL_DEBUG_RET(1,
+                                  ("ssl_tls13_parse_supported_versions_ext"), ret);
+            return ret;
+        }
 
         /*
-         * "cipher_suite_end - p is even" is an invariant of the loop. As
-         * cipher_suites_end - p > 0, we have cipher_suites_end - p >= 2 and
-         * it is thus safe to read two bytes.
+         * The supported versions extension was parsed successfully as the
+         * value returned by ssl_tls13_parse_supported_versions_ext() is
+         * positive. The return value is then equal to
+         * MBEDTLS_SSL_VERSION_TLS1_2 or MBEDTLS_SSL_VERSION_TLS1_3, defining
+         * the TLS version to negotiate.
          */
-        cipher_suite = MBEDTLS_GET_UINT16_BE(p, 0);
-        ciphersuite_info = ssl_tls13_validate_peer_ciphersuite(
-            ssl, cipher_suite);
-        if (ciphersuite_info == NULL) {
-            continue;
+        if (MBEDTLS_SSL_VERSION_TLS1_2 == ret) {
+            return SSL_CLIENT_HELLO_TLS1_2;
         }
+    }
 
-        ssl->session_negotiate->ciphersuite = cipher_suite;
-        handshake->ciphersuite_info = ciphersuite_info;
-        MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
-                                  cipher_suite,
-                                  ciphersuite_info->name));
-        break;
+    /*
+     * We negotiate TLS 1.3.
+     */
+    ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+    ssl->session_negotiate->tls_version = MBEDTLS_SSL_VERSION_TLS1_3;
+    ssl->session_negotiate->endpoint = ssl->conf->endpoint;
+
+    /* Before doing any crypto, make sure we can. */
+    ret = mbedtls_ssl_tls13_crypto_init(ssl);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /*
+     * We are negotiating the version 1.3 of the protocol. Do what we have
+     * postponed: copy of the client random bytes, copy of the legacy session
+     * identifier and selection of the TLS 1.3 cipher suite.
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, random bytes",
+                          random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+    memcpy(&handshake->randbytes[0], random, MBEDTLS_CLIENT_HELLO_RANDOM_LEN);
+
+    if (legacy_session_id_len > sizeof(ssl->session_negotiate->id)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("bad client hello message"));
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
     }
+    ssl->session_negotiate->id_len = legacy_session_id_len;
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, session id",
+                          legacy_session_id, legacy_session_id_len);
+    memcpy(&ssl->session_negotiate->id[0],
+           legacy_session_id, legacy_session_id_len);
+
+    /*
+     * Search for a matching ciphersuite
+     */
+    MBEDTLS_SSL_DEBUG_BUF(3, "client hello, list of cipher suites",
+                          cipher_suites, cipher_suites_len);
+
+    ssl_tls13_select_ciphersuite(ssl, cipher_suites, cipher_suites_end,
+                                 0, PSA_ALG_NONE, &handshake->ciphersuite_info);
 
     if (handshake->ciphersuite_info == NULL) {
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
         return MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE;
     }
-    p = cipher_suites_end;
+    ssl->session_negotiate->ciphersuite = handshake->ciphersuite_info->id;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("selected ciphersuite: %04x - %s",
+                              ((unsigned) handshake->ciphersuite_info->id),
+                              handshake->ciphersuite_info->name));
 
     /* ...
      * opaque legacy_compression_methods<1..2^8-1>;
@@ -1433,13 +1484,18 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
     extensions_end = p + extensions_len;
 
     MBEDTLS_SSL_DEBUG_BUF(3, "client hello extensions", p, extensions_len);
-
     handshake->received_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
 
     while (p < extensions_end) {
         unsigned int extension_type;
         size_t extension_data_len;
         const unsigned char *extension_data_end;
+        uint32_t allowed_exts = MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH;
+
+        if (ssl->handshake->hello_retry_request_flag) {
+            /* Do not accept early data extension in 2nd ClientHello */
+            allowed_exts &= ~MBEDTLS_SSL_EXT_MASK(EARLY_DATA);
+        }
 
         /* RFC 8446, section 4.2.11
          *
@@ -1467,7 +1523,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
 
         ret = mbedtls_ssl_tls13_check_received_extension(
             ssl, MBEDTLS_SSL_HS_CLIENT_HELLO, extension_type,
-            MBEDTLS_SSL_TLS1_3_ALLOWED_EXTS_OF_CH);
+            allowed_exts);
         if (ret != 0) {
             return ret;
         }
@@ -1486,7 +1542,7 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
                 break;
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(PSA_WANT_ALG_ECDH) || defined(PSA_WANT_ALG_FFDH)
             case MBEDTLS_TLS_EXT_SUPPORTED_GROUPS:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found supported group extension"));
 
@@ -1499,15 +1555,15 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
                 ret = ssl_tls13_parse_supported_groups_ext(
                     ssl, p, extension_data_end);
                 if (ret != 0) {
-                    MBEDTLS_SSL_DEBUG_RET(1,
-                                          "mbedtls_ssl_parse_supported_groups_ext", ret);
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "ssl_tls13_parse_supported_groups_ext", ret);
                     return ret;
                 }
 
                 break;
-#endif /* MBEDTLS_ECDH_C */
+#endif /* PSA_WANT_ALG_ECDH || PSA_WANT_ALG_FFDH*/
 
-#if defined(MBEDTLS_ECDH_C)
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
             case MBEDTLS_TLS_EXT_KEY_SHARE:
                 MBEDTLS_SSL_DEBUG_MSG(3, ("found key share extension"));
 
@@ -1521,8 +1577,8 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
                 ret = ssl_tls13_parse_key_shares_ext(
                     ssl, p, extension_data_end);
                 if (ret == SSL_TLS1_3_PARSE_KEY_SHARES_EXT_NO_MATCH) {
-                    MBEDTLS_SSL_DEBUG_MSG(2, ("HRR needed "));
-                    hrr_required = 1;
+                    MBEDTLS_SSL_DEBUG_MSG(2, ("No usable share for key agreement."));
+                    no_usable_share_for_key_agreement = 1;
                 }
 
                 if (ret < 0) {
@@ -1532,23 +1588,16 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
                 }
 
                 break;
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
 
             case MBEDTLS_TLS_EXT_SUPPORTED_VERSIONS:
-                MBEDTLS_SSL_DEBUG_MSG(3, ("found supported versions extension"));
-
-                ret = ssl_tls13_parse_supported_versions_ext(
-                    ssl, p, extension_data_end);
-                if (ret != 0) {
-                    MBEDTLS_SSL_DEBUG_RET(1,
-                                          ("ssl_tls13_parse_supported_versions_ext"), ret);
-                    return ret;
-                }
+                /* Already parsed */
                 break;
 
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
             case MBEDTLS_TLS_EXT_PSK_KEY_EXCHANGE_MODES:
-                MBEDTLS_SSL_DEBUG_MSG(3, ("found psk key exchange modes extension"));
+                MBEDTLS_SSL_DEBUG_MSG(
+                    3, ("found psk key exchange modes extension"));
 
                 ret = ssl_tls13_parse_key_exchange_modes_ext(
                     ssl, p, extension_data_end);
@@ -1600,100 +1649,248 @@ static int ssl_tls13_parse_client_hello(mbedtls_ssl_context *ssl,
                 ret = mbedtls_ssl_parse_sig_alg_ext(
                     ssl, p, extension_data_end);
                 if (ret != 0) {
-                    MBEDTLS_SSL_DEBUG_MSG(1,
-                                          (
-                                              "ssl_parse_supported_signature_algorithms_server_ext ( %d )",
-                                              ret));
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, "mbedtls_ssl_parse_sig_alg_ext", ret);
                     return ret;
                 }
                 break;
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
 
-#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
-            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
-                MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension"));
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+            case MBEDTLS_TLS_EXT_RECORD_SIZE_LIMIT:
+                MBEDTLS_SSL_DEBUG_MSG(3, ("found record_size_limit extension"));
+
+                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(
+                    ssl, p, extension_data_end);
+                if (ret != 0) {
+                    MBEDTLS_SSL_DEBUG_RET(
+                        1, ("mbedtls_ssl_tls13_parse_record_size_limit_ext"), ret);
+                    return ret;
+                }
+                break;
+#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+
+            default:
+                MBEDTLS_SSL_PRINT_EXT(
+                    3, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                    extension_type, "( ignored )");
+                break;
+        }
+
+        p += extension_data_len;
+    }
+
+    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO,
+                           handshake->received_extensions);
+
+    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
+                                             MBEDTLS_SSL_HS_CLIENT_HELLO,
+                                             p - buf);
+    if (0 != ret) {
+        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret);
+        return ret;
+    }
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    /* Update checksum with either
+     * - The entire content of the CH message, if no PSK extension is present
+     * - The content up to but excluding the PSK extension, if present.
+     * Always parse the pre-shared-key extension when present in the
+     * ClientHello even if some pre-requisites for PSK key exchange modes are
+     * not met. That way we always validate the syntax of the extension.
+     */
+    if (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY)) {
+        ret = handshake->update_checksum(ssl, buf,
+                                         pre_shared_key_ext - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
+        ret = ssl_tls13_parse_pre_shared_key_ext(ssl,
+                                                 pre_shared_key_ext,
+                                                 pre_shared_key_ext_end,
+                                                 cipher_suites,
+                                                 cipher_suites_end,
+                                                 &psk);
+        if (ret == 0) {
+            got_psk = 1;
+        } else if (ret != MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "ssl_tls13_parse_pre_shared_key_ext", ret);
+            return ret;
+        }
+    } else
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
+    {
+        ret = handshake->update_checksum(ssl, buf, p - buf);
+        if (0 != ret) {
+            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
+            return ret;
+        }
+    }
+
+    /*
+     * Determine the key exchange algorithm to use.
+     * There are three types of key exchanges supported in TLS 1.3:
+     * - (EC)DH with ECDSA,
+     * - (EC)DH with PSK,
+     * - plain PSK.
+     *
+     * The PSK-based key exchanges may additionally be used with 0-RTT.
+     *
+     * Our built-in order of preference is
+     *  1 ) (EC)DHE-PSK Mode ( psk_ephemeral )
+     *  2 ) Certificate Mode ( ephemeral )
+     *  3 ) Plain PSK Mode ( psk )
+     */
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (got_psk && (psk.key_exchange_mode ==
+                    MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL)) {
+        handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk_ephemeral"));
+
+    } else
+#endif
+    if (ssl_tls13_key_exchange_is_ephemeral_available(ssl)) {
+        handshake->key_exchange_mode =
+            MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: ephemeral"));
+
+    }
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    else if (got_psk && (psk.key_exchange_mode ==
+                         MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK)) {
+        handshake->key_exchange_mode = MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK;
+        MBEDTLS_SSL_DEBUG_MSG(2, ("key exchange mode: psk"));
+    }
+#endif
+    else {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1,
+            ("ClientHello message misses mandatory extensions."));
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_MISSING_EXTENSION,
+                                     MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER);
+        return MBEDTLS_ERR_SSL_ILLEGAL_PARAMETER;
+    }
+
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
+    if (handshake->key_exchange_mode &
+        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ALL) {
+        handshake->ciphersuite_info = psk.ciphersuite_info;
+        ssl->session_negotiate->ciphersuite = psk.ciphersuite_info->id;
+
+        MBEDTLS_SSL_DEBUG_MSG(2, ("Select PSK ciphersuite: %04x - %s",
+                                  ((unsigned) psk.ciphersuite_info->id),
+                                  psk.ciphersuite_info->name));
+
+        if (psk.type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION) {
+            handshake->resume = 1;
+        }
+    }
+#endif
+
+    if (handshake->key_exchange_mode !=
+        MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK) {
+        hrr_required = (no_usable_share_for_key_agreement != 0);
+    }
 
-                ret = mbedtls_ssl_tls13_parse_record_size_limit_ext(ssl, p, extension_data_end);
+    mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info);
 
-                /* TODO: Return unconditionally here until we handle the record size limit correctly.
-                 *            Once handled correctly, only return in case of errors. */
-                return ret;
+    return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK;
+}
 
-                break;
-#endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+static int ssl_tls13_check_early_data_requirements(mbedtls_ssl_context *ssl)
+{
+    mbedtls_ssl_handshake_params *handshake = ssl->handshake;
 
-            default:
-                MBEDTLS_SSL_PRINT_EXT(
-                    3, MBEDTLS_SSL_HS_CLIENT_HELLO,
-                    extension_type, "( ignored )");
-                break;
-        }
+    if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_DISABLED) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1,
+            ("EarlyData: rejected, feature disabled in server configuration."));
+        return -1;
+    }
 
-        p += extension_data_len;
+    if (!handshake->resume) {
+        /* We currently support early data only in the case of PSKs established
+           via a NewSessionTicket message thus in the case of a session
+           resumption. */
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("EarlyData: rejected, not a session resumption."));
+        return -1;
     }
 
-    MBEDTLS_SSL_PRINT_EXTS(3, MBEDTLS_SSL_HS_CLIENT_HELLO,
-                           handshake->received_extensions);
+    /* RFC 8446 4.2.10
+     *
+     * In order to accept early data, the server MUST have accepted a PSK cipher
+     * suite and selected the first key offered in the client's "pre_shared_key"
+     * extension. In addition, it MUST verify that the following values are the
+     * same as those associated with the selected PSK:
+     * - The TLS version number
+     * - The selected cipher suite
+     * - The selected ALPN [RFC7301] protocol, if any
+     *
+     * NOTE:
+     *  - The TLS version number is checked in
+     *    ssl_tls13_offered_psks_check_identity_match_ticket().
+     */
 
-    ret = mbedtls_ssl_add_hs_hdr_to_checksum(ssl,
-                                             MBEDTLS_SSL_HS_CLIENT_HELLO,
-                                             p - buf);
-    if (0 != ret) {
-        MBEDTLS_SSL_DEBUG_RET(1, ("mbedtls_ssl_add_hs_hdr_to_checksum"), ret);
-        return ret;
+    if (handshake->selected_identity != 0) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("EarlyData: rejected, the selected key in "
+                "`pre_shared_key` is not the first one."));
+        return -1;
     }
 
-#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
-    /* Update checksum with either
-     * - The entire content of the CH message, if no PSK extension is present
-     * - The content up to but excluding the PSK extension, if present.
-     */
-    /* If we've settled on a PSK-based exchange, parse PSK identity ext */
-    if (mbedtls_ssl_tls13_some_psk_enabled(ssl) &&
-        mbedtls_ssl_conf_tls13_some_psk_enabled(ssl) &&
-        (handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY))) {
-        ret = handshake->update_checksum(ssl, buf,
-                                         pre_shared_key_ext - buf);
-        if (0 != ret) {
-            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
-            return ret;
-        }
-        ret = ssl_tls13_parse_pre_shared_key_ext(ssl,
-                                                 pre_shared_key_ext,
-                                                 pre_shared_key_ext_end,
-                                                 cipher_suites,
-                                                 cipher_suites_end);
-        if (ret == MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) {
-            handshake->received_extensions &= ~MBEDTLS_SSL_EXT_MASK(PRE_SHARED_KEY);
-        } else if (ret != 0) {
-            MBEDTLS_SSL_DEBUG_RET(
-                1, "ssl_tls13_parse_pre_shared_key_ext", ret);
-            return ret;
-        }
-    } else
-#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED */
-    {
-        ret = handshake->update_checksum(ssl, buf, p - buf);
-        if (0 != ret) {
-            MBEDTLS_SSL_DEBUG_RET(1, ("update_checksum"), ret);
-            return ret;
-        }
+    if (handshake->ciphersuite_info->id !=
+        ssl->session_negotiate->ciphersuite) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("EarlyData: rejected, the selected ciphersuite is not the one "
+                "of the selected pre-shared key."));
+        return -1;
+
     }
 
-    ret = ssl_tls13_determine_key_exchange_mode(ssl);
-    if (ret < 0) {
-        return ret;
+    if (!mbedtls_ssl_tls13_session_ticket_allow_early_data(ssl->session_negotiate)) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1,
+            ("EarlyData: rejected, early_data not allowed in ticket "
+             "permission bits."));
+        return -1;
     }
 
-    mbedtls_ssl_optimize_checksum(ssl, handshake->ciphersuite_info);
+#if defined(MBEDTLS_SSL_ALPN)
+    const char *alpn = mbedtls_ssl_get_alpn_protocol(ssl);
+    size_t alpn_len;
 
-    return hrr_required ? SSL_CLIENT_HELLO_HRR_REQUIRED : SSL_CLIENT_HELLO_OK;
+    if (alpn == NULL && ssl->session_negotiate->ticket_alpn == NULL) {
+        return 0;
+    }
+
+    if (alpn != NULL) {
+        alpn_len = strlen(alpn);
+    }
+
+    if (alpn == NULL ||
+        ssl->session_negotiate->ticket_alpn == NULL ||
+        alpn_len != strlen(ssl->session_negotiate->ticket_alpn) ||
+        (memcmp(alpn, ssl->session_negotiate->ticket_alpn, alpn_len) != 0)) {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("EarlyData: rejected, the selected ALPN is different "
+                                  "from the one associated with the pre-shared key."));
+        return -1;
+    }
+#endif
+
+    return 0;
 }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 
 /* Update the handshake state machine */
 
 MBEDTLS_CHECK_RETURN_CRITICAL
-static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl)
+static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl,
+                                              int hrr_required)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
 
@@ -1716,8 +1913,30 @@ static int ssl_tls13_postprocess_client_hello(mbedtls_ssl_context *ssl)
         return ret;
     }
 
-    return 0;
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(EARLY_DATA)) {
+        ssl->handshake->early_data_accepted =
+            (!hrr_required) && (ssl_tls13_check_early_data_requirements(ssl) == 0);
+
+        if (ssl->handshake->early_data_accepted) {
+            ret = mbedtls_ssl_tls13_compute_early_transform(ssl);
+            if (ret != 0) {
+                MBEDTLS_SSL_DEBUG_RET(
+                    1, "mbedtls_ssl_tls13_compute_early_transform", ret);
+                return ret;
+            }
+        } else {
+            ssl->discard_early_data_record =
+                hrr_required ?
+                MBEDTLS_SSL_EARLY_DATA_DISCARD :
+                MBEDTLS_SSL_EARLY_DATA_TRY_TO_DEPROTECT_AND_DISCARD;
+        }
+    }
+#else
+    ((void) hrr_required);
+#endif /* MBEDTLS_SSL_EARLY_DATA */
 
+    return 0;
 }
 
 /*
@@ -1741,15 +1960,39 @@ static int ssl_tls13_process_client_hello(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_parse_client_hello(ssl, buf,
                                                           buf + buflen));
-    parse_client_hello_ret = ret; /* Store return value of parse_client_hello,
-                                   * only SSL_CLIENT_HELLO_OK or
-                                   * SSL_CLIENT_HELLO_HRR_REQUIRED at this
-                                   * stage as negative error codes are handled
+    parse_client_hello_ret = ret; /* Store positive return value of
+                                   * parse_client_hello,
+                                   * as negative error codes are handled
                                    * by MBEDTLS_SSL_PROC_CHK_NEG. */
 
-    MBEDTLS_SSL_PROC_CHK(ssl_tls13_postprocess_client_hello(ssl));
+    /*
+     * Version 1.2 of the protocol has to be used for the handshake.
+     * If TLS 1.2 is not supported, abort the handshake. Otherwise, set the
+     * ssl->keep_current_message flag for the ClientHello to be kept and parsed
+     * as a TLS 1.2 ClientHello. We also change ssl->tls_version to
+     * MBEDTLS_SSL_VERSION_TLS1_2 thus from now on mbedtls_ssl_handshake_step()
+     * will dispatch to the TLS 1.2 state machine.
+     */
+    if (SSL_CLIENT_HELLO_TLS1_2 == parse_client_hello_ret) {
+        /* Check if server supports TLS 1.2 */
+        if (!mbedtls_ssl_conf_is_tls12_enabled(ssl->conf)) {
+            MBEDTLS_SSL_DEBUG_MSG(
+                1, ("TLS 1.2 not supported."));
+            MBEDTLS_SSL_PEND_FATAL_ALERT(
+                MBEDTLS_SSL_ALERT_MSG_PROTOCOL_VERSION,
+                MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION);
+            return MBEDTLS_ERR_SSL_BAD_PROTOCOL_VERSION;
+        }
+        ssl->keep_current_message = 1;
+        ssl->tls_version = MBEDTLS_SSL_VERSION_TLS1_2;
+        return 0;
+    }
+
+    MBEDTLS_SSL_PROC_CHK(
+        ssl_tls13_postprocess_client_hello(ssl, parse_client_hello_ret ==
+                                           SSL_CLIENT_HELLO_HRR_REQUIRED));
 
-    if (parse_client_hello_ret == SSL_CLIENT_HELLO_OK) {
+    if (SSL_CLIENT_HELLO_OK == parse_client_hello_ret) {
         mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_SERVER_HELLO);
     } else {
         mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HELLO_RETRY_REQUEST);
@@ -1770,10 +2013,6 @@ static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl)
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     unsigned char *server_randbytes =
         ssl->handshake->randbytes + MBEDTLS_CLIENT_HELLO_RANDOM_LEN;
-    if (ssl->conf->f_rng == NULL) {
-        MBEDTLS_SSL_DEBUG_MSG(1, ("no RNG provided"));
-        return MBEDTLS_ERR_SSL_NO_RNG;
-    }
 
     if ((ret = ssl->conf->f_rng(ssl->conf->p_rng, server_randbytes,
                                 MBEDTLS_SERVER_HELLO_RANDOM_LEN)) != 0) {
@@ -1785,7 +2024,7 @@ static int ssl_tls13_prepare_server_hello(mbedtls_ssl_context *ssl)
                           MBEDTLS_SERVER_HELLO_RANDOM_LEN);
 
 #if defined(MBEDTLS_HAVE_TIME)
-    ssl->session_negotiate->start = time(NULL);
+    ssl->session_negotiate->start = mbedtls_time(NULL);
 #endif /* MBEDTLS_HAVE_TIME */
 
     return ret;
@@ -1850,18 +2089,19 @@ static int ssl_tls13_generate_and_write_key_share(mbedtls_ssl_context *ssl,
 
     *out_len = 0;
 
-#if defined(MBEDTLS_ECDH_C)
-    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group)) {
-        ret = mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange(
+#if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED)
+    if (mbedtls_ssl_tls13_named_group_is_ecdhe(named_group) ||
+        mbedtls_ssl_tls13_named_group_is_ffdh(named_group)) {
+        ret = mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange(
             ssl, named_group, buf, end, out_len);
         if (ret != 0) {
             MBEDTLS_SSL_DEBUG_RET(
-                1, "mbedtls_ssl_tls13_generate_and_write_ecdh_key_exchange",
+                1, "mbedtls_ssl_tls13_generate_and_write_xxdh_key_exchange",
                 ret);
             return ret;
         }
     } else
-#endif /* MBEDTLS_ECDH_C */
+#endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_EPHEMERAL_ENABLED */
     if (0 /* Other kinds of KEMs */) {
     } else {
         ((void) ssl);
@@ -2182,9 +2422,8 @@ static int ssl_tls13_write_server_hello(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_server_hello(ssl));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                         MBEDTLS_SSL_HS_SERVER_HELLO, &buf,
-                                                         &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_SERVER_HELLO, &buf, &buf_len));
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_server_hello_body(ssl, buf,
                                                            buf + buf_len,
@@ -2224,7 +2463,7 @@ MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_hello_retry_request(mbedtls_ssl_context *ssl)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    if (ssl->handshake->hello_retry_request_count > 0) {
+    if (ssl->handshake->hello_retry_request_flag) {
         MBEDTLS_SSL_DEBUG_MSG(1, ("Too many HRRs"));
         MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE,
                                      MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE);
@@ -2271,7 +2510,7 @@ static int ssl_tls13_write_hello_retry_request(mbedtls_ssl_context *ssl)
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(ssl, buf_len,
                                                           msg_len));
 
-    ssl->handshake->hello_retry_request_count++;
+    ssl->handshake->hello_retry_request_flag = 1;
 
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
     /* The server sends a dummy change_cipher_spec record immediately
@@ -2329,6 +2568,28 @@ static int ssl_tls13_write_encrypted_extensions_body(mbedtls_ssl_context *ssl,
     p += output_len;
 #endif /* MBEDTLS_SSL_ALPN */
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->handshake->early_data_accepted) {
+        ret = mbedtls_ssl_tls13_write_early_data_ext(
+            ssl, 0, p, end, &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+#if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
+    if (ssl->handshake->received_extensions & MBEDTLS_SSL_EXT_MASK(RECORD_SIZE_LIMIT)) {
+        ret = mbedtls_ssl_tls13_write_record_size_limit_ext(
+            ssl, p, end, &output_len);
+        if (ret != 0) {
+            return ret;
+        }
+        p += output_len;
+    }
+#endif
+
     extensions_len = (p - p_extensions_len) - 2;
     MBEDTLS_PUT_UINT16_BE(extensions_len, p_extensions_len, 0);
 
@@ -2356,15 +2617,16 @@ static int ssl_tls13_write_encrypted_extensions(mbedtls_ssl_context *ssl)
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write encrypted extensions"));
 
-    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                         MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, &buf,
-                                                         &buf_len));
+    MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                             &buf, &buf_len));
 
     MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_encrypted_extensions_body(
                              ssl, buf, buf + buf_len, &msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
-                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS, buf, msg_len));
+                             ssl, MBEDTLS_SSL_HS_ENCRYPTED_EXTENSIONS,
+                             buf, msg_len));
 
     MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                              ssl, buf_len, msg_len));
@@ -2489,15 +2751,16 @@ static int ssl_tls13_write_certificate_request(mbedtls_ssl_context *ssl)
         unsigned char *buf;
         size_t buf_len, msg_len;
 
-        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                             MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
-                                                             &buf, &buf_len));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                 &buf, &buf_len));
 
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_certificate_request_body(
                                  ssl, buf, buf + buf_len, &msg_len));
 
         MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
-                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST, buf, msg_len));
+                                 ssl, MBEDTLS_SSL_HS_CERTIFICATE_REQUEST,
+                                 buf, msg_len));
 
         MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_finish_handshake_msg(
                                  ssl, buf_len, msg_len));
@@ -2558,6 +2821,59 @@ static int ssl_tls13_write_certificate_verify(mbedtls_ssl_context *ssl)
 }
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
 
+/*
+ * RFC 8446 section A.2
+ *
+ *                                | Send ServerHello
+ *                                | K_send = handshake
+ *                                | Send EncryptedExtensions
+ *                                | [Send CertificateRequest]
+ * Can send                       | [Send Certificate + CertificateVerify]
+ * app data                       | Send Finished
+ * after   -->                    | K_send = application
+ * here                  +--------+--------+
+ *              No 0-RTT |                 | 0-RTT
+ *                       |                 |
+ *   K_recv = handshake  |                 | K_recv = early data
+ * [Skip decrypt errors] |    +------> WAIT_EOED -+
+ *                       |    |       Recv |      | Recv EndOfEarlyData
+ *                       |    | early data |      | K_recv = handshake
+ *                       |    +------------+      |
+ *                       |                        |
+ *                       +> WAIT_FLIGHT2 <--------+
+ *                                |
+ *                       +--------+--------+
+ *               No auth |                 | Client auth
+ *                       |                 |
+ *                       |                 v
+ *                       |             WAIT_CERT
+ *                       |        Recv |       | Recv Certificate
+ *                       |       empty |       v
+ *                       | Certificate |    WAIT_CV
+ *                       |             |       | Recv
+ *                       |             v       | CertificateVerify
+ *                       +-> WAIT_FINISHED <---+
+ *                                | Recv Finished
+ *
+ *
+ * The following function handles the state changes after WAIT_FLIGHT2 in the
+ * above diagram. We are not going to receive early data related messages
+ * anymore, prepare to receive the first handshake message of the client
+ * second flight.
+ */
+static void ssl_tls13_prepare_for_handshake_second_flight(
+    mbedtls_ssl_context *ssl)
+{
+    if (ssl->handshake->certificate_request_sent) {
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate"));
+        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify"));
+
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+    }
+}
+
 /*
  * Handler for MBEDTLS_SSL_SERVER_FINISHED
  */
@@ -2579,20 +2895,178 @@ static int ssl_tls13_write_server_finished(mbedtls_ssl_context *ssl)
         return ret;
     }
 
-    MBEDTLS_SSL_DEBUG_MSG(1, ("Switch to handshake keys for inbound traffic"));
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->handshake->early_data_accepted) {
+        /* See RFC 8446 section A.2 for more information */
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Switch to early keys for inbound traffic. "
+                "( K_recv = early data )"));
+        mbedtls_ssl_set_inbound_transform(
+            ssl, ssl->handshake->transform_earlydata);
+        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_END_OF_EARLY_DATA);
+        return 0;
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+    MBEDTLS_SSL_DEBUG_MSG(
+        1, ("Switch to handshake keys for inbound traffic "
+            "( K_recv = handshake )"));
     mbedtls_ssl_set_inbound_transform(ssl, ssl->handshake->transform_handshake);
 
-    if (ssl->handshake->certificate_request_sent) {
-        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_CERTIFICATE);
-    } else {
-        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate"));
-        MBEDTLS_SSL_DEBUG_MSG(2, ("skip parse certificate verify"));
-        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_CLIENT_FINISHED);
+    ssl_tls13_prepare_for_handshake_second_flight(ssl);
+
+    return 0;
+}
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+/*
+ * Handler for MBEDTLS_SSL_END_OF_EARLY_DATA
+ */
+#define SSL_GOT_END_OF_EARLY_DATA      0
+#define SSL_GOT_EARLY_DATA             1
+/* Coordination:
+ * Deals with the ambiguity of not knowing if the next message is an
+ * EndOfEarlyData message or an application message containing early data.
+ * Returns a negative code on failure, or
+ * - SSL_GOT_END_OF_EARLY_DATA
+ * - SSL_GOT_EARLY_DATA
+ * indicating which message is received.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_end_of_early_data_coordinate(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    if ((ret = mbedtls_ssl_read_record(ssl, 0)) != 0) {
+        MBEDTLS_SSL_DEBUG_RET(1, "mbedtls_ssl_read_record", ret);
+        return ret;
+    }
+    ssl->keep_current_message = 1;
+
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE        &&
+        ssl->in_msg[0]  == MBEDTLS_SSL_HS_END_OF_EARLY_DATA) {
+        MBEDTLS_SSL_DEBUG_MSG(3, ("Received an end_of_early_data message."));
+        return SSL_GOT_END_OF_EARLY_DATA;
+    }
+
+    if (ssl->in_msgtype == MBEDTLS_SSL_MSG_APPLICATION_DATA) {
+        if (ssl->in_offt == NULL) {
+            MBEDTLS_SSL_DEBUG_MSG(3, ("Received early data"));
+            /* Set the reading pointer */
+            ssl->in_offt = ssl->in_msg;
+            ret = mbedtls_ssl_tls13_check_early_data_len(ssl, ssl->in_msglen);
+            if (ret != 0) {
+                return ret;
+            }
+        }
+        return SSL_GOT_EARLY_DATA;
     }
 
+    MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_UNEXPECTED_MESSAGE,
+                                 MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE);
+    return MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE;
+}
+
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_parse_end_of_early_data(mbedtls_ssl_context *ssl,
+                                             const unsigned char *buf,
+                                             const unsigned char *end)
+{
+    /* RFC 8446 section 4.5
+     *
+     * struct {} EndOfEarlyData;
+     */
+    if (buf != end) {
+        MBEDTLS_SSL_PEND_FATAL_ALERT(MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR,
+                                     MBEDTLS_ERR_SSL_DECODE_ERROR);
+        return MBEDTLS_ERR_SSL_DECODE_ERROR;
+    }
     return 0;
 }
 
+/*
+ * RFC 8446 section A.2
+ *
+ *                                | Send ServerHello
+ *                                | K_send = handshake
+ *                                | Send EncryptedExtensions
+ *                                | [Send CertificateRequest]
+ * Can send                       | [Send Certificate + CertificateVerify]
+ * app data                       | Send Finished
+ * after   -->                    | K_send = application
+ * here                  +--------+--------+
+ *              No 0-RTT |                 | 0-RTT
+ *                       |                 |
+ *   K_recv = handshake  |                 | K_recv = early data
+ * [Skip decrypt errors] |    +------> WAIT_EOED -+
+ *                       |    |       Recv |      | Recv EndOfEarlyData
+ *                       |    | early data |      | K_recv = handshake
+ *                       |    +------------+      |
+ *                       |                        |
+ *                       +> WAIT_FLIGHT2 <--------+
+ *                                |
+ *                       +--------+--------+
+ *               No auth |                 | Client auth
+ *                       |                 |
+ *                       |                 v
+ *                       |             WAIT_CERT
+ *                       |        Recv |       | Recv Certificate
+ *                       |       empty |       v
+ *                       | Certificate |    WAIT_CV
+ *                       |             |       | Recv
+ *                       |             v       | CertificateVerify
+ *                       +-> WAIT_FINISHED <---+
+ *                                | Recv Finished
+ *
+ * The function handles actions and state changes from 0-RTT to WAIT_FLIGHT2 in
+ * the above diagram.
+ */
+MBEDTLS_CHECK_RETURN_CRITICAL
+static int ssl_tls13_process_end_of_early_data(mbedtls_ssl_context *ssl)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+
+    MBEDTLS_SSL_DEBUG_MSG(2, ("=> ssl_tls13_process_end_of_early_data"));
+
+    MBEDTLS_SSL_PROC_CHK_NEG(ssl_tls13_end_of_early_data_coordinate(ssl));
+
+    if (ret == SSL_GOT_END_OF_EARLY_DATA) {
+        unsigned char *buf;
+        size_t buf_len;
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_tls13_fetch_handshake_msg(
+                                 ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,
+                                 &buf, &buf_len));
+
+        MBEDTLS_SSL_PROC_CHK(ssl_tls13_parse_end_of_early_data(
+                                 ssl, buf, buf + buf_len));
+
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Switch to handshake keys for inbound traffic"
+                "( K_recv = handshake )"));
+        mbedtls_ssl_set_inbound_transform(
+            ssl, ssl->handshake->transform_handshake);
+
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_add_hs_msg_to_checksum(
+                                 ssl, MBEDTLS_SSL_HS_END_OF_EARLY_DATA,
+                                 buf, buf_len));
+
+        ssl_tls13_prepare_for_handshake_second_flight(ssl);
+
+    } else if (ret == SSL_GOT_EARLY_DATA) {
+        ret = MBEDTLS_ERR_SSL_RECEIVED_EARLY_DATA;
+        goto cleanup;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(1, ("should never happen"));
+        ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
+        goto cleanup;
+    }
+
+cleanup:
+    MBEDTLS_SSL_DEBUG_MSG(2, ("<= ssl_tls13_process_end_of_early_data"));
+    return ret;
+}
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
 /*
  * Handler for MBEDTLS_SSL_CLIENT_FINISHED
  */
@@ -2608,8 +3082,8 @@ static int ssl_tls13_process_client_finished(mbedtls_ssl_context *ssl)
 
     ret = mbedtls_ssl_tls13_compute_resumption_master_secret(ssl);
     if (ret != 0) {
-        MBEDTLS_SSL_DEBUG_RET(1,
-                              "mbedtls_ssl_tls13_compute_resumption_master_secret", ret);
+        MBEDTLS_SSL_DEBUG_RET(
+            1, "mbedtls_ssl_tls13_compute_resumption_master_secret", ret);
     }
 
     mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_WRAPUP);
@@ -2633,8 +3107,9 @@ static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
  *       expected to be resolved with issue#6395.
  */
     /* Sent NewSessionTicket message only when client supports PSK */
-    if (mbedtls_ssl_tls13_some_psk_enabled(ssl)) {
-        mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+    if (mbedtls_ssl_tls13_is_some_psk_supported(ssl)) {
+        mbedtls_ssl_handshake_set_state(
+            ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
     } else
 #endif
     {
@@ -2643,6 +3118,7 @@ static int ssl_tls13_handshake_wrapup(mbedtls_ssl_context *ssl)
     return 0;
 }
 
+#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 /*
  * Handler for MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET
  */
@@ -2672,7 +3148,6 @@ static int ssl_tls13_write_new_session_ticket_coordinate(mbedtls_ssl_context *ss
     return SSL_NEW_SESSION_TICKET_WRITE;
 }
 
-#if defined(MBEDTLS_SSL_SESSION_TICKETS)
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
                                                 unsigned char *ticket_nonce,
@@ -2686,19 +3161,34 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> prepare NewSessionTicket msg"));
 
-#if defined(MBEDTLS_HAVE_TIME)
-    session->start = mbedtls_time(NULL);
-#endif
-
     /* Set ticket_flags depends on the advertised psk key exchange mode */
-    mbedtls_ssl_session_clear_ticket_flags(
+    mbedtls_ssl_tls13_session_clear_ticket_flags(
         session, MBEDTLS_SSL_TLS1_3_TICKET_FLAGS_MASK);
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_SOME_PSK_ENABLED)
-    mbedtls_ssl_session_set_ticket_flags(
+    mbedtls_ssl_tls13_session_set_ticket_flags(
         session, ssl->handshake->tls13_kex_modes);
 #endif
+
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (ssl->conf->early_data_enabled == MBEDTLS_SSL_EARLY_DATA_ENABLED &&
+        ssl->conf->max_early_data_size > 0) {
+        mbedtls_ssl_tls13_session_set_ticket_flags(
+            session, MBEDTLS_SSL_TLS1_3_TICKET_ALLOW_EARLY_DATA);
+        session->max_early_data_size = ssl->conf->max_early_data_size;
+    }
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
     MBEDTLS_SSL_PRINT_TICKET_FLAGS(4, session->ticket_flags);
 
+#if defined(MBEDTLS_SSL_EARLY_DATA) && defined(MBEDTLS_SSL_ALPN)
+    if (session->ticket_alpn == NULL) {
+        ret = mbedtls_ssl_session_set_ticket_alpn(session, ssl->alpn_chosen);
+        if (ret != 0) {
+            return ret;
+        }
+    }
+#endif
+
     /* Generate ticket_age_add */
     if ((ret = ssl->conf->f_rng(ssl->conf->p_rng,
                                 (unsigned char *) &session->ticket_age_add,
@@ -2720,7 +3210,7 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
 
     ciphersuite_info =
         (mbedtls_ssl_ciphersuite_t *) ssl->handshake->ciphersuite_info;
-    psa_hash_alg = mbedtls_psa_translate_md(ciphersuite_info->mac);
+    psa_hash_alg = mbedtls_md_psa_alg_from_type((mbedtls_md_type_t) ciphersuite_info->mac);
     hash_length = PSA_HASH_LENGTH(psa_hash_alg);
     if (hash_length == -1 ||
         (size_t) hash_length > sizeof(session->resumption_key)) {
@@ -2780,12 +3270,13 @@ static int ssl_tls13_prepare_new_session_ticket(mbedtls_ssl_context *ssl,
  * The following fields are placed inside the ticket by the
  * f_ticket_write() function:
  *
- *  - creation time (start)
- *  - flags (flags)
+ *  - creation time (ticket_creation_time)
+ *  - flags (ticket_flags)
  *  - age add (ticket_age_add)
- *  - key (key)
- *  - key length (key_len)
+ *  - key (resumption_key)
+ *  - key length (resumption_key_len)
  *  - ciphersuite (ciphersuite)
+ *  - max_early_data_size (max_early_data_size)
  */
 MBEDTLS_CHECK_RETURN_CRITICAL
 static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
@@ -2800,6 +3291,7 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
     mbedtls_ssl_session *session = ssl->session;
     size_t ticket_len;
     uint32_t ticket_lifetime;
+    unsigned char *p_extensions_len;
 
     *out_len = 0;
     MBEDTLS_SSL_DEBUG_MSG(2, ("=> write NewSessionTicket msg"));
@@ -2813,6 +3305,9 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
     MBEDTLS_SSL_CHK_BUF_PTR(p, end, 4 + 4 + 1 + ticket_nonce_size + 2);
 
     /* Generate ticket and ticket_lifetime */
+#if defined(MBEDTLS_HAVE_TIME)
+    session->ticket_creation_time = mbedtls_ms_time();
+#endif
     ret = ssl->conf->f_ticket_write(ssl->conf->p_ticket,
                                     session,
                                     p + 9 + ticket_nonce_size + 2,
@@ -2823,20 +3318,21 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
         MBEDTLS_SSL_DEBUG_RET(1, "write_ticket", ret);
         return ret;
     }
-    /* RFC 8446 4.6.1
+
+    /* RFC 8446 section 4.6.1
+     *
      *  ticket_lifetime:  Indicates the lifetime in seconds as a 32-bit
-     *      unsigned integer in network byte order from the time of ticket
-     *      issuance.  Servers MUST NOT use any value greater than
-     *      604800 seconds (7 days).  The value of zero indicates that the
-     *      ticket should be discarded immediately.  Clients MUST NOT cache
-     *      tickets for longer than 7 days, regardless of the ticket_lifetime,
-     *      and MAY delete tickets earlier based on local policy.  A server
-     *      MAY treat a ticket as valid for a shorter period of time than what
-     *      is stated in the ticket_lifetime.
+     *     unsigned integer in network byte order from the time of ticket
+     *     issuance.  Servers MUST NOT use any value greater than
+     *     604800 seconds (7 days) ...
      */
-    if (ticket_lifetime > 604800) {
-        ticket_lifetime = 604800;
+    if (ticket_lifetime > MBEDTLS_SSL_TLS1_3_MAX_ALLOWED_TICKET_LIFETIME) {
+        MBEDTLS_SSL_DEBUG_MSG(
+            1, ("Ticket lifetime (%u) is greater than 7 days.",
+                (unsigned int) ticket_lifetime));
+        return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
     }
+
     MBEDTLS_PUT_UINT32_BE(ticket_lifetime, p, 0);
     MBEDTLS_SSL_DEBUG_MSG(3, ("ticket_lifetime: %u",
                               (unsigned int) ticket_lifetime));
@@ -2861,15 +3357,35 @@ static int ssl_tls13_write_new_session_ticket_body(mbedtls_ssl_context *ssl,
 
     /* Ticket Extensions
      *
-     * Note: We currently don't have any extensions.
-     * Set length to zero.
+     * Extension extensions<0..2^16-2>;
      */
     ssl->handshake->sent_extensions = MBEDTLS_SSL_EXT_MASK_NONE;
 
     MBEDTLS_SSL_CHK_BUF_PTR(p, end, 2);
-    MBEDTLS_PUT_UINT16_BE(0, p, 0);
+    p_extensions_len = p;
     p += 2;
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+    if (mbedtls_ssl_tls13_session_ticket_allow_early_data(session)) {
+        size_t output_len;
+
+        if ((ret = mbedtls_ssl_tls13_write_early_data_ext(
+                 ssl, 1, p, end, &output_len)) != 0) {
+            MBEDTLS_SSL_DEBUG_RET(
+                1, "mbedtls_ssl_tls13_write_early_data_ext", ret);
+            return ret;
+        }
+        p += output_len;
+    } else {
+        MBEDTLS_SSL_DEBUG_MSG(
+            4, ("early_data not allowed, "
+                "skip early_data extension in NewSessionTicket"));
+    }
+
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
+    MBEDTLS_PUT_UINT16_BE(p - p_extensions_len - 2, p_extensions_len, 0);
+
     *out_len = p - buf;
     MBEDTLS_SSL_DEBUG_BUF(4, "ticket", buf, *out_len);
     MBEDTLS_SSL_DEBUG_MSG(2, ("<= write new session ticket"));
@@ -2897,9 +3413,9 @@ static int ssl_tls13_write_new_session_ticket(mbedtls_ssl_context *ssl)
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_prepare_new_session_ticket(
                                  ssl, ticket_nonce, sizeof(ticket_nonce)));
 
-        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(ssl,
-                                                             MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
-                                                             &buf, &buf_len));
+        MBEDTLS_SSL_PROC_CHK(mbedtls_ssl_start_handshake_msg(
+                                 ssl, MBEDTLS_SSL_HS_NEW_SESSION_TICKET,
+                                 &buf, &buf_len));
 
         MBEDTLS_SSL_PROC_CHK(ssl_tls13_write_new_session_ticket_body(
                                  ssl, buf, buf + buf_len, &msg_len,
@@ -2942,7 +3458,7 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
     }
 
     MBEDTLS_SSL_DEBUG_MSG(2, ("tls13 server state: %s(%d)",
-                              mbedtls_ssl_states_str(ssl->state),
+                              mbedtls_ssl_states_str((mbedtls_ssl_states) ssl->state),
                               ssl->state));
 
     switch (ssl->state) {
@@ -3006,9 +3522,10 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
 
         case MBEDTLS_SSL_SERVER_CCS_AFTER_SERVER_HELLO:
             ret = mbedtls_ssl_tls13_write_change_cipher_spec(ssl);
-            if (ret == 0) {
-                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
+            if (ret != 0) {
+                break;
             }
+            mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_ENCRYPTED_EXTENSIONS);
             break;
 #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
 
@@ -3016,6 +3533,12 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
             ret = ssl_tls13_write_server_finished(ssl);
             break;
 
+#if defined(MBEDTLS_SSL_EARLY_DATA)
+        case MBEDTLS_SSL_END_OF_EARLY_DATA:
+            ret = ssl_tls13_process_end_of_early_data(ssl);
+            break;
+#endif /* MBEDTLS_SSL_EARLY_DATA */
+
         case MBEDTLS_SSL_CLIENT_FINISHED:
             ret = ssl_tls13_process_client_finished(ssl);
             break;
@@ -3067,7 +3590,8 @@ int mbedtls_ssl_tls13_handshake_server_step(mbedtls_ssl_context *ssl)
             if (ssl->handshake->new_session_tickets_count == 0) {
                 mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_HANDSHAKE_OVER);
             } else {
-                mbedtls_ssl_handshake_set_state(ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
+                mbedtls_ssl_handshake_set_state(
+                    ssl, MBEDTLS_SSL_TLS1_3_NEW_SESSION_TICKET);
             }
             break;
 
diff --git a/lib/libmbedtls/mbedtls/library/threading.c b/lib/libmbedtls/mbedtls/library/threading.c
index 130c6963d4193f525983f05c77aee8232a2cf44b..85db243f213ff4122d9a34fe7c6af020ecd6cfe5 100644
--- a/lib/libmbedtls/mbedtls/library/threading.c
+++ b/lib/libmbedtls/mbedtls/library/threading.c
@@ -2,19 +2,7 @@
  *  Threading abstraction layer
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 /*
@@ -68,28 +56,27 @@ static void threading_mutex_init_pthread(mbedtls_threading_mutex_t *mutex)
         return;
     }
 
-    /* A nonzero value of is_valid indicates a successfully initialized
-     * mutex. This is a workaround for not being able to return an error
-     * code for this function. The lock/unlock functions return an error
-     * if is_valid is nonzero. The Mbed TLS unit test code uses this field
-     * to distinguish more states of the mutex; see
-     * tests/src/threading_helpers for details. */
-    mutex->is_valid = pthread_mutex_init(&mutex->mutex, NULL) == 0;
+    /* One problem here is that calling lock on a pthread mutex without first
+     * having initialised it is undefined behaviour. Obviously we cannot check
+     * this here in a thread safe manner without a significant performance
+     * hit, so state transitions are checked in tests only via the state
+     * variable. Please make sure any new mutex that gets added is exercised in
+     * tests; see tests/src/threading_helpers.c for more details. */
+    (void) pthread_mutex_init(&mutex->mutex, NULL);
 }
 
 static void threading_mutex_free_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if (mutex == NULL || !mutex->is_valid) {
+    if (mutex == NULL) {
         return;
     }
 
     (void) pthread_mutex_destroy(&mutex->mutex);
-    mutex->is_valid = 0;
 }
 
 static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if (mutex == NULL || !mutex->is_valid) {
+    if (mutex == NULL) {
         return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
     }
 
@@ -102,7 +89,7 @@ static int threading_mutex_lock_pthread(mbedtls_threading_mutex_t *mutex)
 
 static int threading_mutex_unlock_pthread(mbedtls_threading_mutex_t *mutex)
 {
-    if (mutex == NULL || !mutex->is_valid) {
+    if (mutex == NULL) {
         return MBEDTLS_ERR_THREADING_BAD_INPUT_DATA;
     }
 
@@ -161,6 +148,11 @@ void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),
 #if defined(THREADING_USE_GMTIME)
     mbedtls_mutex_init(&mbedtls_threading_gmtime_mutex);
 #endif
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_mutex_init(&mbedtls_threading_key_slot_mutex);
+    mbedtls_mutex_init(&mbedtls_threading_psa_globaldata_mutex);
+    mbedtls_mutex_init(&mbedtls_threading_psa_rngdata_mutex);
+#endif
 }
 
 /*
@@ -174,6 +166,11 @@ void mbedtls_threading_free_alt(void)
 #if defined(THREADING_USE_GMTIME)
     mbedtls_mutex_free(&mbedtls_threading_gmtime_mutex);
 #endif
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+    mbedtls_mutex_free(&mbedtls_threading_key_slot_mutex);
+    mbedtls_mutex_free(&mbedtls_threading_psa_globaldata_mutex);
+    mbedtls_mutex_free(&mbedtls_threading_psa_rngdata_mutex);
+#endif
 }
 #endif /* MBEDTLS_THREADING_ALT */
 
@@ -189,5 +186,10 @@ mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT;
 #if defined(THREADING_USE_GMTIME)
 mbedtls_threading_mutex_t mbedtls_threading_gmtime_mutex MUTEX_INIT;
 #endif
+#if defined(MBEDTLS_PSA_CRYPTO_C)
+mbedtls_threading_mutex_t mbedtls_threading_key_slot_mutex MUTEX_INIT;
+mbedtls_threading_mutex_t mbedtls_threading_psa_globaldata_mutex MUTEX_INIT;
+mbedtls_threading_mutex_t mbedtls_threading_psa_rngdata_mutex MUTEX_INIT;
+#endif
 
 #endif /* MBEDTLS_THREADING_C */
diff --git a/lib/libmbedtls/mbedtls/library/timing.c b/lib/libmbedtls/mbedtls/library/timing.c
index 6852033ea61174a05e712648e252784200fe1947..58f1c1ec2eba8765d25bc0dabb4d6ea4de7f5ad1 100644
--- a/lib/libmbedtls/mbedtls/library/timing.c
+++ b/lib/libmbedtls/mbedtls/library/timing.c
@@ -2,19 +2,7 @@
  *  Portable interface to the CPU cycle counter
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
diff --git a/lib/libmbedtls/mbedtls/library/version.c b/lib/libmbedtls/mbedtls/library/version.c
index 4f78c9cb123e22959ffdc7fd7b66403859a2d10e..04397332bbfe8a43a793de8210c86d8c1dd5d53a 100644
--- a/lib/libmbedtls/mbedtls/library/version.c
+++ b/lib/libmbedtls/mbedtls/library/version.c
@@ -2,19 +2,7 @@
  *  Version information
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
diff --git a/lib/libmbedtls/mbedtls/library/version_features.c b/lib/libmbedtls/mbedtls/library/version_features.c
index 0a6ff2200e817fde01e14a9dbc15a83f58b0b8e6..f542d9808f59fe54e18e8ce2671cdfeecf1eb474 100644
--- a/lib/libmbedtls/mbedtls/library/version_features.c
+++ b/lib/libmbedtls/mbedtls/library/version_features.c
@@ -2,19 +2,7 @@
  *  Version feature information
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
@@ -28,757 +16,799 @@
 static const char * const features[] = {
 #if defined(MBEDTLS_VERSION_FEATURES)
     #if defined(MBEDTLS_HAVE_ASM)
-    "MBEDTLS_HAVE_ASM",
+    "HAVE_ASM", //no-check-names
 #endif /* MBEDTLS_HAVE_ASM */
 #if defined(MBEDTLS_NO_UDBL_DIVISION)
-    "MBEDTLS_NO_UDBL_DIVISION",
+    "NO_UDBL_DIVISION", //no-check-names
 #endif /* MBEDTLS_NO_UDBL_DIVISION */
 #if defined(MBEDTLS_NO_64BIT_MULTIPLICATION)
-    "MBEDTLS_NO_64BIT_MULTIPLICATION",
+    "NO_64BIT_MULTIPLICATION", //no-check-names
 #endif /* MBEDTLS_NO_64BIT_MULTIPLICATION */
 #if defined(MBEDTLS_HAVE_SSE2)
-    "MBEDTLS_HAVE_SSE2",
+    "HAVE_SSE2", //no-check-names
 #endif /* MBEDTLS_HAVE_SSE2 */
 #if defined(MBEDTLS_HAVE_TIME)
-    "MBEDTLS_HAVE_TIME",
+    "HAVE_TIME", //no-check-names
 #endif /* MBEDTLS_HAVE_TIME */
 #if defined(MBEDTLS_HAVE_TIME_DATE)
-    "MBEDTLS_HAVE_TIME_DATE",
+    "HAVE_TIME_DATE", //no-check-names
 #endif /* MBEDTLS_HAVE_TIME_DATE */
 #if defined(MBEDTLS_PLATFORM_MEMORY)
-    "MBEDTLS_PLATFORM_MEMORY",
+    "PLATFORM_MEMORY", //no-check-names
 #endif /* MBEDTLS_PLATFORM_MEMORY */
 #if defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS)
-    "MBEDTLS_PLATFORM_NO_STD_FUNCTIONS",
+    "PLATFORM_NO_STD_FUNCTIONS", //no-check-names
 #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */
 #if defined(MBEDTLS_PLATFORM_SETBUF_ALT)
-    "MBEDTLS_PLATFORM_SETBUF_ALT",
+    "PLATFORM_SETBUF_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_SETBUF_ALT */
 #if defined(MBEDTLS_PLATFORM_EXIT_ALT)
-    "MBEDTLS_PLATFORM_EXIT_ALT",
+    "PLATFORM_EXIT_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_EXIT_ALT */
 #if defined(MBEDTLS_PLATFORM_TIME_ALT)
-    "MBEDTLS_PLATFORM_TIME_ALT",
+    "PLATFORM_TIME_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_TIME_ALT */
 #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT)
-    "MBEDTLS_PLATFORM_FPRINTF_ALT",
+    "PLATFORM_FPRINTF_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */
 #if defined(MBEDTLS_PLATFORM_PRINTF_ALT)
-    "MBEDTLS_PLATFORM_PRINTF_ALT",
+    "PLATFORM_PRINTF_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */
 #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT)
-    "MBEDTLS_PLATFORM_SNPRINTF_ALT",
+    "PLATFORM_SNPRINTF_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */
 #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT)
-    "MBEDTLS_PLATFORM_VSNPRINTF_ALT",
+    "PLATFORM_VSNPRINTF_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */
 #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
-    "MBEDTLS_PLATFORM_NV_SEED_ALT",
+    "PLATFORM_NV_SEED_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
 #if defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT)
-    "MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT",
+    "PLATFORM_SETUP_TEARDOWN_ALT", //no-check-names
 #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */
+#if defined(MBEDTLS_PLATFORM_MS_TIME_ALT)
+    "PLATFORM_MS_TIME_ALT", //no-check-names
+#endif /* MBEDTLS_PLATFORM_MS_TIME_ALT */
+#if defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
+    "PLATFORM_GMTIME_R_ALT", //no-check-names
+#endif /* MBEDTLS_PLATFORM_GMTIME_R_ALT */
+#if defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
+    "PLATFORM_ZEROIZE_ALT", //no-check-names
+#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
 #if defined(MBEDTLS_DEPRECATED_WARNING)
-    "MBEDTLS_DEPRECATED_WARNING",
+    "DEPRECATED_WARNING", //no-check-names
 #endif /* MBEDTLS_DEPRECATED_WARNING */
 #if defined(MBEDTLS_DEPRECATED_REMOVED)
-    "MBEDTLS_DEPRECATED_REMOVED",
+    "DEPRECATED_REMOVED", //no-check-names
 #endif /* MBEDTLS_DEPRECATED_REMOVED */
 #if defined(MBEDTLS_TIMING_ALT)
-    "MBEDTLS_TIMING_ALT",
+    "TIMING_ALT", //no-check-names
 #endif /* MBEDTLS_TIMING_ALT */
 #if defined(MBEDTLS_AES_ALT)
-    "MBEDTLS_AES_ALT",
+    "AES_ALT", //no-check-names
 #endif /* MBEDTLS_AES_ALT */
 #if defined(MBEDTLS_ARIA_ALT)
-    "MBEDTLS_ARIA_ALT",
+    "ARIA_ALT", //no-check-names
 #endif /* MBEDTLS_ARIA_ALT */
 #if defined(MBEDTLS_CAMELLIA_ALT)
-    "MBEDTLS_CAMELLIA_ALT",
+    "CAMELLIA_ALT", //no-check-names
 #endif /* MBEDTLS_CAMELLIA_ALT */
 #if defined(MBEDTLS_CCM_ALT)
-    "MBEDTLS_CCM_ALT",
+    "CCM_ALT", //no-check-names
 #endif /* MBEDTLS_CCM_ALT */
 #if defined(MBEDTLS_CHACHA20_ALT)
-    "MBEDTLS_CHACHA20_ALT",
+    "CHACHA20_ALT", //no-check-names
 #endif /* MBEDTLS_CHACHA20_ALT */
 #if defined(MBEDTLS_CHACHAPOLY_ALT)
-    "MBEDTLS_CHACHAPOLY_ALT",
+    "CHACHAPOLY_ALT", //no-check-names
 #endif /* MBEDTLS_CHACHAPOLY_ALT */
 #if defined(MBEDTLS_CMAC_ALT)
-    "MBEDTLS_CMAC_ALT",
+    "CMAC_ALT", //no-check-names
 #endif /* MBEDTLS_CMAC_ALT */
 #if defined(MBEDTLS_DES_ALT)
-    "MBEDTLS_DES_ALT",
+    "DES_ALT", //no-check-names
 #endif /* MBEDTLS_DES_ALT */
 #if defined(MBEDTLS_DHM_ALT)
-    "MBEDTLS_DHM_ALT",
+    "DHM_ALT", //no-check-names
 #endif /* MBEDTLS_DHM_ALT */
 #if defined(MBEDTLS_ECJPAKE_ALT)
-    "MBEDTLS_ECJPAKE_ALT",
+    "ECJPAKE_ALT", //no-check-names
 #endif /* MBEDTLS_ECJPAKE_ALT */
 #if defined(MBEDTLS_GCM_ALT)
-    "MBEDTLS_GCM_ALT",
+    "GCM_ALT", //no-check-names
 #endif /* MBEDTLS_GCM_ALT */
 #if defined(MBEDTLS_NIST_KW_ALT)
-    "MBEDTLS_NIST_KW_ALT",
+    "NIST_KW_ALT", //no-check-names
 #endif /* MBEDTLS_NIST_KW_ALT */
 #if defined(MBEDTLS_MD5_ALT)
-    "MBEDTLS_MD5_ALT",
+    "MD5_ALT", //no-check-names
 #endif /* MBEDTLS_MD5_ALT */
 #if defined(MBEDTLS_POLY1305_ALT)
-    "MBEDTLS_POLY1305_ALT",
+    "POLY1305_ALT", //no-check-names
 #endif /* MBEDTLS_POLY1305_ALT */
 #if defined(MBEDTLS_RIPEMD160_ALT)
-    "MBEDTLS_RIPEMD160_ALT",
+    "RIPEMD160_ALT", //no-check-names
 #endif /* MBEDTLS_RIPEMD160_ALT */
 #if defined(MBEDTLS_RSA_ALT)
-    "MBEDTLS_RSA_ALT",
+    "RSA_ALT", //no-check-names
 #endif /* MBEDTLS_RSA_ALT */
 #if defined(MBEDTLS_SHA1_ALT)
-    "MBEDTLS_SHA1_ALT",
+    "SHA1_ALT", //no-check-names
 #endif /* MBEDTLS_SHA1_ALT */
 #if defined(MBEDTLS_SHA256_ALT)
-    "MBEDTLS_SHA256_ALT",
+    "SHA256_ALT", //no-check-names
 #endif /* MBEDTLS_SHA256_ALT */
 #if defined(MBEDTLS_SHA512_ALT)
-    "MBEDTLS_SHA512_ALT",
+    "SHA512_ALT", //no-check-names
 #endif /* MBEDTLS_SHA512_ALT */
 #if defined(MBEDTLS_ECP_ALT)
-    "MBEDTLS_ECP_ALT",
+    "ECP_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_ALT */
 #if defined(MBEDTLS_MD5_PROCESS_ALT)
-    "MBEDTLS_MD5_PROCESS_ALT",
+    "MD5_PROCESS_ALT", //no-check-names
 #endif /* MBEDTLS_MD5_PROCESS_ALT */
 #if defined(MBEDTLS_RIPEMD160_PROCESS_ALT)
-    "MBEDTLS_RIPEMD160_PROCESS_ALT",
+    "RIPEMD160_PROCESS_ALT", //no-check-names
 #endif /* MBEDTLS_RIPEMD160_PROCESS_ALT */
 #if defined(MBEDTLS_SHA1_PROCESS_ALT)
-    "MBEDTLS_SHA1_PROCESS_ALT",
+    "SHA1_PROCESS_ALT", //no-check-names
 #endif /* MBEDTLS_SHA1_PROCESS_ALT */
 #if defined(MBEDTLS_SHA256_PROCESS_ALT)
-    "MBEDTLS_SHA256_PROCESS_ALT",
+    "SHA256_PROCESS_ALT", //no-check-names
 #endif /* MBEDTLS_SHA256_PROCESS_ALT */
 #if defined(MBEDTLS_SHA512_PROCESS_ALT)
-    "MBEDTLS_SHA512_PROCESS_ALT",
+    "SHA512_PROCESS_ALT", //no-check-names
 #endif /* MBEDTLS_SHA512_PROCESS_ALT */
 #if defined(MBEDTLS_DES_SETKEY_ALT)
-    "MBEDTLS_DES_SETKEY_ALT",
+    "DES_SETKEY_ALT", //no-check-names
 #endif /* MBEDTLS_DES_SETKEY_ALT */
 #if defined(MBEDTLS_DES_CRYPT_ECB_ALT)
-    "MBEDTLS_DES_CRYPT_ECB_ALT",
+    "DES_CRYPT_ECB_ALT", //no-check-names
 #endif /* MBEDTLS_DES_CRYPT_ECB_ALT */
 #if defined(MBEDTLS_DES3_CRYPT_ECB_ALT)
-    "MBEDTLS_DES3_CRYPT_ECB_ALT",
+    "DES3_CRYPT_ECB_ALT", //no-check-names
 #endif /* MBEDTLS_DES3_CRYPT_ECB_ALT */
 #if defined(MBEDTLS_AES_SETKEY_ENC_ALT)
-    "MBEDTLS_AES_SETKEY_ENC_ALT",
+    "AES_SETKEY_ENC_ALT", //no-check-names
 #endif /* MBEDTLS_AES_SETKEY_ENC_ALT */
 #if defined(MBEDTLS_AES_SETKEY_DEC_ALT)
-    "MBEDTLS_AES_SETKEY_DEC_ALT",
+    "AES_SETKEY_DEC_ALT", //no-check-names
 #endif /* MBEDTLS_AES_SETKEY_DEC_ALT */
 #if defined(MBEDTLS_AES_ENCRYPT_ALT)
-    "MBEDTLS_AES_ENCRYPT_ALT",
+    "AES_ENCRYPT_ALT", //no-check-names
 #endif /* MBEDTLS_AES_ENCRYPT_ALT */
 #if defined(MBEDTLS_AES_DECRYPT_ALT)
-    "MBEDTLS_AES_DECRYPT_ALT",
+    "AES_DECRYPT_ALT", //no-check-names
 #endif /* MBEDTLS_AES_DECRYPT_ALT */
 #if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
-    "MBEDTLS_ECDH_GEN_PUBLIC_ALT",
+    "ECDH_GEN_PUBLIC_ALT", //no-check-names
 #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
 #if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
-    "MBEDTLS_ECDH_COMPUTE_SHARED_ALT",
+    "ECDH_COMPUTE_SHARED_ALT", //no-check-names
 #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
-    "MBEDTLS_ECDSA_VERIFY_ALT",
+    "ECDSA_VERIFY_ALT", //no-check-names
 #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
-    "MBEDTLS_ECDSA_SIGN_ALT",
+    "ECDSA_SIGN_ALT", //no-check-names
 #endif /* MBEDTLS_ECDSA_SIGN_ALT */
 #if defined(MBEDTLS_ECDSA_GENKEY_ALT)
-    "MBEDTLS_ECDSA_GENKEY_ALT",
+    "ECDSA_GENKEY_ALT", //no-check-names
 #endif /* MBEDTLS_ECDSA_GENKEY_ALT */
 #if defined(MBEDTLS_ECP_INTERNAL_ALT)
-    "MBEDTLS_ECP_INTERNAL_ALT",
+    "ECP_INTERNAL_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
 #if defined(MBEDTLS_ECP_NO_FALLBACK)
-    "MBEDTLS_ECP_NO_FALLBACK",
+    "ECP_NO_FALLBACK", //no-check-names
 #endif /* MBEDTLS_ECP_NO_FALLBACK */
 #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT)
-    "MBEDTLS_ECP_RANDOMIZE_JAC_ALT",
+    "ECP_RANDOMIZE_JAC_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */
 #if defined(MBEDTLS_ECP_ADD_MIXED_ALT)
-    "MBEDTLS_ECP_ADD_MIXED_ALT",
+    "ECP_ADD_MIXED_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */
 #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT)
-    "MBEDTLS_ECP_DOUBLE_JAC_ALT",
+    "ECP_DOUBLE_JAC_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT)
-    "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT",
+    "ECP_NORMALIZE_JAC_MANY_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT */
 #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT)
-    "MBEDTLS_ECP_NORMALIZE_JAC_ALT",
+    "ECP_NORMALIZE_JAC_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */
 #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT)
-    "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT",
+    "ECP_DOUBLE_ADD_MXZ_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */
 #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT)
-    "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT",
+    "ECP_RANDOMIZE_MXZ_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */
 #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT)
-    "MBEDTLS_ECP_NORMALIZE_MXZ_ALT",
+    "ECP_NORMALIZE_MXZ_ALT", //no-check-names
 #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */
 #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
-    "MBEDTLS_ENTROPY_HARDWARE_ALT",
+    "ENTROPY_HARDWARE_ALT", //no-check-names
 #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
 #if defined(MBEDTLS_AES_ROM_TABLES)
-    "MBEDTLS_AES_ROM_TABLES",
+    "AES_ROM_TABLES", //no-check-names
 #endif /* MBEDTLS_AES_ROM_TABLES */
 #if defined(MBEDTLS_AES_FEWER_TABLES)
-    "MBEDTLS_AES_FEWER_TABLES",
+    "AES_FEWER_TABLES", //no-check-names
 #endif /* MBEDTLS_AES_FEWER_TABLES */
+#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
+    "AES_ONLY_128_BIT_KEY_LENGTH", //no-check-names
+#endif /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+    "AES_USE_HARDWARE_ONLY", //no-check-names
+#endif /* MBEDTLS_AES_USE_HARDWARE_ONLY */
 #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY)
-    "MBEDTLS_CAMELLIA_SMALL_MEMORY",
+    "CAMELLIA_SMALL_MEMORY", //no-check-names
 #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */
 #if defined(MBEDTLS_CHECK_RETURN_WARNING)
-    "MBEDTLS_CHECK_RETURN_WARNING",
+    "CHECK_RETURN_WARNING", //no-check-names
 #endif /* MBEDTLS_CHECK_RETURN_WARNING */
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
-    "MBEDTLS_CIPHER_MODE_CBC",
+    "CIPHER_MODE_CBC", //no-check-names
 #endif /* MBEDTLS_CIPHER_MODE_CBC */
 #if defined(MBEDTLS_CIPHER_MODE_CFB)
-    "MBEDTLS_CIPHER_MODE_CFB",
+    "CIPHER_MODE_CFB", //no-check-names
 #endif /* MBEDTLS_CIPHER_MODE_CFB */
 #if defined(MBEDTLS_CIPHER_MODE_CTR)
-    "MBEDTLS_CIPHER_MODE_CTR",
+    "CIPHER_MODE_CTR", //no-check-names
 #endif /* MBEDTLS_CIPHER_MODE_CTR */
 #if defined(MBEDTLS_CIPHER_MODE_OFB)
-    "MBEDTLS_CIPHER_MODE_OFB",
+    "CIPHER_MODE_OFB", //no-check-names
 #endif /* MBEDTLS_CIPHER_MODE_OFB */
 #if defined(MBEDTLS_CIPHER_MODE_XTS)
-    "MBEDTLS_CIPHER_MODE_XTS",
+    "CIPHER_MODE_XTS", //no-check-names
 #endif /* MBEDTLS_CIPHER_MODE_XTS */
 #if defined(MBEDTLS_CIPHER_NULL_CIPHER)
-    "MBEDTLS_CIPHER_NULL_CIPHER",
+    "CIPHER_NULL_CIPHER", //no-check-names
 #endif /* MBEDTLS_CIPHER_NULL_CIPHER */
 #if defined(MBEDTLS_CIPHER_PADDING_PKCS7)
-    "MBEDTLS_CIPHER_PADDING_PKCS7",
+    "CIPHER_PADDING_PKCS7", //no-check-names
 #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
 #if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS)
-    "MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS",
+    "CIPHER_PADDING_ONE_AND_ZEROS", //no-check-names
 #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN)
-    "MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN",
+    "CIPHER_PADDING_ZEROS_AND_LEN", //no-check-names
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
 #if defined(MBEDTLS_CIPHER_PADDING_ZEROS)
-    "MBEDTLS_CIPHER_PADDING_ZEROS",
+    "CIPHER_PADDING_ZEROS", //no-check-names
 #endif /* MBEDTLS_CIPHER_PADDING_ZEROS */
 #if defined(MBEDTLS_CTR_DRBG_USE_128_BIT_KEY)
-    "MBEDTLS_CTR_DRBG_USE_128_BIT_KEY",
+    "CTR_DRBG_USE_128_BIT_KEY", //no-check-names
 #endif /* MBEDTLS_CTR_DRBG_USE_128_BIT_KEY */
+#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
+    "ECDH_VARIANT_EVEREST_ENABLED", //no-check-names
+#endif /* MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP192R1_ENABLED",
+    "ECP_DP_SECP192R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP224R1_ENABLED",
+    "ECP_DP_SECP224R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP256R1_ENABLED",
+    "ECP_DP_SECP256R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP384R1_ENABLED",
+    "ECP_DP_SECP384R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP521R1_ENABLED",
+    "ECP_DP_SECP521R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP192K1_ENABLED",
+    "ECP_DP_SECP192K1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP224K1_ENABLED",
+    "ECP_DP_SECP224K1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED)
-    "MBEDTLS_ECP_DP_SECP256K1_ENABLED",
+    "ECP_DP_SECP256K1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED)
-    "MBEDTLS_ECP_DP_BP256R1_ENABLED",
+    "ECP_DP_BP256R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED)
-    "MBEDTLS_ECP_DP_BP384R1_ENABLED",
+    "ECP_DP_BP384R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED)
-    "MBEDTLS_ECP_DP_BP512R1_ENABLED",
+    "ECP_DP_BP512R1_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */
 #if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED)
-    "MBEDTLS_ECP_DP_CURVE25519_ENABLED",
+    "ECP_DP_CURVE25519_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */
 #if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED)
-    "MBEDTLS_ECP_DP_CURVE448_ENABLED",
+    "ECP_DP_CURVE448_ENABLED", //no-check-names
 #endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */
 #if defined(MBEDTLS_ECP_NIST_OPTIM)
-    "MBEDTLS_ECP_NIST_OPTIM",
+    "ECP_NIST_OPTIM", //no-check-names
 #endif /* MBEDTLS_ECP_NIST_OPTIM */
 #if defined(MBEDTLS_ECP_RESTARTABLE)
-    "MBEDTLS_ECP_RESTARTABLE",
+    "ECP_RESTARTABLE", //no-check-names
 #endif /* MBEDTLS_ECP_RESTARTABLE */
+#if defined(MBEDTLS_ECP_WITH_MPI_UINT)
+    "ECP_WITH_MPI_UINT", //no-check-names
+#endif /* MBEDTLS_ECP_WITH_MPI_UINT */
 #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
-    "MBEDTLS_ECDSA_DETERMINISTIC",
+    "ECDSA_DETERMINISTIC", //no-check-names
 #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
 #if defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_PSK_ENABLED",
+    "KEY_EXCHANGE_PSK_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED",
+    "KEY_EXCHANGE_DHE_PSK_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED",
+    "KEY_EXCHANGE_ECDHE_PSK_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED",
+    "KEY_EXCHANGE_RSA_PSK_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED",
+    "KEY_EXCHANGE_RSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED",
+    "KEY_EXCHANGE_DHE_RSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED",
+    "KEY_EXCHANGE_ECDHE_RSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED",
+    "KEY_EXCHANGE_ECDHE_ECDSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED",
+    "KEY_EXCHANGE_ECDH_ECDSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED",
+    "KEY_EXCHANGE_ECDH_RSA_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED */
 #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
-    "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED",
+    "KEY_EXCHANGE_ECJPAKE_ENABLED", //no-check-names
 #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
 #if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
-    "MBEDTLS_PK_PARSE_EC_EXTENDED",
+    "PK_PARSE_EC_EXTENDED", //no-check-names
 #endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */
+#if defined(MBEDTLS_PK_PARSE_EC_COMPRESSED)
+    "PK_PARSE_EC_COMPRESSED", //no-check-names
+#endif /* MBEDTLS_PK_PARSE_EC_COMPRESSED */
 #if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
-    "MBEDTLS_ERROR_STRERROR_DUMMY",
+    "ERROR_STRERROR_DUMMY", //no-check-names
 #endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
 #if defined(MBEDTLS_GENPRIME)
-    "MBEDTLS_GENPRIME",
+    "GENPRIME", //no-check-names
 #endif /* MBEDTLS_GENPRIME */
 #if defined(MBEDTLS_FS_IO)
-    "MBEDTLS_FS_IO",
+    "FS_IO", //no-check-names
 #endif /* MBEDTLS_FS_IO */
 #if defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
-    "MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES",
+    "NO_DEFAULT_ENTROPY_SOURCES", //no-check-names
 #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
 #if defined(MBEDTLS_NO_PLATFORM_ENTROPY)
-    "MBEDTLS_NO_PLATFORM_ENTROPY",
+    "NO_PLATFORM_ENTROPY", //no-check-names
 #endif /* MBEDTLS_NO_PLATFORM_ENTROPY */
 #if defined(MBEDTLS_ENTROPY_FORCE_SHA256)
-    "MBEDTLS_ENTROPY_FORCE_SHA256",
+    "ENTROPY_FORCE_SHA256", //no-check-names
 #endif /* MBEDTLS_ENTROPY_FORCE_SHA256 */
 #if defined(MBEDTLS_ENTROPY_NV_SEED)
-    "MBEDTLS_ENTROPY_NV_SEED",
+    "ENTROPY_NV_SEED", //no-check-names
 #endif /* MBEDTLS_ENTROPY_NV_SEED */
 #if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER)
-    "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER",
+    "PSA_CRYPTO_KEY_ID_ENCODES_OWNER", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER */
 #if defined(MBEDTLS_MEMORY_DEBUG)
-    "MBEDTLS_MEMORY_DEBUG",
+    "MEMORY_DEBUG", //no-check-names
 #endif /* MBEDTLS_MEMORY_DEBUG */
 #if defined(MBEDTLS_MEMORY_BACKTRACE)
-    "MBEDTLS_MEMORY_BACKTRACE",
+    "MEMORY_BACKTRACE", //no-check-names
 #endif /* MBEDTLS_MEMORY_BACKTRACE */
 #if defined(MBEDTLS_PK_RSA_ALT_SUPPORT)
-    "MBEDTLS_PK_RSA_ALT_SUPPORT",
+    "PK_RSA_ALT_SUPPORT", //no-check-names
 #endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */
 #if defined(MBEDTLS_PKCS1_V15)
-    "MBEDTLS_PKCS1_V15",
+    "PKCS1_V15", //no-check-names
 #endif /* MBEDTLS_PKCS1_V15 */
 #if defined(MBEDTLS_PKCS1_V21)
-    "MBEDTLS_PKCS1_V21",
+    "PKCS1_V21", //no-check-names
 #endif /* MBEDTLS_PKCS1_V21 */
 #if defined(MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS)
-    "MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS",
+    "PSA_CRYPTO_BUILTIN_KEYS", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_BUILTIN_KEYS */
 #if defined(MBEDTLS_PSA_CRYPTO_CLIENT)
-    "MBEDTLS_PSA_CRYPTO_CLIENT",
+    "PSA_CRYPTO_CLIENT", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_CLIENT */
-#if defined(MBEDTLS_PSA_CRYPTO_DRIVERS)
-    "MBEDTLS_PSA_CRYPTO_DRIVERS",
-#endif /* MBEDTLS_PSA_CRYPTO_DRIVERS */
 #if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
-    "MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG",
+    "PSA_CRYPTO_EXTERNAL_RNG", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG */
 #if defined(MBEDTLS_PSA_CRYPTO_SPM)
-    "MBEDTLS_PSA_CRYPTO_SPM",
+    "PSA_CRYPTO_SPM", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_SPM */
+#if defined(MBEDTLS_PSA_KEY_STORE_DYNAMIC)
+    "PSA_KEY_STORE_DYNAMIC", //no-check-names
+#endif /* MBEDTLS_PSA_KEY_STORE_DYNAMIC */
+#if defined(MBEDTLS_PSA_P256M_DRIVER_ENABLED)
+    "PSA_P256M_DRIVER_ENABLED", //no-check-names
+#endif /* MBEDTLS_PSA_P256M_DRIVER_ENABLED */
 #if defined(MBEDTLS_PSA_INJECT_ENTROPY)
-    "MBEDTLS_PSA_INJECT_ENTROPY",
+    "PSA_INJECT_ENTROPY", //no-check-names
 #endif /* MBEDTLS_PSA_INJECT_ENTROPY */
+#if defined(MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS)
+    "PSA_ASSUME_EXCLUSIVE_BUFFERS", //no-check-names
+#endif /* MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS */
 #if defined(MBEDTLS_RSA_NO_CRT)
-    "MBEDTLS_RSA_NO_CRT",
+    "RSA_NO_CRT", //no-check-names
 #endif /* MBEDTLS_RSA_NO_CRT */
 #if defined(MBEDTLS_SELF_TEST)
-    "MBEDTLS_SELF_TEST",
+    "SELF_TEST", //no-check-names
 #endif /* MBEDTLS_SELF_TEST */
 #if defined(MBEDTLS_SHA256_SMALLER)
-    "MBEDTLS_SHA256_SMALLER",
+    "SHA256_SMALLER", //no-check-names
 #endif /* MBEDTLS_SHA256_SMALLER */
 #if defined(MBEDTLS_SHA512_SMALLER)
-    "MBEDTLS_SHA512_SMALLER",
+    "SHA512_SMALLER", //no-check-names
 #endif /* MBEDTLS_SHA512_SMALLER */
 #if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
-    "MBEDTLS_SSL_ALL_ALERT_MESSAGES",
+    "SSL_ALL_ALERT_MESSAGES", //no-check-names
 #endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
-    "MBEDTLS_SSL_DTLS_CONNECTION_ID",
+    "SSL_DTLS_CONNECTION_ID", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
 #if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT)
-    "MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT",
+    "SSL_DTLS_CONNECTION_ID_COMPAT", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT */
 #if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
-    "MBEDTLS_SSL_ASYNC_PRIVATE",
+    "SSL_ASYNC_PRIVATE", //no-check-names
 #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
 #if defined(MBEDTLS_SSL_CONTEXT_SERIALIZATION)
-    "MBEDTLS_SSL_CONTEXT_SERIALIZATION",
+    "SSL_CONTEXT_SERIALIZATION", //no-check-names
 #endif /* MBEDTLS_SSL_CONTEXT_SERIALIZATION */
 #if defined(MBEDTLS_SSL_DEBUG_ALL)
-    "MBEDTLS_SSL_DEBUG_ALL",
+    "SSL_DEBUG_ALL", //no-check-names
 #endif /* MBEDTLS_SSL_DEBUG_ALL */
 #if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC)
-    "MBEDTLS_SSL_ENCRYPT_THEN_MAC",
+    "SSL_ENCRYPT_THEN_MAC", //no-check-names
 #endif /* MBEDTLS_SSL_ENCRYPT_THEN_MAC */
 #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
-    "MBEDTLS_SSL_EXTENDED_MASTER_SECRET",
+    "SSL_EXTENDED_MASTER_SECRET", //no-check-names
 #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */
 #if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
-    "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE",
+    "SSL_KEEP_PEER_CERTIFICATE", //no-check-names
 #endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
 #if defined(MBEDTLS_SSL_RENEGOTIATION)
-    "MBEDTLS_SSL_RENEGOTIATION",
+    "SSL_RENEGOTIATION", //no-check-names
 #endif /* MBEDTLS_SSL_RENEGOTIATION */
 #if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH)
-    "MBEDTLS_SSL_MAX_FRAGMENT_LENGTH",
+    "SSL_MAX_FRAGMENT_LENGTH", //no-check-names
 #endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
 #if defined(MBEDTLS_SSL_RECORD_SIZE_LIMIT)
-    "MBEDTLS_SSL_RECORD_SIZE_LIMIT",
+    "SSL_RECORD_SIZE_LIMIT", //no-check-names
 #endif /* MBEDTLS_SSL_RECORD_SIZE_LIMIT */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_2)
-    "MBEDTLS_SSL_PROTO_TLS1_2",
+    "SSL_PROTO_TLS1_2", //no-check-names
 #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
 #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
-    "MBEDTLS_SSL_PROTO_TLS1_3",
+    "SSL_PROTO_TLS1_3", //no-check-names
 #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
 #if defined(MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE)
-    "MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE",
+    "SSL_TLS1_3_COMPATIBILITY_MODE", //no-check-names
 #endif /* MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE */
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED)
-    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED",
+    "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED", //no-check-names
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_ENABLED */
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED)
-    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED",
+    "SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED", //no-check-names
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_EPHEMERAL_ENABLED */
 #if defined(MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED)
-    "MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED",
+    "SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED", //no-check-names
 #endif /* MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_PSK_EPHEMERAL_ENABLED */
 #if defined(MBEDTLS_SSL_EARLY_DATA)
-    "MBEDTLS_SSL_EARLY_DATA",
+    "SSL_EARLY_DATA", //no-check-names
 #endif /* MBEDTLS_SSL_EARLY_DATA */
-#if defined(MBEDTLS_SSL_MAX_EARLY_DATA_SIZE)
-    "MBEDTLS_SSL_MAX_EARLY_DATA_SIZE",
-#endif /* MBEDTLS_SSL_MAX_EARLY_DATA_SIZE */
 #if defined(MBEDTLS_SSL_PROTO_DTLS)
-    "MBEDTLS_SSL_PROTO_DTLS",
+    "SSL_PROTO_DTLS", //no-check-names
 #endif /* MBEDTLS_SSL_PROTO_DTLS */
 #if defined(MBEDTLS_SSL_ALPN)
-    "MBEDTLS_SSL_ALPN",
+    "SSL_ALPN", //no-check-names
 #endif /* MBEDTLS_SSL_ALPN */
 #if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY)
-    "MBEDTLS_SSL_DTLS_ANTI_REPLAY",
+    "SSL_DTLS_ANTI_REPLAY", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_ANTI_REPLAY */
 #if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY)
-    "MBEDTLS_SSL_DTLS_HELLO_VERIFY",
+    "SSL_DTLS_HELLO_VERIFY", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */
 #if defined(MBEDTLS_SSL_DTLS_SRTP)
-    "MBEDTLS_SSL_DTLS_SRTP",
+    "SSL_DTLS_SRTP", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_SRTP */
 #if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE)
-    "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE",
+    "SSL_DTLS_CLIENT_PORT_REUSE", //no-check-names
 #endif /* MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE */
 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
-    "MBEDTLS_SSL_SESSION_TICKETS",
+    "SSL_SESSION_TICKETS", //no-check-names
 #endif /* MBEDTLS_SSL_SESSION_TICKETS */
 #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    "MBEDTLS_SSL_SERVER_NAME_INDICATION",
+    "SSL_SERVER_NAME_INDICATION", //no-check-names
 #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
 #if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH)
-    "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH",
+    "SSL_VARIABLE_BUFFER_LENGTH", //no-check-names
 #endif /* MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH */
 #if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN)
-    "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN",
+    "TEST_CONSTANT_FLOW_MEMSAN", //no-check-names
 #endif /* MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN */
 #if defined(MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND)
-    "MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND",
+    "TEST_CONSTANT_FLOW_VALGRIND", //no-check-names
 #endif /* MBEDTLS_TEST_CONSTANT_FLOW_VALGRIND */
 #if defined(MBEDTLS_TEST_HOOKS)
-    "MBEDTLS_TEST_HOOKS",
+    "TEST_HOOKS", //no-check-names
 #endif /* MBEDTLS_TEST_HOOKS */
 #if defined(MBEDTLS_THREADING_ALT)
-    "MBEDTLS_THREADING_ALT",
+    "THREADING_ALT", //no-check-names
 #endif /* MBEDTLS_THREADING_ALT */
 #if defined(MBEDTLS_THREADING_PTHREAD)
-    "MBEDTLS_THREADING_PTHREAD",
+    "THREADING_PTHREAD", //no-check-names
 #endif /* MBEDTLS_THREADING_PTHREAD */
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    "MBEDTLS_USE_PSA_CRYPTO",
+    "USE_PSA_CRYPTO", //no-check-names
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 #if defined(MBEDTLS_PSA_CRYPTO_CONFIG)
-    "MBEDTLS_PSA_CRYPTO_CONFIG",
+    "PSA_CRYPTO_CONFIG", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_CONFIG */
 #if defined(MBEDTLS_VERSION_FEATURES)
-    "MBEDTLS_VERSION_FEATURES",
+    "VERSION_FEATURES", //no-check-names
 #endif /* MBEDTLS_VERSION_FEATURES */
 #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
-    "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK",
+    "X509_TRUSTED_CERTIFICATE_CALLBACK", //no-check-names
 #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
 #if defined(MBEDTLS_X509_REMOVE_INFO)
-    "MBEDTLS_X509_REMOVE_INFO",
+    "X509_REMOVE_INFO", //no-check-names
 #endif /* MBEDTLS_X509_REMOVE_INFO */
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
-    "MBEDTLS_X509_RSASSA_PSS_SUPPORT",
+    "X509_RSASSA_PSS_SUPPORT", //no-check-names
 #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
 #if defined(MBEDTLS_AESNI_C)
-    "MBEDTLS_AESNI_C",
+    "AESNI_C", //no-check-names
 #endif /* MBEDTLS_AESNI_C */
 #if defined(MBEDTLS_AESCE_C)
-    "MBEDTLS_AESCE_C",
+    "AESCE_C", //no-check-names
 #endif /* MBEDTLS_AESCE_C */
 #if defined(MBEDTLS_AES_C)
-    "MBEDTLS_AES_C",
+    "AES_C", //no-check-names
 #endif /* MBEDTLS_AES_C */
 #if defined(MBEDTLS_ASN1_PARSE_C)
-    "MBEDTLS_ASN1_PARSE_C",
+    "ASN1_PARSE_C", //no-check-names
 #endif /* MBEDTLS_ASN1_PARSE_C */
 #if defined(MBEDTLS_ASN1_WRITE_C)
-    "MBEDTLS_ASN1_WRITE_C",
+    "ASN1_WRITE_C", //no-check-names
 #endif /* MBEDTLS_ASN1_WRITE_C */
 #if defined(MBEDTLS_BASE64_C)
-    "MBEDTLS_BASE64_C",
+    "BASE64_C", //no-check-names
 #endif /* MBEDTLS_BASE64_C */
+#if defined(MBEDTLS_BLOCK_CIPHER_NO_DECRYPT)
+    "BLOCK_CIPHER_NO_DECRYPT", //no-check-names
+#endif /* MBEDTLS_BLOCK_CIPHER_NO_DECRYPT */
 #if defined(MBEDTLS_BIGNUM_C)
-    "MBEDTLS_BIGNUM_C",
+    "BIGNUM_C", //no-check-names
 #endif /* MBEDTLS_BIGNUM_C */
 #if defined(MBEDTLS_CAMELLIA_C)
-    "MBEDTLS_CAMELLIA_C",
+    "CAMELLIA_C", //no-check-names
 #endif /* MBEDTLS_CAMELLIA_C */
 #if defined(MBEDTLS_ARIA_C)
-    "MBEDTLS_ARIA_C",
+    "ARIA_C", //no-check-names
 #endif /* MBEDTLS_ARIA_C */
 #if defined(MBEDTLS_CCM_C)
-    "MBEDTLS_CCM_C",
+    "CCM_C", //no-check-names
 #endif /* MBEDTLS_CCM_C */
 #if defined(MBEDTLS_CHACHA20_C)
-    "MBEDTLS_CHACHA20_C",
+    "CHACHA20_C", //no-check-names
 #endif /* MBEDTLS_CHACHA20_C */
 #if defined(MBEDTLS_CHACHAPOLY_C)
-    "MBEDTLS_CHACHAPOLY_C",
+    "CHACHAPOLY_C", //no-check-names
 #endif /* MBEDTLS_CHACHAPOLY_C */
 #if defined(MBEDTLS_CIPHER_C)
-    "MBEDTLS_CIPHER_C",
+    "CIPHER_C", //no-check-names
 #endif /* MBEDTLS_CIPHER_C */
 #if defined(MBEDTLS_CMAC_C)
-    "MBEDTLS_CMAC_C",
+    "CMAC_C", //no-check-names
 #endif /* MBEDTLS_CMAC_C */
 #if defined(MBEDTLS_CTR_DRBG_C)
-    "MBEDTLS_CTR_DRBG_C",
+    "CTR_DRBG_C", //no-check-names
 #endif /* MBEDTLS_CTR_DRBG_C */
 #if defined(MBEDTLS_DEBUG_C)
-    "MBEDTLS_DEBUG_C",
+    "DEBUG_C", //no-check-names
 #endif /* MBEDTLS_DEBUG_C */
 #if defined(MBEDTLS_DES_C)
-    "MBEDTLS_DES_C",
+    "DES_C", //no-check-names
 #endif /* MBEDTLS_DES_C */
 #if defined(MBEDTLS_DHM_C)
-    "MBEDTLS_DHM_C",
+    "DHM_C", //no-check-names
 #endif /* MBEDTLS_DHM_C */
 #if defined(MBEDTLS_ECDH_C)
-    "MBEDTLS_ECDH_C",
+    "ECDH_C", //no-check-names
 #endif /* MBEDTLS_ECDH_C */
 #if defined(MBEDTLS_ECDSA_C)
-    "MBEDTLS_ECDSA_C",
+    "ECDSA_C", //no-check-names
 #endif /* MBEDTLS_ECDSA_C */
 #if defined(MBEDTLS_ECJPAKE_C)
-    "MBEDTLS_ECJPAKE_C",
+    "ECJPAKE_C", //no-check-names
 #endif /* MBEDTLS_ECJPAKE_C */
 #if defined(MBEDTLS_ECP_C)
-    "MBEDTLS_ECP_C",
+    "ECP_C", //no-check-names
 #endif /* MBEDTLS_ECP_C */
 #if defined(MBEDTLS_ENTROPY_C)
-    "MBEDTLS_ENTROPY_C",
+    "ENTROPY_C", //no-check-names
 #endif /* MBEDTLS_ENTROPY_C */
 #if defined(MBEDTLS_ERROR_C)
-    "MBEDTLS_ERROR_C",
+    "ERROR_C", //no-check-names
 #endif /* MBEDTLS_ERROR_C */
 #if defined(MBEDTLS_GCM_C)
-    "MBEDTLS_GCM_C",
+    "GCM_C", //no-check-names
 #endif /* MBEDTLS_GCM_C */
+#if defined(MBEDTLS_GCM_LARGE_TABLE)
+    "GCM_LARGE_TABLE", //no-check-names
+#endif /* MBEDTLS_GCM_LARGE_TABLE */
 #if defined(MBEDTLS_HKDF_C)
-    "MBEDTLS_HKDF_C",
+    "HKDF_C", //no-check-names
 #endif /* MBEDTLS_HKDF_C */
 #if defined(MBEDTLS_HMAC_DRBG_C)
-    "MBEDTLS_HMAC_DRBG_C",
+    "HMAC_DRBG_C", //no-check-names
 #endif /* MBEDTLS_HMAC_DRBG_C */
 #if defined(MBEDTLS_LMS_C)
-    "MBEDTLS_LMS_C",
+    "LMS_C", //no-check-names
 #endif /* MBEDTLS_LMS_C */
 #if defined(MBEDTLS_LMS_PRIVATE)
-    "MBEDTLS_LMS_PRIVATE",
+    "LMS_PRIVATE", //no-check-names
 #endif /* MBEDTLS_LMS_PRIVATE */
 #if defined(MBEDTLS_NIST_KW_C)
-    "MBEDTLS_NIST_KW_C",
+    "NIST_KW_C", //no-check-names
 #endif /* MBEDTLS_NIST_KW_C */
 #if defined(MBEDTLS_MD_C)
-    "MBEDTLS_MD_C",
+    "MD_C", //no-check-names
 #endif /* MBEDTLS_MD_C */
 #if defined(MBEDTLS_MD5_C)
-    "MBEDTLS_MD5_C",
+    "MD5_C", //no-check-names
 #endif /* MBEDTLS_MD5_C */
 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
-    "MBEDTLS_MEMORY_BUFFER_ALLOC_C",
+    "MEMORY_BUFFER_ALLOC_C", //no-check-names
 #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */
 #if defined(MBEDTLS_NET_C)
-    "MBEDTLS_NET_C",
+    "NET_C", //no-check-names
 #endif /* MBEDTLS_NET_C */
 #if defined(MBEDTLS_OID_C)
-    "MBEDTLS_OID_C",
+    "OID_C", //no-check-names
 #endif /* MBEDTLS_OID_C */
 #if defined(MBEDTLS_PADLOCK_C)
-    "MBEDTLS_PADLOCK_C",
+    "PADLOCK_C", //no-check-names
 #endif /* MBEDTLS_PADLOCK_C */
 #if defined(MBEDTLS_PEM_PARSE_C)
-    "MBEDTLS_PEM_PARSE_C",
+    "PEM_PARSE_C", //no-check-names
 #endif /* MBEDTLS_PEM_PARSE_C */
 #if defined(MBEDTLS_PEM_WRITE_C)
-    "MBEDTLS_PEM_WRITE_C",
+    "PEM_WRITE_C", //no-check-names
 #endif /* MBEDTLS_PEM_WRITE_C */
 #if defined(MBEDTLS_PK_C)
-    "MBEDTLS_PK_C",
+    "PK_C", //no-check-names
 #endif /* MBEDTLS_PK_C */
 #if defined(MBEDTLS_PK_PARSE_C)
-    "MBEDTLS_PK_PARSE_C",
+    "PK_PARSE_C", //no-check-names
 #endif /* MBEDTLS_PK_PARSE_C */
 #if defined(MBEDTLS_PK_WRITE_C)
-    "MBEDTLS_PK_WRITE_C",
+    "PK_WRITE_C", //no-check-names
 #endif /* MBEDTLS_PK_WRITE_C */
 #if defined(MBEDTLS_PKCS5_C)
-    "MBEDTLS_PKCS5_C",
+    "PKCS5_C", //no-check-names
 #endif /* MBEDTLS_PKCS5_C */
 #if defined(MBEDTLS_PKCS7_C)
-    "MBEDTLS_PKCS7_C",
+    "PKCS7_C", //no-check-names
 #endif /* MBEDTLS_PKCS7_C */
 #if defined(MBEDTLS_PKCS12_C)
-    "MBEDTLS_PKCS12_C",
+    "PKCS12_C", //no-check-names
 #endif /* MBEDTLS_PKCS12_C */
 #if defined(MBEDTLS_PLATFORM_C)
-    "MBEDTLS_PLATFORM_C",
+    "PLATFORM_C", //no-check-names
 #endif /* MBEDTLS_PLATFORM_C */
 #if defined(MBEDTLS_POLY1305_C)
-    "MBEDTLS_POLY1305_C",
+    "POLY1305_C", //no-check-names
 #endif /* MBEDTLS_POLY1305_C */
 #if defined(MBEDTLS_PSA_CRYPTO_C)
-    "MBEDTLS_PSA_CRYPTO_C",
+    "PSA_CRYPTO_C", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_C */
 #if defined(MBEDTLS_PSA_CRYPTO_SE_C)
-    "MBEDTLS_PSA_CRYPTO_SE_C",
+    "PSA_CRYPTO_SE_C", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_SE_C */
 #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C)
-    "MBEDTLS_PSA_CRYPTO_STORAGE_C",
+    "PSA_CRYPTO_STORAGE_C", //no-check-names
 #endif /* MBEDTLS_PSA_CRYPTO_STORAGE_C */
 #if defined(MBEDTLS_PSA_ITS_FILE_C)
-    "MBEDTLS_PSA_ITS_FILE_C",
+    "PSA_ITS_FILE_C", //no-check-names
 #endif /* MBEDTLS_PSA_ITS_FILE_C */
 #if defined(MBEDTLS_RIPEMD160_C)
-    "MBEDTLS_RIPEMD160_C",
+    "RIPEMD160_C", //no-check-names
 #endif /* MBEDTLS_RIPEMD160_C */
 #if defined(MBEDTLS_RSA_C)
-    "MBEDTLS_RSA_C",
+    "RSA_C", //no-check-names
 #endif /* MBEDTLS_RSA_C */
 #if defined(MBEDTLS_SHA1_C)
-    "MBEDTLS_SHA1_C",
+    "SHA1_C", //no-check-names
 #endif /* MBEDTLS_SHA1_C */
 #if defined(MBEDTLS_SHA224_C)
-    "MBEDTLS_SHA224_C",
+    "SHA224_C", //no-check-names
 #endif /* MBEDTLS_SHA224_C */
 #if defined(MBEDTLS_SHA256_C)
-    "MBEDTLS_SHA256_C",
+    "SHA256_C", //no-check-names
 #endif /* MBEDTLS_SHA256_C */
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT)
+    "SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT", //no-check-names
+#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT */
 #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
-    "MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT",
+    "SHA256_USE_A64_CRYPTO_IF_PRESENT", //no-check-names
 #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
+#if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY)
+    "SHA256_USE_ARMV8_A_CRYPTO_ONLY", //no-check-names
+#endif /* MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY */
 #if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
-    "MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY",
+    "SHA256_USE_A64_CRYPTO_ONLY", //no-check-names
 #endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
 #if defined(MBEDTLS_SHA384_C)
-    "MBEDTLS_SHA384_C",
+    "SHA384_C", //no-check-names
 #endif /* MBEDTLS_SHA384_C */
 #if defined(MBEDTLS_SHA512_C)
-    "MBEDTLS_SHA512_C",
+    "SHA512_C", //no-check-names
 #endif /* MBEDTLS_SHA512_C */
+#if defined(MBEDTLS_SHA3_C)
+    "SHA3_C", //no-check-names
+#endif /* MBEDTLS_SHA3_C */
 #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
-    "MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT",
+    "SHA512_USE_A64_CRYPTO_IF_PRESENT", //no-check-names
 #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
 #if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
-    "MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY",
+    "SHA512_USE_A64_CRYPTO_ONLY", //no-check-names
 #endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
 #if defined(MBEDTLS_SSL_CACHE_C)
-    "MBEDTLS_SSL_CACHE_C",
+    "SSL_CACHE_C", //no-check-names
 #endif /* MBEDTLS_SSL_CACHE_C */
 #if defined(MBEDTLS_SSL_COOKIE_C)
-    "MBEDTLS_SSL_COOKIE_C",
+    "SSL_COOKIE_C", //no-check-names
 #endif /* MBEDTLS_SSL_COOKIE_C */
 #if defined(MBEDTLS_SSL_TICKET_C)
-    "MBEDTLS_SSL_TICKET_C",
+    "SSL_TICKET_C", //no-check-names
 #endif /* MBEDTLS_SSL_TICKET_C */
 #if defined(MBEDTLS_SSL_CLI_C)
-    "MBEDTLS_SSL_CLI_C",
+    "SSL_CLI_C", //no-check-names
 #endif /* MBEDTLS_SSL_CLI_C */
 #if defined(MBEDTLS_SSL_SRV_C)
-    "MBEDTLS_SSL_SRV_C",
+    "SSL_SRV_C", //no-check-names
 #endif /* MBEDTLS_SSL_SRV_C */
 #if defined(MBEDTLS_SSL_TLS_C)
-    "MBEDTLS_SSL_TLS_C",
+    "SSL_TLS_C", //no-check-names
 #endif /* MBEDTLS_SSL_TLS_C */
 #if defined(MBEDTLS_THREADING_C)
-    "MBEDTLS_THREADING_C",
+    "THREADING_C", //no-check-names
 #endif /* MBEDTLS_THREADING_C */
 #if defined(MBEDTLS_TIMING_C)
-    "MBEDTLS_TIMING_C",
+    "TIMING_C", //no-check-names
 #endif /* MBEDTLS_TIMING_C */
 #if defined(MBEDTLS_VERSION_C)
-    "MBEDTLS_VERSION_C",
+    "VERSION_C", //no-check-names
 #endif /* MBEDTLS_VERSION_C */
 #if defined(MBEDTLS_X509_USE_C)
-    "MBEDTLS_X509_USE_C",
+    "X509_USE_C", //no-check-names
 #endif /* MBEDTLS_X509_USE_C */
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
-    "MBEDTLS_X509_CRT_PARSE_C",
+    "X509_CRT_PARSE_C", //no-check-names
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
-    "MBEDTLS_X509_CRL_PARSE_C",
+    "X509_CRL_PARSE_C", //no-check-names
 #endif /* MBEDTLS_X509_CRL_PARSE_C */
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
-    "MBEDTLS_X509_CSR_PARSE_C",
+    "X509_CSR_PARSE_C", //no-check-names
 #endif /* MBEDTLS_X509_CSR_PARSE_C */
 #if defined(MBEDTLS_X509_CREATE_C)
-    "MBEDTLS_X509_CREATE_C",
+    "X509_CREATE_C", //no-check-names
 #endif /* MBEDTLS_X509_CREATE_C */
 #if defined(MBEDTLS_X509_CRT_WRITE_C)
-    "MBEDTLS_X509_CRT_WRITE_C",
+    "X509_CRT_WRITE_C", //no-check-names
 #endif /* MBEDTLS_X509_CRT_WRITE_C */
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
-    "MBEDTLS_X509_CSR_WRITE_C",
+    "X509_CSR_WRITE_C", //no-check-names
 #endif /* MBEDTLS_X509_CSR_WRITE_C */
 #endif /* MBEDTLS_VERSION_FEATURES */
     NULL
@@ -796,6 +826,12 @@ int mbedtls_version_check_feature(const char *feature)
         return -1;
     }
 
+    if (strncmp(feature, "MBEDTLS_", 8)) {
+        return -1;
+    }
+
+    feature += 8;
+
     while (*idx != NULL) {
         if (!strcmp(*idx, feature)) {
             return 0;
diff --git a/lib/libmbedtls/mbedtls/library/x509.c b/lib/libmbedtls/mbedtls/library/x509.c
index fc13b92133ae284b33637dc49f4c4b649ca189a6..f97fb44589ed7ef4d5e6379be6421b72b2e81b5b 100644
--- a/lib/libmbedtls/mbedtls/library/x509.c
+++ b/lib/libmbedtls/mbedtls/library/x509.c
@@ -2,19 +2,7 @@
  *  X.509 common functions for parsing and verification
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
@@ -31,7 +19,7 @@
 
 #if defined(MBEDTLS_X509_USE_C)
 
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
 #include "mbedtls/asn1.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
@@ -43,6 +31,8 @@
 #include "mbedtls/pem.h"
 #endif
 
+#include "mbedtls/asn1write.h"
+
 #include "mbedtls/platform.h"
 
 #if defined(MBEDTLS_HAVE_TIME)
@@ -53,15 +43,17 @@
 #include <time.h>
 #endif
 
-#include "mbedtls/legacy_or_psa.h"
+#define CHECK(code)                                     \
+    do {                                                \
+        if ((ret = (code)) != 0) {                      \
+            return ret;                                 \
+        }                                               \
+    } while (0)
 
-#define CHECK(code) if ((ret = (code)) != 0) { return ret; }
 #define CHECK_RANGE(min, max, val)                      \
-    do                                                  \
-    {                                                   \
-        if ((val) < (min) || (val) > (max))    \
-        {                                               \
-            return ret;                              \
+    do {                                                \
+        if ((val) < (min) || (val) > (max)) {           \
+            return ret;                                 \
         }                                               \
     } while (0)
 
@@ -132,34 +124,36 @@ int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
 /*
  * Convert md type to string
  */
+#if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+
 static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
 {
     switch (md_alg) {
-#if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_MD5)
         case MBEDTLS_MD_MD5:
             return "MD5";
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
         case MBEDTLS_MD_SHA1:
             return "SHA1";
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA224)
         case MBEDTLS_MD_SHA224:
             return "SHA224";
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA256)
         case MBEDTLS_MD_SHA256:
             return "SHA256";
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA384)
         case MBEDTLS_MD_SHA384:
             return "SHA384";
 #endif
-#if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA512)
         case MBEDTLS_MD_SHA512:
             return "SHA512";
 #endif
-#if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA)
+#if defined(MBEDTLS_MD_CAN_RIPEMD160)
         case MBEDTLS_MD_RIPEMD160:
             return "RIPEMD160";
 #endif
@@ -170,6 +164,8 @@ static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
     }
 }
 
+#endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */
+
 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
 /*
  * HashAlgorithm ::= AlgorithmIdentifier
@@ -567,117 +563,82 @@ error:
     return ret;
 }
 
-static int x509_parse_int(unsigned char **p, size_t n, int *res)
-{
-    *res = 0;
-
-    for (; n > 0; --n) {
-        if ((**p < '0') || (**p > '9')) {
-            return MBEDTLS_ERR_X509_INVALID_DATE;
-        }
-
-        *res *= 10;
-        *res += (*(*p)++ - '0');
-    }
-
-    return 0;
-}
-
 static int x509_date_is_valid(const mbedtls_x509_time *t)
 {
-    int ret = MBEDTLS_ERR_X509_INVALID_DATE;
-    int month_len;
-
-    CHECK_RANGE(0, 9999, t->year);
-    CHECK_RANGE(0, 23,   t->hour);
-    CHECK_RANGE(0, 59,   t->min);
-    CHECK_RANGE(0, 59,   t->sec);
-
+    unsigned int month_days;
+    unsigned int year;
     switch (t->mon) {
         case 1: case 3: case 5: case 7: case 8: case 10: case 12:
-            month_len = 31;
+            month_days = 31;
             break;
         case 4: case 6: case 9: case 11:
-            month_len = 30;
+            month_days = 30;
             break;
         case 2:
-            if ((!(t->year % 4) && t->year % 100) ||
-                !(t->year % 400)) {
-                month_len = 29;
-            } else {
-                month_len = 28;
-            }
+            year = (unsigned int) t->year;
+            month_days = ((year & 3) || (!(year % 100)
+                                         && (year % 400)))
+                          ? 28 : 29;
             break;
         default:
-            return ret;
+            return MBEDTLS_ERR_X509_INVALID_DATE;
+    }
+
+    if ((unsigned int) (t->day - 1) >= month_days ||      /* (1 - days in month) */
+        /* (unsigned int) (t->mon - 1) >= 12 || */  /* (1 - 12) checked above */
+        (unsigned int) t->year > 9999 ||         /* (0 - 9999) */
+        (unsigned int) t->hour > 23 ||           /* (0 - 23) */
+        (unsigned int) t->min  > 59 ||           /* (0 - 59) */
+        (unsigned int) t->sec  > 59) {           /* (0 - 59) */
+        return MBEDTLS_ERR_X509_INVALID_DATE;
     }
-    CHECK_RANGE(1, month_len, t->day);
 
     return 0;
 }
 
+static int x509_parse2_int(const unsigned char *p)
+{
+    uint32_t d1 = p[0] - '0';
+    uint32_t d2 = p[1] - '0';
+    return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1;
+}
+
 /*
  * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
  * field.
  */
-static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen,
-                           mbedtls_x509_time *tm)
+static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm,
+                           size_t yearlen)
 {
-    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int x;
 
     /*
-     * Minimum length is 10 or 12 depending on yearlen
+     * Parse year, month, day, hour, minute, second
      */
-    if (len < yearlen + 8) {
+    tm->year = x509_parse2_int(p);
+    if (tm->year < 0) {
         return MBEDTLS_ERR_X509_INVALID_DATE;
     }
-    len -= yearlen + 8;
 
-    /*
-     * Parse year, month, day, hour, minute
-     */
-    CHECK(x509_parse_int(p, yearlen, &tm->year));
-    if (2 == yearlen) {
-        if (tm->year < 50) {
-            tm->year += 100;
+    if (4 == yearlen) {
+        x = tm->year * 100;
+        p += 2;
+        tm->year = x509_parse2_int(p);
+        if (tm->year < 0) {
+            return MBEDTLS_ERR_X509_INVALID_DATE;
         }
-
-        tm->year += 1900;
-    }
-
-    CHECK(x509_parse_int(p, 2, &tm->mon));
-    CHECK(x509_parse_int(p, 2, &tm->day));
-    CHECK(x509_parse_int(p, 2, &tm->hour));
-    CHECK(x509_parse_int(p, 2, &tm->min));
-
-    /*
-     * Parse seconds if present
-     */
-    if (len >= 2) {
-        CHECK(x509_parse_int(p, 2, &tm->sec));
-        len -= 2;
     } else {
-        return MBEDTLS_ERR_X509_INVALID_DATE;
-    }
-
-    /*
-     * Parse trailing 'Z' if present
-     */
-    if (1 == len && 'Z' == **p) {
-        (*p)++;
-        len--;
-    }
-
-    /*
-     * We should have parsed all characters at this point
-     */
-    if (0 != len) {
-        return MBEDTLS_ERR_X509_INVALID_DATE;
+        x = (tm->year < 50) ? 2000 : 1900;
     }
+    tm->year += x;
 
-    CHECK(x509_date_is_valid(tm));
+    tm->mon  = x509_parse2_int(p + 2);
+    tm->day  = x509_parse2_int(p + 4);
+    tm->hour = x509_parse2_int(p + 6);
+    tm->min  = x509_parse2_int(p + 8);
+    tm->sec  = x509_parse2_int(p + 10);
 
-    return 0;
+    return x509_date_is_valid(tm);
 }
 
 /*
@@ -715,7 +676,14 @@ int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
     }
 
-    return x509_parse_time(p, len, year_len, tm);
+    /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */
+    if (len != year_len + 10 &&
+        !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) {
+        return MBEDTLS_ERR_X509_INVALID_DATE;
+    }
+
+    (*p) += len;
+    return x509_parse_time(*p - len, tm, year_len);
 }
 
 int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
@@ -832,6 +800,11 @@ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
     return 0;
 }
 
+static char nibble_to_hex_digit(int i)
+{
+    return (i < 10) ? (i + '0') : (i - 10 + 'A');
+}
+
 /*
  * Store the name in printable form into buf; no more
  * than size characters will be written
@@ -839,11 +812,16 @@ int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
 int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t i, j, n;
+    size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start;
+    /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/
+    unsigned char asn1_tag_len_buf[6];
+    unsigned char *asn1_len_p;
     unsigned char c, merge = 0;
     const mbedtls_x509_name *name;
     const char *short_name = NULL;
+    char lowbits, highbits;
     char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
+    int print_hexstring;
 
     memset(s, 0, sizeof(s));
 
@@ -862,32 +840,91 @@ int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
             MBEDTLS_X509_SAFE_SNPRINTF;
         }
 
-        ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name);
+        print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) &&
+                          (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) &&
+                          (name->val.tag != MBEDTLS_ASN1_IA5_STRING);
 
-        if (ret == 0) {
+        if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) {
             ret = mbedtls_snprintf(p, n, "%s=", short_name);
         } else {
-            ret = mbedtls_snprintf(p, n, "\?\?=");
+            if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) {
+                n -= ret;
+                p += ret;
+                ret = mbedtls_snprintf(p, n, "=");
+                print_hexstring = 1;
+            } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
+                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+            } else {
+                ret = mbedtls_snprintf(p, n, "\?\?=");
+            }
         }
         MBEDTLS_X509_SAFE_SNPRINTF;
 
-        for (i = 0, j = 0; i < name->val.len; i++, j++) {
-            if (j >= sizeof(s) - 1) {
-                return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
-            }
+        if (print_hexstring) {
+            s[0] = '#';
 
-            c = name->val.p[i];
-            // Special characters requiring escaping, RFC 1779
-            if (c && strchr(",=+<>#;\"\\", c)) {
+            asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf);
+            if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) {
+                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+            }
+            asn1_len_size = ret;
+            if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) {
+                return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+            }
+            asn1_tag_size = ret;
+            asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size;
+            for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) {
                 if (j + 1 >= sizeof(s) - 1) {
                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
                 }
-                s[j++] = '\\';
+                c = asn1_tag_len_buf[asn1_tag_len_buf_start+i];
+                lowbits = (c & 0x0F);
+                highbits = c >> 4;
+                s[j++] = nibble_to_hex_digit(highbits);
+                s[j++] = nibble_to_hex_digit(lowbits);
             }
-            if (c < 32 || c >= 127) {
-                s[j] = '?';
-            } else {
-                s[j] = c;
+            for (i = 0; i < name->val.len; i++) {
+                if (j + 1 >= sizeof(s) - 1) {
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
+                c = name->val.p[i];
+                lowbits = (c & 0x0F);
+                highbits = c >> 4;
+                s[j++] = nibble_to_hex_digit(highbits);
+                s[j++] = nibble_to_hex_digit(lowbits);
+            }
+        } else {
+            for (i = 0, j = 0; i < name->val.len; i++, j++) {
+                if (j >= sizeof(s) - 1) {
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
+
+                c = name->val.p[i];
+                // Special characters requiring escaping, RFC 4514 Section 2.4
+                if (c == '\0') {
+                    return MBEDTLS_ERR_X509_INVALID_NAME;
+                } else {
+                    if (strchr(",=+<>;\"\\", c) ||
+                        ((i == 0) && strchr("# ", c)) ||
+                        ((i == name->val.len-1) && (c == ' '))) {
+                        if (j + 1 >= sizeof(s) - 1) {
+                            return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                        }
+                        s[j++] = '\\';
+                    }
+                }
+                if (c < 32 || c >= 127) {
+                    if (j + 3 >= sizeof(s) - 1) {
+                        return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                    }
+                    s[j++] = '\\';
+                    lowbits = (c & 0x0F);
+                    highbits = c >> 4;
+                    s[j++] = nibble_to_hex_digit(highbits);
+                    s[j] = nibble_to_hex_digit(lowbits);
+                } else {
+                    s[j] = c;
+                }
             }
         }
         s[j] = '\0';
@@ -996,81 +1033,45 @@ int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
     return 0;
 }
 
-#if defined(MBEDTLS_HAVE_TIME_DATE)
-/*
- * Set the time structure to the current time.
- * Return 0 on success, non-zero on failure.
- */
-static int x509_get_current_time(mbedtls_x509_time *now)
+int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1,
+                          const mbedtls_x509_time *t2)
 {
-    struct tm *lt, tm_buf;
-    mbedtls_time_t tt;
-    int ret = 0;
-
-    tt = mbedtls_time(NULL);
-    lt = mbedtls_platform_gmtime_r(&tt, &tm_buf);
+    int x;
 
-    if (lt == NULL) {
-        ret = -1;
-    } else {
-        now->year = lt->tm_year + 1900;
-        now->mon  = lt->tm_mon  + 1;
-        now->day  = lt->tm_mday;
-        now->hour = lt->tm_hour;
-        now->min  = lt->tm_min;
-        now->sec  = lt->tm_sec;
+    x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) -
+         ((t2->year << 9) | (t2->mon << 5) | (t2->day)));
+    if (x != 0) {
+        return x;
     }
 
-    return ret;
+    x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) -
+         ((t2->hour << 12) | (t2->min << 6) | (t2->sec)));
+    return x;
 }
 
-/*
- * Return 0 if before <= after, 1 otherwise
- */
-static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after)
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now)
 {
-    if (before->year  > after->year) {
-        return 1;
-    }
-
-    if (before->year == after->year &&
-        before->mon   > after->mon) {
-        return 1;
-    }
-
-    if (before->year == after->year &&
-        before->mon  == after->mon  &&
-        before->day   > after->day) {
-        return 1;
-    }
-
-    if (before->year == after->year &&
-        before->mon  == after->mon  &&
-        before->day  == after->day  &&
-        before->hour  > after->hour) {
-        return 1;
-    }
+    struct tm tm;
 
-    if (before->year == after->year &&
-        before->mon  == after->mon  &&
-        before->day  == after->day  &&
-        before->hour == after->hour &&
-        before->min   > after->min) {
-        return 1;
-    }
-
-    if (before->year == after->year &&
-        before->mon  == after->mon  &&
-        before->day  == after->day  &&
-        before->hour == after->hour &&
-        before->min  == after->min  &&
-        before->sec   > after->sec) {
-        return 1;
+    if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) {
+        return -1;
     }
 
+    now->year = tm.tm_year + 1900;
+    now->mon  = tm.tm_mon  + 1;
+    now->day  = tm.tm_mday;
+    now->hour = tm.tm_hour;
+    now->min  = tm.tm_min;
+    now->sec  = tm.tm_sec;
     return 0;
 }
 
+static int x509_get_current_time(mbedtls_x509_time *now)
+{
+    return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now);
+}
+
 int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
 {
     mbedtls_x509_time now;
@@ -1079,7 +1080,7 @@ int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
         return 1;
     }
 
-    return x509_check_time(&now, to);
+    return mbedtls_x509_time_cmp(to, &now) < 0;
 }
 
 int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
@@ -1090,7 +1091,7 @@ int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
         return 1;
     }
 
-    return x509_check_time(from, &now);
+    return mbedtls_x509_time_cmp(from, &now) > 0;
 }
 
 #else  /* MBEDTLS_HAVE_TIME_DATE */
@@ -1155,6 +1156,7 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
     if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
         return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
     }
+    other_name->type_id = cur_oid;
 
     p += len;
     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
@@ -1203,57 +1205,23 @@ static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
     return 0;
 }
 
-/*
- * SubjectAltName ::= GeneralNames
- *
- * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+/* Check mbedtls_x509_get_subject_alt_name for detailed description.
  *
- * GeneralName ::= CHOICE {
- *      otherName                       [0]     OtherName,
- *      rfc822Name                      [1]     IA5String,
- *      dNSName                         [2]     IA5String,
- *      x400Address                     [3]     ORAddress,
- *      directoryName                   [4]     Name,
- *      ediPartyName                    [5]     EDIPartyName,
- *      uniformResourceIdentifier       [6]     IA5String,
- *      iPAddress                       [7]     OCTET STRING,
- *      registeredID                    [8]     OBJECT IDENTIFIER }
- *
- * OtherName ::= SEQUENCE {
- *      type-id    OBJECT IDENTIFIER,
- *      value      [0] EXPLICIT ANY DEFINED BY type-id }
- *
- * EDIPartyName ::= SEQUENCE {
- *      nameAssigner            [0]     DirectoryString OPTIONAL,
- *      partyName               [1]     DirectoryString }
- *
- * We list all types, but use the following GeneralName types from RFC 5280:
- * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
- * of type "otherName", as defined in RFC 4108.
+ * In some cases while parsing subject alternative names the sequence tag is optional
+ * (e.g. CertSerialNumber). This function is designed to handle such case.
  */
-int mbedtls_x509_get_subject_alt_name(unsigned char **p,
-                                      const unsigned char *end,
-                                      mbedtls_x509_sequence *subject_alt_name)
+int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
+                                          const unsigned char *end,
+                                          mbedtls_x509_sequence *subject_alt_name)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
-    size_t len, tag_len;
+    size_t tag_len;
     mbedtls_asn1_sequence *cur = subject_alt_name;
 
-    /* Get main sequence tag */
-    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
-                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
-    }
-
-    if (*p + len != end) {
-        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
-    }
-
     while (*p < end) {
-        mbedtls_x509_subject_alternative_name dummy_san_buf;
+        mbedtls_x509_subject_alternative_name tmp_san_name;
         mbedtls_x509_buf tmp_san_buf;
-        memset(&dummy_san_buf, 0, sizeof(dummy_san_buf));
+        memset(&tmp_san_name, 0, sizeof(tmp_san_name));
 
         tmp_san_buf.tag = **p;
         (*p)++;
@@ -1272,9 +1240,10 @@ int mbedtls_x509_get_subject_alt_name(unsigned char **p,
         }
 
         /*
-         * Check that the SAN is structured correctly.
+         * Check that the SAN is structured correctly by parsing it.
+         * The SAN structure is discarded afterwards.
          */
-        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &dummy_san_buf);
+        ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);
         /*
          * In case the extension is malformed, return an error,
          * and clear the allocated sequences.
@@ -1285,6 +1254,7 @@ int mbedtls_x509_get_subject_alt_name(unsigned char **p,
             return ret;
         }
 
+        mbedtls_x509_free_subject_alt_name(&tmp_san_name);
         /* Allocate and assign next pointer */
         if (cur->buf.p != NULL) {
             if (cur->next != NULL) {
@@ -1316,6 +1286,55 @@ int mbedtls_x509_get_subject_alt_name(unsigned char **p,
     return 0;
 }
 
+/*
+ * SubjectAltName ::= GeneralNames
+ *
+ * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
+ *
+ * GeneralName ::= CHOICE {
+ *      otherName                       [0]     OtherName,
+ *      rfc822Name                      [1]     IA5String,
+ *      dNSName                         [2]     IA5String,
+ *      x400Address                     [3]     ORAddress,
+ *      directoryName                   [4]     Name,
+ *      ediPartyName                    [5]     EDIPartyName,
+ *      uniformResourceIdentifier       [6]     IA5String,
+ *      iPAddress                       [7]     OCTET STRING,
+ *      registeredID                    [8]     OBJECT IDENTIFIER }
+ *
+ * OtherName ::= SEQUENCE {
+ *      type-id    OBJECT IDENTIFIER,
+ *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+ *
+ * EDIPartyName ::= SEQUENCE {
+ *      nameAssigner            [0]     DirectoryString OPTIONAL,
+ *      partyName               [1]     DirectoryString }
+ *
+ * We list all types, but use the following GeneralName types from RFC 5280:
+ * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
+ * of type "otherName", as defined in RFC 4108.
+ */
+int mbedtls_x509_get_subject_alt_name(unsigned char **p,
+                                      const unsigned char *end,
+                                      mbedtls_x509_sequence *subject_alt_name)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len;
+
+    /* Get main sequence tag */
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
+}
+
 int mbedtls_x509_get_ns_cert_type(unsigned char **p,
                                   const unsigned char *end,
                                   unsigned char *ns_cert_type)
@@ -1423,9 +1442,24 @@ int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
                    san_buf, sizeof(*san_buf));
         }
         break;
-
         /*
-         * RFC822 Name
+         * IP address
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):
+        {
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_IP_ADDRESS;
+            // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
+            if (san_buf->len == 4 || san_buf->len == 16) {
+                memcpy(&san->san.unstructured_name,
+                       san_buf, sizeof(*san_buf));
+            } else {
+                return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+            }
+        }
+        break;
+        /*
+         * rfc822Name
          */
         case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
         {
@@ -1434,7 +1468,29 @@ int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
             memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
         }
         break;
+        /*
+         * directoryName
+         */
+        case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):
+        {
+            size_t name_len;
+            unsigned char *p = san_buf->p;
+            memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
+            san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
+
+            ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,
+                                       MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+
+            if (ret != 0) {
+                return ret;
+            }
 
+            if ((ret = mbedtls_x509_get_name(&p, p + name_len,
+                                             &san->san.directory_name)) != 0) {
+                return ret;
+            }
+        }
+        break;
         /*
          * Type not supported
          */
@@ -1444,6 +1500,13 @@ int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
     return 0;
 }
 
+void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)
+{
+    if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
+        mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);
+    }
+}
+
 #if !defined(MBEDTLS_X509_REMOVE_INFO)
 int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                                        const mbedtls_x509_sequence
@@ -1485,7 +1548,7 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                 MBEDTLS_X509_SAFE_SNPRINTF;
 
                 if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
-                                    &other_name->value.hardware_module_name.oid) != 0) {
+                                    &other_name->type_id) == 0) {
                     ret = mbedtls_snprintf(p, n, "\n%s        hardware module name :", prefix);
                     MBEDTLS_X509_SAFE_SNPRINTF;
                     ret =
@@ -1519,7 +1582,9 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                 ret = mbedtls_snprintf(p, n, "\n%s    uniformResourceIdentifier : ", prefix);
                 MBEDTLS_X509_SAFE_SNPRINTF;
                 if (san.san.unstructured_name.len >= n) {
-                    *p = '\0';
+                    if (n > 0) {
+                        *p = '\0';
+                    }
                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
                 }
 
@@ -1545,7 +1610,9 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                                        MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
                 MBEDTLS_X509_SAFE_SNPRINTF;
                 if (san.san.unstructured_name.len >= n) {
-                    *p = '\0';
+                    if (n > 0) {
+                        *p = '\0';
+                    }
                     return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
                 }
 
@@ -1554,7 +1621,66 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                 n -= san.san.unstructured_name.len;
             }
             break;
+            /*
+             * iPAddress
+             */
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+            {
+                ret = mbedtls_snprintf(p, n, "\n%s    %s : ",
+                                       prefix, "iPAddress");
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                if (san.san.unstructured_name.len >= n) {
+                    if (n > 0) {
+                        *p = '\0';
+                    }
+                    return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
+                }
 
+                unsigned char *ip = san.san.unstructured_name.p;
+                // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
+                if (san.san.unstructured_name.len == 4) {
+                    ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+                } else if (san.san.unstructured_name.len == 16) {
+                    ret = mbedtls_snprintf(p, n,
+                                           "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X",
+                                           ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
+                                           ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
+                                           ip[14], ip[15]);
+                    MBEDTLS_X509_SAFE_SNPRINTF;
+                } else {
+                    if (n > 0) {
+                        *p = '\0';
+                    }
+                    return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+                }
+            }
+            break;
+            /*
+             * directoryName
+             */
+            case MBEDTLS_X509_SAN_DIRECTORY_NAME:
+            {
+                ret = mbedtls_snprintf(p, n, "\n%s    directoryName : ", prefix);
+                if (ret < 0 || (size_t) ret >= n) {
+                    mbedtls_x509_free_subject_alt_name(&san);
+                }
+
+                MBEDTLS_X509_SAFE_SNPRINTF;
+                ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);
+
+                if (ret < 0) {
+                    mbedtls_x509_free_subject_alt_name(&san);
+                    if (n > 0) {
+                        *p = '\0';
+                    }
+                    return ret;
+                }
+
+                p += ret;
+                n -= ret;
+            }
+            break;
             /*
              * Type not supported, skip item.
              */
@@ -1564,6 +1690,9 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
                 break;
         }
 
+        /* So far memory is freed only in the case of directoryName
+         * parsing succeeding, as mbedtls_x509_get_name allocates memory. */
+        mbedtls_x509_free_subject_alt_name(&san);
         cur = cur->next;
     }
 
@@ -1575,16 +1704,19 @@ int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
     return 0;
 }
 
-#define PRINT_ITEM(i)                           \
-    {                                           \
-        ret = mbedtls_snprintf(p, n, "%s" i, sep);    \
-        MBEDTLS_X509_SAFE_SNPRINTF;                        \
-        sep = ", ";                             \
-    }
+#define PRINT_ITEM(i)                                   \
+    do {                                                \
+        ret = mbedtls_snprintf(p, n, "%s" i, sep);      \
+        MBEDTLS_X509_SAFE_SNPRINTF;                     \
+        sep = ", ";                                     \
+    } while (0)
 
-#define CERT_TYPE(type, name)                    \
-    if (ns_cert_type & (type))                 \
-    PRINT_ITEM(name);
+#define CERT_TYPE(type, name)                           \
+    do {                                                \
+        if (ns_cert_type & (type)) {                    \
+            PRINT_ITEM(name);                           \
+        }                                               \
+    } while (0)
 
 int mbedtls_x509_info_cert_type(char **buf, size_t *size,
                                 unsigned char ns_cert_type)
@@ -1609,9 +1741,12 @@ int mbedtls_x509_info_cert_type(char **buf, size_t *size,
     return 0;
 }
 
-#define KEY_USAGE(code, name)    \
-    if (key_usage & (code))    \
-    PRINT_ITEM(name);
+#define KEY_USAGE(code, name)       \
+    do {                            \
+        if ((key_usage) & (code)) { \
+            PRINT_ITEM(name);       \
+        }                           \
+    } while (0)
 
 int mbedtls_x509_info_key_usage(char **buf, size_t *size,
                                 unsigned int key_usage)
diff --git a/lib/libmbedtls/mbedtls/library/x509_create.c b/lib/libmbedtls/mbedtls/library/x509_create.c
index 50db95688ff0c18681e959febab3a2f68dfc9590..839b5df226ffb6b4c5ff1278895959f4ece3b74e 100644
--- a/lib/libmbedtls/mbedtls/library/x509_create.c
+++ b/lib/libmbedtls/mbedtls/library/x509_create.c
@@ -2,32 +2,24 @@
  *  X.509 base functions for creating certificates / CSRs
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 
 #include "common.h"
 
 #if defined(MBEDTLS_X509_CREATE_C)
 
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 
 #include <string.h>
 
+#include "mbedtls/platform.h"
+
+#include "mbedtls/asn1.h"
+
 /* Structure linking OIDs for X.509 DN AttributeTypes to their
  * string representations and default string encodings used by Mbed TLS. */
 typedef struct {
@@ -35,7 +27,8 @@ typedef struct {
                        * "CN" or "emailAddress". */
     size_t name_len; /* Length of 'name', without trailing 0 byte. */
     const char *oid; /* String representation of OID of AttributeType,
-                      * as per RFC 5280, Appendix A.1. */
+                      * as per RFC 5280, Appendix A.1. encoded as per
+                      * X.690 */
     int default_tag; /* The default character encoding used for the
                       * given attribute type, e.g.
                       * MBEDTLS_ASN1_UTF8_STRING for UTF-8. */
@@ -123,76 +116,261 @@ static const x509_attr_descriptor_t *x509_attr_descr_from_name(const char *name,
     return cur;
 }
 
+static int hex_to_int(char c)
+{
+    return ('0' <= c && c <= '9') ? (c - '0') :
+           ('a' <= c && c <= 'f') ? (c - 'a' + 10) :
+           ('A' <= c && c <= 'F') ? (c - 'A' + 10) : -1;
+}
+
+static int hexpair_to_int(const char *hexpair)
+{
+    int n1 = hex_to_int(*hexpair);
+    int n2 = hex_to_int(*(hexpair + 1));
+
+    if (n1 != -1 && n2 != -1) {
+        return (n1 << 4) | n2;
+    } else {
+        return -1;
+    }
+}
+
+static int parse_attribute_value_string(const char *s,
+                                        int len,
+                                        unsigned char *data,
+                                        size_t *data_len)
+{
+    const char *c;
+    const char *end = s + len;
+    unsigned char *d = data;
+    int n;
+
+    for (c = s; c < end; c++) {
+        if (*c == '\\') {
+            c++;
+
+            /* Check for valid escaped characters as per RFC 4514 Section 3 */
+            if (c + 1 < end && (n = hexpair_to_int(c)) != -1) {
+                if (n == 0) {
+                    return MBEDTLS_ERR_X509_INVALID_NAME;
+                }
+                *(d++) = n;
+                c++;
+            } else if (c < end && strchr(" ,=+<>#;\"\\", *c)) {
+                *(d++) = *c;
+            } else {
+                return MBEDTLS_ERR_X509_INVALID_NAME;
+            }
+        } else {
+            *(d++) = *c;
+        }
+
+        if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {
+            return MBEDTLS_ERR_X509_INVALID_NAME;
+        }
+    }
+    *data_len = (size_t) (d - data);
+    return 0;
+}
+
+/** Parse a hexstring containing a DER-encoded string.
+ *
+ * \param s         A string of \p len bytes hexadecimal digits.
+ * \param len       Number of bytes to read from \p s.
+ * \param data      Output buffer of size \p data_size.
+ *                  On success, it contains the payload that's DER-encoded
+ *                  in the input (content without the tag and length).
+ *                  If the DER tag is a string tag, the payload is guaranteed
+ *                  not to contain null bytes.
+ * \param data_size Length of the \p data buffer.
+ * \param data_len  On success, the length of the parsed string.
+ *                  It is guaranteed to be less than
+ *                  #MBEDTLS_X509_MAX_DN_NAME_SIZE.
+ * \param tag       The ASN.1 tag that the payload in \p data is encoded in.
+ *
+ * \retval          0 on success.
+ * \retval          #MBEDTLS_ERR_X509_INVALID_NAME if \p s does not contain
+ *                  a valid hexstring,
+ *                  or if the decoded hexstring is not valid DER,
+ *                  or if the payload does not fit in \p data,
+ *                  or if the payload is more than
+ *                  #MBEDTLS_X509_MAX_DN_NAME_SIZE bytes,
+ *                  of if \p *tag is an ASN.1 string tag and the payload
+ *                  contains a null byte.
+ * \retval          #MBEDTLS_ERR_X509_ALLOC_FAILED on low memory.
+ */
+static int parse_attribute_value_hex_der_encoded(const char *s,
+                                                 size_t len,
+                                                 unsigned char *data,
+                                                 size_t data_size,
+                                                 size_t *data_len,
+                                                 int *tag)
+{
+    /* Step 1: preliminary length checks. */
+    /* Each byte is encoded by exactly two hexadecimal digits. */
+    if (len % 2 != 0) {
+        /* Odd number of hex digits */
+        return MBEDTLS_ERR_X509_INVALID_NAME;
+    }
+    size_t const der_length = len / 2;
+    if (der_length > MBEDTLS_X509_MAX_DN_NAME_SIZE + 4) {
+        /* The payload would be more than MBEDTLS_X509_MAX_DN_NAME_SIZE
+         * (after subtracting the ASN.1 tag and length). Reject this early
+         * to avoid allocating a large intermediate buffer. */
+        return MBEDTLS_ERR_X509_INVALID_NAME;
+    }
+    if (der_length < 1) {
+        /* Avoid empty-buffer shenanigans. A valid DER encoding is never
+         * empty. */
+        return MBEDTLS_ERR_X509_INVALID_NAME;
+    }
+
+    /* Step 2: Decode the hex string into an intermediate buffer. */
+    unsigned char *der = mbedtls_calloc(1, der_length);
+    if (der == NULL) {
+        return MBEDTLS_ERR_X509_ALLOC_FAILED;
+    }
+    /* Beyond this point, der needs to be freed on exit. */
+    for (size_t i = 0; i < der_length; i++) {
+        int c = hexpair_to_int(s + 2 * i);
+        if (c < 0) {
+            goto error;
+        }
+        der[i] = c;
+    }
+
+    /* Step 3: decode the DER. */
+    /* We've checked that der_length >= 1 above. */
+    *tag = der[0];
+    {
+        unsigned char *p = der + 1;
+        if (mbedtls_asn1_get_len(&p, der + der_length, data_len) != 0) {
+            goto error;
+        }
+        /* Now p points to the first byte of the payload inside der,
+         * and *data_len is the length of the payload. */
+
+        /* Step 4: payload validation */
+        if (*data_len > MBEDTLS_X509_MAX_DN_NAME_SIZE) {
+            goto error;
+        }
+        /* Strings must not contain null bytes. */
+        if (MBEDTLS_ASN1_IS_STRING_TAG(*tag)) {
+            for (size_t i = 0; i < *data_len; i++) {
+                if (p[i] == 0) {
+                    goto error;
+                }
+            }
+        }
+
+        /* Step 5: output the payload. */
+        if (*data_len > data_size) {
+            goto error;
+        }
+        memcpy(data, p, *data_len);
+    }
+    mbedtls_free(der);
+
+    return 0;
+
+error:
+    mbedtls_free(der);
+    return MBEDTLS_ERR_X509_INVALID_NAME;
+}
+
 int mbedtls_x509_string_to_names(mbedtls_asn1_named_data **head, const char *name)
 {
-    int ret = 0;
+    int ret = MBEDTLS_ERR_X509_INVALID_NAME;
+    int parse_ret = 0;
     const char *s = name, *c = s;
     const char *end = s + strlen(s);
-    const char *oid = NULL;
+    mbedtls_asn1_buf oid = { .p = NULL, .len = 0, .tag = MBEDTLS_ASN1_NULL };
     const x509_attr_descriptor_t *attr_descr = NULL;
-    int in_tag = 1;
-    char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
-    char *d = data;
+    int in_attr_type = 1;
+    int tag;
+    int numericoid = 0;
+    unsigned char data[MBEDTLS_X509_MAX_DN_NAME_SIZE];
+    size_t data_len = 0;
 
     /* Clear existing chain if present */
     mbedtls_asn1_free_named_data_list(head);
 
     while (c <= end) {
-        if (in_tag && *c == '=') {
-            if ((attr_descr = x509_attr_descr_from_name(s, c - s)) == NULL) {
-                ret = MBEDTLS_ERR_X509_UNKNOWN_OID;
-                goto exit;
+        if (in_attr_type && *c == '=') {
+            if ((attr_descr = x509_attr_descr_from_name(s, (size_t) (c - s))) == NULL) {
+                if ((mbedtls_oid_from_numeric_string(&oid, s, (size_t) (c - s))) != 0) {
+                    return MBEDTLS_ERR_X509_INVALID_NAME;
+                } else {
+                    numericoid = 1;
+                }
+            } else {
+                oid.len = strlen(attr_descr->oid);
+                oid.p = mbedtls_calloc(1, oid.len);
+                memcpy(oid.p, attr_descr->oid, oid.len);
+                numericoid = 0;
             }
 
-            oid = attr_descr->oid;
             s = c + 1;
-            in_tag = 0;
-            d = data;
+            in_attr_type = 0;
         }
 
-        if (!in_tag && *c == '\\' && c != end) {
-            c++;
-
-            /* Check for valid escaped characters */
-            if (c == end || *c != ',') {
-                ret = MBEDTLS_ERR_X509_INVALID_NAME;
-                goto exit;
+        if (!in_attr_type && ((*c == ',' && *(c-1) != '\\') || c == end)) {
+            if (s == c) {
+                mbedtls_free(oid.p);
+                return MBEDTLS_ERR_X509_INVALID_NAME;
+            } else if (*s == '#') {
+                /* We know that c >= s (loop invariant) and c != s (in this
+                 * else branch), hence c - s - 1 >= 0. */
+                parse_ret = parse_attribute_value_hex_der_encoded(
+                    s + 1, (size_t) (c - s) - 1,
+                    data, sizeof(data), &data_len, &tag);
+                if (parse_ret != 0) {
+                    mbedtls_free(oid.p);
+                    return parse_ret;
+                }
+            } else {
+                if (numericoid) {
+                    mbedtls_free(oid.p);
+                    return MBEDTLS_ERR_X509_INVALID_NAME;
+                } else {
+                    if ((parse_ret =
+                             parse_attribute_value_string(s, (int) (c - s), data,
+                                                          &data_len)) != 0) {
+                        mbedtls_free(oid.p);
+                        return parse_ret;
+                    }
+                    tag = attr_descr->default_tag;
+                }
             }
-        } else if (!in_tag && (*c == ',' || c == end)) {
+
             mbedtls_asn1_named_data *cur =
-                mbedtls_asn1_store_named_data(head, oid, strlen(oid),
+                mbedtls_asn1_store_named_data(head, (char *) oid.p, oid.len,
                                               (unsigned char *) data,
-                                              d - data);
-
+                                              data_len);
+            mbedtls_free(oid.p);
+            oid.p = NULL;
             if (cur == NULL) {
                 return MBEDTLS_ERR_X509_ALLOC_FAILED;
             }
 
             // set tagType
-            cur->val.tag = attr_descr->default_tag;
+            cur->val.tag = tag;
 
             while (c < end && *(c + 1) == ' ') {
                 c++;
             }
 
             s = c + 1;
-            in_tag = 1;
-        }
-
-        if (!in_tag && s != c + 1) {
-            *(d++) = *c;
+            in_attr_type = 1;
 
-            if (d - data == MBEDTLS_X509_MAX_DN_NAME_SIZE) {
-                ret = MBEDTLS_ERR_X509_INVALID_NAME;
-                goto exit;
-            }
+            /* Successfully parsed one name, update ret to success */
+            ret = 0;
         }
-
         c++;
     }
-
-exit:
-
+    if (oid.p != NULL) {
+        mbedtls_free(oid.p);
+    }
     return ret;
 }
 
@@ -204,6 +382,10 @@ int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid,
 {
     mbedtls_asn1_named_data *cur;
 
+    if (val_len > (SIZE_MAX  - 1)) {
+        return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+    }
+
     if ((cur = mbedtls_asn1_store_named_data(head, oid, oid_len,
                                              NULL, val_len + 1)) == NULL) {
         return MBEDTLS_ERR_X509_ALLOC_FAILED;
@@ -282,9 +464,11 @@ int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
 
 int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
                            const char *oid, size_t oid_len,
-                           unsigned char *sig, size_t size)
+                           unsigned char *sig, size_t size,
+                           mbedtls_pk_type_t pk_alg)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    int write_null_par;
     size_t len = 0;
 
     if (*p < start || (size_t) (*p - start) < size) {
@@ -307,8 +491,19 @@ int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
 
     // Write OID
     //
-    MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_algorithm_identifier(p, start, oid,
-                                                                      oid_len, 0));
+    if (pk_alg == MBEDTLS_PK_ECDSA) {
+        /*
+         * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature
+         * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and
+         * https://www.rfc-editor.org/rfc/rfc5758#section-3.
+         */
+        write_null_par = 0;
+    } else {
+        write_null_par = 1;
+    }
+    MBEDTLS_ASN1_CHK_ADD(len,
+                         mbedtls_asn1_write_algorithm_identifier_ext(p, start, oid, oid_len,
+                                                                     0, write_null_par));
 
     return (int) len;
 }
diff --git a/lib/libmbedtls/mbedtls/library/x509_crl.c b/lib/libmbedtls/mbedtls/library/x509_crl.c
index f6442030d16ef1bd083df59fede08af5ba8e3cda..7901992e20d8dd9eb86cd8dc89cbb9839ff9f498 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crl.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crl.c
@@ -2,19 +2,7 @@
  *  X.509 Certificate Revocation List (CRL) parsing
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
@@ -32,6 +20,7 @@
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
 
 #include "mbedtls/x509_crl.h"
+#include "x509_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
@@ -379,7 +368,7 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,
     }
 
     end = p + len;
-    crl->tbs.len = end - crl->tbs.p;
+    crl->tbs.len = (size_t) (end - crl->tbs.p);
 
     /*
      * Version  ::=  INTEGER  OPTIONAL {  v1(0), v2(1)  }
@@ -423,7 +412,7 @@ int mbedtls_x509_crl_parse_der(mbedtls_x509_crl *chain,
         return ret;
     }
 
-    crl->issuer_raw.len = p - crl->issuer_raw.p;
+    crl->issuer_raw.len = (size_t) (p - crl->issuer_raw.p);
 
     /*
      * thisUpdate          Time
@@ -587,8 +576,7 @@ int mbedtls_x509_crl_parse_file(mbedtls_x509_crl *chain, const char *path)
 
     ret = mbedtls_x509_crl_parse(chain, buf, n);
 
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
+    mbedtls_zeroize_and_free(buf, n);
 
     return ret;
 }
@@ -704,14 +692,12 @@ void mbedtls_x509_crl_free(mbedtls_x509_crl *crl)
         while (entry_cur != NULL) {
             entry_prv = entry_cur;
             entry_cur = entry_cur->next;
-            mbedtls_platform_zeroize(entry_prv,
+            mbedtls_zeroize_and_free(entry_prv,
                                      sizeof(mbedtls_x509_crl_entry));
-            mbedtls_free(entry_prv);
         }
 
         if (crl_cur->raw.p != NULL) {
-            mbedtls_platform_zeroize(crl_cur->raw.p, crl_cur->raw.len);
-            mbedtls_free(crl_cur->raw.p);
+            mbedtls_zeroize_and_free(crl_cur->raw.p, crl_cur->raw.len);
         }
 
         crl_prv = crl_cur;
diff --git a/lib/libmbedtls/mbedtls/library/x509_crt.c b/lib/libmbedtls/mbedtls/library/x509_crt.c
index cf62532f28b5373f2af57fb9120e2c8e974e514f..53cdcf026629987675920519d27add7a8e20795d 100644
--- a/lib/libmbedtls/mbedtls/library/x509_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509_crt.c
@@ -2,19 +2,7 @@
  *  X.509 certificate parsing and verification
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
@@ -34,6 +22,7 @@
 #if defined(MBEDTLS_X509_CRT_PARSE_C)
 
 #include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
@@ -46,9 +35,10 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
+#include "psa_util_internal.h"
 #include "mbedtls/psa_util.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-#include "hash_info.h"
+#include "pk_internal.h"
 
 #include "mbedtls/platform.h"
 
@@ -58,6 +48,9 @@
 
 #if defined(MBEDTLS_HAVE_TIME)
 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
 #include <windows.h>
 #else
 #include <time.h>
@@ -101,7 +94,7 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
     MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
     MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
     0xFFFFFFF, /* Any PK alg    */
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     /* Curves at or above 128-bit security level. Note that this selection
      * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
@@ -111,9 +104,9 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default =
     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP384R1) |
     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_BP512R1) |
     0,
-#else
+#else /* MBEDTLS_PK_HAVE_ECC_KEYS */
     0,
-#endif
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     2048,
 };
 
@@ -152,13 +145,13 @@ const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb =
     /* Only ECDSA */
     MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA) |
     MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECKEY),
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     /* Only NIST P-256 and P-384 */
     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP256R1) |
     MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_SECP384R1),
-#else
+#else /* MBEDTLS_PK_HAVE_ECC_KEYS */
     0,
-#endif
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
     0,
 };
 
@@ -226,13 +219,13 @@ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile,
 
         return -1;
     }
-#endif
+#endif /* MBEDTLS_RSA_C */
 
-#if defined(MBEDTLS_ECP_C)
+#if defined(MBEDTLS_PK_HAVE_ECC_KEYS)
     if (pk_alg == MBEDTLS_PK_ECDSA ||
         pk_alg == MBEDTLS_PK_ECKEY ||
         pk_alg == MBEDTLS_PK_ECKEY_DH) {
-        const mbedtls_ecp_group_id gid = mbedtls_pk_ec(*pk)->grp.id;
+        const mbedtls_ecp_group_id gid = mbedtls_pk_get_ec_group_id(pk);
 
         if (gid == MBEDTLS_ECP_DP_NONE) {
             return -1;
@@ -244,7 +237,7 @@ static int x509_profile_check_key(const mbedtls_x509_crt_profile *profile,
 
         return -1;
     }
-#endif
+#endif /* MBEDTLS_PK_HAVE_ECC_KEYS */
 
     return -1;
 }
@@ -586,6 +579,114 @@ static int x509_get_ext_key_usage(unsigned char **p,
     return 0;
 }
 
+/*
+ * SubjectKeyIdentifier ::= KeyIdentifier
+ *
+ * KeyIdentifier ::= OCTET STRING
+ */
+static int x509_get_subject_key_id(unsigned char **p,
+                                   const unsigned char *end,
+                                   mbedtls_x509_buf *subject_key_id)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0u;
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_OCTET_STRING)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    subject_key_id->len = len;
+    subject_key_id->tag = MBEDTLS_ASN1_OCTET_STRING;
+    subject_key_id->p = *p;
+    *p += len;
+
+    if (*p != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    return 0;
+}
+
+/*
+ * AuthorityKeyIdentifier ::= SEQUENCE {
+ *        keyIdentifier [0] KeyIdentifier OPTIONAL,
+ *        authorityCertIssuer [1] GeneralNames OPTIONAL,
+ *        authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL }
+ *
+ *    KeyIdentifier ::= OCTET STRING
+ */
+static int x509_get_authority_key_id(unsigned char **p,
+                                     unsigned char *end,
+                                     mbedtls_x509_authority *authority_key_id)
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t len = 0u;
+
+    if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (*p + len != end) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
+    }
+
+    ret = mbedtls_asn1_get_tag(p, end, &len,
+                               MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+
+    /* KeyIdentifier is an OPTIONAL field */
+    if (ret == 0) {
+        authority_key_id->keyIdentifier.len = len;
+        authority_key_id->keyIdentifier.p = *p;
+        /* Setting tag of the keyIdentfier intentionally to 0x04.
+         * Although the .keyIdentfier field is CONTEXT_SPECIFIC ([0] OPTIONAL),
+         * its tag with the content is the payload of on OCTET STRING primitive */
+        authority_key_id->keyIdentifier.tag = MBEDTLS_ASN1_OCTET_STRING;
+
+        *p += len;
+    } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
+        return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+    }
+
+    if (*p < end) {
+        /* Getting authorityCertIssuer using the required specific class tag [1] */
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
+                                        1)) != 0) {
+            /* authorityCertIssuer and authorityCertSerialNumber MUST both
+               be present or both be absent. At this point we expect to have both. */
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+        /* "end" also includes the CertSerialNumber field so "len" shall be used */
+        ret = mbedtls_x509_get_subject_alt_name_ext(p,
+                                                    (*p+len),
+                                                    &authority_key_id->authorityCertIssuer);
+        if (ret != 0) {
+            return ret;
+        }
+
+        /* Getting authorityCertSerialNumber using the required specific class tag [2] */
+        if ((ret = mbedtls_asn1_get_tag(p, end, &len,
+                                        MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2)) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+        authority_key_id->authorityCertSerialNumber.len = len;
+        authority_key_id->authorityCertSerialNumber.p = *p;
+        authority_key_id->authorityCertSerialNumber.tag = MBEDTLS_ASN1_INTEGER;
+        *p += len;
+    }
+
+    if (*p != end) {
+        return MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
+               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+
+    return 0;
+}
+
 /*
  * id-ce-certificatePolicies OBJECT IDENTIFIER ::=  { id-ce 32 }
  *
@@ -884,8 +985,25 @@ static int x509_get_crt_ext(unsigned char **p,
                 }
                 break;
 
+            case MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER:
+                /* Parse subject key identifier */
+                if ((ret = x509_get_subject_key_id(p, end_ext_data,
+                                                   &crt->subject_key_id)) != 0) {
+                    return ret;
+                }
+                break;
+
+            case MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER:
+                /* Parse authority key identifier */
+                if ((ret = x509_get_authority_key_id(p, end_ext_octet,
+                                                     &crt->authority_key_id)) != 0) {
+                    return ret;
+                }
+                break;
             case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
-                /* Parse subject alt name */
+                /* Parse subject alt name
+                 * SubjectAltName ::= GeneralNames
+                 */
                 if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_octet,
                                                              &crt->subject_alt_names)) != 0) {
                     return ret;
@@ -993,7 +1111,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
     }
 
     end = crt_end = p + len;
-    crt->raw.len = crt_end - buf;
+    crt->raw.len = (size_t) (crt_end - buf);
     if (make_copy != 0) {
         /* Create and populate a new buffer for the raw field. */
         crt->raw.p = p = mbedtls_calloc(1, crt->raw.len);
@@ -1023,7 +1141,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
     }
 
     end = p + len;
-    crt->tbs.len = end - crt->tbs.p;
+    crt->tbs.len = (size_t) (end - crt->tbs.p);
 
     /*
      * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
@@ -1070,7 +1188,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
         return ret;
     }
 
-    crt->issuer_raw.len = p - crt->issuer_raw.p;
+    crt->issuer_raw.len = (size_t) (p - crt->issuer_raw.p);
 
     /*
      * Validity ::= SEQUENCE {
@@ -1100,7 +1218,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
         return ret;
     }
 
-    crt->subject_raw.len = p - crt->subject_raw.p;
+    crt->subject_raw.len = (size_t) (p - crt->subject_raw.p);
 
     /*
      * SubjectPublicKeyInfo
@@ -1110,7 +1228,7 @@ static int x509_crt_parse_der_core(mbedtls_x509_crt *crt,
         mbedtls_x509_crt_free(crt);
         return ret;
     }
-    crt->pk_raw.len = p - crt->pk_raw.p;
+    crt->pk_raw.len = (size_t) (p - crt->pk_raw.p);
 
     /*
      *  issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
@@ -1399,8 +1517,7 @@ int mbedtls_x509_crt_parse_file(mbedtls_x509_crt *chain, const char *path)
 
     ret = mbedtls_x509_crt_parse(chain, buf, n);
 
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
+    mbedtls_zeroize_and_free(buf, n);
 
     return ret;
 }
@@ -1429,6 +1546,11 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path)
     p = filename + len;
     filename[len++] = '*';
 
+    /*
+     * Note this function uses the code page CP_ACP which is the system default
+     * ANSI codepage. The input string is always described in BYTES and the
+     * output length is described in WCHARs.
+     */
     w_ret = MultiByteToWideChar(CP_ACP, 0, filename, (int) len, szDir,
                                 MAX_PATH - 3);
     if (w_ret == 0) {
@@ -1447,11 +1569,8 @@ int mbedtls_x509_crt_parse_path(mbedtls_x509_crt *chain, const char *path)
         if (file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
             continue;
         }
-
         w_ret = WideCharToMultiByte(CP_ACP, 0, file_data.cFileName,
-                                    -1,
-                                    p, (int) len,
-                                    NULL, NULL);
+                                    -1, p, (int) len, NULL, NULL);
         if (w_ret == 0) {
             ret = MBEDTLS_ERR_X509_FILE_IO_ERROR;
             goto cleanup;
@@ -1545,6 +1664,27 @@ cleanup:
 #endif /* MBEDTLS_FS_IO */
 
 #if !defined(MBEDTLS_X509_REMOVE_INFO)
+#define PRINT_ITEM(i)                               \
+    do {                                            \
+        ret = mbedtls_snprintf(p, n, "%s" i, sep);  \
+        MBEDTLS_X509_SAFE_SNPRINTF;                 \
+        sep = ", ";                                 \
+    } while (0)
+
+#define CERT_TYPE(type, name)          \
+    do {                               \
+        if (ns_cert_type & (type)) {   \
+            PRINT_ITEM(name);          \
+        }                              \
+    } while (0)
+
+#define KEY_USAGE(code, name)      \
+    do {                           \
+        if (key_usage & (code)) {  \
+            PRINT_ITEM(name);      \
+        }                          \
+    } while (0)
+
 static int x509_info_ext_key_usage(char **buf, size_t *size,
                                    const mbedtls_x509_sequence *extended_key_usage)
 {
@@ -1869,10 +2009,11 @@ int mbedtls_x509_crt_is_revoked(const mbedtls_x509_crt *crt, const mbedtls_x509_
  */
 static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
                               mbedtls_x509_crl *crl_list,
-                              const mbedtls_x509_crt_profile *profile)
+                              const mbedtls_x509_crt_profile *profile,
+                              const mbedtls_x509_time *now)
 {
     int flags = 0;
-    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_algorithm_t psa_algorithm;
 #else
@@ -1912,7 +2053,7 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
         }
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-        psa_algorithm = mbedtls_hash_info_psa_from_md(crl_list->sig_md);
+        psa_algorithm = mbedtls_md_psa_alg_from_type(crl_list->sig_md);
         if (psa_hash_compute(psa_algorithm,
                              crl_list->tbs.p,
                              crl_list->tbs.len,
@@ -1947,16 +2088,20 @@ static int x509_crt_verifycrl(mbedtls_x509_crt *crt, mbedtls_x509_crt *ca,
             break;
         }
 
+#if defined(MBEDTLS_HAVE_TIME_DATE)
         /*
          * Check for validity of CRL (Do not drop out)
          */
-        if (mbedtls_x509_time_is_past(&crl_list->next_update)) {
+        if (mbedtls_x509_time_cmp(&crl_list->next_update, now) < 0) {
             flags |= MBEDTLS_X509_BADCRL_EXPIRED;
         }
 
-        if (mbedtls_x509_time_is_future(&crl_list->this_update)) {
+        if (mbedtls_x509_time_cmp(&crl_list->this_update, now) > 0) {
             flags |= MBEDTLS_X509_BADCRL_FUTURE;
         }
+#else
+        ((void) now);
+#endif
 
         /*
          * Check if certificate is revoked
@@ -1981,7 +2126,7 @@ static int x509_crt_check_signature(const mbedtls_x509_crt *child,
                                     mbedtls_x509_crt_restart_ctx *rs_ctx)
 {
     size_t hash_len;
-    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 #if !defined(MBEDTLS_USE_PSA_CRYPTO)
     const mbedtls_md_info_t *md_info;
     md_info = mbedtls_md_info_from_type(child->sig_md);
@@ -1992,7 +2137,7 @@ static int x509_crt_check_signature(const mbedtls_x509_crt *child,
         return -1;
     }
 #else
-    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(child->sig_md);
+    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(child->sig_md);
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
 
     status = psa_hash_compute(hash_alg,
@@ -2114,7 +2259,8 @@ static int x509_crt_find_parent_in(
     int top,
     unsigned path_cnt,
     unsigned self_cnt,
-    mbedtls_x509_crt_restart_ctx *rs_ctx)
+    mbedtls_x509_crt_restart_ctx *rs_ctx,
+    const mbedtls_x509_time *now)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *parent, *fallback_parent;
@@ -2177,9 +2323,10 @@ check_signature:
             continue;
         }
 
+#if defined(MBEDTLS_HAVE_TIME_DATE)
         /* optional time check */
-        if (mbedtls_x509_time_is_past(&parent->valid_to) ||
-            mbedtls_x509_time_is_future(&parent->valid_from)) {
+        if (mbedtls_x509_time_cmp(&parent->valid_to, now) < 0 ||    /* past */
+            mbedtls_x509_time_cmp(&parent->valid_from, now) > 0) {  /* future */
             if (fallback_parent == NULL) {
                 fallback_parent = parent;
                 fallback_signature_is_good = signature_is_good;
@@ -2187,6 +2334,9 @@ check_signature:
 
             continue;
         }
+#else
+        ((void) now);
+#endif
 
         *r_parent = parent;
         *r_signature_is_good = signature_is_good;
@@ -2232,7 +2382,8 @@ static int x509_crt_find_parent(
     int *signature_is_good,
     unsigned path_cnt,
     unsigned self_cnt,
-    mbedtls_x509_crt_restart_ctx *rs_ctx)
+    mbedtls_x509_crt_restart_ctx *rs_ctx,
+    const mbedtls_x509_time *now)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     mbedtls_x509_crt *search_list;
@@ -2253,7 +2404,7 @@ static int x509_crt_find_parent(
         ret = x509_crt_find_parent_in(child, search_list,
                                       parent, signature_is_good,
                                       *parent_is_trusted,
-                                      path_cnt, self_cnt, rs_ctx);
+                                      path_cnt, self_cnt, rs_ctx, now);
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
         if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
@@ -2374,6 +2525,13 @@ static int x509_crt_verify_chain(
     int signature_is_good;
     unsigned self_cnt;
     mbedtls_x509_crt *cur_trust_ca = NULL;
+    mbedtls_x509_time now;
+
+#if defined(MBEDTLS_HAVE_TIME_DATE)
+    if (mbedtls_x509_time_gmtime(mbedtls_time(NULL), &now) != 0) {
+        return MBEDTLS_ERR_X509_FATAL_ERROR;
+    }
+#endif
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
     /* resume if we had an operation in progress */
@@ -2404,14 +2562,16 @@ static int x509_crt_verify_chain(
         ver_chain->len++;
         flags = &cur->flags;
 
+#if defined(MBEDTLS_HAVE_TIME_DATE)
         /* Check time-validity (all certificates) */
-        if (mbedtls_x509_time_is_past(&child->valid_to)) {
+        if (mbedtls_x509_time_cmp(&child->valid_to, &now) < 0) {
             *flags |= MBEDTLS_X509_BADCERT_EXPIRED;
         }
 
-        if (mbedtls_x509_time_is_future(&child->valid_from)) {
+        if (mbedtls_x509_time_cmp(&child->valid_from, &now) > 0) {
             *flags |= MBEDTLS_X509_BADCERT_FUTURE;
         }
+#endif
 
         /* Stop here for trusted roots (but not for trusted EE certs) */
         if (child_is_trusted) {
@@ -2462,7 +2622,8 @@ find_parent:
         /* Look for a parent in trusted CAs or up the chain */
         ret = x509_crt_find_parent(child, cur_trust_ca, &parent,
                                    &parent_is_trusted, &signature_is_good,
-                                   ver_chain->len - 1, self_cnt, rs_ctx);
+                                   ver_chain->len - 1, self_cnt, rs_ctx,
+                                   &now);
 
 #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
         if (rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS) {
@@ -2511,7 +2672,7 @@ find_parent:
 
 #if defined(MBEDTLS_X509_CRL_PARSE_C)
         /* Check trusted CA's CRL for the given crt */
-        *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile);
+        *flags |= x509_crt_verifycrl(child, parent, ca_crl, profile, &now);
 #else
         (void) ca_crl;
 #endif
@@ -2524,6 +2685,202 @@ find_parent:
     }
 }
 
+#ifdef _WIN32
+#ifdef _MSC_VER
+#pragma comment(lib, "ws2_32.lib")
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#elif (defined(__MINGW32__) || defined(__MINGW64__)) && _WIN32_WINNT >= 0x0600
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+/* inet_pton() is not supported, fallback to software version */
+#define MBEDTLS_TEST_SW_INET_PTON
+#endif
+#elif defined(__sun)
+/* Solaris requires -lsocket -lnsl for inet_pton() */
+#elif defined(__has_include)
+#if __has_include(<sys/socket.h>)
+#include <sys/socket.h>
+#endif
+#if __has_include(<arpa/inet.h>)
+#include <arpa/inet.h>
+#endif
+#endif
+
+/* Use whether or not AF_INET6 is defined to indicate whether or not to use
+ * the platform inet_pton() or a local implementation (below).  The local
+ * implementation may be used even in cases where the platform provides
+ * inet_pton(), e.g. when there are different includes required and/or the
+ * platform implementation requires dependencies on additional libraries.
+ * Specifically, Windows requires custom includes and additional link
+ * dependencies, and Solaris requires additional link dependencies.
+ * Also, as a coarse heuristic, use the local implementation if the compiler
+ * does not support __has_include(), or if the definition of AF_INET6 is not
+ * provided by headers included (or not) via __has_include() above.
+ * MBEDTLS_TEST_SW_INET_PTON is a bypass define to force testing of this code //no-check-names
+ * despite having a platform that has inet_pton. */
+#if !defined(AF_INET6) || defined(MBEDTLS_TEST_SW_INET_PTON) //no-check-names
+/* Definition located further below to possibly reduce compiler inlining */
+static int x509_inet_pton_ipv4(const char *src, void *dst);
+
+#define li_cton(c, n) \
+    (((n) = (c) - '0') <= 9 || (((n) = ((c)&0xdf) - 'A') <= 5 ? ((n) += 10) : 0))
+
+static int x509_inet_pton_ipv6(const char *src, void *dst)
+{
+    const unsigned char *p = (const unsigned char *) src;
+    int nonzero_groups = 0, num_digits, zero_group_start = -1;
+    uint16_t addr[8];
+    do {
+        /* note: allows excess leading 0's, e.g. 1:0002:3:... */
+        uint16_t group = num_digits = 0;
+        for (uint8_t digit; num_digits < 4; num_digits++) {
+            if (li_cton(*p, digit) == 0) {
+                break;
+            }
+            group = (group << 4) | digit;
+            p++;
+        }
+        if (num_digits != 0) {
+            MBEDTLS_PUT_UINT16_BE(group, addr, nonzero_groups);
+            nonzero_groups++;
+            if (*p == '\0') {
+                break;
+            } else if (*p == '.') {
+                /* Don't accept IPv4 too early or late */
+                if ((nonzero_groups == 0 && zero_group_start == -1) ||
+                    nonzero_groups >= 7) {
+                    break;
+                }
+
+                /* Walk back to prior ':', then parse as IPv4-mapped */
+                int steps = 4;
+                do {
+                    p--;
+                    steps--;
+                } while (*p != ':' && steps > 0);
+
+                if (*p != ':') {
+                    break;
+                }
+                p++;
+                nonzero_groups--;
+                if (x509_inet_pton_ipv4((const char *) p,
+                                        addr + nonzero_groups) != 0) {
+                    break;
+                }
+
+                nonzero_groups += 2;
+                p = (const unsigned char *) "";
+                break;
+            } else if (*p != ':') {
+                return -1;
+            }
+        } else {
+            /* Don't accept a second zero group or an invalid delimiter */
+            if (zero_group_start != -1 || *p != ':') {
+                return -1;
+            }
+            zero_group_start = nonzero_groups;
+
+            /* Accept a zero group at start, but it has to be a double colon */
+            if (zero_group_start == 0 && *++p != ':') {
+                return -1;
+            }
+
+            if (p[1] == '\0') {
+                ++p;
+                break;
+            }
+        }
+        ++p;
+    } while (nonzero_groups < 8);
+
+    if (*p != '\0') {
+        return -1;
+    }
+
+    if (zero_group_start != -1) {
+        if (nonzero_groups > 6) {
+            return -1;
+        }
+        int zero_groups = 8 - nonzero_groups;
+        int groups_after_zero = nonzero_groups - zero_group_start;
+
+        /* Move the non-zero part to after the zeroes */
+        if (groups_after_zero) {
+            memmove(addr + zero_group_start + zero_groups,
+                    addr + zero_group_start,
+                    groups_after_zero * sizeof(*addr));
+        }
+        memset(addr + zero_group_start, 0, zero_groups * sizeof(*addr));
+    } else {
+        if (nonzero_groups != 8) {
+            return -1;
+        }
+    }
+    memcpy(dst, addr, sizeof(addr));
+    return 0;
+}
+
+static int x509_inet_pton_ipv4(const char *src, void *dst)
+{
+    const unsigned char *p = (const unsigned char *) src;
+    uint8_t *res = (uint8_t *) dst;
+    uint8_t digit, num_digits = 0;
+    uint8_t num_octets = 0;
+    uint16_t octet;
+
+    do {
+        octet = num_digits = 0;
+        do {
+            digit = *p - '0';
+            if (digit > 9) {
+                break;
+            }
+
+            /* Don't allow leading zeroes. These might mean octal format,
+             * which this implementation does not support. */
+            if (octet == 0 && num_digits > 0) {
+                return -1;
+            }
+
+            octet = octet * 10 + digit;
+            num_digits++;
+            p++;
+        } while (num_digits < 3);
+
+        if (octet >= 256 || num_digits > 3 || num_digits == 0) {
+            return -1;
+        }
+        *res++ = (uint8_t) octet;
+        num_octets++;
+    } while (num_octets < 4 && *p++ == '.');
+    return num_octets == 4 && *p == '\0' ? 0 : -1;
+}
+
+#else
+
+static int x509_inet_pton_ipv6(const char *src, void *dst)
+{
+    return inet_pton(AF_INET6, src, dst) == 1 ? 0 : -1;
+}
+
+static int x509_inet_pton_ipv4(const char *src, void *dst)
+{
+    return inet_pton(AF_INET, src, dst) == 1 ? 0 : -1;
+}
+
+#endif /* !AF_INET6 || MBEDTLS_TEST_SW_INET_PTON */ //no-check-names
+
+size_t mbedtls_x509_crt_parse_cn_inet_pton(const char *cn, void *dst)
+{
+    return strchr(cn, ':') == NULL
+            ? x509_inet_pton_ipv4(cn, dst) == 0 ? 4 : 0
+            : x509_inet_pton_ipv6(cn, dst) == 0 ? 16 : 0;
+}
+
 /*
  * Check for CN match
  */
@@ -2544,23 +2901,80 @@ static int x509_crt_check_cn(const mbedtls_x509_buf *name,
     return -1;
 }
 
+static int x509_crt_check_san_ip(const mbedtls_x509_sequence *san,
+                                 const char *cn, size_t cn_len)
+{
+    uint32_t ip[4];
+    cn_len = mbedtls_x509_crt_parse_cn_inet_pton(cn, ip);
+    if (cn_len == 0) {
+        return -1;
+    }
+
+    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
+        const unsigned char san_type = (unsigned char) cur->buf.tag &
+                                       MBEDTLS_ASN1_TAG_VALUE_MASK;
+        if (san_type == MBEDTLS_X509_SAN_IP_ADDRESS &&
+            cur->buf.len == cn_len && memcmp(cur->buf.p, ip, cn_len) == 0) {
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+static int x509_crt_check_san_uri(const mbedtls_x509_sequence *san,
+                                  const char *cn, size_t cn_len)
+{
+    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
+        const unsigned char san_type = (unsigned char) cur->buf.tag &
+                                       MBEDTLS_ASN1_TAG_VALUE_MASK;
+        if (san_type == MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER &&
+            cur->buf.len == cn_len && memcmp(cur->buf.p, cn, cn_len) == 0) {
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
 /*
  * Check for SAN match, see RFC 5280 Section 4.2.1.6
  */
-static int x509_crt_check_san(const mbedtls_x509_buf *name,
+static int x509_crt_check_san(const mbedtls_x509_sequence *san,
                               const char *cn, size_t cn_len)
 {
-    const unsigned char san_type = (unsigned char) name->tag &
-                                   MBEDTLS_ASN1_TAG_VALUE_MASK;
-
-    /* dNSName */
-    if (san_type == MBEDTLS_X509_SAN_DNS_NAME) {
-        return x509_crt_check_cn(name, cn, cn_len);
+    int san_ip = 0;
+    int san_uri = 0;
+    /* Prioritize DNS name over other subtypes due to popularity */
+    for (const mbedtls_x509_sequence *cur = san; cur != NULL; cur = cur->next) {
+        switch ((unsigned char) cur->buf.tag & MBEDTLS_ASN1_TAG_VALUE_MASK) {
+            case MBEDTLS_X509_SAN_DNS_NAME:
+                if (x509_crt_check_cn(&cur->buf, cn, cn_len) == 0) {
+                    return 0;
+                }
+                break;
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+                san_ip = 1;
+                break;
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+                san_uri = 1;
+                break;
+            /* (We may handle other types here later.) */
+            default: /* Unrecognized type */
+                break;
+        }
+    }
+    if (san_ip) {
+        if (x509_crt_check_san_ip(san, cn, cn_len) == 0) {
+            return 0;
+        }
+    }
+    if (san_uri) {
+        if (x509_crt_check_san_uri(san, cn, cn_len) == 0) {
+            return 0;
+        }
     }
 
-    /* (We may handle other types here later.) */
-
-    /* Unrecognized type */
     return -1;
 }
 
@@ -2572,31 +2986,23 @@ static void x509_crt_verify_name(const mbedtls_x509_crt *crt,
                                  uint32_t *flags)
 {
     const mbedtls_x509_name *name;
-    const mbedtls_x509_sequence *cur;
     size_t cn_len = strlen(cn);
 
     if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
-        for (cur = &crt->subject_alt_names; cur != NULL; cur = cur->next) {
-            if (x509_crt_check_san(&cur->buf, cn, cn_len) == 0) {
-                break;
-            }
-        }
-
-        if (cur == NULL) {
-            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
+        if (x509_crt_check_san(&crt->subject_alt_names, cn, cn_len) == 0) {
+            return;
         }
     } else {
         for (name = &crt->subject; name != NULL; name = name->next) {
             if (MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0 &&
                 x509_crt_check_cn(&name->val, cn, cn_len) == 0) {
-                break;
+                return;
             }
         }
 
-        if (name == NULL) {
-            *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
-        }
     }
+
+    *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
 }
 
 /*
@@ -2837,10 +3243,10 @@ void mbedtls_x509_crt_free(mbedtls_x509_crt *crt)
         mbedtls_asn1_sequence_free(cert_cur->ext_key_usage.next);
         mbedtls_asn1_sequence_free(cert_cur->subject_alt_names.next);
         mbedtls_asn1_sequence_free(cert_cur->certificate_policies.next);
+        mbedtls_asn1_sequence_free(cert_cur->authority_key_id.authorityCertIssuer.next);
 
         if (cert_cur->raw.p != NULL && cert_cur->own_buffer) {
-            mbedtls_platform_zeroize(cert_cur->raw.p, cert_cur->raw.len);
-            mbedtls_free(cert_cur->raw.p);
+            mbedtls_zeroize_and_free(cert_cur->raw.p, cert_cur->raw.len);
         }
 
         cert_prv = cert_cur;
@@ -2886,4 +3292,12 @@ void mbedtls_x509_crt_restart_free(mbedtls_x509_crt_restart_ctx *ctx)
 }
 #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */
 
+int mbedtls_x509_crt_get_ca_istrue(const mbedtls_x509_crt *crt)
+{
+    if ((crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS) != 0) {
+        return crt->MBEDTLS_PRIVATE(ca_istrue);
+    }
+    return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
+}
+
 #endif /* MBEDTLS_X509_CRT_PARSE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509_csr.c b/lib/libmbedtls/mbedtls/library/x509_csr.c
index cd117cbd490d985196916597573470f06f13f1e2..813d64466cc140a3d5e3418137b425377d909c52 100644
--- a/lib/libmbedtls/mbedtls/library/x509_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509_csr.c
@@ -2,19 +2,7 @@
  *  X.509 Certificate Signing Request (CSR) parsing
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  *  The ITU-T X.509 standard defines a certificate format for PKI.
@@ -32,6 +20,7 @@
 #if defined(MBEDTLS_X509_CSR_PARSE_C)
 
 #include "mbedtls/x509_csr.h"
+#include "x509_internal.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
 #include "mbedtls/platform_util.h"
@@ -73,13 +62,17 @@ static int x509_csr_get_version(unsigned char **p,
  * Parse CSR extension requests in DER format
  */
 static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
-                                     unsigned char **p, const unsigned char *end)
+                                     unsigned char **p, const unsigned char *end,
+                                     mbedtls_x509_csr_ext_cb_t cb,
+                                     void *p_ctx)
 {
-    int ret;
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
-    unsigned char *end_ext_data;
+    unsigned char *end_ext_data, *end_ext_octet;
+
     while (*p < end) {
         mbedtls_x509_buf extn_oid = { 0, 0, NULL };
+        int is_critical = 0; /* DEFAULT FALSE */
         int ext_type = 0;
 
         /* Read sequence tag */
@@ -100,13 +93,21 @@ static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
         extn_oid.p = *p;
         *p += extn_oid.len;
 
+        /* Get optional critical */
+        if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
+            (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
+        }
+
         /* Data should be octet string type */
         if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
                                         MBEDTLS_ASN1_OCTET_STRING)) != 0) {
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
         }
 
-        if (*p + len != end_ext_data) {
+        end_ext_octet = *p + len;
+
+        if (end_ext_octet != end_ext_data) {
             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
         }
@@ -116,44 +117,72 @@ static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
          */
         ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
 
-        if (ret == 0) {
-            /* Forbid repeated extensions */
-            if ((csr->ext_types & ext_type) != 0) {
-                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
-                                         MBEDTLS_ERR_ASN1_INVALID_DATA);
+        if (ret != 0) {
+            /* Give the callback (if any) a chance to handle the extension */
+            if (cb != NULL) {
+                ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet);
+                if (ret != 0 && is_critical) {
+                    return ret;
+                }
+                *p = end_ext_octet;
+                continue;
             }
 
-            csr->ext_types |= ext_type;
-
-            switch (ext_type) {
-                case MBEDTLS_X509_EXT_KEY_USAGE:
-                    /* Parse key usage */
-                    if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
-                                                          &csr->key_usage)) != 0) {
-                        return ret;
-                    }
-                    break;
-
-                case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
-                    /* Parse subject alt name */
-                    if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
-                                                                 &csr->subject_alt_names)) != 0) {
-                        return ret;
-                    }
-                    break;
-
-                case MBEDTLS_X509_EXT_NS_CERT_TYPE:
-                    /* Parse netscape certificate type */
-                    if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
-                                                             &csr->ns_cert_type)) != 0) {
-                        return ret;
-                    }
-                    break;
-                default:
-                    break;
+            /* No parser found, skip extension */
+            *p = end_ext_octet;
+
+            if (is_critical) {
+                /* Data is marked as critical: fail */
+                return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                         MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
             }
+            continue;
+        }
+
+        /* Forbid repeated extensions */
+        if ((csr->ext_types & ext_type) != 0) {
+            return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
+                                     MBEDTLS_ERR_ASN1_INVALID_DATA);
+        }
+
+        csr->ext_types |= ext_type;
+
+        switch (ext_type) {
+            case MBEDTLS_X509_EXT_KEY_USAGE:
+                /* Parse key usage */
+                if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
+                                                      &csr->key_usage)) != 0) {
+                    return ret;
+                }
+                break;
+
+            case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
+                /* Parse subject alt name */
+                if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
+                                                             &csr->subject_alt_names)) != 0) {
+                    return ret;
+                }
+                break;
+
+            case MBEDTLS_X509_EXT_NS_CERT_TYPE:
+                /* Parse netscape certificate type */
+                if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
+                                                         &csr->ns_cert_type)) != 0) {
+                    return ret;
+                }
+                break;
+            default:
+                /*
+                 * If this is a non-critical extension, which the oid layer
+                 * supports, but there isn't an x509 parser for it,
+                 * skip the extension.
+                 */
+                if (is_critical) {
+                    return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+                } else {
+                    *p = end_ext_octet;
+                }
         }
-        *p = end_ext_data;
     }
 
     if (*p != end) {
@@ -168,7 +197,9 @@ static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
  * Parse CSR attributes in DER format
  */
 static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
-                                     const unsigned char *start, const unsigned char *end)
+                                     const unsigned char *start, const unsigned char *end,
+                                     mbedtls_x509_csr_ext_cb_t cb,
+                                     void *p_ctx)
 {
     int ret;
     size_t len;
@@ -207,7 +238,7 @@ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
             }
 
-            if ((ret = x509_csr_parse_extensions(csr, p, *p + len)) != 0) {
+            if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) {
                 return ret;
             }
 
@@ -231,8 +262,10 @@ static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
 /*
  * Parse a CSR in DER format
  */
-int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
-                               const unsigned char *buf, size_t buflen)
+static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr,
+                                               const unsigned char *buf, size_t buflen,
+                                               mbedtls_x509_csr_ext_cb_t cb,
+                                               void *p_ctx)
 {
     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
     size_t len;
@@ -296,7 +329,7 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
     }
 
     end = p + len;
-    csr->cri.len = end - csr->cri.p;
+    csr->cri.len = (size_t) (end - csr->cri.p);
 
     /*
      *  Version  ::=  INTEGER {  v1(0) }
@@ -329,7 +362,7 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
         return ret;
     }
 
-    csr->subject_raw.len = p - csr->subject_raw.p;
+    csr->subject_raw.len = (size_t) (p - csr->subject_raw.p);
 
     /*
      *  subjectPKInfo SubjectPublicKeyInfo
@@ -356,7 +389,7 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
     }
 
-    if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) {
+    if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) {
         mbedtls_x509_csr_free(csr);
         return ret;
     }
@@ -395,6 +428,26 @@ int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
     return 0;
 }
 
+/*
+ * Parse a CSR in DER format
+ */
+int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
+                               const unsigned char *buf, size_t buflen)
+{
+    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL);
+}
+
+/*
+ * Parse a CSR in DER format with callback for unknown extensions
+ */
+int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,
+                                           const unsigned char *buf, size_t buflen,
+                                           mbedtls_x509_csr_ext_cb_t cb,
+                                           void *p_ctx)
+{
+    return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx);
+}
+
 /*
  * Parse a CSR, allowing for PEM or raw DER encoding
  */
@@ -460,8 +513,7 @@ int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
 
     ret = mbedtls_x509_csr_parse(csr, buf, n);
 
-    mbedtls_platform_zeroize(buf, n);
-    mbedtls_free(buf);
+    mbedtls_zeroize_and_free(buf, n);
 
     return ret;
 }
@@ -578,8 +630,7 @@ void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
     mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
 
     if (csr->raw.p != NULL) {
-        mbedtls_platform_zeroize(csr->raw.p, csr->raw.len);
-        mbedtls_free(csr->raw.p);
+        mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len);
     }
 
     mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
diff --git a/lib/libmbedtls/mbedtls/library/x509_internal.h b/lib/libmbedtls/mbedtls/library/x509_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..8a2d2ed0074ee3fadfc3b9c07b862572997ff1c8
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/x509_internal.h
@@ -0,0 +1,86 @@
+/**
+ * \file x509.h
+ *
+ * \brief Internal part of the public "x509.h".
+ */
+/*
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#ifndef MBEDTLS_X509_INTERNAL_H
+#define MBEDTLS_X509_INTERNAL_H
+#include "mbedtls/private_access.h"
+
+#include "mbedtls/build_info.h"
+
+#include "mbedtls/x509.h"
+#include "mbedtls/asn1.h"
+#include "pk_internal.h"
+
+#if defined(MBEDTLS_RSA_C)
+#include "mbedtls/rsa.h"
+#endif
+
+int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
+                          mbedtls_x509_name *cur);
+int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
+                              mbedtls_x509_buf *alg);
+int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
+                         mbedtls_x509_buf *alg, mbedtls_x509_buf *params);
+#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
+int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
+                                       mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
+                                       int *salt_len);
+#endif
+int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig);
+int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
+                             mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
+                             void **sig_opts);
+int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
+                          mbedtls_x509_time *t);
+int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
+                            mbedtls_x509_buf *serial);
+int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
+                         mbedtls_x509_buf *ext, int tag);
+#if !defined(MBEDTLS_X509_REMOVE_INFO)
+int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
+                              mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
+                              const void *sig_opts);
+#endif
+int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name);
+int mbedtls_x509_set_extension(mbedtls_asn1_named_data **head, const char *oid, size_t oid_len,
+                               int critical, const unsigned char *val,
+                               size_t val_len);
+int mbedtls_x509_write_extensions(unsigned char **p, unsigned char *start,
+                                  mbedtls_asn1_named_data *first);
+int mbedtls_x509_write_names(unsigned char **p, unsigned char *start,
+                             mbedtls_asn1_named_data *first);
+int mbedtls_x509_write_sig(unsigned char **p, unsigned char *start,
+                           const char *oid, size_t oid_len,
+                           unsigned char *sig, size_t size,
+                           mbedtls_pk_type_t pk_alg);
+int mbedtls_x509_get_ns_cert_type(unsigned char **p,
+                                  const unsigned char *end,
+                                  unsigned char *ns_cert_type);
+int mbedtls_x509_get_key_usage(unsigned char **p,
+                               const unsigned char *end,
+                               unsigned int *key_usage);
+int mbedtls_x509_get_subject_alt_name(unsigned char **p,
+                                      const unsigned char *end,
+                                      mbedtls_x509_sequence *subject_alt_name);
+int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
+                                          const unsigned char *end,
+                                          mbedtls_x509_sequence *subject_alt_name);
+int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
+                                       const mbedtls_x509_sequence
+                                       *subject_alt_name,
+                                       const char *prefix);
+int mbedtls_x509_info_cert_type(char **buf, size_t *size,
+                                unsigned char ns_cert_type);
+int mbedtls_x509_info_key_usage(char **buf, size_t *size,
+                                unsigned int key_usage);
+
+int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,
+                                      const mbedtls_x509_san_list *san_list);
+
+#endif /* MBEDTLS_X509_INTERNAL_H */
diff --git a/lib/libmbedtls/mbedtls/library/x509write.c b/lib/libmbedtls/mbedtls/library/x509write.c
new file mode 100644
index 0000000000000000000000000000000000000000..4704900d3868f685561ef22d5c7bf384eba4e2c1
--- /dev/null
+++ b/lib/libmbedtls/mbedtls/library/x509write.c
@@ -0,0 +1,174 @@
+/*
+ *  X.509 internal, common functions for writing
+ *
+ *  Copyright The Mbed TLS Contributors
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
+ */
+#include "common.h"
+#if defined(MBEDTLS_X509_CSR_WRITE_C) || defined(MBEDTLS_X509_CRT_WRITE_C)
+
+#include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
+#include "mbedtls/asn1write.h"
+#include "mbedtls/error.h"
+#include "mbedtls/oid.h"
+#include "mbedtls/platform.h"
+#include "mbedtls/platform_util.h"
+
+#include <string.h>
+#include <stdint.h>
+
+#if defined(MBEDTLS_PEM_WRITE_C)
+#include "mbedtls/pem.h"
+#endif /* MBEDTLS_PEM_WRITE_C */
+
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+#include "psa/crypto.h"
+#include "mbedtls/psa_util.h"
+#include "md_psa.h"
+#endif /* MBEDTLS_USE_PSA_CRYPTO */
+
+#define CHECK_OVERFLOW_ADD(a, b) \
+    do                         \
+    {                           \
+        if (a > SIZE_MAX - (b)) \
+        { \
+            return MBEDTLS_ERR_X509_BAD_INPUT_DATA; \
+        }                            \
+        a += b; \
+    } while (0)
+
+int mbedtls_x509_write_set_san_common(mbedtls_asn1_named_data **extensions,
+                                      const mbedtls_x509_san_list *san_list)
+{
+    int ret = 0;
+    const mbedtls_x509_san_list *cur;
+    unsigned char *buf;
+    unsigned char *p;
+    size_t len;
+    size_t buflen = 0;
+
+    /* Determine the maximum size of the SubjectAltName list */
+    for (cur = san_list; cur != NULL; cur = cur->next) {
+        /* Calculate size of the required buffer */
+        switch (cur->node.type) {
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+            case MBEDTLS_X509_SAN_RFC822_NAME:
+                /* length of value for each name entry,
+                 * maximum 4 bytes for the length field,
+                 * 1 byte for the tag/type.
+                 */
+                CHECK_OVERFLOW_ADD(buflen, cur->node.san.unstructured_name.len);
+                CHECK_OVERFLOW_ADD(buflen, 4 + 1);
+                break;
+            case MBEDTLS_X509_SAN_DIRECTORY_NAME:
+            {
+                const mbedtls_asn1_named_data *chunk = &cur->node.san.directory_name;
+                while (chunk != NULL) {
+                    // Max 4 bytes for length, +1 for tag,
+                    // additional 4 max for length, +1 for tag.
+                    // See x509_write_name for more information.
+                    CHECK_OVERFLOW_ADD(buflen, 4 + 1 + 4 + 1);
+                    CHECK_OVERFLOW_ADD(buflen, chunk->oid.len);
+                    CHECK_OVERFLOW_ADD(buflen, chunk->val.len);
+                    chunk = chunk->next;
+                }
+                CHECK_OVERFLOW_ADD(buflen, 4 + 1);
+                break;
+            }
+            default:
+                /* Not supported - return. */
+                return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+        }
+    }
+
+    /* Add the extra length field and tag */
+    CHECK_OVERFLOW_ADD(buflen, 4 + 1);
+
+    /* Allocate buffer */
+    buf = mbedtls_calloc(1, buflen);
+    if (buf == NULL) {
+        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
+    }
+    p = buf + buflen;
+
+    /* Write ASN.1-based structure */
+    cur = san_list;
+    len = 0;
+    while (cur != NULL) {
+        size_t single_san_len = 0;
+        switch (cur->node.type) {
+            case MBEDTLS_X509_SAN_DNS_NAME:
+            case MBEDTLS_X509_SAN_RFC822_NAME:
+            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
+            case MBEDTLS_X509_SAN_IP_ADDRESS:
+            {
+                const unsigned char *unstructured_name =
+                    (const unsigned char *) cur->node.san.unstructured_name.p;
+                size_t unstructured_name_len = cur->node.san.unstructured_name.len;
+
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
+                                             mbedtls_asn1_write_raw_buffer(
+                                                 &p, buf,
+                                                 unstructured_name, unstructured_name_len));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len, mbedtls_asn1_write_len(
+                                                 &p, buf, unstructured_name_len));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
+                                             mbedtls_asn1_write_tag(
+                                                 &p, buf,
+                                                 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));
+            }
+            break;
+            case MBEDTLS_X509_SAN_DIRECTORY_NAME:
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
+                                             mbedtls_x509_write_names(&p, buf,
+                                                                      (mbedtls_asn1_named_data *) &
+                                                                      cur->node
+                                                                      .san.directory_name));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
+                                             mbedtls_asn1_write_len(&p, buf, single_san_len));
+                MBEDTLS_ASN1_CHK_CLEANUP_ADD(single_san_len,
+                                             mbedtls_asn1_write_tag(&p, buf,
+                                                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
+                                                                    MBEDTLS_ASN1_CONSTRUCTED |
+                                                                    MBEDTLS_X509_SAN_DIRECTORY_NAME));
+                break;
+            default:
+                /* Error out on an unsupported SAN */
+                ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
+                goto cleanup;
+        }
+        cur = cur->next;
+        /* check for overflow */
+        if (len > SIZE_MAX - single_san_len) {
+            ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA;
+            goto cleanup;
+        }
+        len += single_san_len;
+    }
+
+    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
+    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
+                                 mbedtls_asn1_write_tag(&p, buf,
+                                                        MBEDTLS_ASN1_CONSTRUCTED |
+                                                        MBEDTLS_ASN1_SEQUENCE));
+
+    ret = mbedtls_x509_set_extension(extensions,
+                                     MBEDTLS_OID_SUBJECT_ALT_NAME,
+                                     MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
+                                     0,
+                                     buf + buflen - len, len);
+
+    /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list
+     * was incorrectly calculated and memory is corrupted. */
+    if (p < buf) {
+        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
+    }
+cleanup:
+    mbedtls_free(buf);
+    return ret;
+}
+
+#endif /* MBEDTLS_X509_CSR_WRITE_C || MBEDTLS_X509_CRT_WRITE_C */
diff --git a/lib/libmbedtls/mbedtls/library/x509write_crt.c b/lib/libmbedtls/mbedtls/library/x509write_crt.c
index f481155e98a26578b1ef8817909bb5417c92eeeb..56f23c9fab65577877093fefec42ed50339cd95d 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_crt.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_crt.c
@@ -2,19 +2,7 @@
  *  X.509 certificate writing
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * References:
@@ -28,13 +16,16 @@
 #if defined(MBEDTLS_X509_CRT_WRITE_C)
 
 #include "mbedtls/x509_crt.h"
+#include "x509_internal.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/error.h"
 #include "mbedtls/oid.h"
+#include "mbedtls/platform.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/md.h"
 
 #include <string.h>
+#include <stdint.h>
 
 #if defined(MBEDTLS_PEM_WRITE_C)
 #include "mbedtls/pem.h"
@@ -42,12 +33,10 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
+#include "psa_util_internal.h"
 #include "mbedtls/psa_util.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
-#include "hash_info.h"
-#include "mbedtls/legacy_or_psa.h"
-
 void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
 {
     memset(ctx, 0, sizeof(mbedtls_x509write_cert));
@@ -57,6 +46,10 @@ void mbedtls_x509write_crt_init(mbedtls_x509write_cert *ctx)
 
 void mbedtls_x509write_crt_free(mbedtls_x509write_cert *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_asn1_free_named_data_list(&ctx->subject);
     mbedtls_asn1_free_named_data_list(&ctx->issuer);
     mbedtls_asn1_free_named_data_list(&ctx->extensions);
@@ -153,6 +146,13 @@ int mbedtls_x509write_crt_set_validity(mbedtls_x509write_cert *ctx,
     return 0;
 }
 
+int mbedtls_x509write_crt_set_subject_alternative_name(mbedtls_x509write_cert *ctx,
+                                                       const mbedtls_x509_san_list *san_list)
+{
+    return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);
+}
+
+
 int mbedtls_x509write_crt_set_extension(mbedtls_x509write_cert *ctx,
                                         const char *oid, size_t oid_len,
                                         int critical,
@@ -195,7 +195,7 @@ int mbedtls_x509write_crt_set_basic_constraints(mbedtls_x509write_cert *ctx,
                                             is_ca, buf + sizeof(buf) - len, len);
 }
 
-#if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA)
+#if defined(MBEDTLS_MD_CAN_SHA1)
 static int mbedtls_x509write_crt_set_key_identifier(mbedtls_x509write_cert *ctx,
                                                     int is_ca,
                                                     unsigned char tag)
@@ -280,7 +280,7 @@ int mbedtls_x509write_crt_set_authority_key_identifier(mbedtls_x509write_cert *c
                                                     1,
                                                     (MBEDTLS_ASN1_CONTEXT_SPECIFIC | 0));
 }
-#endif /* MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA_BASED_ON_USE_PSA */
+#endif /* MBEDTLS_MD_CAN_SHA1 */
 
 int mbedtls_x509write_crt_set_key_usage(mbedtls_x509write_cert *ctx,
                                         unsigned int key_usage)
@@ -427,7 +427,7 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
     unsigned char *c, *c2;
     unsigned char sig[MBEDTLS_PK_SIGNATURE_MAX_SIZE];
     size_t hash_length = 0;
-    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
     psa_algorithm_t psa_algorithm;
@@ -436,6 +436,7 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
     size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
     mbedtls_pk_type_t pk_alg;
+    int write_sig_null_par;
 
     /*
      * Prepare data to be signed at the end of the target buffer
@@ -485,7 +486,7 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
      */
     MBEDTLS_ASN1_CHK_ADD(pub_len,
                          mbedtls_pk_write_pubkey_der(ctx->subject_key,
-                                                     buf, c - buf));
+                                                     buf, (size_t) (c - buf)));
     c -= pub_len;
     len += pub_len;
 
@@ -527,9 +528,20 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
     /*
      *  Signature   ::=  AlgorithmIdentifier
      */
+    if (pk_alg == MBEDTLS_PK_ECDSA) {
+        /*
+         * The AlgorithmIdentifier's parameters field must be absent for DSA/ECDSA signature
+         * algorithms, see https://www.rfc-editor.org/rfc/rfc5480#page-17 and
+         * https://www.rfc-editor.org/rfc/rfc5758#section-3.
+         */
+        write_sig_null_par = 0;
+    } else {
+        write_sig_null_par = 1;
+    }
     MBEDTLS_ASN1_CHK_ADD(len,
-                         mbedtls_asn1_write_algorithm_identifier(&c, buf,
-                                                                 sig_oid, strlen(sig_oid), 0));
+                         mbedtls_asn1_write_algorithm_identifier_ext(&c, buf,
+                                                                     sig_oid, strlen(sig_oid),
+                                                                     0, write_sig_null_par));
 
     /*
      *  Serial   ::=  INTEGER
@@ -586,7 +598,7 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
 
     /* Compute hash of CRT. */
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
-    psa_algorithm = mbedtls_hash_info_psa_from_md(ctx->md_alg);
+    psa_algorithm = mbedtls_md_psa_alg_from_type(ctx->md_alg);
 
     status = psa_hash_compute(psa_algorithm,
                               c,
@@ -621,8 +633,8 @@ int mbedtls_x509write_crt_der(mbedtls_x509write_cert *ctx,
      * into the CRT buffer. */
     c2 = buf + size;
     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len, mbedtls_x509_write_sig(&c2, c,
-                                                                 sig_oid, sig_oid_len, sig,
-                                                                 sig_len));
+                                                                 sig_oid, sig_oid_len,
+                                                                 sig, sig_len, pk_alg));
 
     /*
      * Memory layout after this step:
diff --git a/lib/libmbedtls/mbedtls/library/x509write_csr.c b/lib/libmbedtls/mbedtls/library/x509write_csr.c
index deb66174b240d2b40ae1d3013aca9167c2920861..0d6f6bb1d307cedc6a42724a28caed56a9a65a63 100644
--- a/lib/libmbedtls/mbedtls/library/x509write_csr.c
+++ b/lib/libmbedtls/mbedtls/library/x509write_csr.c
@@ -2,19 +2,7 @@
  *  X.509 Certificate Signing Request writing
  *
  *  Copyright The Mbed TLS Contributors
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
+ *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  */
 /*
  * References:
@@ -26,7 +14,7 @@
 
 #if defined(MBEDTLS_X509_CSR_WRITE_C)
 
-#include "mbedtls/x509.h"
+#include "x509_internal.h"
 #include "mbedtls/x509_csr.h"
 #include "mbedtls/asn1write.h"
 #include "mbedtls/error.h"
@@ -35,9 +23,9 @@
 
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
 #include "psa/crypto.h"
+#include "psa_util_internal.h"
 #include "mbedtls/psa_util.h"
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
-#include "hash_info.h"
 
 #include <string.h>
 #include <stdlib.h>
@@ -55,6 +43,10 @@ void mbedtls_x509write_csr_init(mbedtls_x509write_csr *ctx)
 
 void mbedtls_x509write_csr_free(mbedtls_x509write_csr *ctx)
 {
+    if (ctx == NULL) {
+        return;
+    }
+
     mbedtls_asn1_free_named_data_list(&ctx->subject);
     mbedtls_asn1_free_named_data_list(&ctx->extensions);
 
@@ -89,100 +81,7 @@ int mbedtls_x509write_csr_set_extension(mbedtls_x509write_csr *ctx,
 int mbedtls_x509write_csr_set_subject_alternative_name(mbedtls_x509write_csr *ctx,
                                                        const mbedtls_x509_san_list *san_list)
 {
-    int ret = 0;
-    const mbedtls_x509_san_list *cur;
-    unsigned char *buf;
-    unsigned char *p;
-    size_t len;
-    size_t buflen = 0;
-
-    /* Determine the maximum size of the SubjectAltName list */
-    for (cur = san_list; cur != NULL; cur = cur->next) {
-        /* Calculate size of the required buffer */
-        switch (cur->node.type) {
-            case MBEDTLS_X509_SAN_DNS_NAME:
-            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
-            case MBEDTLS_X509_SAN_IP_ADDRESS:
-                /* length of value for each name entry,
-                 * maximum 4 bytes for the length field,
-                 * 1 byte for the tag/type.
-                 */
-                buflen += cur->node.san.unstructured_name.len + 4 + 1;
-                break;
-
-            default:
-                /* Not supported - skip. */
-                break;
-        }
-    }
-
-    /* Add the extra length field and tag */
-    buflen += 4 + 1;
-
-    /* Allocate buffer */
-    buf = mbedtls_calloc(1, buflen);
-    if (buf == NULL) {
-        return MBEDTLS_ERR_ASN1_ALLOC_FAILED;
-    }
-
-    mbedtls_platform_zeroize(buf, buflen);
-    p = buf + buflen;
-
-    /* Write ASN.1-based structure */
-    cur = san_list;
-    len = 0;
-    while (cur != NULL) {
-        switch (cur->node.type) {
-            case MBEDTLS_X509_SAN_DNS_NAME:
-            case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
-            case MBEDTLS_X509_SAN_IP_ADDRESS:
-            {
-                const unsigned char *unstructured_name =
-                    (const unsigned char *) cur->node.san.unstructured_name.p;
-                size_t unstructured_name_len = cur->node.san.unstructured_name.len;
-
-                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
-                                             mbedtls_asn1_write_raw_buffer(
-                                                 &p, buf,
-                                                 unstructured_name, unstructured_name_len));
-                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(
-                                                 &p, buf, unstructured_name_len));
-                MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
-                                             mbedtls_asn1_write_tag(
-                                                 &p, buf,
-                                                 MBEDTLS_ASN1_CONTEXT_SPECIFIC | cur->node.type));
-            }
-            break;
-            default:
-                /* Skip unsupported names. */
-                break;
-        }
-        cur = cur->next;
-    }
-
-    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
-    MBEDTLS_ASN1_CHK_CLEANUP_ADD(len,
-                                 mbedtls_asn1_write_tag(&p, buf,
-                                                        MBEDTLS_ASN1_CONSTRUCTED |
-                                                        MBEDTLS_ASN1_SEQUENCE));
-
-    ret = mbedtls_x509write_csr_set_extension(
-        ctx,
-        MBEDTLS_OID_SUBJECT_ALT_NAME,
-        MBEDTLS_OID_SIZE(MBEDTLS_OID_SUBJECT_ALT_NAME),
-        0,
-        buf + buflen - len,
-        len);
-
-    /* If we exceeded the allocated buffer it means that maximum size of the SubjectAltName list
-     * was incorrectly calculated and memory is corrupted. */
-    if (p < buf) {
-        ret = MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
-    }
-
-cleanup:
-    mbedtls_free(buf);
-    return ret;
+    return mbedtls_x509_write_set_san_common(&ctx->extensions, san_list);
 }
 
 int mbedtls_x509write_csr_set_key_usage(mbedtls_x509write_csr *ctx, unsigned char key_usage)
@@ -243,13 +142,13 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
     const char *sig_oid;
     size_t sig_oid_len = 0;
     unsigned char *c, *c2;
-    unsigned char hash[MBEDTLS_HASH_MAX_SIZE];
+    unsigned char hash[MBEDTLS_MD_MAX_SIZE];
     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;
     size_t len = 0;
     mbedtls_pk_type_t pk_alg;
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     size_t hash_len;
-    psa_algorithm_t hash_alg = mbedtls_hash_info_psa_from_md(ctx->md_alg);
+    psa_algorithm_t hash_alg = mbedtls_md_psa_alg_from_type(ctx->md_alg);
 #endif /* MBEDTLS_USE_PSA_CRYPTO */
 
     /* Write the CSR backwards starting from the end of buf */
@@ -290,7 +189,7 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
 
     MBEDTLS_ASN1_CHK_ADD(pub_len, mbedtls_pk_write_pubkey_der(ctx->key,
-                                                              buf, c - buf));
+                                                              buf, (size_t) (c - buf)));
     c -= pub_len;
     len += pub_len;
 
@@ -363,7 +262,7 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
     c2 = buf + size;
     MBEDTLS_ASN1_CHK_ADD(sig_and_oid_len,
                          mbedtls_x509_write_sig(&c2, buf + len, sig_oid, sig_oid_len,
-                                                sig, sig_len));
+                                                sig, sig_len, pk_alg));
 
     /*
      * Compact the space between the CSR data and signature by moving the
@@ -381,7 +280,7 @@ static int x509write_csr_der_internal(mbedtls_x509write_csr *ctx,
                              MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
 
     /* Zero the unused bytes at the start of buf */
-    memset(buf, 0, c2 - buf);
+    memset(buf, 0, (size_t) (c2 - buf));
 
     return (int) len;
 }
diff --git a/lib/libmbedtls/sub.mk b/lib/libmbedtls/sub.mk
index 05951c0abd0100f88118b4d2df8e535c99093513..a0878a5b6fb89829b67c864108156fb14434cbbf 100644
--- a/lib/libmbedtls/sub.mk
+++ b/lib/libmbedtls/sub.mk
@@ -16,6 +16,7 @@ SRCS_CRYPTO += bignum_core.c
 SRCS_CRYPTO += bignum_mod_raw.c
 SRCS_CRYPTO += camellia.c
 SRCS_CRYPTO += ccm.c
+SRCS_CRYPTO += block_cipher.c
 SRCS_CRYPTO += chacha20.c
 SRCS_CRYPTO += chachapoly.c
 SRCS_CRYPTO += cipher.c
@@ -30,11 +31,11 @@ SRCS_CRYPTO += ecdsa.c
 SRCS_CRYPTO += ecjpake.c
 SRCS_CRYPTO += ecp.c
 SRCS_CRYPTO += ecp_curves.c
+SRCS_CRYPTO += ecp_curves_new.c
 SRCS_CRYPTO += entropy.c
 SRCS_CRYPTO += entropy_poll.c
 SRCS_CRYPTO += error.c
 SRCS_CRYPTO += gcm.c
-SRCS_CRYPTO += hash_info.c
 SRCS_CRYPTO += hkdf.c
 SRCS_CRYPTO += hmac_drbg.c
 SRCS_CRYPTO += lmots.c
@@ -47,6 +48,7 @@ SRCS_CRYPTO += oid.c
 SRCS_CRYPTO += padlock.c
 SRCS_CRYPTO += pem.c
 SRCS_CRYPTO += pk.c
+SRCS_CRYPTO += pk_ecc.c
 SRCS_CRYPTO += pk_wrap.c
 SRCS_CRYPTO += pkcs7.c
 SRCS_CRYPTO += pkcs12.c
@@ -61,6 +63,7 @@ SRCS_CRYPTO += rsa.c
 SRCS_CRYPTO += rsa_alt_helpers.c
 SRCS_CRYPTO += sha1.c
 SRCS_CRYPTO += sha256.c
+SRCS_CRYPTO += sha3.c
 SRCS_CRYPTO += sha512.c
 SRCS_CRYPTO += threading.c
 SRCS_CRYPTO += timing.c
@@ -85,11 +88,12 @@ SRCS_CRYPTO += ecdh.c
 SRCS_CRYPTO += ecdsa.c
 SRCS_CRYPTO += ecp.c
 SRCS_CRYPTO += ecp_curves.c
-SRCS_CRYPTO += hash_info.c
+SRCS_CRYPTO += ecp_curves_new.c
 SRCS_CRYPTO += md.c
 SRCS_CRYPTO += md5.c
 SRCS_CRYPTO += oid.c
 SRCS_CRYPTO += pk.c
+SRCS_CRYPTO += pk_ecc.c
 SRCS_CRYPTO += pk_wrap.c
 SRCS_CRYPTO += platform.c
 SRCS_CRYPTO += platform_util.c
@@ -97,6 +101,7 @@ SRCS_CRYPTO += rsa.c
 SRCS_CRYPTO += rsa_alt_helpers.c
 SRCS_CRYPTO += sha1.c
 SRCS_CRYPTO += sha256.c
+SRCS_CRYPTO += sha3.c
 SRCS_CRYPTO += sha512.c
 endif
 
@@ -107,6 +112,7 @@ SRCS_X509 += x509_create.c
 SRCS_X509 += x509_crl.c
 SRCS_X509 += x509_crt.c
 SRCS_X509 += x509_csr.c
+SRCS_X509 += x509write.c
 SRCS_X509 += x509write_crt.c
 SRCS_X509 += x509write_csr.c
 
@@ -127,9 +133,29 @@ SRCS_TLS += ssl_tls13_client.c
 SRCS_TLS += ssl_tls13_generic.c
 SRCS_TLS += ssl_tls13_server.c
 
+# OBJS_PSA
+SRCS_PSA :=
+SRCS_PSA += psa_crypto_aead.c
+SRCS_PSA += psa_crypto.c
+SRCS_PSA += psa_crypto_cipher.c
+SRCS_PSA += psa_crypto_client.c
+SRCS_PSA += psa_crypto_driver_wrappers_no_static.c
+SRCS_PSA += psa_crypto_ecp.c
+SRCS_PSA += psa_crypto_ffdh.c
+SRCS_PSA += psa_crypto_hash.c
+SRCS_PSA += psa_crypto_mac.c
+SRCS_PSA += psa_crypto_pake.c
+SRCS_PSA += psa_crypto_rsa.c
+SRCS_PSA += psa_crypto_se.c
+SRCS_PSA += psa_crypto_slot_management.c
+SRCS_PSA += psa_crypto_storage.c
+SRCS_PSA += psa_its_file.c
+SRCS_PSA += psa_util.c
+
 srcs-y += $(addprefix mbedtls/library/, $(SRCS_CRYPTO))
 srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_X509))
 srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_TLS))
+srcs-$(sm-$(ta-target)) += $(addprefix mbedtls/library/, $(SRCS_PSA))
 
 cflags-lib-y += -Wno-redundant-decls
 cflags-lib-y += -Wno-switch-default
diff --git a/lib/libunw/sub.mk b/lib/libunw/sub.mk
index e3838010e54a5dc56cfc7d8a50e5e9913adfa5a7..831c9c2e77fb8bafb6fd3b80343861cd382171d0 100644
--- a/lib/libunw/sub.mk
+++ b/lib/libunw/sub.mk
@@ -1,8 +1,10 @@
 global-incdirs-y += include
 ifeq ($(CFG_UNWIND),y)
+ifeq (arm,$(ARCH))
 srcs-y += unwind_arm32.c
+endif
 srcs-$(CFG_ARM64_$(sm)) += unwind_arm64.c
-ifneq (,$(filter y,$(CFG_RV32_$(sm)) $(CFG_RV64_$(sm))))
+ifeq (riscv,$(ARCH))
 srcs-y += unwind_riscv.c
 endif
 endif
diff --git a/lib/libutee/include/pta_benchmark.h b/lib/libutee/include/pta_benchmark.h
deleted file mode 100644
index 2b6f1573f3fac3a2fb23ab0d22b2d5c2d7796771..0000000000000000000000000000000000000000
--- a/lib/libutee/include/pta_benchmark.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: BSD-2-Clause */
-/*
- * Copyright (c) 2017, Linaro Limited
- */
-
-#ifndef __PTA_BENCHMARK_H
-#define __PTA_BENCHMARK_H
-
-/*
- * Interface to the benchmark pseudo-TA, which is used for registering
- * timestamp buffers
- */
-
-#define BENCHMARK_UUID \
-		{ 0x0b9a63b0, 0xb4c6, 0x4c85, \
-		{ 0xa2, 0x84, 0xa2, 0x28, 0xef, 0x54, 0x7b, 0x4e } }
-
-/*
- * Benchmark PTA supported commands
- */
-#define BENCHMARK_CMD(id)	(0xFA190000 | ((id) & 0xFFFF))
-#define BENCHMARK_CMD_ALLOCATE_BUF		BENCHMARK_CMD(1)
-#define BENCHMARK_CMD_GET_MEMREF		BENCHMARK_CMD(2)
-#define BENCHMARK_CMD_UNREGISTER		BENCHMARK_CMD(3)
-
-#endif /* __PTA_BENCHMARK_H */
diff --git a/lib/libutee/include/pta_device.h b/lib/libutee/include/pta_device.h
index 2cd2bcd2e000e2ff120b79d80c73dff63918c153..e54c0d977b1d3a85f31991185ca96c52f1196356 100644
--- a/lib/libutee/include/pta_device.h
+++ b/lib/libutee/include/pta_device.h
@@ -25,5 +25,6 @@
  */
 #define PTA_CMD_GET_DEVICES		0x0 /* before tee-supplicant run */
 #define PTA_CMD_GET_DEVICES_SUPP	0x1 /* after tee-supplicant run */
+#define PTA_CMD_GET_DEVICES_RPMB	0x2 /* probe for RPMB */
 
 #endif /* __PTA_DEVICE_H */
diff --git a/lib/libutee/include/pta_veraison_attestation.h b/lib/libutee/include/pta_veraison_attestation.h
new file mode 100644
index 0000000000000000000000000000000000000000..d0909135fa54c825dd0aa68391f290b0e0833abf
--- /dev/null
+++ b/lib/libutee/include/pta_veraison_attestation.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2024, Institute of Information Security (IISEC)
+ */
+
+#ifndef __PTA_VERAISON_ATTESTATION_H
+#define __PTA_VERAISON_ATTESTATION_H
+
+#define PTA_VERAISON_ATTESTATION_UUID                                  \
+	{                                                              \
+		0xa77955f9, 0xeea1, 0x44fd,                            \
+		{                                                      \
+			0xad, 0xd5, 0x4a, 0x9d, 0x96, 0x2a, 0xfc, 0xf5 \
+		}                                                      \
+	}
+
+/*
+ * Return a CBOR(COSE) evidence
+ *
+ * [in]     memref[0]        Nonce
+ * [out]    memref[1]        Output buffer
+ * [in]     memref[2]        Implementation ID
+ *
+ * Main return codes:
+ * TEE_SUCCESS
+ * TEE_ERROR_ACCESS_DENIED   - Caller is not a user space TA
+ * TEE_ERROR_BAD_PARAMETERS  - Incorrect input param
+ * TEE_ERROR_SHORT_BUFFER    - Output buffer size less than required
+ * TEE_ERROR_NOT_IMPLEMENTED - Command not implemented
+ */
+#define PTA_VERAISON_ATTESTATION_GET_CBOR_EVIDENCE 0x0
+
+#endif /* __PTA_VERAISON_ATTESTATION_H */
diff --git a/lib/libutee/include/pta_widevine.h b/lib/libutee/include/pta_widevine.h
new file mode 100644
index 0000000000000000000000000000000000000000..f76a5fc00f243944a5f6c8b76a80df7e24c2e709
--- /dev/null
+++ b/lib/libutee/include/pta_widevine.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (c) 2023, The ChromiumOS Authors
+ */
+
+#ifndef __PTA_WIDEVINE_H
+#define __PTA_WIDEVINE_H
+
+/*
+ * Interface to the widevine pseudo-TA, which is used for passing parameters
+ * for widevine TA.
+ */
+#define PTA_WIDEVINE_UUID                                              \
+	{                                                              \
+		0x721f4da9, 0xda05, 0x40d4,                            \
+		{                                                      \
+			0xa1, 0xa3, 0x83, 0x77, 0xc1, 0xe0, 0x8b, 0x0a \
+		}                                                      \
+	}
+
+/*
+ * PTA_WIDEVINE_GET_TPM_PUBKEY - Get Widevine TPM public key
+ * PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY - Get Widevine private key
+ *
+ * [out]     memref[0]        Retrieved key data
+ *
+ * Return codes:
+ * TEE_SUCCESS - Invoke command success
+ * TEE_ERROR_BAD_PARAMETERS - Incorrect parameters
+ * TEE_ERROR_SHORT_BUFFER - Output buffer size is too small
+ * TEE_ERROR_NO_DATA - Requested data not available
+ */
+#define PTA_WIDEVINE_GET_TPM_PUBKEY 0
+#define PTA_WIDEVINE_GET_WIDEVINE_PRIVKEY 1
+
+#endif /* __PTA_WIDEVINE_H */
diff --git a/lib/libutee/include/remoteproc_pta.h b/lib/libutee/include/remoteproc_pta.h
index e4be4becd77004b567e2325af88830b92f9b9bd8..28ec3796be0118460b7e5fb191449c9df4f3099d 100644
--- a/lib/libutee/include/remoteproc_pta.h
+++ b/lib/libutee/include/remoteproc_pta.h
@@ -147,4 +147,13 @@ static inline size_t rproc_pta_keyinfo_size(struct rproc_pta_key_info *keyinf)
  */
 #define PTA_RPROC_VERIFY_DIGEST		8
 
+/*
+ * Remote processor resources release.
+ *
+ * Release the resources associated to the remote processor.
+ *
+ * [in]  params[0].value.a:	Unique 32bit remote processor identifier
+ */
+#define PTA_REMOTEPROC_RELEASE		9
+
 #endif /* __REMOTEPROC_PTA_H */
diff --git a/lib/libutee/include/tee_api_types.h b/lib/libutee/include/tee_api_types.h
index b78acd4ef3228cc97da9a7a6b22150fd0b7e6248..b8dd324680f54fb841658a810e974558af0c7838 100644
--- a/lib/libutee/include/tee_api_types.h
+++ b/lib/libutee/include/tee_api_types.h
@@ -190,7 +190,7 @@ typedef uint32_t TEE_BigInt;
 
 typedef uint32_t TEE_BigIntFMM;
 
-typedef uint32_t TEE_BigIntFMMContext __aligned(__alignof__(void *));
+typedef uint32_t TEE_BigIntFMMContext;
 
 /* Tee Secure Element APIs */
 
diff --git a/lib/libutee/include/tee_internal_api.h b/lib/libutee/include/tee_internal_api.h
index 887b52fc703d263532d3d61b5095b2200d4abea3..6ebeaebeada95126bcc223610e6bc156b4f8ff11 100644
--- a/lib/libutee/include/tee_internal_api.h
+++ b/lib/libutee/include/tee_internal_api.h
@@ -125,8 +125,8 @@ void *__GP11_TEE_Realloc(void *buffer, uint32_t newSize);
 
 void TEE_Free(void *buffer);
 
-void *TEE_MemMove(void *dest, const void *src, size_t size);
-void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size);
+void TEE_MemMove(void *dest, const void *src, size_t size);
+void __GP11_TEE_MemMove(void *dest, const void *src, uint32_t size);
 
 /*
  * Note: TEE_MemCompare() has a constant-time implementation (execution time
diff --git a/lib/libutee/include/user_ta_header.h b/lib/libutee/include/user_ta_header.h
index 056b94c7a9b07fada7389f9e246853ab3c939b91..0336c64b2f70d31be952ea3f7d17095e51c24270 100644
--- a/lib/libutee/include/user_ta_header.h
+++ b/lib/libutee/include/user_ta_header.h
@@ -24,18 +24,36 @@
 	 */
 #define TA_FLAG_CONCURRENT		BIT32(8)
 	/*
-	 * Device enumeration is done in two stages by the normal world, first
-	 * before the tee-supplicant has started and then once more when the
-	 * tee-supplicant is started. The flags below control if the TA should
-	 * be reported in the first or second or case.
+	 * Device enumeration is initiated at multiple stages by the normal
+	 * world:
+	 * 1. First when the kernel driver has initialized
+	 * 2. When RPMB is available via inkernel RPMB routing
+	 * 3. When the tee-supplicant is started
+	 *
+	 * The flags below control at which stage a TA will be enumerated:
+	 * TA_FLAG_DEVICE_ENUM - at stage 1
+	 * TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE -
+	 *      when secure storage is available, at stage 2 or 3 depending
+	 *      on whether TEE_STORAGE_PRIVATE is using RPMB FS
+	 *      (CFG_REE_FS=n CFG_RPMB_FS=y) or REE FS (CFG_REE_FS=y). The
+	 *      former utilizes in kernel RPMB routing, and the latter
+	 *      depends on tee-supplicant to access secure storage.
+	 * TA_FLAG_DEVICE_ENUM_SUPP - at stage 3
+	 *
+	 * The TA is enumerated at stage 2 if
+	 * TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE is set and
+	 * TEE_STORAGE_PRIVATE is using RPMB FS, or if it's using REE FS it
+	 * will be enumerated at stage 3.
 	 */
 #define TA_FLAG_DEVICE_ENUM		BIT32(9)  /* without tee-supplicant */
 #define TA_FLAG_DEVICE_ENUM_SUPP	BIT32(10) /* with tee-supplicant */
 	/* See also "gpd.ta.doesNotCloseHandleOnCorruptObject" */
 #define TA_FLAG_DONT_CLOSE_HANDLE_ON_CORRUPT_OBJECT \
 					BIT32(11)
+#define TA_FLAG_DEVICE_ENUM_TEE_STORAGE_PRIVATE	\
+					BIT32(12) /* with TEE_STORAGE_PRIVATE */
 
-#define TA_FLAGS_MASK			GENMASK_32(10, 0)
+#define TA_FLAGS_MASK			GENMASK_32(12, 0)
 
 struct ta_head {
 	TEE_UUID uuid;
diff --git a/lib/libutee/sub.mk b/lib/libutee/sub.mk
index 1a3398ebaf59421cfbdb76dbc64059d285a8ce01..cecd8d3daeb28908c225c328df08f4fd9e34722c 100644
--- a/lib/libutee/sub.mk
+++ b/lib/libutee/sub.mk
@@ -6,7 +6,6 @@ srcs-y += tee_uuid_from_str.c
 srcs-y += trace_ext.c
 
 ifneq ($(sm),ldelf)
-srcs-y += base64.c
 srcs-y += tee_api.c
 srcs-y += tee_api_arith_mpi.c
 cppflags-tee_api_arith_mpi.c-y += -DMBEDTLS_ALLOW_PRIVATE_ACCESS
diff --git a/lib/libutee/tee_api.c b/lib/libutee/tee_api.c
index 4c9b2402b8b04e4c0c12e9d2dc609a8f2ae34bd8..e630804e4a72085d8172f03d692867066b4e1f97 100644
--- a/lib/libutee/tee_api.c
+++ b/lib/libutee/tee_api.c
@@ -133,7 +133,7 @@ static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
 			if (b && s &&
 			    !TEE_CheckMemoryAccessRights(flags, b, s)) {
 				is_tmp_mem[n] = true;
-				tbl += ROUNDUP(s, tmp_align);
+				tbl += ROUNDUP2(s, tmp_align);
 			}
 			break;
 		default:
@@ -159,7 +159,7 @@ static TEE_Result map_tmp_param(struct utee_params *up, void **tmp_buf,
 			s = up->vals[n * 2 + 1];
 			b = (void *)(vaddr_t)up->vals[n * 2];
 			tmp_va[n] = tb;
-			tb += ROUNDUP(s, tmp_align);
+			tb += ROUNDUP2(s, tmp_align);
 			up->vals[n * 2] = (vaddr_t)tmp_va[n];
 			if (TEE_PARAM_TYPE_GET(up->types, n) !=
 			    TEE_PARAM_TYPE_MEMREF_OUTPUT)
@@ -607,14 +607,14 @@ const void *TEE_GetInstanceData(void)
 	return tee_api_instance_data;
 }
 
-void *TEE_MemMove(void *dest, const void *src, size_t size)
+void TEE_MemMove(void *dest, const void *src, size_t size)
 {
-	return memmove(dest, src, size);
+	memmove(dest, src, size);
 }
 
-void *__GP11_TEE_MemMove(void *dest, const void *src, uint32_t size)
+void __GP11_TEE_MemMove(void *dest, const void *src, uint32_t size)
 {
-	return TEE_MemMove(dest, src, size);
+	TEE_MemMove(dest, src, size);
 }
 
 int32_t TEE_MemCompare(const void *buffer1, const void *buffer2, size_t size)
diff --git a/lib/libutee/tee_api_arith_mpi.c b/lib/libutee/tee_api_arith_mpi.c
index 9ccbd7c68073467fcf453df9b4e33577e45a1dab..6b5c7db2fafb98c6da872490f6083219b361b63e 100644
--- a/lib/libutee/tee_api_arith_mpi.c
+++ b/lib/libutee/tee_api_arith_mpi.c
@@ -864,8 +864,10 @@ void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u,
 		mpi_u.s *= s1;
 		mpi_v.s *= s2;
 
-		MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u));
-		MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v));
+		if (u)
+			MPI_CHECK(copy_mpi_to_bigint(&mpi_u, u));
+		if (v)
+			MPI_CHECK(copy_mpi_to_bigint(&mpi_v, v));
 		mbedtls_mpi_free(&mpi_u);
 		mbedtls_mpi_free(&mpi_v);
 	}
diff --git a/lib/libutee/tee_api_operations.c b/lib/libutee/tee_api_operations.c
index 752425ae9627a2b3b35373143510c84b3abc40c9..29fbc103db5c05cb6c22eca04c00273d31193750 100644
--- a/lib/libutee/tee_api_operations.c
+++ b/lib/libutee/tee_api_operations.c
@@ -1115,9 +1115,15 @@ static TEE_Result tee_buffer_update(
 	/* If we can feed from buffer */
 	if ((op->buffer_offs > 0) &&
 	    ((op->buffer_offs + slen) >= (buffer_size + buffer_left))) {
-		l = ROUNDUP(op->buffer_offs + slen - buffer_size,
-				op->block_size);
+		l = ROUNDUP2(op->buffer_offs + slen - buffer_size,
+			     op->block_size);
 		l = MIN(op->buffer_offs, l);
+		/*
+		 * If we're buffering only a single block, process it
+		 * immediately.
+		 */
+		if (!op->buffer_two_blocks)
+			l = op->block_size;
 		tmp_dlen = dlen;
 		res = update_func(op->state, op->buffer, l, dst, &tmp_dlen);
 		if (res != TEE_SUCCESS)
@@ -1139,10 +1145,10 @@ static TEE_Result tee_buffer_update(
 
 	if (slen >= (buffer_size + buffer_left)) {
 		/* Buffer is empty, feed as much as possible from src */
-		if (op->info.algorithm == TEE_ALG_AES_CTS)
-			l = ROUNDUP(slen - buffer_size, op->block_size);
+		if (op->buffer_two_blocks)
+			l = ROUNDUP2(slen - buffer_size, op->block_size);
 		else
-			l = ROUNDUP(slen - buffer_size + 1, op->block_size);
+			l = ROUNDUP2(slen - buffer_size + 1, op->block_size);
 
 		tmp_dlen = dlen;
 		res = update_func(op->state, src, l, dst, &tmp_dlen);
@@ -1206,10 +1212,14 @@ TEE_Result TEE_CipherUpdate(TEE_OperationHandle operation, const void *srcData,
 		req_dlen = srcLen;
 	}
 	if (operation->buffer_two_blocks) {
-		if (req_dlen > operation->block_size * 2)
-			req_dlen -= operation->block_size * 2;
-		else
+		if (operation->buffer_offs + srcLen >
+		    operation->block_size * 2) {
+			req_dlen = operation->buffer_offs + srcLen -
+				   operation->block_size * 2;
+			req_dlen = ROUNDUP2(req_dlen, operation->block_size);
+		} else {
 			req_dlen = 0;
+		}
 	}
 	/*
 	 * Check that required destLen is big enough before starting to feed
@@ -1684,8 +1694,8 @@ static TEE_Result ae_update_helper(TEE_OperationHandle operation,
 	 * can't restore sync with this API.
 	 */
 	if (operation->block_size > 1) {
-		req_dlen = ROUNDDOWN(operation->buffer_offs + slen,
-				     operation->block_size);
+		req_dlen = ROUNDDOWN2(operation->buffer_offs + slen,
+				      operation->block_size);
 	} else {
 		req_dlen = slen;
 	}
diff --git a/lib/libutee/tee_api_property.c b/lib/libutee/tee_api_property.c
index 5f33e2ca802a543e866b5965319178af16f19fbf..acbfc657caadbbec1fbb6c078535a9188237ca74 100644
--- a/lib/libutee/tee_api_property.c
+++ b/lib/libutee/tee_api_property.c
@@ -3,12 +3,14 @@
  * Copyright (c) 2014, STMicroelectronics International N.V.
  * Copyright (c) 2017-2020, Linaro Limited
  */
+#include <base64.h>
 #include <printk.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <tee_api_defines.h>
+#include <string_ext.h>
 #include <tee_api.h>
+#include <tee_api_defines.h>
 #include <tee_api_types.h>
 #include <tee_arith_internal.h>
 #include <tee_internal_api_extensions.h>
@@ -17,8 +19,6 @@
 #include <utee_syscalls.h>
 #include <util.h>
 
-#include "base64.h"
-#include "string_ext.h"
 #include "tee_api_private.h"
 
 #define PROP_STR_MAX    80
@@ -108,7 +108,7 @@ static TEE_Result propget_get_ext_prop(const struct user_ta_property *ep,
 		 * string
 		 */
 		l = *len;
-		if (!_base64_dec(ep->value, strlen(ep->value), buf, &l) &&
+		if (!base64_dec(ep->value, strlen(ep->value), buf, &l) &&
 		    l <= *len)
 			return TEE_ERROR_GENERIC;
 		if (*len < l) {
@@ -231,7 +231,7 @@ TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
 				 * with the size of the of the base64 encoded
 				 * see base64_enc() function
 				 */
-				tmp_len = _base64_enc_len(tmp_len);
+				tmp_len = base64_enc_len(tmp_len);
 			}
 			*value_len = tmp_len;
 		}
@@ -266,7 +266,7 @@ TEE_Result TEE_GetPropertyAsString(TEE_PropSetHandle propsetOrEnumerator,
 
 	case USER_TA_PROP_TYPE_BINARY_BLOCK:
 		l = *value_len;	/* l includes the zero-termination */
-		if (!_base64_enc(tmp_buf, tmp_len, value, &l) &&
+		if (!base64_enc(tmp_buf, tmp_len, value, &l) &&
 		    l <= *value_len) {
 			res = TEE_ERROR_GENERIC;
 			goto out;
diff --git a/lib/libutils/ext/array.c b/lib/libutils/ext/array.c
new file mode 100644
index 0000000000000000000000000000000000000000..d3d611c5463f2c5243601b3c561bb9880817637e
--- /dev/null
+++ b/lib/libutils/ext/array.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, Linaro Limited
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <string.h>
+#include <string_ext.h>
+
+void *ins_array_elem(void *base, size_t elem_count, size_t elem_size,
+		     size_t pos, const void *elem)
+{
+	uint8_t *b = base;
+	void *e = b + pos * elem_size;
+
+	assert(pos < elem_count);
+
+	memmove(b + (pos + 1) * elem_size, e,
+		(elem_count - pos - 1) * elem_size);
+
+	if (elem)
+		memcpy(e, elem, elem_size);
+
+	return e;
+}
+
+void *ins_array_elem_zero_init(void *base, size_t elem_count, size_t elem_size,
+			       size_t pos)
+{
+	return memset(ins_array_elem(base, elem_count, elem_size, pos, NULL),
+		      0, elem_size);
+}
+
+void rem_array_elem(void *base, size_t elem_count, size_t elem_size,
+		    size_t pos)
+{
+	uint8_t *b = base;
+
+	assert(pos < elem_count);
+
+	memmove(b + pos * elem_size, b + (pos + 1) * elem_size,
+		(elem_count - pos - 1) * elem_size);
+}
+
+void rem_array_elem_zero_pad(void *base, size_t elem_count, size_t elem_size,
+			     size_t pos)
+{
+	rem_array_elem(base, elem_count, elem_size, pos);
+	memset((uint8_t *)base + (elem_count - 1) * elem_size, 0, elem_size);
+}
diff --git a/lib/libutee/base64.c b/lib/libutils/ext/base64.c
similarity index 91%
rename from lib/libutee/base64.c
rename to lib/libutils/ext/base64.c
index a1eacec1bbc17e56996ff4abe147c111537a46b4..e106e15f4077e3834f9b20448322280b83b4e94d 100644
--- a/lib/libutee/base64.c
+++ b/lib/libutils/ext/base64.c
@@ -8,18 +8,18 @@
 static const char base64_table[] =
 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
-size_t _base64_enc_len(size_t size)
+size_t base64_enc_len(size_t size)
 {
 	return 4 * ((size + 2) / 3) + 1;
 }
 
-bool _base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
+bool base64_enc(const void *data, size_t dlen, char *buf, size_t *blen)
 {
 	size_t n = 0;
 	size_t boffs = 0;
 	const unsigned char *d = data;
 
-	n = _base64_enc_len(dlen);
+	n = base64_enc_len(dlen);
 	if (*blen < n) {
 		*blen = n;
 		return false;
@@ -70,7 +70,7 @@ static bool get_idx(char ch, uint8_t *idx)
 	return false;
 }
 
-bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen)
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen)
 {
 	bool ret = false;
 	size_t n = 0;
diff --git a/lib/libutee/base64.h b/lib/libutils/ext/include/base64.h
similarity index 55%
rename from lib/libutee/base64.h
rename to lib/libutils/ext/include/base64.h
index ed4ba36cb650a4d291a184ec79fbda422da146bf..6a5fbfec4e87f5d3cb0ab730fac087f6de1f1ad1 100644
--- a/lib/libutee/base64.h
+++ b/lib/libutils/ext/include/base64.h
@@ -9,8 +9,8 @@
 #include <stdbool.h>
 #include <stddef.h>
 
-bool _base64_enc(const void *data, size_t size, char *buf, size_t *blen);
-bool _base64_dec(const char *data, size_t size, void *buf, size_t *blen);
-size_t _base64_enc_len(size_t size);
+bool base64_enc(const void *data, size_t size, char *buf, size_t *blen);
+bool base64_dec(const char *data, size_t size, void *buf, size_t *blen);
+size_t base64_enc_len(size_t size);
 
 #endif /* BASE64_H */
diff --git a/lib/libutils/ext/include/compiler.h b/lib/libutils/ext/include/compiler.h
index 47e8838bf61b885c8f71a7de5550c54bcd65e54f..712842da29b45597c4bbb7fef41e06dbc511d489 100644
--- a/lib/libutils/ext/include/compiler.h
+++ b/lib/libutils/ext/include/compiler.h
@@ -15,6 +15,11 @@
  * the conflicting defines has the same meaning in that environment.
  * Surrounding the troublesome defines with #ifndef should be enough.
  */
+
+#ifndef __has_attribute
+#define __has_attribute(x) 0
+#endif
+
 #define __deprecated	__attribute__((deprecated))
 #ifndef __packed
 #define __packed	__attribute__((packed))
@@ -24,6 +29,15 @@
 #ifndef __noreturn
 #define __noreturn	__attribute__((__noreturn__))
 #endif
+
+#ifndef __no_stack_protector
+#if __has_attribute(no_stack_protector)
+#define __no_stack_protector __attribute__((no_stack_protector))
+#else
+#define __no_stack_protector
+#endif
+#endif
+
 #define __pure		__attribute__((pure))
 #define __aligned(x)	__attribute__((aligned(x)))
 #define __printf(a, b)	__attribute__((format(printf, a, b)))
diff --git a/lib/libutils/ext/include/fault_mitigation.h b/lib/libutils/ext/include/fault_mitigation.h
index 06a6f7f017ba5c64f4305c5b8ba57b4b4601f084..eefe5f576e66d88caf5a6657c92538c4ddf85b28 100644
--- a/lib/libutils/ext/include/fault_mitigation.h
+++ b/lib/libutils/ext/include/fault_mitigation.h
@@ -154,6 +154,21 @@ typedef int (*ftmn_memcmp_t)(const void *p1, const void *p2, size_t nb);
 
 #define __FTMN_FUNC_BYTE(f, o, l)	((o) < (l) ? (uint8_t)(f)[(o)] : 0)
 
+#ifdef __ILP32__
+#define __FTMN_GET_FUNC_U32(f, o, l) \
+	(SHIFT_U32(__FTMN_FUNC_BYTE((f), (o), (l)), 0) | \
+	 SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 1, (l)), 8) | \
+	 SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 2, (l)), 16) | \
+	 SHIFT_U32(__FTMN_FUNC_BYTE((f), (o) + 3, (l)), 24))
+
+#define __FTMN_FUNC_HASH64(f, o, l) \
+	(__FTMN_GET_FUNC_U32((f), (o), (l)) ^ \
+	 __FTMN_GET_FUNC_U32((f), (o) + 4, (l)))
+
+#define __FTMN_FUNC_HASH32(f, o, l) \
+	(__FTMN_FUNC_HASH64((f), (o), (l)) ^ \
+	 __FTMN_FUNC_HASH64((f), (o) + __FTMN_MAX_FUNC_NAME_LEN / 16, (l)))
+#else
 #define __FTMN_GET_FUNC_U64(f, o, l) \
 	(SHIFT_U64(__FTMN_FUNC_BYTE((f), (o), (l)), 0) | \
 	 SHIFT_U64(__FTMN_FUNC_BYTE((f), (o) + 1, (l)), 8) | \
@@ -167,6 +182,7 @@ typedef int (*ftmn_memcmp_t)(const void *p1, const void *p2, size_t nb);
 #define __FTMN_FUNC_HASH32(f, o, l) \
 	(__FTMN_GET_FUNC_U64((f), (o), (l)) ^ \
 	 __FTMN_GET_FUNC_U64((f), (o) + 8, (l)))
+#endif
 
 #define __FTMN_FUNC_HASH16(f, o, l) \
 	(__FTMN_FUNC_HASH32((f), (o), (l)) ^ \
@@ -184,13 +200,7 @@ typedef int (*ftmn_memcmp_t)(const void *p1, const void *p2, size_t nb);
 	(__FTMN_FUNC_HASH4(f, 0, l) ^ \
 	 __FTMN_FUNC_HASH4(f, __FTMN_MAX_FUNC_NAME_LEN / 2, l))
 
-#ifdef __ILP32__
-#define __FTMN_FUNC_HASH(f, l) \
-	(unsigned long)(__FTMN_FUNC_HASH2((f), (l)) ^ \
-		        (__FTMN_FUNC_HASH2((f), (l)) >> 32))
-#else
 #define __FTMN_FUNC_HASH(f, l)	(unsigned long)__FTMN_FUNC_HASH2((f), (l))
-#endif
 
 #define __ftmn_step_count_1(c0) ((c0) * FTMN_INCR0)
 #define __ftmn_step_count_2(c0, c1) \
diff --git a/lib/libutils/ext/include/speculation_barrier.h b/lib/libutils/ext/include/speculation_barrier.h
index ef74e3617d62e05966d5d785f11f86a9991783e5..548c1657ed1a71d1b1d6c15d53cc40630995e18f 100644
--- a/lib/libutils/ext/include/speculation_barrier.h
+++ b/lib/libutils/ext/include/speculation_barrier.h
@@ -501,6 +501,72 @@
 #define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr) \
   (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr))
 
+#elif defined(RV32) || defined(RV64)
+
+#define __load_no_speculate1(__ptr, __low, __high, __failval, __cmpptr, __sz) \
+(__extension__ ({                                                             \
+  __typeof__ (0 + (*(__ptr)))  __nln_val;                                     \
+      asm volatile (                                                          \
+      "fence\trw,rw\n\t"                                                      \
+      "fence.i\n\t"                                                           \
+      "fence\tr,r\n\t"                                                        \
+      "l" __sz "\t%[__v], %[__p]\n"                                           \
+      /* The value we have loaded. */                                         \
+      : [__v] "=&r" (__nln_val)                                               \
+      :                                                                       \
+      /* The memory location from which we will load. */                      \
+      [__p] "m" (*(__ptr))                                                    \
+      : );                                                                    \
+  (__typeof__ (*(__ptr))) __nln_val;                                          \
+}))
+
+#define __load_no_speculate(__ptr, __low, __high, __failval, __cmpptr)  \
+(__extension__ ({                                                       \
+  __typeof__ (0 + *(__ptr)) __nl_val;                                   \
+                                                                        \
+  switch (sizeof(*(__ptr))) {                                           \
+    case 1:                                                             \
+      __nl_val = __load_no_speculate1 (__ptr, __low, __high,            \
+                                       __failval, __cmpptr, "b");       \
+      break;                                                            \
+    case 2:                                                             \
+      __nl_val = __load_no_speculate1 (__ptr, __low, __high,            \
+                                       __failval, __cmpptr, "h");       \
+      break;                                                            \
+    case 4:                                                             \
+      __nl_val = __load_no_speculate1 (__ptr, __low, __high,            \
+                                       __failval, __cmpptr, "w");       \
+      break;                                                            \
+    case 8:                                                             \
+      __nl_val = __load_no_speculate1 (__ptr, __low, __high,            \
+                                       __failval, __cmpptr, "d");       \
+      break;                                                            \
+    default:                                                            \
+      {                                                                 \
+        char __static_assert_no_speculate_load_size_too_big             \
+                [sizeof (__nl_val) > 8 ? -1 : 1] __UNUSED;              \
+        break;                                                          \
+      }                                                                 \
+  }                                                                     \
+                                                                        \
+  (__typeof__ (*(__ptr))) __nl_val;                                     \
+}))
+
+#define load_no_speculate(__ptr, __low, __high)                         \
+(__extension__ ({                                                       \
+  __typeof__ ((__ptr)) __ptr_once = (__ptr);                            \
+  __load_no_speculate (__ptr_once, __low, __high, 0, __ptr_once);       \
+}))
+
+#define load_no_speculate_fail(__ptr, __low, __high, __failval)           \
+(__extension__ ({                                                         \
+  __typeof__ ((__ptr)) __ptr_once = (__ptr);                              \
+  __load_no_speculate (__ptr_once, __low, __high, __failval, __ptr_once); \
+}))
+
+#define load_no_speculate_cmp(__ptr, __low, __high, __failval, __cmpptr)  \
+  (__load_no_speculate (__ptr, __low, __high, __failval, __cmpptr))
+
 #else
 #error "No fallback provided for load_no_speculate"
 #endif
diff --git a/lib/libutils/ext/include/string_ext.h b/lib/libutils/ext/include/string_ext.h
index 0ee908e543e904f78fadc248ad68e6a2c7e25d00..d3821b36008fa12fe4532dca9fc33d1348b4e810 100644
--- a/lib/libutils/ext/include/string_ext.h
+++ b/lib/libutils/ext/include/string_ext.h
@@ -52,4 +52,66 @@ char *nex_strdup(const char *s);
  */
 void memzero_explicit(void *s, size_t count);
 
+/*
+ * ins_array_elem() - insert an element in an array
+ * @base:        start of the array
+ * @elem_count:  the number of elements in the array
+ * @elem_size:   the size of each element in the array
+ * @pos:         element position counted in units of @elem_size
+ * @elem:        pointer the the element to inser or NULL
+ *
+ * Makes room in the array at @pos by moving the element after this
+ * position one position further back.
+ *
+ * If @elem is non-NULL it's copied into the array at the indicated
+ * position.
+ *
+ * Returns a pointer to the inserted element.
+ */
+void *ins_array_elem(void *base, size_t elem_count, size_t elem_size,
+		     size_t pos, const void *elem);
+
+/*
+ * ins_array_elem_zero_init() - insert a zero-initialized element in an array
+ * @base:        start of the array
+ * @elem_count:  the number of elements in the array
+ * @elem_size:   the size of each element in the array
+ * @pos:         element position counted in units of @elem_size
+ *
+ * Makes room in the array at @pos by moving the element after this
+ * position one position further back. The free position is
+ * zero-initialized.
+ *
+ * Returns a pointer to the free position.
+ */
+void *ins_array_elem_zero_init(void *base, size_t elem_count, size_t elem_size,
+			       size_t pos);
+
+/*
+ * rem_array_elem() - remove an element from an array
+ * @base:        start of the array
+ * @elem_count:  the number of elements in the array
+ * @elem_size:   the size of each element in the array
+ * @pos:         element position counted in units of @elem_size
+ *
+ * Removes the element at @pos by advancing the element after this position
+ * to fill the space.
+ */
+void rem_array_elem(void *base, size_t elem_count, size_t elem_size,
+		    size_t pos);
+
+/*
+ * rem_array_elem_zero_pad() - remove an element from an array
+ * @base:        start of the array
+ * @elem_count:  the number of elements in the array
+ * @elem_size:   the size of each element in the array
+ * @pos:         element position counted in units of @elem_size
+ *
+ * Removes the element at @pos by advancing the element after this position
+ * to fill the space. The now unused element at the end of the array is
+ * zero-initialized.
+ */
+void rem_array_elem_zero_pad(void *base, size_t elem_count, size_t elem_size,
+			     size_t pos);
+
 #endif /* __STRING_EXT_H */
diff --git a/lib/libutils/ext/include/types_ext.h b/lib/libutils/ext/include/types_ext.h
index 0bbade5c5605375a57ce28f0cbf620d450bd188b..38a9d5ef0f67cd6f42f4cf4a4d75758b1a04b924 100644
--- a/lib/libutils/ext/include/types_ext.h
+++ b/lib/libutils/ext/include/types_ext.h
@@ -20,12 +20,16 @@ typedef uintptr_t vaddr_t;
 #if defined(__ILP32__) && defined(CFG_CORE_LARGE_PHYS_ADDR)
 typedef uint64_t paddr_t;
 typedef uint64_t paddr_size_t;
+#define PADDR_MAX		UINT64_MAX
+#define PADDR_SIZE_MAX		UINT64_MAX
 #define PRIxPA			PRIx64
 #define PRIxPASZ		PRIx64
 #define __SIZEOF_PADDR__	8
 #else
 typedef uintptr_t paddr_t;
 typedef uintptr_t paddr_size_t;
+#define PADDR_MAX		UINTPTR_MAX
+#define PADDR_SIZE_MAX		UINTPTR_MAX
 #define PRIxPA			PRIxPTR
 #define PRIxPASZ		PRIxPTR
 #define __SIZEOF_PADDR__	__SIZEOF_POINTER__
diff --git a/lib/libutils/ext/include/util.h b/lib/libutils/ext/include/util.h
index aedd50804d0bc8839499f4aec39db47cbb602bd7..256849fb96cf87621233918fbd62c61e966655f8 100644
--- a/lib/libutils/ext/include/util.h
+++ b/lib/libutils/ext/include/util.h
@@ -8,6 +8,11 @@
 #include <compiler.h>
 #include <inttypes.h>
 
+#ifndef __ASSEMBLER__
+#include <assert.h>
+#include <stddef.h>
+#endif
+
 #define SIZE_4K	UINTPTR_C(0x1000)
 #define SIZE_1M	UINTPTR_C(0x100000)
 #define SIZE_2M	UINTPTR_C(0x200000)
@@ -45,38 +50,103 @@
 #endif
 
 #ifndef __ASSEMBLER__
-/* Round up the even multiple of size, size has to be a multiple of 2 */
-#define ROUNDUP(v, size) (((v) + ((__typeof__(v))(size) - 1)) & \
-			  ~((__typeof__(v))(size) - 1))
-
-#define ROUNDUP_OVERFLOW(v, size, res) (__extension__({ \
-	typeof(*(res)) __roundup_tmp = 0; \
-	typeof(v) __roundup_mask = (typeof(v))(size) - 1; \
-	\
-	ADD_OVERFLOW((v), __roundup_mask, &__roundup_tmp) ? 1 : \
-		((void)(*(res) = __roundup_tmp & ~__roundup_mask), 0); \
-}))
+/* Round up the even multiple of size */
+#define ROUNDUP(x, y) \
+	((((x) + (__typeof__(x))(y) - 1) / (__typeof__(x))(y)) * \
+	 (__typeof__(x))(y))
+
+/* Round up the even multiple of size, size has to be a power of 2 */
+#define ROUNDUP2(v, size) \
+	(__extension__({ \
+		assert(IS_POWER_OF_TWO(size)); \
+		(((v) + ((__typeof__(v))(size) - 1)) & \
+		 ~((__typeof__(v))(size) - 1)); \
+	}))
+
+/*
+ * ROUNDUP_OVERFLOW(v, size, res)
+ *
+ * @v: Input value to round
+ * @size: Rounding operand
+ * @res: Pointer where boolean overflow status (0/false or 1/true) is stored
+ * @return: boolean overflow status of the resulting rounded value
+ *
+ * Round up value @v to the even multiple of @size and return if result
+ * overflows the output value range pointed by @res. The rounded value is
+ * stored in the memory address pointed by @res.
+ */
+#define ROUNDUP_OVERFLOW(v, size, res) \
+	(__extension__({ \
+		typeof(v) __roundup_mod = 0; \
+		typeof(v) __roundup_add = 0; \
+		\
+		__roundup_mod = (v) % (typeof(v))(size); \
+		if (__roundup_mod) \
+			__roundup_add = (typeof(v))(size) - __roundup_mod; \
+		ADD_OVERFLOW((v), __roundup_add, (res)); \
+	}))
+
+/*
+ * ROUNDUP2_OVERFLOW(v, size, res)
+ *
+ * @v: Input value to round
+ * @size: Rounding operand, must be a power of 2
+ * @res: Pointer where boolean overflow status (0/false or 1/true) is stored
+ * @return: boolean overflow status of the resulting rounded value
+ *
+ * Round up value @v to the even multiple of @size and return if result
+ * overflows the output value range pointed by @res. The rounded value is
+ * stored in the memory address pointed by @res.
+ */
+#define ROUNDUP2_OVERFLOW(v, size, res) \
+	(__extension__({ \
+		typeof(*(res)) __roundup_tmp = 0; \
+		typeof(v) __roundup_mask = (typeof(v))(size) - 1; \
+		\
+		assert(IS_POWER_OF_TWO(size)); \
+		ADD_OVERFLOW((v), __roundup_mask, &__roundup_tmp) ? 1 : \
+			((void)(*(res) = __roundup_tmp & ~__roundup_mask), 0); \
+	}))
 
 /*
+ * ROUNDUP2_DIV(x, y)
+ *
  * Rounds up to the nearest multiple of y and then divides by y. Safe
- * against overflow, y has to be a multiple of 2.
+ * against overflow, y has to be a power of 2.
  *
  * This macro is intended to be used to convert from "number of bytes" to
  * "number of pages" or similar units. Example:
- * num_pages = ROUNDUP_DIV(num_bytes, SMALL_PAGE_SIZE);
+ * num_pages = ROUNDUP2_DIV(num_bytes, SMALL_PAGE_SIZE);
  */
-#define ROUNDUP_DIV(x, y) (__extension__({ \
-	typeof(x) __roundup_x = (x); \
-	typeof(y) __roundup_mask = (typeof(x))(y) - 1; \
-	\
-	(__roundup_x / (y)) + (__roundup_x & __roundup_mask ? 1 : 0); \
-}))
+#define ROUNDUP2_DIV(x, y) \
+	(__extension__({ \
+		typeof(x) __roundup_x = (x); \
+		typeof(y) __roundup_mask = (typeof(x))(y) - 1; \
+		\
+		assert(IS_POWER_OF_TWO(y)); \
+		(__roundup_x / (y)) + (__roundup_x & __roundup_mask ? 1 : 0); \
+	}))
 
-/* Round down the even multiple of size, size has to be a multiple of 2 */
-#define ROUNDDOWN(v, size) ((v) & ~((__typeof__(v))(size) - 1))
+/*
+ * ROUNDUP_DIV(x, y)
+ *
+ * Rounds up to the nearest multiple of y and then divides by y. Safe
+ * against overflow.
+ */
+#define ROUNDUP_DIV(x, y) (ROUNDUP((x), (y)) / (__typeof__(x))(y))
+
+/* Round down the even multiple of size */
+#define ROUNDDOWN(x, y)		(((x) / (__typeof__(x))(y)) * (__typeof__(x))(y))
+
+/* Round down the even multiple of size, size has to be a power of 2 */
+#define ROUNDDOWN2(v, size) \
+	(__extension__({ \
+		assert(IS_POWER_OF_TWO(size)); \
+		((v) & ~((__typeof__(v))(size) - 1)); \
+	}))
 
 /*
- * Round up the result of x / y to the nearest upper integer if result is not 
+ * Round up the result of x / y to the nearest upper integer if result is not
  * already an integer.
  */
 #define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
@@ -86,11 +156,11 @@
 	(__extension__ ({ __typeof__(x) _x = (x); \
 	  __typeof__(y) _y = (y); \
 	  (_x + (_y / 2)) / _y; }))
-#else
+#else /* __ASSEMBLER__ */
 #define ROUNDUP(x, y)			((((x) + (y) - 1) / (y)) * (y))
-#define ROUNDDOWN(x, y)		(((x) / (y)) * (y))
+#define ROUNDDOWN(x, y)			(((x) / (y)) * (y))
 #define UDIV_ROUND_NEAREST(x, y)	(((x) + ((y) / 2)) / (y))
-#endif
+#endif /* __ASSEMBLER__ */
 
 /* x has to be of an unsigned type */
 #define IS_POWER_OF_TWO(x) (((x) != 0) && (((x) & (~(x) + 1)) == (x)))
@@ -135,7 +205,8 @@
  * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000.
  */
 #define GENMASK_32(h, l) \
-	(((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h))))
+	((UINT32_C(0xffffffff) << (l)) & \
+	 (UINT32_C(0xffffffff) >> (32 - 1 - (h))))
 
 #define GENMASK_64(h, l) \
 	(((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h))))
@@ -183,7 +254,40 @@ static inline void reg_pair_from_64(uint64_t val, uint32_t *reg0,
 	*reg1 = low32_from_64(val);
 }
 
-/* Get and set bit fields  */
+/*
+ * Functions to get and set bit fields in a 32/64-bit bitfield.
+ *
+ * These helper functions allow setting and extracting specific bits in
+ * a bitfield @reg according to a given mask @mask. The mask
+ * specifies which bits in the bitfield should be updated or extracted.
+ * These functions exist in both 32-bit and 64-bit versions.
+ *
+ * set_field_u32()
+ * set_field_u64() - Modifies specific bits in a bitfield by clearing
+ *		     the bits specified by the mask and then setting
+ *		     these bits to the new value @val.
+ * @reg:  The original 32-bit or 64-bit bitfield value.
+ * @mask: A bitmask indicating which bits in the bitfield should be
+ *	  updated.
+ * @val:  The new value to be loaded into the bitfield, left shifted
+ * 	  according to @mask rightmost non-zero bit position.
+ * Returns the updated bitfield value with the specified bits set to
+ * the new value.
+ *
+ * E.g. set_bitfield_u32(0x123456, 0xf0ff00, 0xabcd) returns 0xa2cd56.
+ *
+ * get_field_u32()
+ * get_field_u64() - Extracts the value of specific bits in a bitfield
+ *		     by isolating the bits specified by the mask and
+ *		     then shifting them to the rightmost position.
+ * @reg:  The original 32-bit or 64-bit bitfield value.
+ * @mask: A bitmask indicating which bits in the bitfield should be
+ *	  extracted.
+ * Returns the value of the bits specified by the mask, shifted to the
+ * @mask rightmost non-zero bit position.
+ *
+ * E.g. get_bitfield_u32(0x123456, 0xf0ff00) returns 0x1034.
+ */
 static inline uint32_t get_field_u32(uint32_t reg, uint32_t mask)
 {
 	return (reg & mask) / (mask & ~(mask - 1));
@@ -203,6 +307,22 @@ static inline uint64_t set_field_u64(uint64_t reg, uint64_t mask, uint64_t val)
 {
 	return (reg & ~mask) | (val * (mask & ~(mask - 1)));
 }
+
+/* Helper function for qsort with standard types */
+void qsort_int(int *aa, size_t n);
+void qsort_uint(unsigned int *aa, size_t n);
+void qsort_long(long int *aa, size_t n);
+void qsort_ul(unsigned long int *aa, size_t n);
+void qsort_ll(long long int *aa, size_t n);
+void qsort_ull(unsigned long long int *aa, size_t n);
+void qsort_s8(int8_t *aa, size_t n);
+void qsort_u8(uint8_t *aa, size_t n);
+void qsort_s16(int16_t *aa, size_t n);
+void qsort_u16(uint16_t *aa, size_t n);
+void qsort_s32(int32_t *aa, size_t n);
+void qsort_u32(uint32_t *aa, size_t n);
+void qsort_s64(int64_t *aa, size_t n);
+void qsort_u64(uint64_t *aa, size_t n);
 #endif
 
 #endif /*UTIL_H*/
diff --git a/lib/libutils/ext/qsort_helpers.c b/lib/libutils/ext/qsort_helpers.c
new file mode 100644
index 0000000000000000000000000000000000000000..36523b72e549f8809d46bab244c364bacb1cf985
--- /dev/null
+++ b/lib/libutils/ext/qsort_helpers.c
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2024, STMicroelectronics
+ */
+
+#include <stdlib.h>
+#include <util.h>
+
+#define QSORT_HELPER(name, type)				\
+static int cmp_ ## name(const void *a, const void *b)		\
+{								\
+	const type *ia = a;					\
+	const type *ib = b;					\
+								\
+	return CMP_TRILEAN(*ia, *ib);				\
+}								\
+								\
+void qsort_ ## name(type *aa, size_t n)				\
+{								\
+	qsort(aa, n, sizeof(*aa), cmp_ ## name);		\
+}
+
+QSORT_HELPER(int, int);
+QSORT_HELPER(uint, unsigned int);
+QSORT_HELPER(long, long int);
+QSORT_HELPER(ul, unsigned long int);
+QSORT_HELPER(ll, long long int);
+QSORT_HELPER(ull, unsigned long long int);
+QSORT_HELPER(s8, int8_t);
+QSORT_HELPER(u8, uint8_t);
+QSORT_HELPER(s16, int16_t);
+QSORT_HELPER(u16, uint16_t);
+QSORT_HELPER(s32, int32_t);
+QSORT_HELPER(u32, uint32_t);
+QSORT_HELPER(s64, int64_t);
+QSORT_HELPER(u64, uint64_t);
diff --git a/lib/libutils/ext/sub.mk b/lib/libutils/ext/sub.mk
index 3ab5afd5ad7a9faaa2796a44f9ce380c154b7c05..00bb23de01fc609c2d47a7cacb64c04bbc5c1e2f 100644
--- a/lib/libutils/ext/sub.mk
+++ b/lib/libutils/ext/sub.mk
@@ -9,6 +9,9 @@ srcs-y += nex_strdup.c
 srcs-y += consttime_memcmp.c
 srcs-y += memzero_explicit.c
 srcs-y += fault_mitigation.c
+srcs-y += qsort_helpers.c
+srcs-y += array.c
+srcs-y += base64.c
 
 ifneq (,$(filter ta_%,$(sm)))
 srcs-y += pthread_stubs.c
diff --git a/lib/libutils/isoc/arch/arm/sub.mk b/lib/libutils/isoc/arch/arm/sub.mk
index 1e11502fde1d988397df92359d18aecf498e8292..a115cd0493cb067b3f4fd8aebdd4333c15fc0816 100644
--- a/lib/libutils/isoc/arch/arm/sub.mk
+++ b/lib/libutils/isoc/arch/arm/sub.mk
@@ -7,7 +7,6 @@ srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod_a32.S
 srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_ldivmod.c
 srcs-$(CFG_ARM32_$(sm)) += arm32_aeabi_shift.c
 
-ifeq ($(CFG_ULIBS_MCOUNT),y)
 # We would not like to profile __aeabi functions as these provide
 # internal implementations for "/ %" operations. Also, "/ %" operations
 # could be used inside profiling code which could create an incorrect
@@ -15,7 +14,6 @@ ifeq ($(CFG_ULIBS_MCOUNT),y)
 cflags-remove-arm32_aeabi_divmod.c-y += -pg
 cflags-remove-arm32_aeabi_ldivmod.c-y += -pg
 cflags-remove-arm32_aeabi_shift.c-y += -pg
-endif
 
 srcs-$(CFG_ARM32_$(sm)) += setjmp_a32.S
 srcs-$(CFG_ARM64_$(sm)) += setjmp_a64.S
diff --git a/lib/libutils/isoc/include/malloc.h b/lib/libutils/isoc/include/malloc.h
index 4e405c03c763044db270363fd8970f4cbe34e696..1e4826425dc060289fb09baea18a5a9f6036333a 100644
--- a/lib/libutils/isoc/include/malloc.h
+++ b/lib/libutils/isoc/include/malloc.h
@@ -140,6 +140,10 @@ void nex_malloc_reset_stats(void);
 #define nex_calloc(nmemb, size) calloc(nmemb, size)
 #define nex_realloc(ptr, size) realloc(ptr, size)
 #define nex_memalign(alignment, size) memalign(alignment, size)
+#define nex_malloc_buffer_overlaps_heap(buf, len) \
+	malloc_buffer_overlaps_heap(buf, len)
+#define nex_malloc_buffer_is_within_alloced(buf, len) \
+	malloc_buffer_is_within_alloced(buf, len)
 
 #endif	/* CFG_NS_VIRTUALIZATION */
 
diff --git a/lib/libutils/isoc/include/sys/fcntl.h b/lib/libutils/isoc/include/sys/fcntl.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ff76980e56490cd2d0088d0eae1d3ccdf568291
--- /dev/null
+++ b/lib/libutils/isoc/include/sys/fcntl.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (c) 1994-2009  Red Hat, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_FCNTL_H_
+#define _SYS_FCNTL_H_
+
+#define	_FAPPEND	0x0008	/* append (writes guaranteed at the end) */
+#define	_FCREAT		0x0200	/* open with file create */
+#define	_FTRUNC		0x0400	/* open with truncation */
+
+/*
+ * Flag values for open(2) and fcntl(2)
+ */
+#define	O_RDONLY	0		/* +1 == FREAD */
+#define	O_WRONLY	1		/* +1 == FWRITE */
+#define	O_RDWR		2		/* +1 == FREAD|FWRITE */
+#define	O_APPEND	_FAPPEND
+#define	O_CREAT		_FCREAT
+#define	O_TRUNC		_FTRUNC
+
+#endif /* _SYS_FCNTL_H_ */
diff --git a/lib/libutils/isoc/sub.mk b/lib/libutils/isoc/sub.mk
index ef1ca5da8cf025407839434377295b14bf7e6875..705090211627eb39fe819e5a7ae62fe4159d0f49 100644
--- a/lib/libutils/isoc/sub.mk
+++ b/lib/libutils/isoc/sub.mk
@@ -3,6 +3,7 @@ global-incdirs-y += include
 srcs-y += bget_malloc.c
 cflags-remove-bget_malloc.c-y += -Wold-style-definition -Wredundant-decls
 cflags-bget_malloc.c-y += -Wno-sign-compare -Wno-cast-align
+cflags-bget_malloc.c-y += $(call cc-option,-Wno-deprecated-non-prototype)
 ifeq ($(sm),core)
 cflags-remove-bget_malloc.c-y += $(cflags_kasan)
 endif
diff --git a/mk/checkconf.mk b/mk/checkconf.mk
index 449b1c2b89ca303922e192e9da9529ed9dee6323..bb08d6b150a8ceef0662c965193580cbbe353bae 100644
--- a/mk/checkconf.mk
+++ b/mk/checkconf.mk
@@ -17,7 +17,8 @@ define check-conf-h
 	cnf='$(strip $(foreach var,				\
 		$(call cfg-vars-by-prefix,$1),			\
 		$(call cfg-make-define,$(var))))';		\
-	guard="_`echo $@ | tr -- -/.+ _`_";			\
+	guardpath="$(patsubst $(out-dir)/%,%,$@)"		\
+	guard="_`echo "$${guardpath}" | tr -- -/.+ _`_";	\
 	mkdir -p $(dir $@);					\
 	echo "#ifndef $${guard}" >$@.tmp;			\
 	echo "#define $${guard}" >>$@.tmp;			\
diff --git a/mk/clang.mk b/mk/clang.mk
index a045beee8482fc09bb703fbc584b09c5b8d84321..d08b26e6f9585eac8ec6b5076c04e60b8eed5eb2 100644
--- a/mk/clang.mk
+++ b/mk/clang.mk
@@ -26,7 +26,8 @@ nostdinc$(sm)	:= -nostdinc -isystem $(shell $(CC$(sm)) \
 			-print-file-name=include 2> /dev/null)
 
 comp-cflags-warns-clang := -Wno-language-extension-token \
-			 -Wno-gnu-zero-variadic-macro-arguments
+			 -Wno-gnu-zero-variadic-macro-arguments \
+			 -Wno-gnu-alignof-expression
 
 # Note, use the compiler runtime library (libclang_rt.builtins.*.a) instead of
 # libgcc for clang
diff --git a/mk/compile.mk b/mk/compile.mk
index b3d807ba42cde9d80ce0a0bb540b818f0f1bb45a..aa3f78aed37c4059d201412fb80ee0267b073f9d 100644
--- a/mk/compile.mk
+++ b/mk/compile.mk
@@ -80,7 +80,8 @@ comp-compiler-$2 := $$(CC$(sm))
 comp-flags-$2 = $$(filter-out $$(CFLAGS_REMOVE) $$(cflags-remove) \
 			      $$(cflags-remove-$$(comp-sm-$2)) \
 			      $$(cflags-remove-$2), \
-		   $$(CFLAGS$$(arch-bits-$$(comp-sm-$2))) $$(CFLAGS_WARNS) \
+		   $$(CFLAGS$$(arch-bits-$$(comp-sm-$2))) $$(CFLAGS) \
+		   $$(CFLAGS_WARNS) \
 		   $$(comp-cflags$$(comp-sm-$2)) $$(cflags$$(comp-sm-$2)) \
 		   $$(cflags-lib$$(comp-lib-$2)) $$(cflags-$2))
 ifeq ($C,1)
@@ -120,7 +121,7 @@ comp-cppflags-$2 = $$(filter-out $$(CPPFLAGS_REMOVE) $$(cppflags-remove) \
 		      $$(addprefix -I,$$(incdirs-$2)) \
 		      $$(cppflags$$(comp-sm-$2)) \
 		      $$(cppflags-lib$$(comp-lib-$2)) $$(cppflags-$2)) \
-		      -D__FILE_ID__=$$(subst -,_,$$(subst /,_,$$(subst .,_,$1)))
+		      -D__FILE_ID__=$$(subst -,_,$$(subst /,_,$$(subst .,_,$$(patsubst $$(out-dir)/%,%,$1))))
 
 comp-flags-$2 += -MD -MF $$(comp-dep-$2) -MT $$@
 comp-flags-$2 += $$(comp-cppflags-$2)
@@ -162,8 +163,7 @@ $2: $1 FORCE-GENSRC$(sm)
 
 endef
 
-$(foreach f, $(srcs), $(eval $(call \
-	process_srcs,$(f),$(out-dir)/$(base-prefix)$$(basename $f).o)))
+$(foreach f, $(srcs), $(eval $(call process_srcs,$(f),$$(oname-$(sm)-$(f)))))
 
 # Handle generated source files, that is, files that are compiled from out-dir
 $(foreach f, $(gen-srcs), $(eval $(call process_srcs,$(f),$$(basename $f).o)))
@@ -253,8 +253,6 @@ $(foreach f,$(asm-defines-files),$(eval $(call gen-asm-defines-file,$(f),$(out-d
 
 # Device tree source file compilation
 DTC := dtc
-DTC_FLAGS += -I dts -O dtb
-DTC_FLAGS += -Wno-unit_address_vs_reg
 
 define gen-dtb-file
 # dts file path/name in $1
@@ -263,6 +261,7 @@ define gen-dtb-file
 dtb-basename-$2	:= $$(basename $$(notdir $2))
 dtb-predts-$2   := $$(dir $2)$$(dtb-basename-$2).pre.dts
 dtb-predep-$2	:= $$(dir $2).$$(dtb-basename-$2).pre.dts.d
+dtb-precmd-file-$2 := $$(dir $2).$$(dtb-basename-$2).pre.dts.cmd
 dtb-dep-$2	:= $$(dir $2).$$(notdir $2).d
 dtb-cmd-file-$2	:= $$(dir $2).$$(notdir $2).cmd
 
@@ -272,34 +271,40 @@ cleanfiles := $$(cleanfiles) $2 \
 
 dtb-cppflags-$2 := -Icore/include/ -x assembler-with-cpp -Ulinux -Uunix \
 		   -E -ffreestanding $$(CPPFLAGS) \
-		   -MD -MF $$(dtb-predep-$2) -MT $2
+		   -MD -MF $$(dtb-predep-$2) -MT $$(dtb-predts-$2)
 
-dtb-dtcflags-$2	:= $$(DTC_FLAGS) -d $$(dtb-dep-$2)
+dtb-dtcflags-$2	:= $$(DTC_FLAGS) -I dts -O dtb -Wno-unit_address_vs_reg \
+		   -d $$(dtb-dep-$2)
 
 -include $$(dtb-dep-$2)
 -include $$(dtb-predep-$2)
 -include $$(dtb-cmd-file-$2)
+-include $$(dtb-precmd-file-$2)
 
 dtb-precmd-$2 = $$(CPP$(sm)) $$(dtb-cppflags-$2) -o $$(dtb-predts-$2) $$<
 dtb-cmd-$2 = $$(DTC) $$(dtb-dtcflags-$2) -o $$@ $$(dtb-predts-$2)
 
-$2: $1 FORCE
-# Check if any prerequisites are newer than the target and
-# check if command line has changed
+$$(dtb-predts-$2): $1 FORCE
 	$$(if $$(strip $$(filter-out FORCE, $$?) \
 	    $$(filter-out $$(dtb-precmd-$2), $$(dtb-old-precmd-$2)) 	\
-	    $$(filter-out $$(dtb-old-precmd-$2), $$(dtb-precmd-$2)) 	\
-	    $$(filter-out $$(dtb-cmd-$2), $$(dtb-old-cmd-$2)) 		\
-	    $$(filter-out $$(dtb-old-cmd-$2), $$(dtb-cmd-$2))),		\
-		@set -e; 						\
+	    $$(filter-out $$(dtb-old-precmd-$2), $$(dtb-precmd-$2))), 	\
+		$(q)set -e; 						\
 		mkdir -p $$(dir $2); 					\
 		$(cmd-echo-silent) '  CPP     $$(dtb-predts-$2)'; 	\
 		$$(dtb-precmd-$2);					\
+		echo "dtb-old-precmd-$2 := $$(subst \",\\\",$$(dtb-precmd-$2))" > \
+			$$(dtb-precmd-file-$2) ;\
+	)
+
+$2: $$(dtb-predts-$2) FORCE
+	$$(if $$(strip $$(filter-out FORCE, $$?) \
+	    $$(filter-out $$(dtb-cmd-$2), $$(dtb-old-cmd-$2)) 		\
+	    $$(filter-out $$(dtb-old-cmd-$2), $$(dtb-cmd-$2))),		\
+		$(q)set -e; 						\
+		mkdir -p $$(dir $2); 					\
 		$(cmd-echo-silent) '  DTC     $$@'; 			\
 		$$(dtb-cmd-$2);						\
-		echo "dtb-old-precmd-$2 := $$(subst \",\\\",$$(dtb-precmd-$2))" > \
-			$$(dtb-cmd-file-$2) ;\
-		echo "dtb-old-cmd-$2 := $$(subst \",\\\",$$(dtb-cmd-$2))" >> \
+		echo "dtb-old-cmd-$2 := $$(subst \",\\\",$$(dtb-cmd-$2))" > \
 			$$(dtb-cmd-file-$2) ;\
 	)
 
diff --git a/mk/config.mk b/mk/config.mk
index 1247ccef935472ef6cb267f884ac464790982040..5bc6ac415f6b37d4845933fd8e5a0dee81eb5ab3 100644
--- a/mk/config.mk
+++ b/mk/config.mk
@@ -17,9 +17,15 @@
 # (CFG_* variables only).
 
 # Cross-compiler prefix and suffix
+ifeq ($(ARCH),arm)
 CROSS_COMPILE ?= arm-linux-gnueabihf-
-CROSS_COMPILE32 ?= $(CROSS_COMPILE)
 CROSS_COMPILE64 ?= aarch64-linux-gnu-
+endif
+ifeq ($(ARCH),riscv)
+CROSS_COMPILE ?= riscv-linux-gnu-
+CROSS_COMPILE64 ?= riscv64-linux-gnu-
+endif
+CROSS_COMPILE32 ?= $(CROSS_COMPILE)
 COMPILER ?= gcc
 
 # For convenience
@@ -121,17 +127,12 @@ CFG_OS_REV_REPORTS_GIT_SHA1 ?= y
 # with limited depth not including any tag, so there is really no guarantee
 # that TEE_IMPL_VERSION contains the major and minor revision numbers.
 CFG_OPTEE_REVISION_MAJOR ?= 4
-CFG_OPTEE_REVISION_MINOR ?= 1
+CFG_OPTEE_REVISION_MINOR ?= 5
 CFG_OPTEE_REVISION_EXTRA ?=
 
 # Trusted OS implementation version
 TEE_IMPL_VERSION ?= $(shell git describe --always --dirty=-dev 2>/dev/null || \
 		      echo Unknown_$(CFG_OPTEE_REVISION_MAJOR).$(CFG_OPTEE_REVISION_MINOR))$(CFG_OPTEE_REVISION_EXTRA)
-ifeq ($(CFG_OS_REV_REPORTS_GIT_SHA1),y)
-TEE_IMPL_GIT_SHA1 := 0x$(shell git rev-parse --short=8 HEAD 2>/dev/null || echo 0)
-else
-TEE_IMPL_GIT_SHA1 := 0x0
-endif
 
 # Trusted OS implementation manufacturer name
 CFG_TEE_MANUFACTURER ?= LINARO
@@ -213,6 +214,14 @@ CFG_RPMB_TESTKEY ?= n
 # - RPMB key provisioning in a controlled environment (factory setup)
 CFG_RPMB_WRITE_KEY ?= n
 
+# For the kernel driver to enable in-kernel RPMB routing it must know in
+# advance that OP-TEE supports it. Setting CFG_RPMB_ANNOUNCE_PROBE_CAP=y
+# will announce OP-TEE's capability for RPMB probing to the kernel and it
+# will use in-kernel RPMB routing, without it all RPMB commands will be
+# routed to tee-supplicant. This option is intended give some control over
+# how the RPMB commands are routed to simplify testing.
+CFG_RPMB_ANNOUNCE_PROBE_CAP ?= y
+
 _CFG_WITH_SECURE_STORAGE := $(call cfg-one-enabled,CFG_REE_FS CFG_RPMB_FS)
 
 # Signing key for OP-TEE TA's
@@ -514,6 +523,13 @@ endif
 # editing of the supplied DTB.
 CFG_DTB_MAX_SIZE ?= 0x10000
 
+# CFG_DT_CACHED_NODE_INFO, when enabled, parses the embedded DT at boot
+# time and caches some information to speed up retrieve of DT node data,
+# more specifically those for which libfdt parses the full DTB to find
+# the target node information.
+CFG_DT_CACHED_NODE_INFO ?= $(CFG_EMBED_DTB)
+$(eval $(call cfg-depends-all,CFG_DT_CACHED_NODE_INFO,CFG_EMBED_DTB))
+
 # Maximum size of the init info data passed to Secure Partitions.
 CFG_SP_INIT_INFO_MAX_SIZE ?= 0x1000
 
@@ -703,13 +719,6 @@ CFG_CORE_LARGE_PHYS_ADDR ?= n
 # Set this to a lower value to reduce the TA memory footprint.
 CFG_TA_BIGNUM_MAX_BITS ?= 2048
 
-# Define the maximum size, in bits, for big numbers in the TEE core (privileged
-# layer).
-# This value is an upper limit for the key size in any cryptographic algorithm
-# implemented by the TEE core.
-# Set this to a lower value to reduce the memory footprint.
-CFG_CORE_BIGNUM_MAX_BITS ?= 4096
-
 # Not used since libmpa was removed. Force the values to catch build scripts
 # that would set = n.
 $(call force,CFG_TA_MBEDTLS_MPI,y)
@@ -890,7 +899,7 @@ CFG_PREALLOC_RPC_CACHE ?= y
 # CFG_DRIVERS_CLK_FIXED add support for "fixed-clock" compatible clocks
 # CFG_DRIVERS_CLK_EARLY_PROBE makes clocks probed at early_init initcall level.
 # CFG_DRIVERS_CLK_PRINT_TREE embeds a helper function to print the clock tree
-# state on OP-TEE core console with the debug trace level.
+# state on OP-TEE core console with the info trace level.
 CFG_DRIVERS_CLK ?= n
 CFG_DRIVERS_CLK_DT ?= $(call cfg-all-enabled,CFG_DRIVERS_CLK CFG_DT)
 CFG_DRIVERS_CLK_FIXED ?= $(CFG_DRIVERS_CLK_DT)
@@ -963,6 +972,12 @@ endif
 endif # CFG_WARN_INSECURE defined
 CFG_INSECURE ?= y
 
+ifneq ($(CFG_INSECURE),y)
+ifneq ($(CFG_CORE_ASLR_SEED),)
+$(error CFG_CORE_ASLR_SEED requires CFG_INSECURE=y)
+endif
+endif
+
 # Enables warnings for declarations mixed with statements
 CFG_WARN_DECL_AFTER_STATEMENT ?= y
 
@@ -1023,6 +1038,15 @@ CFG_CORE_ASYNC_NOTIF ?= n
 $(call force,_CFG_CORE_ASYNC_NOTIF_DEFAULT_IMPL,$(CFG_CORE_ASYNC_NOTIF))
 endif
 
+# Enable callout service
+CFG_CALLOUT ?= $(CFG_CORE_ASYNC_NOTIF)
+
+# Enable notification based test watchdog
+CFG_NOTIF_TEST_WD ?= $(call cfg-all-enabled,CFG_ENABLE_EMBEDDED_TESTS \
+		       CFG_CALLOUT CFG_CORE_ASYNC_NOTIF)
+$(eval $(call cfg-depends-all,CFG_NOTIF_TEST_WD,CFG_CALLOUT \
+	 CFG_CORE_ASYNC_NOTIF))
+
 $(eval $(call cfg-enable-all-depends,CFG_MEMPOOL_REPORT_LAST_OFFSET, \
 	 CFG_WITH_STATS))
 
@@ -1095,6 +1119,26 @@ ifeq (y-y,$(CFG_CORE_PREALLOC_EL0_TBLS)-$(CFG_WITH_PAGER))
 $(error "CFG_WITH_PAGER can't support CFG_CORE_PREALLOC_EL0_TBLS")
 endif
 
+# CFG_PGT_CACHE_ENTRIES defines the number of entries on the memory
+# mapping page table cache used for Trusted Application mapping.
+# CFG_PGT_CACHE_ENTRIES is ignored when CFG_CORE_PREALLOC_EL0_TBLS
+# is enabled.
+#
+# A proper value for CFG_PGT_CACHE_ENTRIES depends on many factors:
+# CFG_WITH_LPAE, CFG_TA_ASLR, size of TAs, size of memrefs passed
+# to TA, CFG_ULIBS_SHARED and possibly others. The default value
+# is based on the number of threads as an indicator on how large
+# the system might be.
+ifeq ($(CFG_NUM_THREADS),1)
+CFG_PGT_CACHE_ENTRIES ?= 4
+endif
+ifeq ($(CFG_NUM_THREADS),2)
+ifneq ($(CFG_WITH_LPAE),y)
+CFG_PGT_CACHE_ENTRIES ?= 8
+endif
+endif
+CFG_PGT_CACHE_ENTRIES ?= ($(CFG_NUM_THREADS) * 2)
+
 # User TA runtime context dump.
 # When this option is enabled, OP-TEE provides a debug method for
 # developer to dump user TA's runtime context, including TA's heap stats.
@@ -1125,6 +1169,15 @@ CFG_TA_OPTEE_CORE_API_COMPAT_1_1 ?= n
 # Note that this violates GP requirements of HMAC size range.
 CFG_HMAC_64_1024_RANGE ?= n
 
+# CFG_RSA_PUB_EXPONENT_3, when enabled, allows RSA public exponents in the
+# range 3 <= e < 2^256. This is needed to pass AOSP KeyMint VTS tests:
+#    Link to tests: https://android.googlesource.com/platform/hardware/interfaces/+/refs/heads/main/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+#    Module: VtsAidlKeyMintTargetTest
+#    Testcases: - PerInstance/EncryptionOperationsTest.RsaNoPaddingSuccess
+# When CFG_RSA_PUB_EXPONENT_3 is disabled, RSA public exponents must conform
+# to NIST SP800-56B recommendation and be in the range 65537 <= e < 2^256.
+CFG_RSA_PUB_EXPONENT_3 ?= n
+
 # Enable a hardware pbkdf2 function
 # By default use standard pbkdf2 implementation
 CFG_CRYPTO_HW_PBKDF2 ?= n
@@ -1148,4 +1201,72 @@ CFG_DRIVERS_REMOTEPROC ?= n
 
 # CFG_REMOTEPROC_PTA, when enabled, embeds remote processor management PTA
 # service.
-CFG_REMOTEPROC_PTA ?= n
\ No newline at end of file
+CFG_REMOTEPROC_PTA ?= n
+
+# When enabled, CFG_WIDEVINE_HUK uses the widevine HUK provided by secure
+# DTB as OP-TEE HUK.
+CFG_WIDEVINE_HUK ?= n
+$(eval $(call cfg-depends-all,CFG_WIDEVINE_HUK,CFG_DT))
+
+# When enabled, CFG_WIDEVINE_PTA embeds a PTA that exposes the keys under
+# DT node "/options/op-tee/widevine" to some specific TAs.
+CFG_WIDEVINE_PTA ?= n
+$(eval $(call cfg-depends-all,CFG_WIDEVINE_PTA,CFG_DT CFG_WIDEVINE_HUK))
+
+# When enabled, CFG_VERAISON_ATTESTATION_PTA embeds remote attestation PTA
+# service. Note: This is an experimental feature and should be used
+# with caution in production environments.
+CFG_VERAISON_ATTESTATION_PTA ?= n
+ifeq ($(CFG_VERAISON_ATTESTATION_PTA),y)
+$(call force,CFG_QCBOR,y)
+endif
+
+# When enabled, CFG_VERAISON_ATTESTATION_PTA_TEST_KEY embeds a test key.
+# Note: CFG_VERAISON_ATTESTATION_PTA_TEST_KEY must be enabled for
+# CFG_VERAISON_ATTESTATION_PTA to work.
+CFG_VERAISON_ATTESTATION_PTA_TEST_KEY ?= y
+ifneq ($(CFG_VERAISON_ATTESTATION_PTA_TEST_KEY),y)
+$(error "CFG_VERAISON_ATTESTATION_PTA_TEST_KEY must be enabled")
+endif
+
+# CFG_SEMIHOSTING_CONSOLE, when enabled, embeds a semihosting console driver.
+# When CFG_SEMIHOSTING_CONSOLE_FILE=NULL, OP-TEE console reads/writes
+# trace messages from/to the debug terminal of the semihosting host computer.
+# When CFG_SEMIHOSTING_CONSOLE_FILE="{your_log_file}", OP-TEE console
+# outputs trace messages to that file. Output to "optee.log" by default.
+CFG_SEMIHOSTING_CONSOLE ?= n
+ifeq ($(CFG_SEMIHOSTING_CONSOLE),y)
+$(call force,CFG_SEMIHOSTING,y)
+endif
+CFG_SEMIHOSTING_CONSOLE_FILE ?= "optee.log"
+ifeq ($(CFG_SEMIHOSTING_CONSOLE_FILE),)
+$(error CFG_SEMIHOSTING_CONSOLE_FILE cannot be empty)
+endif
+
+# Semihosting is a debugging mechanism that enables code running on an embedded
+# system (also called the target) to communicate with and use the I/O of the
+# host computer.
+CFG_SEMIHOSTING ?= n
+
+# CFG_FFA_CONSOLE, when enabled, embeds a FFA console driver. OP-TEE console
+# writes trace messages via FFA interface to the SPM (Secure Partition Manager)
+# like hafnium.
+CFG_FFA_CONSOLE ?= n
+
+# CFG_CORE_UNSAFE_MODEXP, when enabled, makes modular exponentiation on TEE
+# core use 'unsafe' algorithm having better performance. To resist against
+# timing attacks, 'safe' one is designed to take constant-time that is
+# generally much slower.
+CFG_CORE_UNSAFE_MODEXP ?= n
+
+# CFG_TA_MBEDTLS_UNSAFE_MODEXP, similar to CFG_CORE_UNSAFE_MODEXP,
+# when enabled, makes MBedTLS library for TAs use 'unsafe' modular
+# exponentiation algorithm.
+CFG_TA_MEBDTLS_UNSAFE_MODEXP ?= n
+
+# CFG_BOOT_MEM, when enabled, adds stack like memory allocation during boot.
+ifeq ($(ARCH),arm)
+$(call force,CFG_BOOT_MEM,y)
+else
+CFG_BOOT_MEM ?= n
+endif
diff --git a/mk/lib.mk b/mk/lib.mk
index 029260d7af8bf3133793d5363b72fccf83ddb9ea..315cae250382241dbd85ed785e5e68535f623adf 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -40,8 +40,10 @@ endif
 cleanfiles	:= $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(cleanfiles)
 libfiles	:= $(lib-libfile) $(lib-shlibfile) $(lib-shlibstrippedfile) $(lib-shlibtafile) $(lib-libuuidln) $(libfiles)
 libdirs 	:= $(out-dir)/$(base-prefix)$(libdir) $(libdirs)
+ifneq (,$(objs))
 libnames	:= $(libname) $(libnames)
 libdeps		:= $(lib-libfile) $(libdeps)
+endif
 
 SIGN = scripts/sign_encrypt.py
 TA_SIGN_KEY ?= keys/default_ta.pem
diff --git a/mk/macros.mk b/mk/macros.mk
index 277ecf2212cf3836792bffbe2816551d95ef1fea..93d13fb22b260140f1fd3931d1fb5c09f65d6f6c 100644
--- a/mk/macros.mk
+++ b/mk/macros.mk
@@ -7,3 +7,37 @@ define mv-if-changed
 		mv $1 $2;					\
 	fi
 endef
+
+define update-buildcount
+	@$(cmd-echo-silent) '  UPD     $(1)'
+	$(q)if [ ! -f $(1) ]; then \
+		mkdir -p $(dir $(1)); \
+		echo 1 >$(1); \
+	else \
+		expr 0`cat $(1)` + 1 >$(1); \
+	fi
+endef
+
+# filter-out to workaround objdump warning
+version-o-cflags = $(filter-out -g3,$(CFLAGS) $(core-platform-cflags) \
+			$(platform-cflags) $(cflagscore))
+# SOURCE_DATE_EPOCH defined for reproducible builds
+ifneq ($(SOURCE_DATE_EPOCH),)
+date-opts = -d @$(SOURCE_DATE_EPOCH)
+endif
+DATE_STR = `LC_ALL=C date -u $(date-opts)`
+CORE_CC_VERSION = `$(CCcore) -v 2>&1 | grep "version " | sed 's/ *$$//'`
+define gen-version-o
+	$(call update-buildcount,$(link-out-dir)/.buildcount)
+	@$(cmd-echo-silent) '  GEN     $(link-out-dir)/version.o'
+	$(q)cd $(link-out-dir) && \
+		BUILD_COUNT_STR=`cat .buildcount` && \
+		echo -e "const char core_v_str[] =" \
+		"\"$(TEE_IMPL_VERSION) \"" \
+		"\"($(CORE_CC_VERSION)) \"" \
+		"\"#$${BUILD_COUNT_STR} \"" \
+		"\"$(DATE_STR) \"" \
+		"\"$(CFG_KERN_LINKER_ARCH)\";\n" \
+		| $(CCcore) $(version-o-cflags) \
+			-xc - -c -o version.o
+endef
diff --git a/mk/subdir.mk b/mk/subdir.mk
index d280c309ecf54fefd31c8fa381e7d3f8468e77b1..3ca414b8211fe1337794b5604d02ad2f2d53b659 100644
--- a/mk/subdir.mk
+++ b/mk/subdir.mk
@@ -23,33 +23,18 @@ asm-defines-files :=
 
 uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
 
-define process-subdir-srcs-y
-ifeq ($$(sub-dir),.)
-srcs 				+= $1
-oname				:= $(out-dir)/$(base-prefix)$(basename $1).o
-else
-ifneq ($(filter /%,$(1)),)
-# $1 is an absolute path - start with "/"
-srcs 				+= $1
-oname				:= $(out-dir)/$(base-prefix)$(basename $1).o
-else
-srcs				+= $(sub-dir)/$1
-oname				:= $(out-dir)/$(base-prefix)$(basename $$(sub-dir)/$1).o
-endif
-endif
-cflags-$$(oname) 		:= $$(cflags-y) $$(cflags-$(1)-y)
-cflags-remove-$$(oname) 	:= $$(cflags-remove-y) \
-					$$(cflags-remove-$(1)-y)
-cxxflags-$$(oname) 		:= $$(cxxflags-y) $$(cxxflags-$(1)-y)
-cxxflags-remove-$$(oname) 	:= $$(cxxflags-remove-y) \
-					$$(cxxflags-remove-$(1)-y)
-cppflags-$$(oname) 		:= $$(cppflags-y) $$(cppflags-$(1)-y)
-cppflags-remove-$$(oname) 	:= $$(cppflags-remove-y) \
-					$$(cppflags-remove-$(1)-y)
-aflags-$$(oname) 		:= $$(aflags-y) $$(aflags-$(1)-y)
-aflags-remove-$$(oname) 	:= $$(aflags-remove-y) \
-					$$(aflags-remove-$(1)-y)
-incdirs-$$(oname)		:= $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y))
+define process-file-vars-helper
+# $1 is local source file name
+# $2 is output file name
+cflags-$(2) 		:= $$(cflags-y) $$(cflags-$(1)-y)
+cflags-remove-$(2) 	:= $$(cflags-remove-y) $$(cflags-remove-$(1)-y)
+cxxflags-$(2) 		:= $$(cxxflags-y) $$(cxxflags-$(1)-y)
+cxxflags-remove-$(2) 	:= $$(cxxflags-remove-y) $$(cxxflags-remove-$(1)-y)
+cppflags-$(2) 		:= $$(cppflags-y) $$(cppflags-$(1)-y)
+cppflags-remove-$(2) 	:= $$(cppflags-remove-y) $$(cppflags-remove-$(1)-y)
+aflags-$(2) 		:= $$(aflags-y) $$(aflags-$(1)-y)
+aflags-remove-$(2) 	:= $$(aflags-remove-y) $$(aflags-remove-$(1)-y)
+incdirs-$(2)		:= $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y))
 # Clear local filename specific variables to avoid accidental reuse
 # in another subdirectory
 cflags-$(1)-y 			:=
@@ -64,8 +49,48 @@ cppflags-lib-y			:=
 aflags-$(1)-y 			:=
 aflags-remove-$(1)-y		:=
 incdirs-$(1)-y			:=
-fname				:=
-oname				:=
+endef #process-file-vars-helper
+
+define process-file-vars
+# $1 is local source file name
+# $2 is output file name
+# $3 is tree source file name
+oname-$(sm)-$3	:= $$(if $$(oname-$1-y),$(out-dir)/$(base-prefix)/$$(oname-$1-y),$2)
+$$(eval $$(call process-file-vars-helper,$1,$$(oname-$(sm)-$3)))
+endef
+
+define process-subdir-srcs-y
+ifeq ($$(sub-dir),.)
+srcs 		+= $1
+fname		:= $1
+oname		:= $(out-dir)/$(base-prefix)$(basename $1).o
+else
+ifneq ($(filter /%,$(1)),)
+# $1 is an absolute path - start with "/"
+srcs 		+= $1
+fname		:= $1
+oname		:= $(out-dir)/$(base-prefix)$(basename $1).o
+else
+srcs		+= $(sub-dir)/$1
+fname		:= $(sub-dir)/$1
+oname		:= $(out-dir)/$(base-prefix)$(basename $$(sub-dir)/$1).o
+endif
+endif
+$$(eval $$(call process-file-vars,$1,$$(oname),$$(fname)))
+endef #process-subdir-srcs-y
+
+define process-subdir-srcs_ext-y
+ifneq ($(filter /%,$(1)),)
+$$(error Absolute path not supported for srcs_ext-y: $(1))
+endif
+srcs		+= $2/$1
+fname		:= $2/$1
+ifeq ($$(sub-dir),.)
+oname		:= $(out-dir)/$(base-prefix)$(basename $1).o
+else
+oname		:= $(out-dir)/$(base-prefix)$(basename $$(sub-dir)/$1).o
+endif
+$$(eval $$(call process-file-vars,$1,$$(oname),$$(fname)))
 endef #process-subdir-srcs-y
 
 define process-subdir-gensrcs-helper
@@ -90,36 +115,7 @@ $2: $$(depends-$1)
 	$(q)mkdir -p $4
 	$(q)$$(recipe-$2)
 
-cflags-$$(oname) 		:= $$(cflags-y) $$(cflags-$(1)-y)
-cflags-remove-$$(oname) 	:= $$(cflags-remove-y) \
-					$$(cflags-remove-$(1)-y)
-cxxflags-$$(oname) 		:= $$(cxxflags-y) $$(cxxflags-$(1)-y)
-cxxflags-remove-$$(oname) 	:= $$(cxxflags-remove-y) \
-					$$(cxxflags-remove-$(1)-y)
-cppflags-$$(oname) 		:= $$(cppflags-y) $$(cppflags-$(1)-y)
-cppflags-remove-$$(oname) 	:= $$(cppflags-remove-y) \
-					$$(cppflags-remove-$(1)-y)
-aflags-$$(oname) 		:= $$(aflags-y) $$(aflags-$(1)-y)
-aflags-remove-$$(oname) 	:= $$(aflags-remove-y) \
-					$$(aflags-remove-$(1)-y)
-incdirs-$$(oname)		:= $$(thissubdir-incdirs) $$(addprefix $(sub-dir)/,$$(incdirs-$(1)-y))
-# Clear local filename specific variables to avoid accidental reuse
-# in another subdirectory
-cflags-$(1)-y 			:=
-cflags-remove-$(1)-y		:=
-cflags-lib-y			:=
-cxxflags-$(1)-y 			:=
-cxxflags-remove-$(1)-y		:=
-cxxflags-lib-y			:=
-cppflags-$(1)-y			:=
-cppflags-remove-$(1)-y		:=
-cppflags-lib-y			:=
-aflags-$(1)-y 			:=
-aflags-remove-$(1)-y		:=
-incdirs-$(1)-y			:=
-fname				:=
-oname				:=
-
+$$(eval $$(call process-file-vars,$1,$$(oname)))
 endef #process-subdir-gensrcs-helper
 
 define process-subdir-gensrcs-y
@@ -140,7 +136,8 @@ endif
 
 include $1/sub.mk
 sub-subdirs := $$(addprefix $1/,$$(subdirs-y)) $$(subdirs_ext-y)
-incdirs$(sm) := $(incdirs$(sm)) $$(addprefix $1/,$$(global-incdirs-y))
+incdirs$(sm) := $(incdirs$(sm)) $$(addprefix $1/,$$(global-incdirs-y)) $$(global-incdirs_ext-y)
+cppflags$(sm) := $$(cppflags$(sm)) $$(global-cppflags-y)
 thissubdir-incdirs := $(out-dir)/$(base-prefix)$1 $$(addprefix $1/,$$(incdirs-y)) $$(incdirs_ext-y)
 ifneq ($$(libname),)
 incdirs-lib$$(libname)-$$(sm) := $$(incdirs-lib$$(libname)-$$(sm)) $$(addprefix $1/,$$(incdirs-lib-y))
@@ -152,9 +149,13 @@ endif
 # Process files in current directory
 $$(foreach g, $$(gensrcs-y), $$(eval $$(call process-subdir-gensrcs-y,$$(g))))
 $$(foreach s, $$(srcs-y), $$(eval $$(call process-subdir-srcs-y,$$(s))))
+$$(foreach s, $$(srcs_ext-y), $$(eval $$(call \
+	process-subdir-srcs_ext-y,$$(s),$$(firstword $$(srcs_ext_base-y)))))
 $$(foreach a, $$(asm-defines-y), $$(eval $$(call process-subdir-asm-defines-y,$$(a))))
 # Clear flags used when processing current directory
 srcs-y :=
+srcs_ext-y :=
+srcs_ext_base-y :=
 cflags-y :=
 cflags-lib-y :=
 cxxflags-y :=
@@ -168,6 +169,8 @@ aflags-remove-y :=
 subdirs-y :=
 subdirs_ext-y :=
 global-incdirs-y :=
+global-incdirs_ext-y :=
+global-cppflags-y :=
 incdirs-lib-y :=
 incdirs-y :=
 incdirs_ext-y :=
diff --git a/scripts/checkpatch_inc.sh b/scripts/checkpatch_inc.sh
index 166774af53a59d42861e65033424fe77894d5494..83adda4c15b0158620d2ea711b00ce5df81d324e 100644
--- a/scripts/checkpatch_inc.sh
+++ b/scripts/checkpatch_inc.sh
@@ -13,6 +13,7 @@ CHECKPATCH_IGNORE=$(echo \
 		core/arch/arm/plat-ti/api_monitor_index_a{9,15}.h \
 		core/arch/arm/dts \
 		ta/pkcs11/scripts/verify-helpers.sh \
+		core/lib/qcbor \
 		core/arch/riscv/include/encoding.h )
 _CP_EXCL=$(for p in $CHECKPATCH_IGNORE; do echo ":(exclude)$p" ; done)
 
diff --git a/scripts/ftrace_format.py b/scripts/ftrace_format.py
index 50a947db870430c57d0ebb319fa6241bce264961..b1f16c4636d9117ad3fc638a6ddf75257a7ab217 100755
--- a/scripts/ftrace_format.py
+++ b/scripts/ftrace_format.py
@@ -31,9 +31,12 @@ def format_time(ns):
     if ns < 1000000:
         us = ns / 1000
         return f"{us:7.3f} us"
-    else:
+    elif ns < 1000000000:
         ms = ns / 1000000
         return f"{ms:7.3f} ms"
+    else:
+        s = ns / 1000000000
+        return f"{s:7.3f} s "
 
 
 def display(depth, val):
diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py
index 1d2b49e91c19d943a29b72e5eb6539dc334a94ba..5bdad12a10bf13025c64d50d1d295bbcea457edb 100755
--- a/scripts/gen_compile_commands.py
+++ b/scripts/gen_compile_commands.py
@@ -177,7 +177,7 @@ def process_line(root_directory, command_prefix, file_path):
     # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the
     # kernel version). The compile_commands.json file is not interpreted
     # by Make, so this code replaces the escaped version with '#'.
-    prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#')  # noqa: W605
+    prefix = command_prefix.replace(r'\#', '#').replace('$(pound)', '#')
 
     # Use os.path.abspath() to normalize the path resolving '.' and '..' .
     abs_path = os.path.abspath(os.path.join(root_directory, file_path))
diff --git a/scripts/sign_encrypt.py b/scripts/sign_encrypt.py
index 435d63be76057679459c269d9f23531a7fa9af27..ad47a417b692b6a18557bf79cc83477d144e766f 100755
--- a/scripts/sign_encrypt.py
+++ b/scripts/sign_encrypt.py
@@ -245,7 +245,7 @@ def get_args():
     arg_add_dig(parser_digest)
 
     parser_stitch = subparsers.add_parser(
-        'stitch', aliases=['stitch-ta'], prog=parser.prog + ' stich',
+        'stitch', aliases=['stitch-ta'], prog=parser.prog + ' stitch',
         help='Generate loadable signed and encrypted TA binary image file' +
         ' from TA raw image and its signature')
     parser_stitch.set_defaults(func=command_stitch)
@@ -266,6 +266,7 @@ def get_args():
     arg_add_uuid(parser_verify)
     arg_add_in(parser_verify)
     arg_add_key(parser_verify)
+    arg_add_enc_key(parser_verify)
 
     parser_display = subparsers.add_parser(
         'display', prog=parser.prog + ' display',
@@ -505,9 +506,9 @@ class BinaryImage:
                 offs += EHDR_SIZE
                 [enc_algo, flags, nonce_len,
                  tag_len] = struct.unpack('<IIHH', self.ehdr)
-                if enc_value not in enc_tee_alg.values():
+                if enc_algo not in enc_tee_alg.values():
                     raise Exception('Unrecognized encrypt algorithm: 0x{:08x}'
-                                    .format(enc_value))
+                                    .format(enc_algo))
                 if nonce_len != 12:
                     raise Exception("Unexpected nonce len: {}"
                                     .format(nonce_len))
@@ -516,8 +517,10 @@ class BinaryImage:
 
                 if tag_len != 16:
                     raise Exception("Unexpected tag len: {}".format(tag_len))
-                self.tag = self.inf[-tag_len:]
-                self.ciphertext = self.inf[offs:-tag_len]
+                self.tag = self.inf[offs:offs + tag_len]
+                offs += tag_len
+
+                self.ciphertext = self.inf[offs:]
                 if len(self.ciphertext) != img_size:
                     raise Exception("Unexpected ciphertext size: ",
                                     "got {}, expected {}"
@@ -598,7 +601,7 @@ class BinaryImage:
 
                 if enc_algo not in enc_tee_alg.values():
                     raise Exception('Unrecognized encrypt algorithm: 0x{:08x}'
-                                    .format(enc_value))
+                                    .format(enc_algo))
 
                 flags_name = 'Unkown'
                 if flags in enc_key_type.values():
@@ -617,10 +620,12 @@ class BinaryImage:
                 print('  tag_size:   {} (bytes)'.format(tag_len))
                 if tag_len != TAG_SIZE:
                     raise Exception("Unexpected tag len: {}".format(tag_len))
-                tag = self.inf[-tag_len:]
+                tag = self.inf[offs:offs+tag_len]
                 print('  tag:        {}'
                       .format(binascii.hexlify(tag).decode('ascii')))
-                ciphertext = self.inf[offs:-tag_len]
+                offs += tag_len
+
+                ciphertext = self.inf[offs:]
                 print(' TA offset:  {} (0x{:x}) bytes'.format(offs, offs))
                 print(' TA size:    {} (0x{:x}) bytes'
                       .format(len(ciphertext), len(ciphertext)))
@@ -628,7 +633,6 @@ class BinaryImage:
                     raise Exception("Unexpected ciphertext size: ",
                                     "got {}, expected {}"
                                     .format(len(ciphertext), img_size))
-                offs += tag_len
             else:
                 img = self.inf[offs:]
                 print(' TA offset:  {} (0x{:x}) bytes'.format(offs, offs))
@@ -717,11 +721,11 @@ class BinaryImage:
             else:
                 raise Exception("Unsupported image type: {}".format(img_type))
 
-    def decrypt_ta(enc_key):
+    def decrypt_ta(self, enc_key):
         from cryptography.hazmat.primitives.ciphers.aead import AESGCM
 
         cipher = AESGCM(bytes.fromhex(enc_key))
-        self.img = cipher.decrypt(self.nonce, self.ciphertext, None)
+        self.img = cipher.decrypt(self.nonce, self.ciphertext + self.tag, None)
 
     def __get_padding(self):
         from cryptography.hazmat.primitives.asymmetric import padding
@@ -911,7 +915,7 @@ def command_verify(args):
                                             next_uuid))
             if hasattr(image, 'ciphertext'):
                 if args.enc_key is None:
-                    logger.error('--enc_key needed to decrypt TA')
+                    logger.error('--enc-key needed to decrypt TA')
                     sys.exit(1)
                 image.decrypt_ta(args.enc_key)
             image.verify_signature()
diff --git a/ta/avb/entry.c b/ta/avb/entry.c
index a257c116f728b6879d9de0996ba70a2d7ddcdd51..207cf7c00a2dc8dfc2bcf44a8c899d16fcd53bf7 100644
--- a/ta/avb/entry.c
+++ b/ta/avb/entry.c
@@ -6,7 +6,6 @@
 #include <tee_internal_api_extensions.h>
 
 #include <string.h>
-#include <util.h>
 
 #define DEFAULT_LOCK_STATE	0
 
diff --git a/ta/avb/user_ta_header_defines.h b/ta/avb/user_ta_header_defines.h
index 21e49a7c24407300019282ddfb2b62dd3b649e95..f3619ceb5f912f72ef341709ada4f4395d7c34e5 100644
--- a/ta/avb/user_ta_header_defines.h
+++ b/ta/avb/user_ta_header_defines.h
@@ -14,4 +14,8 @@
 #define TA_STACK_SIZE			(16 * 1024)
 #define TA_DATA_SIZE			(16 * 1024)
 
+#define TA_VERSION			"1.0"
+
+#define TA_DESCRIPTION			"Android Verfied Boot"
+
 #endif /*__USER_TA_HEADER_DEFINES_H*/
diff --git a/ta/mk/ta_dev_kit.mk b/ta/mk/ta_dev_kit.mk
index 6d544a7a4effa408e96239094b9eddbca818d092..699470fb5f7ed92598e593016b46e712349cdc0f 100644
--- a/ta/mk/ta_dev_kit.mk
+++ b/ta/mk/ta_dev_kit.mk
@@ -126,11 +126,10 @@ include  $(ta-dev-kit-dir$(sm))/mk/subdir.mk
 
 ifneq ($(user-ta-uuid),)
 # Build target is TA
-vpath %.c $(ta-dev-kit-dir$(sm))/src
-srcs += user_ta_header.c
+spec-out-dir := $(link-out-dir$(sm))
+spec-srcs += $(ta-dev-kit-dir$(sm))/src/user_ta_header.c
 ifeq ($(sm),ta_arm32)
-vpath %.S $(ta-dev-kit-dir$(sm))/src
-srcs += ta_entry_a32.S
+spec-srcs += $(ta-dev-kit-dir$(sm))/src/ta_entry_a32.S
 endif
 endif
 
diff --git a/ta/pkcs11/include/pkcs11_ta.h b/ta/pkcs11/include/pkcs11_ta.h
index b66ed21f2838c59afd6aef81b9586570d4244698..1d7707a740908302a4b04891750bc58b690514e1 100644
--- a/ta/pkcs11/include/pkcs11_ta.h
+++ b/ta/pkcs11/include/pkcs11_ta.h
@@ -13,8 +13,8 @@
 			 { 0xa4, 0x9c, 0xbb, 0xd8, 0x27, 0xae, 0x86, 0xee } }
 
 /* PKCS11 trusted application version information */
-#define PKCS11_TA_VERSION_MAJOR			0
-#define PKCS11_TA_VERSION_MINOR			1
+#define PKCS11_TA_VERSION_MAJOR			1
+#define PKCS11_TA_VERSION_MINOR			0
 #define PKCS11_TA_VERSION_PATCH			0
 
 /* Attribute specific values */
@@ -1274,6 +1274,7 @@ enum pkcs11_certificate_category {
 enum pkcs11_mechanism_id {
 	PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN	= 0x00000,
 	PKCS11_CKM_RSA_PKCS			= 0x00001,
+	PKCS11_CKM_RSA_X_509			= 0x00003,
 	PKCS11_CKM_MD5_RSA_PKCS			= 0x00005,
 	PKCS11_CKM_SHA1_RSA_PKCS		= 0x00006,
 	PKCS11_CKM_RSA_PKCS_OAEP		= 0x00009,
@@ -1322,6 +1323,7 @@ enum pkcs11_mechanism_id {
 	PKCS11_CKM_AES_CBC			= 0x01082,
 	PKCS11_CKM_AES_CBC_PAD			= 0x01085,
 	PKCS11_CKM_AES_CTR			= 0x01086,
+	PKCS11_CKM_AES_GCM			= 0x01087,
 	PKCS11_CKM_AES_CTS			= 0x01089,
 	PKCS11_CKM_AES_CMAC			= 0x0108a,
 	PKCS11_CKM_AES_CMAC_GENERAL		= 0x0108b,
diff --git a/ta/pkcs11/src/attributes.c b/ta/pkcs11/src/attributes.c
index 1083ceae86090043937697e0511b15e90216a6b5..8f6071c15cb4f2d65554a8c0a63741229e5e9797 100644
--- a/ta/pkcs11/src/attributes.c
+++ b/ta/pkcs11/src/attributes.c
@@ -11,7 +11,6 @@
 #include <string.h>
 #include <string_ext.h>
 #include <tee_internal_api.h>
-#include <tee_internal_api_extensions.h>
 #include <trace.h>
 #include <util.h>
 
diff --git a/ta/pkcs11/src/handle.c b/ta/pkcs11/src/handle.c
index d956874b4cb710b90444558427661b19ca2718c3..e9d0e1ca5a2ec84d4fec283b992c794bc2b474a4 100644
--- a/ta/pkcs11/src/handle.c
+++ b/ta/pkcs11/src/handle.c
@@ -5,7 +5,6 @@
 
 #include <stdlib.h>
 #include <tee_internal_api.h>
-#include <tee_internal_api_extensions.h>
 
 #include "handle.h"
 
diff --git a/ta/pkcs11/src/object.c b/ta/pkcs11/src/object.c
index bbd2b682288f4f3932aab9825bea80b25db169ac..c9a95e1b274d5560455b206a074c0d3f2cb901a2 100644
--- a/ta/pkcs11/src/object.c
+++ b/ta/pkcs11/src/object.c
@@ -1094,6 +1094,7 @@ enum pkcs11_rc entry_set_attribute_value(struct pkcs11_client *client,
 	if (get_bool(obj->attributes, PKCS11_CKA_TOKEN)) {
 		rc = update_persistent_object_attributes(obj);
 		if (rc) {
+			TEE_Free(obj->attributes);
 			obj->attributes = head_old;
 			goto out;
 		}
diff --git a/ta/pkcs11/src/persistent_token.c b/ta/pkcs11/src/persistent_token.c
index 4efc7427dbbb7c981fac693f54f4b1e8f6427f58..aecbb54547dc6204cf76a9939bd80cd995ad8c85 100644
--- a/ta/pkcs11/src/persistent_token.c
+++ b/ta/pkcs11/src/persistent_token.c
@@ -584,6 +584,8 @@ struct ck_token *init_persistent_db(unsigned int token_id)
 	struct token_persistent_main *db_main = NULL;
 	struct token_persistent_objs *db_objs = NULL;
 	void *ptr = NULL;
+	void *initial_data = NULL;
+	uint32_t initial_data_size = 0;
 
 	if (!token)
 		return NULL;
@@ -666,34 +668,34 @@ struct ck_token *init_persistent_db(unsigned int token_id)
 		/*
 		 * Object stores persistent state + persistent object
 		 * references.
+		 *
+		 * Allocate the initial_data buffer to encompass the data from
+		 * both db_main and db_objs. Since the initial data for the
+		 * objects will be zeroed out upon creation, there’s no need
+		 * to copy it from db_objs.
 		 */
+		initial_data_size = sizeof(*db_main) + sizeof(*db_objs);
+		initial_data = TEE_Malloc(initial_data_size,
+					  TEE_MALLOC_FILL_ZERO);
+		if (!initial_data) {
+			EMSG("Failed to allocate initial_data buffer");
+			goto error;
+		}
+		TEE_MemMove(initial_data, db_main, sizeof(*db_main));
 		res = TEE_CreatePersistentObject(TEE_STORAGE_PRIVATE,
 						 file, sizeof(file),
 						 TEE_DATA_FLAG_ACCESS_READ |
 						 TEE_DATA_FLAG_ACCESS_WRITE,
 						 TEE_HANDLE_NULL,
-						 db_main, sizeof(*db_main),
+						 initial_data,
+						 initial_data_size,
 						 &db_hdl);
+		TEE_Free(initial_data);
 		if (res) {
 			EMSG("Failed to create db: %#"PRIx32, res);
 			goto error;
 		}
 
-		res = TEE_TruncateObjectData(db_hdl, sizeof(*db_main) +
-						     sizeof(*db_objs));
-		if (res)
-			TEE_Panic(0);
-
-		res = TEE_SeekObjectData(db_hdl, sizeof(*db_main),
-					 TEE_DATA_SEEK_SET);
-		if (res)
-			TEE_Panic(0);
-
-		db_objs->count = 0;
-		res = TEE_WriteObjectData(db_hdl, db_objs, sizeof(*db_objs));
-		if (res)
-			TEE_Panic(0);
-
 	} else {
 		goto error;
 	}
diff --git a/ta/pkcs11/src/pkcs11_attributes.c b/ta/pkcs11/src/pkcs11_attributes.c
index c0e9d7c51e9f8063dea982f6cff3261a4df4c739..2c6750a2636f27730f4da2629e957d278de77cb9 100644
--- a/ta/pkcs11/src/pkcs11_attributes.c
+++ b/ta/pkcs11/src/pkcs11_attributes.c
@@ -11,7 +11,6 @@
 #include <mbedtls/pk.h>
 #include <pkcs11_ta.h>
 #include <stdlib.h>
-#include <string_ext.h>
 #include <tee_internal_api_extensions.h>
 #include <tee_internal_api.h>
 #include <trace.h>
@@ -259,8 +258,8 @@ static enum pkcs11_rc set_mandatory_attributes(struct obj_attrs **out,
 	return rc;
 }
 
-static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id, void **value,
-					uint32_t *size)
+static enum pkcs11_rc get_default_value(enum pkcs11_attr_id id __maybe_unused,
+					void **value, uint32_t *size)
 {
 	/* should have been taken care of already */
 	assert(!pkcs11_attr_is_boolean(id));
@@ -1644,8 +1643,9 @@ static bool __maybe_unused check_attr_bval(uint32_t proc_id __maybe_unused,
  * @proc_id - PKCS11_CKM_xxx
  * @head - head of the attributes of the to-be-created object.
  */
-enum pkcs11_rc check_created_attrs_against_processing(uint32_t proc_id,
-						      struct obj_attrs *head)
+enum pkcs11_rc
+check_created_attrs_against_processing(uint32_t proc_id,
+				       struct obj_attrs *head __maybe_unused)
 {
 	/*
 	 * Processings that do not create secrets are not expected to call
@@ -1824,7 +1824,7 @@ enum pkcs11_rc check_created_attrs(struct obj_attrs *key1,
 					       &key_length);
 			if (rc)
 				return PKCS11_CKR_TEMPLATE_INCONSISTENT;
-			key_length = ROUNDUP(key_length, 8) / 8;
+			key_length = ROUNDUP_DIV(key_length, 8);
 			break;
 		case PKCS11_CKK_EC:
 		case PKCS11_CKK_EC_EDWARDS:
@@ -1945,6 +1945,7 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
 	case PKCS11_CKM_AES_CBC:
 	case PKCS11_CKM_AES_CTS:
 	case PKCS11_CKM_AES_CTR:
+	case PKCS11_CKM_AES_GCM:
 	case PKCS11_CKM_AES_CMAC:
 	case PKCS11_CKM_AES_CMAC_GENERAL:
 		if (key_class == PKCS11_CKO_SECRET_KEY &&
@@ -2081,6 +2082,7 @@ check_parent_attrs_against_processing(enum pkcs11_mechanism_id proc_id,
 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
 	case PKCS11_CKM_RSA_PKCS_OAEP:
 	case PKCS11_CKM_RSA_PKCS_PSS:
+	case PKCS11_CKM_RSA_X_509:
 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
@@ -2539,6 +2541,11 @@ static enum pkcs11_rc set_private_key_data_rsa(struct obj_attrs **head,
 	}
 
 	rsa = mbedtls_pk_rsa(pk);
+	if (!rsa) {
+		rc = PKCS11_CKR_GENERAL_ERROR;
+		goto out;
+	}
+
 	mbedtls_rc = mbedtls_rsa_export(rsa, &n, &p, &q, &d, &e);
 	if (mbedtls_rc) {
 		rc = PKCS11_CKR_ARGUMENTS_BAD;
@@ -2730,6 +2737,11 @@ encode_rsa_private_key_der(struct obj_attrs *head, void **data, uint32_t *sz)
 		goto out;
 
 	rsa = mbedtls_pk_rsa(pk);
+	if (!rsa) {
+		rc = PKCS11_CKR_GENERAL_ERROR;
+		goto out;
+	}
+
 	mbedtls_rc = mbedtls_rsa_import_raw(rsa, n, n_len, p, p_len,
 					    q, q_len, d, d_len, e, e_len);
 	if (mbedtls_rc) {
diff --git a/ta/pkcs11/src/pkcs11_helpers.c b/ta/pkcs11/src/pkcs11_helpers.c
index 364c7e6306953011e53d29d77acdc7a26d2a4cb1..2c6c3147de6fc6efffacc96caad90812e1fe0b14 100644
--- a/ta/pkcs11/src/pkcs11_helpers.c
+++ b/ta/pkcs11/src/pkcs11_helpers.c
@@ -256,6 +256,7 @@ static const struct any_id __maybe_unused string_rc[] = {
 	PKCS11_ID(PKCS11_CKR_ATTRIBUTE_TYPE_INVALID),
 	PKCS11_ID(PKCS11_CKR_ATTRIBUTE_VALUE_INVALID),
 	PKCS11_ID(PKCS11_CKR_ACTION_PROHIBITED),
+	PKCS11_ID(PKCS11_CKR_DATA_INVALID),
 	PKCS11_ID(PKCS11_CKR_DATA_LEN_RANGE),
 	PKCS11_ID(PKCS11_CKR_DEVICE_MEMORY),
 	PKCS11_ID(PKCS11_CKR_ENCRYPTED_DATA_INVALID),
diff --git a/ta/pkcs11/src/pkcs11_token.c b/ta/pkcs11/src/pkcs11_token.c
index 2633b369723b495991193fcd338171b2248ebc6a..23ecbc7c8535a0531de31a534059aa02ee91284a 100644
--- a/ta/pkcs11/src/pkcs11_token.c
+++ b/ta/pkcs11/src/pkcs11_token.c
@@ -230,7 +230,7 @@ enum pkcs11_rc set_processing_state(struct pkcs11_session *session,
 	proc->step = PKCS11_FUNC_STEP_INIT;
 	proc->tee_op_handle = TEE_HANDLE_NULL;
 	proc->tee_hash_algo = 0;
-	proc->tee_hash_op_handle = TEE_HANDLE_NULL;
+	proc->tee_op_handle2 = TEE_HANDLE_NULL;
 
 	if (obj1 && get_bool(obj1->attributes, PKCS11_CKA_ALWAYS_AUTHENTICATE))
 		proc->always_authen = true;
diff --git a/ta/pkcs11/src/pkcs11_token.h b/ta/pkcs11/src/pkcs11_token.h
index 062f1ff5405633fe651ceb5cf98ffb04b9ea1544..42563e016b5778a17b3f46b4b07f1014472a12f2 100644
--- a/ta/pkcs11/src/pkcs11_token.h
+++ b/ta/pkcs11/src/pkcs11_token.h
@@ -137,9 +137,8 @@ enum pkcs11_proc_state {
  * @relogged - true once client logged since last operation update
  * @op_step - last active operation step - update, final or one-shot
  * @tee_op_handle - handle on active crypto operation or TEE_HANDLE_NULL
+ * @tee_op_handle2 - second handle for specific operations or TEE_HANDLE_NULL
  * @tee_hash_algo - hash algorithm identifier.
- * @tee_hash_op_handle - handle on active hashing crypto operation or
- * TEE_HANDLE_NULL
  * @extra_ctx - context for the active processing
  */
 struct active_processing {
@@ -149,8 +148,8 @@ struct active_processing {
 	bool always_authen;
 	bool relogged;
 	TEE_OperationHandle tee_op_handle;
+	TEE_OperationHandle tee_op_handle2;
 	uint32_t tee_hash_algo;
-	TEE_OperationHandle tee_hash_op_handle;
 	void *extra_ctx;
 };
 
diff --git a/ta/pkcs11/src/processing.c b/ta/pkcs11/src/processing.c
index 0fc26b37597b0c4936cada804b84ee8eb0d8bef2..6ce078dcafb793d367098bf996d14c7c8672fdfb 100644
--- a/ta/pkcs11/src/processing.c
+++ b/ta/pkcs11/src/processing.c
@@ -104,10 +104,12 @@ void release_active_processing(struct pkcs11_session *session)
 	if (!session->processing)
 		return;
 
-	if (session->processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
-		TEE_FreeOperation(session->processing->tee_hash_op_handle);
-		session->processing->tee_hash_op_handle = TEE_HANDLE_NULL;
-		session->processing->tee_hash_algo = 0;
+	switch (session->processing->mecha_type) {
+	case PKCS11_CKM_AES_GCM:
+		tee_release_gcm_operation(session);
+		break;
+	default:
+		break;
 	}
 
 	if (session->processing->tee_op_handle != TEE_HANDLE_NULL) {
@@ -115,6 +117,11 @@ void release_active_processing(struct pkcs11_session *session)
 		session->processing->tee_op_handle = TEE_HANDLE_NULL;
 	}
 
+	if (session->processing->tee_op_handle2 != TEE_HANDLE_NULL) {
+		TEE_FreeOperation(session->processing->tee_op_handle2);
+		session->processing->tee_op_handle2 = TEE_HANDLE_NULL;
+	}
+
 	TEE_Free(session->processing->extra_ctx);
 
 	TEE_Free(session->processing);
diff --git a/ta/pkcs11/src/processing.h b/ta/pkcs11/src/processing.h
index 9f84732be81f7d12e894cd29007c815099001b22..ac6d0808a03dda7d043c1ab2ed320b1a54ddf37c 100644
--- a/ta/pkcs11/src/processing.h
+++ b/ta/pkcs11/src/processing.h
@@ -173,6 +173,22 @@ enum pkcs11_rc unwrap_key_by_symm(struct pkcs11_session *session, void *data,
 				  uint32_t data_sz, void **out_buf,
 				  uint32_t *out_sz);
 
+enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session,
+				     void *in, size_t in_size);
+
+enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session,
+				    void *out, size_t *out_size);
+
+enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session,
+				    void *out, size_t *out_size);
+
+void tee_release_gcm_operation(struct pkcs11_session *session);
+
+enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session,
+				      void *proc_params, size_t params_size);
+
+enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session);
+
 /* Digest specific functions */
 bool processing_is_tee_digest(enum pkcs11_mechanism_id mecha_id);
 
@@ -267,4 +283,6 @@ enum pkcs11_rc pkcs2tee_algo_ecdh(uint32_t *tee_id,
 				  struct pkcs11_attribute_head *proc_params,
 				  struct pkcs11_object *obj);
 
+enum pkcs11_rc pkcs2tee_rsa_nopad_context(struct active_processing *proc);
+
 #endif /*PKCS11_TA_PROCESSING_H*/
diff --git a/ta/pkcs11/src/processing_aes.c b/ta/pkcs11/src/processing_aes.c
index f60ca4c30b3ef28603fb84be0dfecd1a6f0b5380..ed813dc6f8cfab7912cdc6111c32a68f64ca9844 100644
--- a/ta/pkcs11/src/processing_aes.c
+++ b/ta/pkcs11/src/processing_aes.c
@@ -6,6 +6,7 @@
 #include <assert.h>
 #include <compiler.h>
 #include <tee_internal_api.h>
+#include <tee_internal_api_extensions.h>
 #include <trace.h>
 #include <util.h>
 
@@ -14,6 +15,405 @@
 #include "processing.h"
 #include "serializer.h"
 
+/*
+ * Authenticated ciphering: (AES GCM)
+ *
+ * As per PKCS#11, GCM decryption shall not reveal the data until the
+ * decryption is completed and the MAC verified. The pkcs11 TA retains the
+ * ciphered data until the operation is completed. Therefore every chunk of
+ * decrypted data is saved in a allocated buffer during AE update processing
+ * and only copied into the client's output buffer at AE finalization when
+ * tag is authenticated.
+ *
+ * As per PKCS#11, GCM decryption expect the tag data to be provided
+ * inside the input data for C_DecryptUpdate() and friends, appended to the
+ * input encyprted data hence we do not know which is the last call to
+ * C_DecryptUpdate() where last bytes are not ciphered data but the requested
+ * tag bytes for message autehntication. To handle this, the TA saves
+ * the last input data bytes (length is defined by the tag byte size) in the
+ * AE context and waits the C_DecryptFinal() to either treat these as data
+ * bytes or tag/MAC bytes. Refer to pending_tag and pending_size in struct
+ * ae_aes_context.
+ */
+
+/*
+ * struct out_data_ref - AE decyrption output data chunks
+ * @size - byte size of the allocated buffer
+ * @data - pointer to allocated data
+ */
+struct out_data_ref {
+	size_t size;
+	void *data;
+};
+
+/*
+ * struct ae_aes_context - Extra context data got AE operations
+ * @tag_byte_len - Tag size in byte
+ * @pending_tag - Input data that could be the appended tag
+ * @pending_size - Size of pending input data that could be the tag
+ * @out_data - Pointer to an array of output data references.
+ * @out_count - Number of buffer references in out_data
+ */
+struct ae_aes_context {
+	size_t tag_byte_len;
+	char *pending_tag;
+	size_t pending_size;
+	struct out_data_ref *out_data;
+	size_t out_count;
+};
+
+static enum pkcs11_rc init_ae_aes_context(struct ae_aes_context *ctx)
+{
+	struct out_data_ref *out_data = NULL;
+	char *pending_tag = NULL;
+
+	assert(!ctx->out_data && !ctx->out_count &&
+	       !ctx->pending_tag && !ctx->pending_size);
+
+	out_data = TEE_Malloc(sizeof(*out_data), TEE_MALLOC_FILL_ZERO);
+	pending_tag = TEE_Malloc(ctx->tag_byte_len, TEE_MALLOC_FILL_ZERO);
+
+	if (!out_data || !pending_tag) {
+		TEE_Free(out_data);
+		TEE_Free(pending_tag);
+		return PKCS11_CKR_DEVICE_MEMORY;
+	}
+
+	ctx->pending_tag = pending_tag;
+	ctx->out_data = out_data;
+
+	return PKCS11_CKR_OK;
+}
+
+static void release_ae_aes_context(struct ae_aes_context *ctx)
+{
+	size_t n = 0;
+
+	for (n = 0; n < ctx->out_count; n++)
+		TEE_Free(ctx->out_data[n].data);
+
+	TEE_Free(ctx->out_data);
+	ctx->out_data = NULL;
+	ctx->out_count = 0;
+
+	TEE_Free(ctx->pending_tag);
+	ctx->pending_tag = NULL;
+	ctx->pending_size = 0;
+}
+
+/*
+ * This function feeds the AE decryption processing with client
+ * input data. There are 2 constraints to consider.
+ *
+ * Firstly we don't know yet which are the ciphered data and which are
+ * the tag data. GP TEE Internal API function requires we split data and
+ * tag when TEE_AEDecryptFinal() will be called.
+ *
+ * Secondly any generated data must be kept in the TA and only revealed
+ * once tag if succefully processed.
+ */
+enum pkcs11_rc tee_ae_decrypt_update(struct pkcs11_session *session,
+				     void *in, size_t in_size)
+{
+	struct ae_aes_context *ctx = session->processing->extra_ctx;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	enum pkcs11_rc rc = PKCS11_CKR_OK;
+	size_t data_len = 0;
+	size_t ct_size = 0;
+	void *ptr = NULL;
+	char *ct = NULL;
+
+	if (!in_size)
+		return PKCS11_CKR_OK;
+
+	if (!in)
+		return PKCS11_CKR_ARGUMENTS_BAD;
+
+	/*
+	 * Save the last input bytes in case they are the tag
+	 * bytes and not ciphered data bytes to be decrypted.
+	 */
+
+	if (ctx->pending_size + in_size <= ctx->tag_byte_len) {
+		/*
+		 * Data bytes are all potential tag bytes.
+		 * We only need to update the pending_tag buffer,
+		 * and cannot treat any byte as data byte.
+		 */
+		TEE_MemMove(ctx->pending_tag + ctx->pending_size, in, in_size);
+
+		ctx->pending_size += in_size;
+
+		return PKCS11_CKR_OK;
+	}
+
+	/* Size of data that are not potential tag in pending and input data */
+	data_len = in_size + ctx->pending_size - ctx->tag_byte_len;
+
+	/* Process pending bytes that are effective data byte */
+	if (ctx->pending_size &&
+	    (ctx->pending_size + in_size) >= ctx->tag_byte_len) {
+		uint32_t len = MIN(data_len, ctx->pending_size);
+
+		res = TEE_AEUpdate(session->processing->tee_op_handle,
+				   ctx->pending_tag, len, NULL, &ct_size);
+		if (res && res != TEE_ERROR_SHORT_BUFFER) {
+			rc = tee2pkcs_error(res);
+			goto out;
+		}
+		assert(res == TEE_ERROR_SHORT_BUFFER || !ct_size);
+
+		/*
+		 * If output data to store (not revealed yet), redo with
+		 * an allocated temporary reference.
+		 */
+		if (ct_size) {
+			ct = TEE_Malloc(ct_size, TEE_MALLOC_FILL_ZERO);
+			if (!ct) {
+				rc = PKCS11_CKR_DEVICE_MEMORY;
+				goto out;
+			}
+
+			res = TEE_AEUpdate(session->processing->tee_op_handle,
+					   ctx->pending_tag, len, ct, &ct_size);
+			if (res) {
+				rc = tee2pkcs_error(res);
+				goto out;
+			}
+			assert(ct_size);
+		}
+
+		/* Save potential tag bytes for later */
+		TEE_MemMove(ctx->pending_tag, ctx->pending_tag + len,
+			    ctx->pending_size - len);
+
+		ctx->pending_size -= len;
+		data_len -= len;
+	}
+
+	/* Process input data that are not potential tag bytes */
+	if (data_len) {
+		size_t size = 0;
+
+		res = TEE_AEUpdate(session->processing->tee_op_handle,
+				   in, data_len, NULL, &size);
+		if (res != TEE_ERROR_SHORT_BUFFER &&
+		    (res != TEE_SUCCESS || size)) {
+			/* This is not expected */
+			rc = PKCS11_CKR_GENERAL_ERROR;
+			goto out;
+		}
+
+		if (size) {
+			ptr = TEE_Realloc(ct, ct_size + size);
+			if (!ptr) {
+				rc = PKCS11_CKR_DEVICE_MEMORY;
+				goto out;
+			}
+			ct = ptr;
+
+			res = TEE_AEUpdate(session->processing->tee_op_handle,
+					   in, data_len, ct + ct_size, &size);
+			if (res) {
+				rc = tee2pkcs_error(res);
+				goto out;
+			}
+
+			ct_size += size;
+		}
+	}
+
+	/* Update pending tag in context if any */
+	data_len = in_size - data_len;
+	if (data_len > (ctx->tag_byte_len - ctx->pending_size)) {
+		/* This is not expected */
+		rc = PKCS11_CKR_GENERAL_ERROR;
+		goto out;
+	}
+
+	if (data_len) {
+		TEE_MemMove(ctx->pending_tag + ctx->pending_size,
+			    (char *)in + in_size - data_len, data_len);
+
+		ctx->pending_size += data_len;
+	}
+
+	/* Save output data reference in the context */
+	if (ct_size) {
+		ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) *
+				  sizeof(struct out_data_ref));
+		if (!ptr) {
+			rc = PKCS11_CKR_DEVICE_MEMORY;
+			goto out;
+		}
+		ctx->out_data = ptr;
+		ctx->out_data[ctx->out_count].size = ct_size;
+		ctx->out_data[ctx->out_count].data = ct;
+		ctx->out_count++;
+	}
+
+	rc = PKCS11_CKR_OK;
+
+out:
+	if (rc)
+		TEE_Free(ct);
+
+	return rc;
+}
+
+static enum pkcs11_rc reveal_ae_data(struct ae_aes_context *ctx,
+				     void *out, size_t *out_size)
+{
+	uint32_t req_size = 0;
+	char *out_ptr = out;
+	size_t n = 0;
+
+	for (req_size = 0, n = 0; n < ctx->out_count; n++)
+		req_size += ctx->out_data[n].size;
+
+	if (*out_size < req_size) {
+		*out_size = req_size;
+		return PKCS11_CKR_BUFFER_TOO_SMALL;
+	}
+
+	if (!out_ptr)
+		return PKCS11_CKR_ARGUMENTS_BAD;
+
+	for (n = 0; n < ctx->out_count; n++) {
+		TEE_MemMove(out_ptr, ctx->out_data[n].data,
+			    ctx->out_data[n].size);
+		out_ptr += ctx->out_data[n].size;
+	}
+
+	release_ae_aes_context(ctx);
+
+	*out_size = req_size;
+
+	return PKCS11_CKR_OK;
+}
+
+enum pkcs11_rc tee_ae_decrypt_final(struct pkcs11_session *session,
+				    void *out, size_t *out_size)
+{
+	struct ae_aes_context *ctx = session->processing->extra_ctx;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	enum pkcs11_rc rc = 0;
+	void *data_ptr = NULL;
+	size_t data_size = 0;
+
+	if (!out_size) {
+		DMSG("Expect at least a buffer for the output data");
+		return PKCS11_CKR_ARGUMENTS_BAD;
+	}
+
+	/* Final is already completed, only need to output the data */
+	if (!ctx->pending_tag)
+		return reveal_ae_data(ctx, out, out_size);
+
+	if (ctx->pending_size != ctx->tag_byte_len) {
+		DMSG("Not enough samples: %zu/%zu",
+		     ctx->pending_size, ctx->tag_byte_len);
+		return PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
+	}
+
+	/* Query tag size if any */
+	data_size = 0;
+	res = TEE_AEDecryptFinal(session->processing->tee_op_handle,
+				 NULL, 0, NULL, &data_size,
+				 ctx->pending_tag, ctx->tag_byte_len);
+
+	if (res == TEE_ERROR_SHORT_BUFFER) {
+		data_ptr = TEE_Malloc(data_size, TEE_MALLOC_FILL_ZERO);
+		if (!data_ptr) {
+			rc = PKCS11_CKR_DEVICE_MEMORY;
+			goto out;
+		}
+
+		res = TEE_AEDecryptFinal(session->processing->tee_op_handle,
+					 NULL, 0, data_ptr, &data_size,
+					 ctx->pending_tag, ctx->tag_byte_len);
+		assert(res || data_size);
+	}
+
+	/* AE decryption is completed */
+	TEE_Free(ctx->pending_tag);
+	ctx->pending_tag = NULL;
+
+	rc = tee2pkcs_error(res);
+	if (rc)
+		goto out;
+
+	if (data_ptr) {
+		void *tmp_ptr = NULL;
+
+		tmp_ptr = TEE_Realloc(ctx->out_data, (ctx->out_count + 1) *
+				sizeof(struct out_data_ref));
+		if (!tmp_ptr) {
+			rc = PKCS11_CKR_DEVICE_MEMORY;
+			goto out;
+		}
+		ctx->out_data = tmp_ptr;
+		ctx->out_data[ctx->out_count].size = data_size;
+		ctx->out_data[ctx->out_count].data = data_ptr;
+		ctx->out_count++;
+
+		data_ptr = NULL;
+	}
+
+	rc = reveal_ae_data(ctx, out, out_size);
+
+out:
+	TEE_Free(data_ptr);
+
+	return rc;
+}
+
+enum pkcs11_rc tee_ae_encrypt_final(struct pkcs11_session *session,
+				    void *out, size_t *out_size)
+{
+	struct ae_aes_context *ctx = session->processing->extra_ctx;
+	TEE_Result res = TEE_ERROR_GENERIC;
+	uint8_t *tag = NULL;
+	size_t tag_len = 0;
+	size_t size = 0;
+
+	if (!out || !out_size)
+		return PKCS11_CKR_ARGUMENTS_BAD;
+
+	/* Check the required sizes (warning: 2 output len: data + tag) */
+	res = TEE_AEEncryptFinal(session->processing->tee_op_handle,
+				 NULL, 0, NULL, &size,
+				 &tag, &tag_len);
+
+	if (tag_len != ctx->tag_byte_len ||
+	    (res != TEE_SUCCESS && res != TEE_ERROR_SHORT_BUFFER)) {
+		EMSG("Unexpected tag length %zu/%zu or rc 0x%" PRIx32,
+		     tag_len, ctx->tag_byte_len, res);
+		return PKCS11_CKR_GENERAL_ERROR;
+	}
+
+	if (*out_size < size + tag_len) {
+		*out_size = size + tag_len;
+		return PKCS11_CKR_BUFFER_TOO_SMALL;
+	}
+
+	/* Process data and tag input the client output buffer */
+	tag = (uint8_t *)out + size;
+
+	res = TEE_AEEncryptFinal(session->processing->tee_op_handle,
+				 NULL, 0, out, &size, tag, &tag_len);
+
+	if (tag_len != ctx->tag_byte_len) {
+		EMSG("Unexpected tag length");
+		return PKCS11_CKR_GENERAL_ERROR;
+	}
+
+	if (!res)
+		*out_size = size + tag_len;
+
+	return tee2pkcs_error(res);
+}
+
 enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing,
 				      void *proc_params, size_t params_size)
 {
@@ -50,3 +450,118 @@ enum pkcs11_rc tee_init_ctr_operation(struct active_processing *processing,
 
 	return PKCS11_CKR_OK;
 }
+
+enum pkcs11_rc tee_init_gcm_operation(struct pkcs11_session *session,
+				      void *proc_params, size_t params_size)
+{
+	struct ae_aes_context *params = NULL;
+	enum pkcs11_rc rc = PKCS11_CKR_OK;
+	struct serialargs args = { };
+	/* GCM parameters */
+	uint32_t tag_bitlen = 0;
+	uint32_t tag_len = 0;
+	uint32_t iv_len = 0;
+	void *iv = NULL;
+	uint32_t aad_len = 0;
+	void *aad = NULL;
+
+	TEE_MemFill(&args, 0, sizeof(args));
+
+	if (!proc_params)
+		return PKCS11_CKR_ARGUMENTS_BAD;
+
+	serialargs_init(&args, proc_params, params_size);
+
+	rc = serialargs_get(&args, &iv_len, sizeof(uint32_t));
+	if (rc)
+		goto out;
+
+	rc = serialargs_get_ptr(&args, &iv, iv_len);
+	if (rc)
+		goto out;
+
+	rc = serialargs_get(&args, &aad_len, sizeof(uint32_t));
+	if (rc)
+		goto out;
+
+	rc = serialargs_get_ptr(&args, &aad, aad_len);
+	if (rc)
+		goto out;
+
+	rc = serialargs_get(&args, &tag_bitlen, sizeof(uint32_t));
+	if (rc)
+		goto out;
+
+	tag_len = ROUNDUP_DIV(tag_bitlen, 8);
+
+	/* As per pkcs#11 mechanism specification */
+	if (tag_bitlen > 128 || !iv_len || iv_len > 256) {
+		DMSG("Invalid parameters: tag_bit_len %"PRIu32
+		     ", iv_len %"PRIu32, tag_bitlen, iv_len);
+		rc = PKCS11_CKR_MECHANISM_PARAM_INVALID;
+		goto out;
+	}
+
+	params = TEE_Malloc(sizeof(*params), TEE_MALLOC_FILL_ZERO);
+	if (!params) {
+		rc = PKCS11_CKR_DEVICE_MEMORY;
+		goto out;
+	}
+
+	/* Store the byte round up byte length for the tag */
+	params->tag_byte_len = tag_len;
+	rc = init_ae_aes_context(params);
+	if (rc)
+		goto out;
+
+	/* Session processing owns the active processing params */
+	assert(!session->processing->extra_ctx);
+	session->processing->extra_ctx = params;
+
+	TEE_AEInit(session->processing->tee_op_handle,
+		   iv, iv_len, tag_bitlen, 0, 0);
+
+	if (aad_len)
+		TEE_AEUpdateAAD(session->processing->tee_op_handle,
+				aad, aad_len);
+
+	/*
+	 * Save initialized operation state to reset to this state
+	 * on one-shot AE request that queries its output buffer size.
+	 */
+	TEE_CopyOperation(session->processing->tee_op_handle2,
+			  session->processing->tee_op_handle);
+
+	rc = PKCS11_CKR_OK;
+
+out:
+	if (rc && params) {
+		release_ae_aes_context(params);
+		TEE_Free(params);
+	}
+
+	return rc;
+}
+
+/* Release extra resources related to the GCM processing*/
+void tee_release_gcm_operation(struct pkcs11_session *session)
+{
+	struct ae_aes_context *ctx = session->processing->extra_ctx;
+
+	release_ae_aes_context(ctx);
+	TEE_Free(session->processing->extra_ctx);
+	session->processing->extra_ctx = NULL;
+}
+
+/* Reset processing state to the state it was after initialization */
+enum pkcs11_rc tee_ae_reinit_gcm_operation(struct pkcs11_session *session)
+{
+	struct ae_aes_context *ctx = session->processing->extra_ctx;
+
+	TEE_CopyOperation(session->processing->tee_op_handle,
+			  session->processing->tee_op_handle2);
+
+	release_ae_aes_context(ctx);
+
+	return init_ae_aes_context(ctx);
+}
diff --git a/ta/pkcs11/src/processing_asymm.c b/ta/pkcs11/src/processing_asymm.c
index 30348c0759490191b8b83f2c0cfc1c636945a9c7..2f59922b08f874102ef0baef197cf24c3ed4b3f3 100644
--- a/ta/pkcs11/src/processing_asymm.c
+++ b/ta/pkcs11/src/processing_asymm.c
@@ -6,6 +6,7 @@
 #include <assert.h>
 #include <compiler.h>
 #include <mbedtls/nist_kw.h>
+#include <string_ext.h>
 #include <tee_api_defines.h>
 #include <tee_internal_api.h>
 #include <tee_internal_api_extensions.h>
@@ -22,6 +23,7 @@ bool processing_is_tee_asymm(uint32_t proc_id)
 	/* RSA flavors */
 	case PKCS11_CKM_RSA_AES_KEY_WRAP:
 	case PKCS11_CKM_RSA_PKCS:
+	case PKCS11_CKM_RSA_X_509:
 	case PKCS11_CKM_RSA_PKCS_OAEP:
 	case PKCS11_CKM_RSA_PKCS_PSS:
 	case PKCS11_CKM_MD5_RSA_PKCS:
@@ -66,6 +68,7 @@ pkcs2tee_algorithm(uint32_t *tee_id, uint32_t *tee_hash_id,
 		{ PKCS11_CKM_RSA_PKCS, TEE_ALG_RSAES_PKCS1_V1_5, 0 },
 		{ PKCS11_CKM_RSA_PKCS_OAEP, 1, 0 },
 		{ PKCS11_CKM_RSA_PKCS_PSS, 1, 0 },
+		{ PKCS11_CKM_RSA_X_509, TEE_ALG_RSA_NOPAD, 0 },
 		{ PKCS11_CKM_MD5_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_MD5,
 		  TEE_ALG_MD5 },
 		{ PKCS11_CKM_SHA1_RSA_PKCS, TEE_ALG_RSASSA_PKCS1_V1_5_SHA1,
@@ -222,17 +225,38 @@ allocate_tee_operation(struct pkcs11_session *session,
 	struct active_processing *processing = session->processing;
 
 	assert(processing->tee_op_handle == TEE_HANDLE_NULL);
-	assert(processing->tee_hash_op_handle == TEE_HANDLE_NULL);
+	assert(processing->tee_op_handle2 == TEE_HANDLE_NULL);
 
 	if (pkcs2tee_algorithm(&algo, &hash_algo, function, params, obj))
 		return PKCS11_CKR_FUNCTION_FAILED;
 
-	pkcs2tee_mode(&mode, function);
+	/*
+	 * PKCS#11 allows Sign/Verify with CKM_RSA_X_509 while GP TEE API
+	 * only permits Encrypt/Decrypt with TEE_ALG_RSA_NOPAD.
+	 * For other algorithm, use simple 1-to-1 ID conversion pkcs2tee_mode().
+	 */
+	if (params->id == PKCS11_CKM_RSA_X_509) {
+		assert(!hash_algo);
+		switch (function) {
+		case PKCS11_FUNCTION_ENCRYPT:
+		case PKCS11_FUNCTION_VERIFY:
+			mode = TEE_MODE_ENCRYPT;
+			break;
+		case PKCS11_FUNCTION_DECRYPT:
+		case PKCS11_FUNCTION_SIGN:
+			mode = TEE_MODE_DECRYPT;
+			break;
+		default:
+			TEE_Panic(0);
+		}
+	} else {
+		pkcs2tee_mode(&mode, function);
+	}
 
 	if (hash_algo) {
 		pkcs2tee_mode(&hash_mode, PKCS11_FUNCTION_DIGEST);
 
-		res = TEE_AllocateOperation(&processing->tee_hash_op_handle,
+		res = TEE_AllocateOperation(&processing->tee_op_handle2,
 					    hash_algo, hash_mode, 0);
 		if (res) {
 			EMSG("TEE_AllocateOp. failed %#"PRIx32" %#"PRIx32,
@@ -255,9 +279,9 @@ allocate_tee_operation(struct pkcs11_session *session,
 		return PKCS11_CKR_MECHANISM_INVALID;
 
 	if (res != TEE_SUCCESS &&
-	    processing->tee_hash_op_handle != TEE_HANDLE_NULL) {
-		TEE_FreeOperation(session->processing->tee_hash_op_handle);
-		processing->tee_hash_op_handle = TEE_HANDLE_NULL;
+	    processing->tee_op_handle2 != TEE_HANDLE_NULL) {
+		TEE_FreeOperation(session->processing->tee_op_handle2);
+		processing->tee_op_handle2 = TEE_HANDLE_NULL;
 		processing->tee_hash_algo = 0;
 	}
 
@@ -385,6 +409,9 @@ init_tee_operation(struct pkcs11_session *session,
 	struct active_processing *proc = session->processing;
 
 	switch (proc_params->id) {
+	case PKCS11_CKM_RSA_X_509:
+		rc = pkcs2tee_rsa_nopad_context(proc);
+		break;
 	case PKCS11_CKM_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA1_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA224_RSA_PKCS_PSS:
@@ -457,10 +484,12 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
 	void *in2_buf = NULL;
 	void *out_buf = NULL;
 	void *hash_buf = NULL;
+	void *temp_buf = NULL;
 	uint32_t in_size = 0;
 	uint32_t in2_size = 0;
 	size_t out_size = 0;
 	size_t hash_size = 0;
+	size_t temp_size = 0;
 	TEE_Attribute *tee_attrs = NULL;
 	size_t tee_attrs_count = 0;
 	bool output_data = false;
@@ -610,10 +639,9 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
 		case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
 		case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
 		case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
-			assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
+			assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
 
-			TEE_DigestUpdate(proc->tee_hash_op_handle, in_buf,
-					 in_size);
+			TEE_DigestUpdate(proc->tee_op_handle2, in_buf, in_size);
 			rc = PKCS11_CKR_OK;
 			break;
 		default:
@@ -649,16 +677,15 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
 	case PKCS11_CKM_SHA256_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA384_RSA_PKCS_PSS:
 	case PKCS11_CKM_SHA512_RSA_PKCS_PSS:
-		assert(proc->tee_hash_op_handle != TEE_HANDLE_NULL);
+		assert(proc->tee_op_handle2 != TEE_HANDLE_NULL);
 
 		hash_size = TEE_ALG_GET_DIGEST_SIZE(proc->tee_hash_algo);
 		hash_buf = TEE_Malloc(hash_size, 0);
 		if (!hash_buf)
 			return PKCS11_CKR_DEVICE_MEMORY;
 
-		res = TEE_DigestDoFinal(proc->tee_hash_op_handle,
-					in_buf, in_size, hash_buf,
-					&hash_size);
+		res = TEE_DigestDoFinal(proc->tee_op_handle2, in_buf, in_size,
+					hash_buf, &hash_size);
 
 		rc = tee2pkcs_error(res);
 		if (rc != PKCS11_CKR_OK)
@@ -714,6 +741,7 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
 		}
 		break;
 	case PKCS11_CKM_RSA_PKCS:
+	case PKCS11_CKM_RSA_X_509:
 	case PKCS11_CKM_MD5_RSA_PKCS:
 	case PKCS11_CKM_SHA1_RSA_PKCS:
 	case PKCS11_CKM_SHA224_RSA_PKCS:
@@ -797,6 +825,135 @@ enum pkcs11_rc step_asymm_operation(struct pkcs11_session *session,
 			break;
 		}
 		break;
+
+	case PKCS11_CKM_RSA_X_509:
+		switch (function) {
+		case PKCS11_FUNCTION_ENCRYPT:
+			/*
+			 * Input message size shall be at most the key size
+			 * As encrypting with raw RSA can be unsafe, it
+			 * remains the responsibility of the client to
+			 * prolerly pad the message for safe usage.
+			 */
+			if (in_size > sz) {
+				rc = PKCS11_CKR_DATA_LEN_RANGE;
+				break;
+			}
+			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
+						    tee_attrs, tee_attrs_count,
+						    in_buf, in_size,
+						    out_buf, &out_size);
+			output_data = true;
+			rc = tee2pkcs_error(res);
+			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
+				rc = PKCS11_CKR_DATA_LEN_RANGE;
+			break;
+		case PKCS11_FUNCTION_DECRYPT:
+			/*
+			 * Input message size shall be at most the key size
+			 * As decrypting with raw RSA can be unsafe, it
+			 * remains the responsibility of the encryption
+			 * instance to have prolerly padded its message.
+			 */
+			if (in_size > sz) {
+				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
+				break;
+			}
+
+			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
+						    tee_attrs, tee_attrs_count,
+						    in_buf, in_size,
+						    out_buf, &out_size);
+			output_data = true;
+			rc = tee2pkcs_error(res);
+			if (rc == PKCS11_CKR_ARGUMENTS_BAD)
+				rc = PKCS11_CKR_ENCRYPTED_DATA_LEN_RANGE;
+			break;
+		case PKCS11_FUNCTION_SIGN:
+			/*
+			 * GP TEE API only allows Decrypt, not Verify operation,
+			 * on TEE_ALG_RSA_NOPAD. Be a bit strict on the size and
+			 * content of the message and ensure the generate
+			 * signature as the size of the modulus (@sz here).
+			 *
+			 * It remains the responsibility of the client to have
+			 * a safe padding scheme for the provided message data.
+			 */
+			if (in_size != sz) {
+				EMSG("Invalid data size %"PRIu32" != %zu",
+				     in_size, sz);
+				rc = PKCS11_CKR_DATA_LEN_RANGE;
+				break;
+			}
+
+			if (out_size < sz) {
+				rc = PKCS11_CKR_BUFFER_TOO_SMALL;
+				out_size = sz;
+				output_data = true;
+				break;
+			}
+
+			temp_size = sz;
+			temp_buf = proc->extra_ctx;
+			res = TEE_AsymmetricDecrypt(proc->tee_op_handle,
+						    tee_attrs, tee_attrs_count,
+						    in_buf, in_size,
+						    temp_buf, &temp_size);
+			if (!res && temp_size != sz) {
+				EMSG("CMK_RSA_X509: signature size %zu != %zu",
+				     temp_size, sz);
+				rc = PKCS11_CKR_DATA_INVALID;
+				break;
+			}
+			if (!res) {
+				TEE_MemMove(out_buf, temp_buf, sz);
+				TEE_MemFill(temp_buf, 0xa5, sz);
+			}
+			output_data = true;
+			rc = tee2pkcs_error(res);
+			out_size = sz;
+			break;
+		case PKCS11_FUNCTION_VERIFY:
+			/*
+			 * GP TEE API only allows Encrypt, not Verify operation,
+			 * on TEE_ALG_RSA_NOPAD. Encrypt signature in
+			 * temporary buffer preallocated to the size of the key.
+			 */
+			temp_size = sz;
+			temp_buf = proc->extra_ctx;
+			res = TEE_AsymmetricEncrypt(proc->tee_op_handle,
+						    tee_attrs, tee_attrs_count,
+						    in2_buf, in2_size,
+						    temp_buf, &temp_size);
+			rc = tee2pkcs_error(res);
+			if (rc == PKCS11_CKR_OK) {
+				/*
+				 * Skip nul bytes heading message before
+				 * comparing encrypted signature.
+				 */
+				char *ptr = in_buf;
+				size_t n = 0;
+
+				for (n = 0; n < in_size; n++)
+					if (ptr[n])
+						break;
+				in_size -= n;
+				ptr += n;
+				if (n > 1)
+					IMSG("Unsafe signature: skip %zu bytes",
+					     n);
+
+				if (temp_size != in_size ||
+				    consttime_memcmp(temp_buf, ptr, in_size))
+					rc = PKCS11_CKR_SIGNATURE_INVALID;
+			}
+			break;
+		default:
+			TEE_Panic(function);
+			break;
+		}
+		break;
+
 	case PKCS11_CKM_ECDSA_SHA1:
 	case PKCS11_CKM_ECDSA_SHA224:
 	case PKCS11_CKM_ECDSA_SHA256:
diff --git a/ta/pkcs11/src/processing_rsa.c b/ta/pkcs11/src/processing_rsa.c
index 94eabbfa7496984b37577984f4d979548e9762b9..08118b7283c51e4c0b2444682293076abc6113af 100644
--- a/ta/pkcs11/src/processing_rsa.c
+++ b/ta/pkcs11/src/processing_rsa.c
@@ -101,7 +101,7 @@ enum pkcs11_rc pkcs2tee_validate_rsa_pss(struct active_processing *proc,
 	if ((modulus_size % 8) == 1)
 		k = modulus_size / 8;
 	else
-		k = ROUNDUP(modulus_size, 8) / 8;
+		k = ROUNDUP_DIV(modulus_size, 8);
 
 	if (rsa_pss_ctx->salt_len > (k - 2 - hash_size))
 		return PKCS11_CKR_KEY_SIZE_RANGE;
@@ -569,6 +569,8 @@ enum pkcs11_rc load_tee_rsa_key_attrs(TEE_Attribute **tee_attrs,
 			break;
 		}
 
+		rc = PKCS11_CKR_GENERAL_ERROR;
+
 		if (pkcs2tee_load_attr(&attrs[count], TEE_ATTR_RSA_PRIME1, obj,
 				       PKCS11_CKA_PRIME_1))
 			count++;
@@ -775,3 +777,22 @@ size_t rsa_get_input_max_byte_size(TEE_OperationHandle op)
 
 	return info.maxKeySize / 8;
 }
+
+enum pkcs11_rc pkcs2tee_rsa_nopad_context(struct active_processing *proc)
+{
+	size_t key_size = 0;
+
+	/*
+	 * RSA no-pad (CKM_RSA_X_509) verify needs a buffer of the size
+	 * of the key to safely run.
+	 */
+	key_size = rsa_get_input_max_byte_size(proc->tee_op_handle);
+	if (!key_size)
+		return PKCS11_CKR_GENERAL_ERROR;
+
+	proc->extra_ctx = TEE_Malloc(key_size, TEE_USER_MEM_HINT_NO_FILL_ZERO);
+	if (!proc->extra_ctx)
+		return PKCS11_CKR_DEVICE_MEMORY;
+
+	return PKCS11_CKR_OK;
+}
diff --git a/ta/pkcs11/src/processing_symm.c b/ta/pkcs11/src/processing_symm.c
index 73631506b1818af4550d53c1cbb08e1a0496cc82..093c61d56981b84ab882f09a3bb3dae6740c8b84 100644
--- a/ta/pkcs11/src/processing_symm.c
+++ b/ta/pkcs11/src/processing_symm.c
@@ -48,6 +48,7 @@ bool processing_is_tee_symm(enum pkcs11_mechanism_id proc_id)
 	case PKCS11_CKM_AES_CBC:
 	case PKCS11_CKM_AES_CTS:
 	case PKCS11_CKM_AES_CTR:
+	case PKCS11_CKM_AES_GCM:
 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
 		return true;
@@ -70,6 +71,7 @@ pkcs2tee_algorithm(uint32_t *tee_id, struct pkcs11_attribute_head *proc_params)
 		{ PKCS11_CKM_AES_CBC_ENCRYPT_DATA, TEE_ALG_AES_CBC_NOPAD },
 		{ PKCS11_CKM_AES_CTR, TEE_ALG_AES_CTR },
 		{ PKCS11_CKM_AES_CTS, TEE_ALG_AES_CTS },
+		{ PKCS11_CKM_AES_GCM, TEE_ALG_AES_GCM },
 		{ PKCS11_CKM_AES_CMAC, TEE_ALG_AES_CMAC },
 		{ PKCS11_CKM_AES_CMAC_GENERAL, TEE_ALG_AES_CMAC },
 		/* HMAC flavors */
@@ -207,7 +209,8 @@ allocate_tee_operation(struct pkcs11_session *session,
 	uint32_t min_key_size = 0;
 	TEE_Result res = TEE_ERROR_GENERIC;
 
-	assert(session->processing->tee_op_handle == TEE_HANDLE_NULL);
+	assert(session->processing->tee_op_handle == TEE_HANDLE_NULL &&
+	       session->processing->tee_op_handle2 == TEE_HANDLE_NULL);
 
 	if (pkcs2tee_algorithm(&algo, params))
 		return PKCS11_CKR_FUNCTION_FAILED;
@@ -263,6 +266,20 @@ allocate_tee_operation(struct pkcs11_session *session,
 	if (res == TEE_ERROR_NOT_SUPPORTED)
 		return PKCS11_CKR_MECHANISM_INVALID;
 
+	if (res == TEE_SUCCESS || params->id == PKCS11_CKM_AES_GCM) {
+		/*
+		 * Allocate a 2nd operation handler to save the operation state
+		 * on AES GCM one-shot processing that queries the output
+		 * buffer size. This is needed as we will need to reset and
+		 * re-init the TEE operation once we report the expected output
+		 * buffer size to client that we call again the AE processing
+		 * function.
+		 */
+		TEE_OperationHandle *hdl = &session->processing->tee_op_handle2;
+
+		res = TEE_AllocateOperation(hdl, algo, mode, size);
+	}
+
 	return tee2pkcs_error(res);
 }
 
@@ -595,6 +612,11 @@ init_tee_operation(struct pkcs11_session *session,
 					    proc_params->data,
 					    proc_params->size);
 		break;
+	case PKCS11_CKM_AES_GCM:
+		rc = tee_init_gcm_operation(session,
+					    proc_params->data,
+					    proc_params->size);
+		break;
 	case PKCS11_CKM_AES_ECB_ENCRYPT_DATA:
 	case PKCS11_CKM_AES_CBC_ENCRYPT_DATA:
 		rc = tee_init_derive_symm(session->processing, proc_params);
@@ -726,6 +748,7 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 	uint32_t hmac_len = 0;
 	uint8_t computed_mac[TEE_MAX_HASH_SIZE] = { 0 };
 	size_t computed_mac_size = TEE_MAX_HASH_SIZE;
+	size_t ae_out_size = 0;
 
 	if (TEE_PARAM_TYPE_GET(ptypes, 1) == TEE_PARAM_TYPE_MEMREF_INPUT) {
 		in_buf = params[1].memref.buffer;
@@ -742,6 +765,7 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 	if (TEE_PARAM_TYPE_GET(ptypes, 2) == TEE_PARAM_TYPE_MEMREF_OUTPUT) {
 		out_buf = params[2].memref.buffer;
 		out_size = params[2].memref.size;
+		ae_out_size = out_size;
 		if (out_size && !out_buf)
 			return PKCS11_CKR_ARGUMENTS_BAD;
 	}
@@ -829,7 +853,44 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 			break;
 		}
 		break;
+	case PKCS11_CKM_AES_GCM:
+		if (step == PKCS11_FUNC_STEP_FINAL)
+			break;
+
+		switch (function) {
+		case PKCS11_FUNCTION_ENCRYPT:
+			res = TEE_AEUpdate(proc->tee_op_handle,
+					   in_buf, in_size, out_buf, &out_size);
 
+			output_data = true;
+			rc = tee2pkcs_error(res);
+			if (rc && rc != PKCS11_CKR_BUFFER_TOO_SMALL)
+				return rc;
+			if (step == PKCS11_FUNC_STEP_ONESHOT) {
+				if (rc == PKCS11_CKR_BUFFER_TOO_SMALL) {
+					/* Return output data size incl. tag*/
+					out_size += 16;
+					goto out;
+				}
+				out_buf = (char *)out_buf + out_size;
+				/* Remaining space for the tag data */
+				ae_out_size -= out_size;
+			}
+			break;
+		case PKCS11_FUNCTION_DECRYPT:
+			rc = tee_ae_decrypt_update(session, in_buf, in_size);
+			assert(rc != PKCS11_CKR_BUFFER_TOO_SMALL);
+			if (rc)
+				return rc;
+			/* Do not output decrypted data until tag is verified */
+			out_size = 0;
+			output_data = true;
+			break;
+		default:
+			TEE_Panic(function);
+			break;
+		}
+		break;
 	default:
 		TEE_Panic(proc->mecha_type);
 		break;
@@ -841,7 +902,7 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 	/*
 	 * Finalize (PKCS11_FUNC_STEP_ONESHOT/_FINAL) operation
 	 */
-	switch (session->processing->mecha_type) {
+	switch (proc->mecha_type) {
 	case PKCS11_CKM_AES_CMAC:
 	case PKCS11_CKM_MD5_HMAC:
 	case PKCS11_CKM_SHA_1_HMAC:
@@ -880,8 +941,8 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 	case PKCS11_CKM_SHA256_HMAC_GENERAL:
 	case PKCS11_CKM_SHA384_HMAC_GENERAL:
 	case PKCS11_CKM_SHA512_HMAC_GENERAL:
-		assert(session->processing->extra_ctx);
-		hmac_len = *(uint32_t *)session->processing->extra_ctx;
+		assert(proc->extra_ctx);
+		hmac_len = *(uint32_t *)proc->extra_ctx;
 
 		switch (function) {
 		case PKCS11_FUNCTION_SIGN:
@@ -963,6 +1024,43 @@ enum pkcs11_rc step_symm_operation(struct pkcs11_session *session,
 			break;
 		}
 		break;
+	case PKCS11_CKM_AES_GCM:
+		switch (function) {
+		case PKCS11_FUNCTION_ENCRYPT:
+			rc = tee_ae_encrypt_final(session, out_buf,
+						  &ae_out_size);
+			output_data = true;
+			if (step == PKCS11_FUNC_STEP_ONESHOT)
+				out_size += ae_out_size;
+			else
+				out_size = ae_out_size;
+			break;
+		case PKCS11_FUNCTION_DECRYPT:
+			/* Now we're ready to reveal data */
+			out_size = ae_out_size;
+			rc = tee_ae_decrypt_final(session, out_buf, &out_size);
+			output_data = true;
+			break;
+		default:
+			TEE_Panic(function);
+			break;
+		}
+
+		if (step == PKCS11_FUNC_STEP_ONESHOT &&
+		    rc == PKCS11_CKR_BUFFER_TOO_SMALL) {
+			enum pkcs11_rc rc2 = PKCS11_CKR_OK;
+
+			/*
+			 * Change operation state to its initial state
+			 * as client will likely request again the
+			 * one-shot processing but possibly with
+			 * different input data.
+			 */
+			rc2 = tee_ae_reinit_gcm_operation(session);
+			if (rc2)
+				return rc2;
+		}
+		break;
 	default:
 		TEE_Panic(proc->mecha_type);
 		break;
diff --git a/ta/pkcs11/src/sanitize_object.c b/ta/pkcs11/src/sanitize_object.c
index 5fdde553d7ad4eca135e13911e26a0197b204561..132833284780db8a521743d4a09a67a6d5c16ea2 100644
--- a/ta/pkcs11/src/sanitize_object.c
+++ b/ta/pkcs11/src/sanitize_object.c
@@ -10,7 +10,6 @@
 #include <string.h>
 #include <util.h>
 #include <tee_internal_api.h>
-#include <tee_internal_api_extensions.h>
 #include <trace.h>
 
 #include "attributes.h"
diff --git a/ta/pkcs11/src/token_capabilities.c b/ta/pkcs11/src/token_capabilities.c
index e76c1df0b79ff0be18e97ed5fa4ccd035f1b00de..e1a6c0b2cd3b8214f1ab3ce7ab10647ca9cc4281 100644
--- a/ta/pkcs11/src/token_capabilities.c
+++ b/ta/pkcs11/src/token_capabilities.c
@@ -73,6 +73,7 @@ static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
 	MECHANISM(PKCS11_CKM_AES_CBC_PAD, CKFM_CIPHER_WRAP, ANY_PART),
 	MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER_WRAP, ANY_PART),
 	MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER_WRAP, ANY_PART),
+	MECHANISM(PKCS11_CKM_AES_GCM, CKFM_CIPHER_WRAP, ANY_PART),
 	MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER, ANY_PART),
 	MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER, ANY_PART),
 	MECHANISM(PKCS11_CKM_AES_ECB_ENCRYPT_DATA, PKCS11_CKFM_DERIVE,
@@ -131,6 +132,9 @@ static const struct pkcs11_mechachism_modes pkcs11_modes[] = {
 		  CKFM_AUTH_WITH_RECOVER, SINGLE_PART_ONLY),
 	MECHANISM(PKCS11_CKM_RSA_PKCS_OAEP, CKFM_CIPHER_WRAP,
 		  SINGLE_PART_ONLY),
+	MECHANISM(PKCS11_CKM_RSA_X_509, CKFM_CIPHER_WRAP |
+		  CKFM_AUTH_NO_RECOVER | CKFM_AUTH_WITH_RECOVER,
+		  SINGLE_PART_ONLY),
 	MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER,
 		  SINGLE_PART_ONLY),
 	MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER, ANY_PART),
@@ -231,6 +235,7 @@ const struct pkcs11_mechachism_modes token_mechanism[] = {
 	TA_MECHANISM(PKCS11_CKM_AES_ECB, CKFM_CIPHER_WRAP),
 	TA_MECHANISM(PKCS11_CKM_AES_CBC, CKFM_CIPHER_WRAP),
 	TA_MECHANISM(PKCS11_CKM_AES_CTR, CKFM_CIPHER),
+	TA_MECHANISM(PKCS11_CKM_AES_GCM, CKFM_CIPHER),
 	TA_MECHANISM(PKCS11_CKM_AES_CTS, CKFM_CIPHER),
 	TA_MECHANISM(PKCS11_CKM_AES_CMAC, CKFM_AUTH_NO_RECOVER),
 	TA_MECHANISM(PKCS11_CKM_AES_CMAC_GENERAL, CKFM_AUTH_NO_RECOVER),
@@ -272,6 +277,9 @@ const struct pkcs11_mechachism_modes token_mechanism[] = {
 	TA_MECHANISM(PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN,
 		     PKCS11_CKFM_GENERATE_KEY_PAIR),
 	TA_MECHANISM(PKCS11_CKM_RSA_PKCS, CKFM_CIPHER | CKFM_AUTH_NO_RECOVER),
+#ifdef CFG_PKCS11_TA_RSA_X_509
+	TA_MECHANISM(PKCS11_CKM_RSA_X_509, CKFM_CIPHER | CKFM_AUTH_NO_RECOVER),
+#endif
 	TA_MECHANISM(PKCS11_CKM_RSA_PKCS_PSS, CKFM_AUTH_NO_RECOVER),
 	TA_MECHANISM(PKCS11_CKM_MD5_RSA_PKCS, CKFM_AUTH_NO_RECOVER),
 	TA_MECHANISM(PKCS11_CKM_SHA1_RSA_PKCS, CKFM_AUTH_NO_RECOVER),
@@ -386,6 +394,7 @@ void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id,
 	case PKCS11_CKM_AES_CBC:
 	case PKCS11_CKM_AES_CBC_PAD:
 	case PKCS11_CKM_AES_CTR:
+	case PKCS11_CKM_AES_GCM:
 	case PKCS11_CKM_AES_CTS:
 	case PKCS11_CKM_AES_CMAC:
 	case PKCS11_CKM_AES_CMAC_GENERAL:
@@ -410,6 +419,7 @@ void pkcs11_mechanism_supported_key_sizes(uint32_t proc_id,
 		break;
 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
 	case PKCS11_CKM_RSA_PKCS:
+	case PKCS11_CKM_RSA_X_509:
 	case PKCS11_CKM_MD5_RSA_PKCS:
 	case PKCS11_CKM_SHA1_RSA_PKCS:
 	case PKCS11_CKM_RSA_PKCS_OAEP:
@@ -452,8 +462,8 @@ void mechanism_supported_key_sizes_bytes(uint32_t proc_id,
 	case PKCS11_CKM_ECDSA_SHA512:
 	case PKCS11_CKM_RSA_PKCS_KEY_PAIR_GEN:
 		/* Size is in bits -> convert to bytes and ceil */
-		*min_key_size = ROUNDUP(*min_key_size, 8) / 8;
-		*max_key_size = ROUNDUP(*max_key_size, 8) / 8;
+		*min_key_size = ROUNDUP_DIV(*min_key_size, 8);
+		*max_key_size = ROUNDUP_DIV(*max_key_size, 8);
 		break;
 	default:
 		/* Size is already in bytes */
diff --git a/ta/pkcs11/sub.mk b/ta/pkcs11/sub.mk
index aa66ee0ef0429c3f54412fd9b71fb5ee49282d42..9ce6b6944fe18fc0517bf320be0d7308b252acf2 100644
--- a/ta/pkcs11/sub.mk
+++ b/ta/pkcs11/sub.mk
@@ -13,6 +13,11 @@ CFG_PKCS11_TA_TOKEN_COUNT ?= 3
 # When enabled, embed support for object checksum value computation
 CFG_PKCS11_TA_CHECK_VALUE_ATTRIBUTE ?= y
 
+# When enabled, embed support for CKM_RSA_X_509 (a.k.a. Raw RSA) ciphering
+# and authentication. The feature can be needed for some TLS v1.2 connections.
+# Raw RSA can be unsafe if client uses a weak clear data padding scheme.
+CFG_PKCS11_TA_RSA_X_509 ?= n
+
 global-incdirs-y += include
 global-incdirs-y += src
 subdirs-y += src
diff --git a/ta/remoteproc/include/ta_remoteproc.h b/ta/remoteproc/include/ta_remoteproc.h
index 71a15451568eef0f30fa9710700b2fa462393882..bc1b125fd2b8634563f9921dfcbaa3044695522a 100644
--- a/ta/remoteproc/include/ta_remoteproc.h
+++ b/ta/remoteproc/include/ta_remoteproc.h
@@ -61,4 +61,14 @@
  */
 #define TA_RPROC_CMD_GET_COREDUMP	5
 
+/*
+ * Release remote processor firmware images and associated resources.
+ * This command should be used in case an error occurs between the loading of
+ * the firmware images (TA_RPROC_CMD_LOAD_FW) and the starting of the remote
+ * processor (TA_RPROC_CMD_START_FW) or after stopping the remote processor
+ * to release associated resources (TA_RPROC_CMD_STOP_FW).
+ *
+ * [in]  params[0].value.a: Unique 32-bit remote processor identifier
+ */
+#define TA_RPROC_CMD_RELEASE_FW		6
 #endif /*TA_REMOTEPROC_H*/
diff --git a/ta/remoteproc/src/remoteproc_core.c b/ta/remoteproc/src/remoteproc_core.c
index c3b815d9be1d0f6a4b63129069a02a5c3564b08e..811706e9803f1d9184daadb6c1f21efa858aaf56 100644
--- a/ta/remoteproc/src/remoteproc_core.c
+++ b/ta/remoteproc/src/remoteproc_core.c
@@ -893,6 +893,10 @@ static TEE_Result remoteproc_load_fw(uint32_t pt,
 	if (!ctx)
 		return TEE_ERROR_OUT_OF_MEMORY;
 
+	/* The firmware is already loaded, do nothing */
+	if (ctx->state == REMOTEPROC_LOADED)
+		return TEE_SUCCESS;
+
 	if (ctx->state != REMOTEPROC_OFF)
 		return TEE_ERROR_BAD_STATE;
 
@@ -1033,6 +1037,35 @@ static TEE_Result remoteproc_get_rsc_table(uint32_t pt,
 	return TEE_SUCCESS;
 }
 
+static TEE_Result remoteproc_release_fw(uint32_t pt,
+					TEE_Param params[TEE_NUM_PARAMS])
+{
+	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_INPUT,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE,
+						TEE_PARAM_TYPE_NONE);
+	struct remoteproc_context *ctx = NULL;
+	uint32_t rproc_id = params[0].value.a;
+	TEE_Result res = TEE_ERROR_GENERIC;
+
+	if (pt != exp_pt)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	ctx = remoteproc_find_firmware(rproc_id);
+	if (!ctx)
+		return TEE_ERROR_BAD_PARAMETERS;
+
+	if (ctx->state == REMOTEPROC_STARTED)
+		return TEE_ERROR_BAD_STATE;
+
+	res = TEE_InvokeTACommand(pta_session, TEE_TIMEOUT_INFINITE,
+				  PTA_REMOTEPROC_RELEASE, pt, params, NULL);
+	if (res == TEE_SUCCESS)
+		ctx->state = REMOTEPROC_OFF;
+
+	return res;
+}
+
 TEE_Result TA_CreateEntryPoint(void)
 {
 	return TEE_SUCCESS;
@@ -1097,6 +1130,8 @@ TEE_Result TA_InvokeCommandEntryPoint(void *sess __unused, uint32_t cmd_id,
 		return remoteproc_get_rsc_table(pt, params);
 	case TA_RPROC_CMD_GET_COREDUMP:
 		return TEE_ERROR_NOT_IMPLEMENTED;
+	case TA_RPROC_CMD_RELEASE_FW:
+		return remoteproc_release_fw(pt, params);
 	default:
 		return TEE_ERROR_BAD_PARAMETERS;
 	}
diff --git a/ta/trusted_keys/user_ta_header_defines.h b/ta/trusted_keys/user_ta_header_defines.h
index 2fc6689a04e9f4f6737131afb90fe7d0c8b292aa..bf249dfc05c2ed59fed22cae2c325d7469ca4796 100644
--- a/ta/trusted_keys/user_ta_header_defines.h
+++ b/ta/trusted_keys/user_ta_header_defines.h
@@ -17,4 +17,8 @@
 #define TA_STACK_SIZE			(4 * 1024)
 #define TA_DATA_SIZE			(16 * 1024)
 
+#define TA_VERSION			"1.0"
+
+#define TA_DESCRIPTION			"Trusted Keys"
+
 #endif /*USER_TA_HEADER_DEFINES_H*/
diff --git a/ta/user_ta_header.c b/ta/user_ta_header.c
index d602f9226de05d0fefb271e0acd3d68939bb4591..3125af55c44c8ab8d3ba48d163f495d4c94ee166 100644
--- a/ta/user_ta_header.c
+++ b/ta/user_ta_header.c
@@ -39,15 +39,17 @@ struct utee_params;
 TEE_Result __utee_entry(unsigned long func, unsigned long session_id,
 			struct utee_params *up, unsigned long cmd_id);
 
-void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func,
-					unsigned long session_id,
-					struct utee_params *up,
-					unsigned long cmd_id);
-
-void __noreturn _C_FUNCTION(__ta_entry)(unsigned long func,
-					unsigned long session_id,
-					struct utee_params *up,
-					unsigned long cmd_id)
+void __noreturn __no_stack_protector
+_C_FUNCTION(__ta_entry)(unsigned long func,
+			unsigned long session_id,
+			struct utee_params *up,
+			unsigned long cmd_id);
+
+void __noreturn __no_stack_protector
+_C_FUNCTION(__ta_entry)(unsigned long func,
+			unsigned long session_id,
+			struct utee_params *up,
+			unsigned long cmd_id)
 {
 	static bool stack_canary_inited;
 	TEE_Result res = TEE_ERROR_GENERIC;